import com.sun.opengl.util.*; import com.sun.opengl.util.texture.*; import java.io.*; import java.awt.event.*; import java.nio.*; import javax.swing.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; public class VboFrame extends JFrame implements GLEventListener, MouseListener, MouseMotionListener, WindowListener, KeyListener { private static final int SLICES = 200; private static final int STACKS = 100; private static final float RADIUS = 1.0f; private static final double PI_2 = Math.PI*2; private GLCanvas canvas; private Animator animator; private float angleX, angleY; private float angleX0, angleY0; private float dist = 2.0f; private float dist0; private int mouseX, mouseY; private int lastButton; //vertices private float [] vs; //vertex indices private int [][] vi; //colors private float [] cs; //normals private float [] ns; private GLU myGLU = new GLU(); private GLUT myGLUT = new GLUT(); private int theSphere; private FPSCounter fpscounter = new FPSCounter(); private boolean linemode = false; private int fkey = KeyEvent.VK_F3; private FloatBuffer nbuf, cbuf, vbuf; private IntBuffer ibuf1, ibuf3; private IntBuffer[] ibuf2; private int[] ibufcount; private IntBuffer ibuf4; public VboFrame(String title) { super(title); //this.setUndecorated(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); angleX = 0.0f; angleY = 0.0f; GLCapabilities capabilities = new GLCapabilities(); capabilities.setHardwareAccelerated(true); capabilities.setDoubleBuffered(true); canvas = new GLCanvas(capabilities); canvas.addGLEventListener(this); canvas.addMouseListener(this); canvas.addMouseMotionListener(this); canvas.addKeyListener(this); canvas.setVisible(true); this.getContentPane().add(canvas); this.setSize(640, 480); this.setLocation(100, 100); animator = new Animator(canvas); this.addWindowListener(this); this.show(); animator.start(); } /*** implementing GLEventListener methods ***/ public void init(GLAutoDrawable glDrawable) { GL myGL = glDrawable.getGL(); initSphere(SLICES, STACKS, RADIUS); theSphere = myGL.glGenLists(1); myGL.glNewList(theSphere, GL.GL_COMPILE); renderSphere(); myGL.glEndList(); float[] lightAmbient = {0.3f, 0.3f, 0.3f, 1.0f}; float[] lightDiffuse = {0.7f, 0.7f, 0.7f, 1.0f}; float[] lightSpecular = {1.0f, 1.0f, 1.0f, 1.0f}; float[] lightPosition = {10.0f, 10.0f, 10.0f, 0.0f}; myGL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); myGL.glShadeModel(GL.GL_SMOOTH); myGL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, lightAmbient, 0); myGL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, lightDiffuse, 0); myGL.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, lightSpecular, 0); myGL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0); //myGL.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE); myGL.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE); myGL.glCullFace(GL.GL_FRONT); myGL.glEnable(GL.GL_DEPTH_TEST); myGL.glEnable(GL.GL_LIGHT0); myGL.glEnable(GL.GL_LIGHTING); myGL.glEnable(GL.GL_COLOR_MATERIAL); myGL.glEnable(GL.GL_CULL_FACE); } public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) { GL myGL = glDrawable.getGL(); float aspect = w/(float)h; myGL.glMatrixMode(GL.GL_PROJECTION); myGL.glLoadIdentity(); myGL.glFrustum(-0.017*aspect, 0.017*aspect, -0.017, 0.017, 0.02, 100); } public void display(GLAutoDrawable glDrawable) { GL myGL = glDrawable.getGL(); fpscounter.update(); if (linemode) { myGL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); } else { myGL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); } myGL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); myGL.glMatrixMode(GL.GL_MODELVIEW); myGL.glLoadIdentity(); myGL.glTranslatef(0.0f, 0.0f, -dist); myGL.glRotatef(angleX, 1.0f, 0.0f, 0.0f); myGL.glRotatef(angleY, 0.0f, 1.0f, 0.0f); switch (fkey) { case KeyEvent.VK_F1 : renderSphere(); break; case KeyEvent.VK_F2 : myGL.glCallList(theSphere); break; case KeyEvent.VK_F3 : renderArraySphere(); break; } drawInfo(myGL); } public void displayChanged(GLAutoDrawable glDrawable, boolean b, boolean b1) { } /*** implementing MouseListener methods **/ public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { lastButton = e.getButton(); if (lastButton == MouseEvent.BUTTON1) { angleX0 = angleX; angleY0 = angleY; mouseX = e.getX(); mouseY = e.getY(); } else if (lastButton == MouseEvent.BUTTON3) { dist0 = dist; mouseY = e.getY(); } } public void mouseReleased(MouseEvent e) { } /*** implementing MouseMotionListener methods ***/ public void mouseDragged(MouseEvent e) { int dx, dy, dz; if (lastButton == MouseEvent.BUTTON1) { dx = mouseX - e.getX(); dy = mouseY - e.getY(); angleY = angleY0 - dx; angleX = angleX0 - dy; } if (lastButton == MouseEvent.BUTTON3) { dz = mouseY - e.getY(); dist = dist0 + dz/100.0f; } } public void mouseMoved(MouseEvent e) {} /***implementing WindowListener methods ***/ public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowClosing(WindowEvent e) { close(); } public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} /*** implementing KeyListener **/ public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); char keyChar = e.getKeyChar(); switch (keyCode) { case KeyEvent.VK_ESCAPE : close(); break; case KeyEvent.VK_F1 : fkey = KeyEvent.VK_F1; break; case KeyEvent.VK_F2 : fkey = KeyEvent.VK_F2; break; case KeyEvent.VK_F3 : fkey = KeyEvent.VK_F3; break; } switch (keyChar) { case 'f' : linemode=false; break; case 'l' : linemode=true; break; } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } /*** private methods ***/ private void stopAnimation() { if (animator != null) animator.stop(); } private void close() { stopAnimation(); System.exit(0); } private void fill3f(float[] fv, int index, float f1, float f2, float f3) { fv[index]=f1; fv[index+1]=f2; fv[index+2]=f3; } private void out(int index) { System.out.println(vs[index*3] + " " + vs[index*3+1] + " " + vs[index*3+2]); System.out.println(ns[index*3] + " " + ns[index*3+1] + " " + ns[index*3+2]); System.out.println(cs[index*3] + " " + cs[index*3+1] + " " + cs[index*3+2]); } private void initSphere(int slices, int stacks, float radius) { float x, y, z; vs = new float[(slices*(stacks-1)+2)*3]; ns = new float[(slices*(stacks-1)+2)*3]; cs = new float[(slices*(stacks-1)+2)*3]; fill3f(vs, 0, 0.0f, 0.0f, radius); fill3f(ns, 0, 0.0f, 0.0f, 1.0f); fill3f(cs, 0, 0.5f, 0.5f, 1.0f); for (int j=1; j<stacks; ++j) { for (int i=0; i<slices; ++i) { x = (float)Math.sin((i*PI_2)/slices) * (float)Math.sin(j*Math.PI/stacks); y = (float)Math.cos((i*PI_2)/slices) * (float)Math.sin(j*Math.PI/stacks); z = (float)Math.cos(j*Math.PI/stacks); fill3f(vs, 3+(j-1)*3*slices+i*3, x*radius, y*radius, z*radius); fill3f(ns, 3+(j-1)*3*slices+i*3, x, y, z); fill3f(cs, 3+(j-1)*3*slices+i*3, x/2.0f+0.5f, y/2.0f+0.5f, z/2.0f+0.5f); } } fill3f(vs, (slices*(stacks-1)+1)*3, 0.0f, 0.0f, -radius); fill3f(ns, (slices*(stacks-1)+1)*3, 0.0f, 0.0f, -1.0f); fill3f(cs, (slices*(stacks-1)+1)*3, 0.5f, 0.5f, 0.0f); vi = new int[stacks][]; vi[0]=new int[slices+2]; vi[0][0]=0; for (int i=0; i<slices+1; ++i) { vi[0][1+i]=i < slices ? i+1 : 1; } for (int j=1; j<stacks-1; ++j) { vi[j]=new int[(slices+1)*2]; for (int i=0; i<slices+1; ++i) { vi[j][i*2]=i < slices ? 1+(j-1)*slices+i : 1+(j-1)*slices; vi[j][i*2+1]=i < slices ? 1+j*slices+i : 1+j*slices; } } vi[stacks-1]=new int[slices+2]; vi[stacks-1][0]=slices*(stacks-1)+1; for (int i=0; i<slices+1; ++i) { vi[stacks-1][slices-i+1]=i<slices ? 1+(stacks-2)*slices+i : 1+(stacks-2)*slices; } nbuf = BufferUtil.newFloatBuffer(ns.length); nbuf.put(ns); nbuf.rewind(); cbuf = BufferUtil.newFloatBuffer(cs.length); cbuf.put(cs); cbuf.rewind(); vbuf = BufferUtil.newFloatBuffer(vs.length); vbuf.put(vs); vbuf.rewind(); ibuf1 = BufferUtil.newIntBuffer(vi[0].length); ibuf1.put(vi[0]); ibuf1.rewind(); ibuf3 = BufferUtil.newIntBuffer(vi[vi.length-1].length); ibuf3.put(vi[vi.length-1]); ibuf3.rewind(); ibuf2 = new IntBuffer[stacks-2]; ibufcount = new int[stacks-2]; for (int i=0; i<stacks-2; ++i) { ibufcount[i]=vi[i+1].length; ibuf2[i] = BufferUtil.newIntBuffer(vi[i+1].length); ibuf2[i].put(vi[i+1]); ibuf2[i].rewind(); } ibuf4 = BufferUtil.newIntBuffer(ibufcount.length); ibuf4.put(ibufcount); ibuf4.rewind(); } private void renderSphere() { GL myGL = GLContext.getCurrent().getGL(); myGL.glBegin(GL.GL_TRIANGLE_FAN); for (int i=0; i<vi[0].length; ++i) { myGL.glColor3fv(cs, vi[0][i]*3); myGL.glNormal3fv(ns, vi[0][i]*3); myGL.glVertex3fv(vs, vi[0][i]*3); } myGL.glEnd(); for (int j=0; j<vi.length-1; ++j) { myGL.glBegin(GL.GL_QUAD_STRIP); for (int i=0; i<vi[j].length; ++i) { myGL.glColor3fv(cs, vi[j][i]*3); myGL.glNormal3fv(ns, vi[j][i]*3); myGL.glVertex3fv(vs, vi[j][i]*3); } myGL.glEnd(); } myGL.glBegin(GL.GL_TRIANGLE_FAN); for (int i=0; i<vi[vi.length-1].length; ++i) { myGL.glColor3fv(cs, vi[vi.length-1][i]*3); myGL.glNormal3fv(ns, vi[vi.length-1][i]*3); myGL.glVertex3fv(vs, vi[vi.length-1][i]*3); } myGL.glEnd(); } private void renderArraySphere() { GL myGL = GLContext.getCurrent().getGL(); myGL.glEnableClientState(GL.GL_NORMAL_ARRAY); myGL.glEnableClientState(GL.GL_COLOR_ARRAY); myGL.glEnableClientState(GL.GL_VERTEX_ARRAY); myGL.glNormalPointer(GL.GL_FLOAT, 0, nbuf); myGL.glColorPointer(3, GL.GL_FLOAT, 0, cbuf); myGL.glVertexPointer(3, GL.GL_FLOAT, 0, vbuf); myGL.glDrawElements(GL.GL_TRIANGLE_FAN, vi[0].length, GL.GL_UNSIGNED_INT, ibuf1); /*for (int i=0; i<ibufcount.length; ++i) { myGL.glDrawElements(GL.GL_QUAD_STRIP, ibufcount[i], GL.GL_UNSIGNED_INT, ibuf2[i]); }*/ /*myGL.glMultiDrawElements(GL.GL_QUAD_STRIP, ibufcount, 0, GL.GL_UNSIGNED_INT, ibuf2, ibufcount.length);*/ myGL.glMultiDrawElements(GL.GL_QUAD_STRIP, ibuf4, GL.GL_UNSIGNED_INT, ibuf2, ibufcount.length); myGL.glDrawElements(GL.GL_TRIANGLE_FAN, vi[vi.length-1].length, GL.GL_UNSIGNED_INT, ibuf3); myGL.glDisableClientState(GL.GL_NORMAL_ARRAY); myGL.glDisableClientState(GL.GL_COLOR_ARRAY); myGL.glDisableClientState(GL.GL_VERTEX_ARRAY); } public synchronized void drawInfo(GL myGL) { myGL.glPushAttrib(GL.GL_ALL_ATTRIB_BITS); myGL.glDisable(GL.GL_TEXTURE_2D); myGL.glDisable(GL.GL_DEPTH_TEST); myGL.glDisable(GL.GL_BLEND); myGL.glDisable(GL.GL_LIGHTING); myGL.glDisable(GL.GL_LIGHT0); myGL.glDisable(GL.GL_CULL_FACE); myGL.glDisable(GL.GL_COLOR_MATERIAL); myGL.glMatrixMode(GL.GL_PROJECTION); myGL.glPushMatrix(); myGL.glLoadIdentity(); myGLU.gluOrtho2D(0, 500, 300, 0); myGL.glMatrixMode(GL.GL_MODELVIEW); myGL.glPushMatrix(); myGL.glLoadIdentity(); myGL.glColor3f(1.0f, 1.0f, 0.0f); myGL.glRasterPos2f(430, 15); myGLUT.glutBitmapString(GLUT.BITMAP_8_BY_13, "Fps : " + fpscounter.getFps()); myGL.glMatrixMode(GL.GL_PROJECTION); myGL.glPopMatrix(); myGL.glMatrixMode(GL.GL_MODELVIEW); myGL.glPopMatrix(); myGL.glPopAttrib(); myGL.glFlush(); } /*** the main ***/ public static void main(String args[]) { VboFrame frm = new VboFrame("Vbo Test"); } }