- init() – обычно включает в себя установку z-(глубинного) буфера, создание света, загрузку текстур и построение списка для отображения (для метода display()).
- display() – в нем идет отображение;
- reshape() – в нем происходят действия, связанные с перересовкой, например растянули окно или переместили его, что также включается при первоначальном рисовании на экране. Это делает этот метод стандартным местом для помещения в него команд OpenGL для установки области просмотра(viewport) и проекционной матрицы (projection matrix);
- dispose() – в нем нужно производить действия, связанные с уничтожением объектов.
CubeGL.java
import java.awt.Container; import java.awt.Dimension; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.media.opengl.awt.GLCanvas; import javax.swing.JFrame; import javax.swing.JPanel; import com.jogamp.opengl.util.FPSAnimator; public class CubeGL extends JFrame { private FPSAnimator animator; private GLCanvas canvas; private JPanel renderPane; private CubeGLListener listener; public CubeGL(int fps) { super("CubeGL (Basic)"); Container c = getContentPane(); c.add(makeRenderPanel(fps)); // добавим слушателя для выхода из программы (в другом трэде) addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { new Thread(new Runnable() { public void run() { if (animator.isAnimating()) animator.stop(); System.exit(0); } }).start(); } }); pack(); animator.start(); setVisible(true); canvas.requestFocus(); } private JPanel makeRenderPanel(int fps) { renderPane = new JPanel(); renderPane.setLayout(new BorderLayout()); // renderPane.setOpaque(false); canvas = new GLCanvas(); // the canvas canvas.setSize(new Dimension(300, 300)); // the listener listener = new CubeGLListener(); canvas.addGLEventListener(listener); // the animator uses fixed rate scheduling animator = new FPSAnimator(canvas, fps, true); renderPane.setSize(canvas.getPreferredSize()); renderPane.add(canvas, BorderLayout.CENTER); return renderPane; } public static void main(String[] args) { new CubeGL(60); } }
CubeGLListener.java
import java.util.Random; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.glu.GLU; public class CubeGLListener implements GLEventListener{ private static final float INCR_MAX = 1.0f; // rotation increments private int cubeDList; // display list for displaying the cube // rotation variables private float rotX, rotY, rotZ; // total rotations in x,y,z axes private float incrX, incrY, incrZ; // increments for x,y,z rotations private static final double Z_DIST = 7.0; // for camera position private float[][] verts = { {-1.0f,-1.0f, 1.0f}, // vertex 0 {-1.0f, 1.0f, 1.0f}, // 1 { 1.0f, 1.0f, 1.0f}, // 2 { 1.0f,-1.0f, 1.0f}, // 3 {-1.0f,-1.0f,-1.0f}, // 4 {-1.0f, 1.0f,-1.0f}, // 5 { 1.0f, 1.0f,-1.0f}, // 6 { 1.0f,-1.0f,-1.0f}, // 7 }; @Override public void display(GLAutoDrawable drawable) { // TODO Auto-generated method stub // update the rotations rotX = (rotX + incrX) % 360.0f; rotY = (rotY + incrY) % 360.0f; rotZ = (rotZ + incrZ) % 360.0f; GL2 gl = drawable.getGL().getGL2(); GLU glu = new GLU(); // clear color and depth buffers gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); glu.gluLookAt(0, 0, Z_DIST, 0, 0, 0, 0, 1, 0); // position camera // apply rotations to the x,y,z axes gl.glRotatef(rotX, 1.0f, 0.0f, 0.0f); gl.glRotatef(rotY, 0.0f, 1.0f, 0.0f); gl.glRotatef(rotZ, 0.0f, 0.0f, 1.0f); gl.glCallList(cubeDList); //execute display list for drawing cube } @Override public void dispose(GLAutoDrawable drawable) { // TODO Auto-generated method stub } @Override public void init(GLAutoDrawable drawable) { // TODO Auto-generated method stub GL2 gl = drawable.getGL().getGL2(); // don't make this gl a global! // initialize the rotation variables rotX = 0; rotY = 0; rotZ = 0; Random random = new Random(); incrX = random.nextFloat()*INCR_MAX; // 0 - INCR_MAX degrees incrY = random.nextFloat()*INCR_MAX; incrZ = random.nextFloat()*INCR_MAX; gl.glClearColor(0.17f, 0.65f, 0.92f, 0.0f); //sky color background // z- (depth) buffer initialization for hidden surface removal gl.glEnable(GL2.GL_DEPTH_TEST); // create a display list for drawing the cube cubeDList = gl.glGenLists(1); gl.glNewList(cubeDList, GL2.GL_COMPILE); drawColourCube(gl); gl.glEndList(); } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { // TODO Auto-generated method stub GL2 gl = drawable.getGL().getGL2(); GLU glu = new GLU(); if (height == 0)height = 1; // to avoid division by 0 in aspect ratio below gl.glViewport(x, y, width, height); // size of drawing area gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); // camera's angle of view, aspect ratio, near & far clipping planes glu.gluPerspective(45.0, (float)width/(float)height, 1, 100); gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); } // six-sided cube, with a different color on each face private void drawColourCube(GL2 gl) { gl.glColor3f(1.0f, 0.0f, 0.0f); // red drawPolygon(gl, 0, 3, 2, 1); // front face gl.glColor3f(0.0f, 1.0f, 0.0f); // green drawPolygon(gl, 2, 3, 7, 6); // right gl.glColor3f(0.0f, 0.0f, 1.0f); // blue drawPolygon(gl, 3, 0, 4, 7); // bottom gl.glColor3f(1.0f, 1.0f, 0.0f); // yellow drawPolygon(gl, 1, 2, 6, 5); // top gl.glColor3f(0.0f, 1.0f, 1.0f); // light blue drawPolygon(gl, 4, 5, 6, 7); // back gl.glColor3f(1.0f, 0.0f, 1.0f); // purple drawPolygon(gl, 5, 4, 0, 1); // left } // the polygon vertices come from the verts[] array private void drawPolygon(GL2 gl, int vIdx0, int vIdx1, int vIdx2, int vIdx3) { gl.glBegin(GL2.GL_POLYGON); gl.glVertex3f(verts[vIdx0][0],verts[vIdx0][1], verts[vIdx0][2] ); gl.glVertex3f(verts[vIdx1][0],verts[vIdx1][1], verts[vIdx1][2] ); gl.glVertex3f(verts[vIdx2][0],verts[vIdx2][1], verts[vIdx2][2] ); gl.glVertex3f(verts[vIdx3][0],verts[vIdx3][1], verts[vIdx3][2] ); gl.glEnd(); } } Документация jogl предостерегает от использования глобального GL инстанса (объекта), поскольку это искушает программистов вызывать функции OpenGL от мышей и клавиатур или других тэдов. И это приводит к краху приложения, поскольку контекст OpenGL (его внутреннее состояние(?)) связано с GLEventListener'ом. В то же время можно делать глобальным GLU, но только для методов обратного вызова. Вершины(verts) соответствуют точкам на рисунке:
Позиция вершины в массиве используется в методе drawPolygon() чтобы нарисовать кубик. В drawPolygon() после объявления начала рисования(GL.glBegin()) идет опция рисования полигона GL2.GL_POLYGON, существуют также опции рисования GL2.GL_POINTS, GL2.GL_LINES, вроде понятно что это.
(x, y) аргументы метода reshape() определяют позицию канваса относительно объемлющего его контейнера. В этом примере они (0,0). GL-объект заново создается из входного аргумента GLAutoDrawable. Вызов GL.glViewport() определяет размеры рисуемого окна, начиная с НИЖНЕГО ЛЕВОГО угла + ширина и высота. Режим матрицы переключается в проекцию (PROJECTION) gl.glMatrixMode(GL2.GL_PROJECTION) – определяет маппинг 3х мерной сцены в 2х мерную. gl.glLoadIdentity() – обнуляет матрицу. В конце режим матрицы переключается в MODELVIEW. Это определяет систему координат сцены, используемой при размещении или перемещении 3D объекта. Этот режим устанавливается вконце, так как следующим будет вызван display(), рисующий сцену.

Комментариев нет:
Отправить комментарий