1、swt是什么:http://www.eclipse.org/swt/
2、jogl是什么:https://jogl.dev.java.net/
3、opengl是什么: http://www.opengl.org/
一、环境搭建:
首先到jogl网站https://jogl.dev.java.net/下载最新的JOGL包jogl-1.1.0-windows-i586.zip (根据自己的环境选择相应的包),然后解压,本示例中解压到E:\wyc\学习资料\计算机\opengl\jogl\jogl-1.1.0-windows-i586。
二、配置eclipse环境:
1、到eclipse网站www.eclipse.org下载最新的eclipse版本,最好下载用于RCP(富客户端程序)开发的eclipse版本,因为该版本包含了开发SWT/JFACE图形界面的所有相关包,这里使用的是eclipse-rcp-europa-fall2-win32.zip。下载完成有解压并运行eclipse。
2、在eclipse中新建一个java工程Test,如附件中图1
3、配置Java build path: 将jogl相关的两个包gluegen-rt.jar,jogl.jar;SWT/JFACE相关的三个包添加到 build path中;并将jogl相关的DLL文件所在路径设置到Native library location中,如附件中图2:
4、编写代码:JOGL对AWT/SWING提供了很好的支持,在这里,本人仿照NEHE的JOGL示例代码编写了一些通用的基础类:
GLSEventListener 类:类似于jogl中的GLEventListener类,唯一不同的是方法中传入的参数不同,GLEventListener类中方法的参数都是GLAutoDrawable参数,而GLSEventListener是GLSCanvas,这里的GLSCanvas也是自己写的一个继承自SWT中GLCanvas的类。
package org.mywater.common;
import org.eclipse.swt.graphics.Rectangle;
public interface GLSEventListener{
public void display(GLSCanvas canvas);
public void displayChanged(GLSCanvas canvas, boolean modeChanged,
boolean deviceChanged);
public void init(GLSCanvas canvas);
public void reshape(GLSCanvas canvas, Rectangle rect);
}
由于AWT中的GLCanvas类提供了很好的OPENGL事件支持,而SWT中的GLCanvas类没有相关的方法支持,因此在这里仿照AWT中的GLCanvas类对SWT中的GLCanvas类进行了扩展。
package org.mywater.common;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
public class GLSCanvas extends GLCanvas {
private List eventListeners = new ArrayList();
private GLContext glContext;
public GLSCanvas(Composite parent, int style, GLData data) {
super(parent, style, data);
//添加窗口变化响应处理
this.addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
Rectangle rect = GLSCanvas.this.getClientArea();
reshape(rect);
}
});
//添加重绘响应处理
this.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
display();
}
});
}
public void display() {
for ( int i = 0; i < eventListeners.size(); i++ ) {
( eventListeners.get( i ) ).display(this);
}
}
public void displayChanged(boolean b, boolean b1 ) {
for ( int i = 0; i < eventListeners.size(); i++ ) {
( eventListeners.get( i ) ).displayChanged( this, b, b1 );
}
}
public void init() {
for ( int i = 0; i < eventListeners.size(); i++ ) {
( eventListeners.get( i ) ).init( this );
}
}
public void reshape(Rectangle rect) {
for ( int i = 0; i < eventListeners.size(); i++ ) {
( eventListeners.get( i ) ).reshape( this, rect);
}
}
public void addGLEventListener(GLSEventListener glEventListener) {
eventListeners.add( glEventListener );
}
public void removeGLEventListener(GLSEventListener glEventListener) {
eventListeners.remove( glEventListener );
}
public GLContext getGlContext(){
if(glContext == null){
setCurrent();
glContext = GLDrawableFactory.getFactory().createExternalGLContext();
}
return glContext;
}
public GL getGL(){
return getGlContext().getGL();
}
}
为了避免每次都编写窗口相关的代码,仿照NEHE的JOGL示例代码编写了GLDisplay类来处理基本的窗口操作。
package org.mywater.common;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class GLDisplay {
private static final int DEFAULT_WIDTH = 640;
private static final int DEFAULT_HEIGHT = 480;
private GLSCanvas glSCanvas;
private Shell shell;
private ExceptionHandler exceptionHandler = new ExceptionHandler();
public static GLDisplay createGLDisplay( String title ) {
return new GLDisplay( title, DEFAULT_WIDTH, DEFAULT_HEIGHT, false );
}
private GLDisplay( String title, int width, int height, boolean fullscreen ) {
Display display = Display.getDefault();
shell = new Shell(display);
GLData glData = new GLData();
glData.doubleBuffer = true;
glSCanvas = new GLSCanvas(shell, SWT.NO_BACKGROUND, glData);
shell.setText(title);
shell.setLayout(new FillLayout());
}
public void start() {
try {
glSCanvas.init();
shell.open();
Display display = shell.getDisplay();
while(!shell.isDisposed()){
while(!display.readAndDispatch()){
display.sleep();
}
}
display.dispose();
} catch ( Exception e ) {
exceptionHandler.handleException( e );
}
}
public void addGLEventListener( GLSEventListener glEventListener ) {
glSCanvas.addGLEventListener(glEventListener);
}
public void removeGLEventListener( GLSEventListener glEventListener ) {
glSCanvas.removeGLEventListener( glEventListener );
}
public void addKeyListener( KeyListener l ) {
glSCanvas.addKeyListener( l );
}
public void addMouseListener( MouseListener l ) {
glSCanvas.addMouseListener( l );
}
public void removeKeyListener( KeyListener l ) {
glSCanvas.removeKeyListener( l );
}
public void removeMouseListener( MouseListener l ) {
glSCanvas.removeMouseListener( l );
}
public String getTitle() {
return shell.getText();
}
public void setTitle( String title ) {
shell.setText( title );
}
private class ExceptionHandler{
public void handleException( final Exception e ) {
Display.getDefault().syncExec( new Runnable() {
public void run() {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter( stringWriter );
e.printStackTrace( printWriter );
MessageDialog.openInformation( shell, stringWriter.toString(), "Exception occurred");
}
} );
}
}
}
最后,编写OPENL相关代码,运行该类,可得到一个黑色的背景上面画着一个白色矩形的窗口。
package org.mywater.lessons.lesson001;
import javax.media.opengl.GL;
import javax.media.opengl.GLContext;
import org.eclipse.swt.graphics.Rectangle;
import org.mywater.common.GLDisplay;
import org.mywater.common.GLSCanvas;
import org.mywater.common.GLSEventListener;
public class Lesson001 implements GLSEventListener {
public static void main(String[] args){
GLDisplay glDisplay = GLDisplay.createGLDisplay("test");
glDisplay.addGLEventListener(new Lesson001());
glDisplay.start();
}
public void display(GLSCanvas canvas) {
canvas.setCurrent();
GLContext context = canvas.getGlContext();
context.makeCurrent();
GL gl = canvas.getGL();
gl.glClear (GL.GL_COLOR_BUFFER_BIT);
gl.glBegin(GL.GL_POLYGON);
gl.glVertex3f (0.25f, 0.25f, 0.0f);
gl.glVertex3f (0.75f, 0.25f, 0.0f);
gl.glVertex3f (0.75f, 0.75f, 0.0f);
gl.glVertex3f (0.25f, 0.75f, 0.0f);
gl.glEnd();
gl.glFlush();
canvas.swapBuffers();
context.release();
}
public void displayChanged(GLSCanvas canvas, boolean modeChanged,
boolean deviceChanged) {
// TODO Auto-generated method stub
}
public void init(GLSCanvas canvas) {
canvas.setCurrent();
GLContext context = canvas.getGlContext();
context.makeCurrent();
GL gl = canvas.getGL();
gl.glLoadIdentity();
gl.glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear (GL.GL_COLOR_BUFFER_BIT);
gl.glColor3f (1.0f, 1.0f, 1.0f);
context.release();
}
public void reshape(GLSCanvas canvas, Rectangle rect) {
canvas.setCurrent();
GLContext context = canvas.getGlContext();
context.makeCurrent();
GL gl = context.getGL ();
gl.glViewport(0, 0, rect.width, rect.height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
context.release();
}
}
具体的代码都比较简单,所以细节没有做详细的解释,如果哪位仁兄看到该文章并且有疑问,欢迎邮件联系讨论wuyangchun1984@gmail.com
声名:本人OPENGL新手,所以考虑的东西比较简单,相应的代码会在本人学习OPENGL的过程中不断改进,欢迎高手指点。