Можно ли смешивать код C ++ OpenGL с Java, используя LWJGL? - PullRequest
0 голосов
/ 10 декабря 2018

Я хочу сделать приложение Java.используя библиотеку CEF3.CEF - это библиотека для встроенного браузера Google Chrome в любом приложении.И LWJGL используется для написания кода GL на Java.Но прежде чем использовать CEF, основной вопрос заключается в том, как смешать C ++ и Java.

  1. Основные вызовы Java C ++-часть как DLL

  2. C ++-часть создает окнои установить контекст GL

  3. В цикле сообщений C ++ снова вызывает Java-часть для выполнения некоторой работы GL в Java.

После тестакод завершается с сообщением:

FATAL ERROR в нативном методе: Thread [main, 5, main]: контекст не является текущим или функция, которая недоступна в текущем контексте, была вызвана.JVM прервет выполнение.
в org.lwjgl.opengl.GL11.glColor3f (собственный метод)
в Main.run (Main.java:18)
в Main.cppmain (собственный метод)
at Main.main (Main.java:10)

Возможно, потому что часть Java не знает о контексте GL, созданном частью C ++.У меня вопрос, как я могу настроить контекст GL так, чтобы и C ++, и Java могли вызывать функции GL?


Main.java

import org.lwjgl.opengl.GL11;

public class Main implements Runnable {
    {
        System.loadLibrary("cppgl");
    }

    public static void main(String[] args) {
        Main me = new Main();
        me.cppmain(me);
    }

    private native void cppmain(Runnable callback);

    @Override
    public void run() {
        // callback from cpp
        GL11.glColor3f(1.0f, 0.0f, 1.0f);
    }
}

cppgl.cpp

#pragma comment(lib, "OpenGL32.lib")

#include <windows.h>
#include <tchar.h>
#include <functional>
#include <gl/gl.h>
#include <jni.h>
#pragma comment(lib, "jvm.lib")

LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam) {
    if (mes == WM_DESTROY || mes == WM_CLOSE) { PostQuitMessage(0); return 0; }
    return DefWindowProc(hWnd, mes, wParam, lParam);
}

extern "C" JNIEXPORT void JNICALL Java_Main_cppmain
(JNIEnv *env, jobject, jobject callback) {

    LPCTSTR title = L"gl test";

    // prepare JNI call
    jclass cls = env->FindClass("Ljava/lang/Runnable;");
    jmethodID mid = env->GetMethodID(cls, "run", "()V");

    // window class
    HINSTANCE hInstance = ::GetModuleHandle(NULL);
    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(wcex));
    wcex.cbSize = sizeof(wcex);
    wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName = title;
    if (!RegisterClassEx(&wcex)) return;

    // window
    RECT R = { 0, 0, 640, 480 };
    AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, FALSE);
    HWND hWnd = CreateWindow(title, title, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, R.right - R.left, R.bottom - R.top,
        NULL, NULL, hInstance, NULL);
    if (!hWnd) return;

    // GL context
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    HDC dc = GetDC(hWnd);
    int format = ChoosePixelFormat(dc, &pfd);
    SetPixelFormat(dc, format, &pfd);
    HGLRC glRC = wglCreateContext(dc);
    if (!wglMakeCurrent(dc, glRC)) return;

    // message loop
    ShowWindow(hWnd, SW_SHOW);
    MSG msg;
    do {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            wglMakeCurrent(dc, glRC);
            glClearColor(0.0f, 0.5f, 1.0f, 1.0f);

            // call Java and change clear color here
            env->CallVoidMethod(callback, mid);

            glClear(GL_COLOR_BUFFER_BIT);
            glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
            glFlush();
            SwapBuffers(dc);
            wglMakeCurrent(NULL, NULL);
        }
    } while (msg.message != WM_QUIT);

    // clean up
    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(glRC);
    ReleaseDC(hWnd, dc);
}

1 Ответ

0 голосов
/ 10 декабря 2018

Вы можете вызвать это один раз в начале, прежде чем делать какой-либо рендеринг из Java.

    // This line is critical for LWJGL's interoperation with GLFW's
    // OpenGL context, or any context that is managed externally.
    // LWJGL detects the context that is current in the current thread,
    // creates the GLCapabilities instance and makes the OpenGL
    // bindings available for use.
    GL.createCapabilities();
...