在 Java AWT Canvas 中嵌入 OpenGL






4.50/5 (4投票s)
2000年10月26日

147241

592
本文展示了如何使用 JDK1.3 的 JAWT 接口在 Java AWT 画布中使用 OpenGL 调用。
引言
本文提供了一个将 OpenGL 代码添加到 Java 应用程序的框架。示例项目展示了如何在 AWT 画布小部件内运行 OpenGL 动画。这得益于最新 JDK1.3 中的基于 JNI 的 JAWT 接口。
为了实现这一点,需要解决两个主要问题。
问题 #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 文件包含本文的所有源代码,以及用于构建和运行代码的批处理文件。
- jGuru.com 上的 JNI 常见问题解答
http://www.jguru.com/faq/JNI - Java 技巧 86:在 JDK 1.3 中支持本机渲染
http://www.javaworld.com/javaworld/javatips/jw-javatip86.html - Sun 对 AWT 本机接口的介绍
hhttp://java.sun.com/j2se/1.3/docs/guide/awt/AWT_Native_Interface.html - Sun 关于 Java 2 SDK 版本 1.3 中 AWT 增强功能的介绍
http://java.sun.com/products/jdk/1.3/docs/guide/awt/enhancements.html - Sun 关于 JAWT 接口改进的本机绘图,Kestrel 之后(需要免费注册)
http://developer.java.sun.com/developer/bugParade/bugs/4281429.html - “使用 Java 本机接口 (JNI) 增强您的 Java 应用程序”,Tal Lyron(JavaWorld,1999 年 10 月)
http://www.javaworld.com/javaworld/jw-10-1999/jw-10-jni.html - “Java 技巧 23:编写本机方法”,John D. Mitchell (JavaWorld):
http://www.javaworld.com/javaworld/javatips/jw-javatip23.html