65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Java AWT Canvas 中嵌入 OpenGL

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (4投票s)

2000年10月26日

viewsIcon

147241

downloadIcon

592

本文展示了如何使用 JDK1.3 的 JAWT 接口在 Java AWT 画布中使用 OpenGL 调用。

  • 下载源代码和演示文件 - 6 Kb
  • Sample Image - opengl.gif

    引言

    本文提供了一个将 OpenGL 代码添加到 Java 应用程序的框架。示例项目展示了如何在 AWT 画布小部件内运行 OpenGL 动画。这得益于最新 JDK1.3 中的基于 JNI 的 JAWT 接口。

    为了实现这一点,需要解决两个主要问题。

  • 问题 #1 - 获取 Java AWT 画布的 HWND。
  • 问题 #2 - 如何使用 OpenGL 调用在此 HWND 上绘制。
  • 问题 #1 通过使用 JDK 1.3 中提供的已记录的 API 解决。以下网址解释了 JAWT 接口及其使用方法:

    http://java.sun.com/j2se/1.3/docs/guide/awt/AWT_Native_Interface.html

    以下是项目中的一段摘录,展示了实现方式:

    // Helper class for accessing JAWT Information.
    class JAWT_Info 
    {
    private:
        JAWT awt;
        JAWT_DrawingSurface* ds;
        JAWT_DrawingSurfaceInfo* dsi;
        JAWT_Win32DrawingSurfaceInfo* dsi_win;
    public:
        JAWT_Info(JNIEnv *env, jobject panel)
        {
            jboolean result;
            jint lock;
    
            // Get the AWT
            awt.version = JAWT_VERSION_1_3;
            result = JAWT_GetAWT(env, &awt);
            assert(result != JNI_FALSE);
            // Get the drawing surface
            ds = awt.GetDrawingSurface(env, panel);
            if(ds == NULL)
                return;
            // Lock the drawing surface
            lock = ds->Lock(ds);
            assert((lock & JAWT_LOCK_ERROR) == 0);
    
            // Get the drawing surface info
            dsi = ds->GetDrawingSurfaceInfo(ds);
    
            // Get the platform-specific drawing info
            dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
        }
        HWND getHWND()
        {
            if(dsi_win == NULL)
                return NULL;
            return dsi_win->hwnd;
        }
        HDC getHDC()
        {
            if(dsi_win == NULL)
                return NULL;
            return dsi_win->hdc;
        }
        virtual ~JAWT_Info()
        {
            if(ds != NULL)
            {
                // Free the drawing surface info
                ds->FreeDrawingSurfaceInfo(dsi);
                // Unlock the drawing surface
                ds->Unlock(ds);
                // Free the drawing surface
                awt.FreeDrawingSurface(ds);
            }
        }
    };
    

    问题 #2 在获得 HWND 后就变得很简单了。以下是项目中的一段摘录,展示了如何初始化 OpenGL:

    // Static variables for the OpenGL calls.
    static HGLRC    hRC = NULL;
    static HDC      hDC = NULL;
    
    /*
     * Class:     MyWindow
     * Method:    initializeOpenGL
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_MyWindow_initializeOpenGL
      (JNIEnv *env, jobject panel)
    {
        // get the window handle
        JAWT_Info info(env, panel);
        HWND hWnd = (HWND)info.getHWND();
    
        if(hWnd == NULL)
            return;
    
        PIXELFORMATDESCRIPTOR pfd;
        int iFormat;
    
        // get the device context (DC)
        HWND hwnd = info.getHWND();
        hDC = ::GetDC(hwnd);
    
        // set the pixel format for the DC
        ::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 = 24;
        pfd.cDepthBits = 16;
        pfd.iLayerType = PFD_MAIN_PLANE;
        iFormat = ::ChoosePixelFormat( hDC, &pfd );
        ::SetPixelFormat( hDC, iFormat, &pfd );
    
        // create and enable the render context (RC)
        hRC = ::wglCreateContext( hDC );
        ::wglMakeCurrent( hDC, hRC );
    }
    

    以下是项目中的一段摘录,展示了如何使用 OpenGL 进行绘制:

    /*
     * Class:     MyWindow
     * Method:    paint
     * Signature: (Ljava/awt/Graphics;)V
     */
    JNIEXPORT void JNICALL Java_MyWindow_paintOpenGL
      (JNIEnv *env, jobject panel)
    {
        static float theta = 0.0f;
        // get the window handle
        JAWT_Info info(env, panel);
        HWND hWnd = (HWND)info.getHWND();
    
        if(hWnd == NULL)
            return;
    
        // OpenGL animation code goes here
        ::glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
        ::glClear( GL_COLOR_BUFFER_BIT );
    
        ::glPushMatrix();
        ::glRotatef( theta, 0.0f, 0.0f, 1.0f );
        ::glBegin( GL_TRIANGLES );
        ::glColor3f( 1.0f, 0.0f, 0.0f ); glVertex2f( 0.0f, 1.0f );
        ::glColor3f( 0.0f, 1.0f, 0.0f ); glVertex2f( 0.87f, -0.5f );
        ::glColor3f( 0.0f, 0.0f, 1.0f ); glVertex2f( -0.87f, -0.5f );
        ::glEnd();
        ::glPopMatrix();
    
        ::SwapBuffers( hDC );
    
        theta += 1.0f;
    }
    

    完成之后,这是清理代码:

    /*
     * Class:     MyWindow
     * Method:    cleanupOpenGL
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_MyWindow_cleanupOpenGL
    (JNIEnv *env, jobject panel)
    {
        // get the window handle
        JAWT_Info info(env, panel);
        HWND hWnd = (HWND)info.getHWND();
        if(hWnd == NULL)
            return;
    
        ::wglMakeCurrent( NULL, NULL );
        ::wglDeleteContext( hRC );
        ::ReleaseDC( hWnd, hDC );
    }
    

    上述 zip 文件包含本文的所有源代码,以及用于构建和运行代码的批处理文件。

    资源

    © . All rights reserved.