package classwork; import java.awt.event.KeyEvent; import java.io.*; import javax.media.opengl.*; import jocode.*; import jomodel.*; /** * GLART_6_displaylist.java * * Creates a display list of the teapot model. Display lists are * opengl rendering commands (glVertex, glNormal, glColor etc.) wrapped * up in a very efficient data structure. In many cases display * lists can greatly improve rendering performance. They freeze * the model though, so only can be used in cases where the geometry * won't change (won't work for alpha rendering, where we have to * sort triangles from back to front so they will draw correctly). * * See the init() function for the display list code. */ public class GLART_6_displayList extends JOApp { private float rotation = 0; private JOMesh obj; // Material object will hold color values JOMaterial material = new JOMaterial(); // texture handle (a number that refers to an allocated texture) int marbleTextureHandle = 0; // Handle for a display list int teapotDisplayList = -1; boolean useDisplayList = false; /** * Main function just creates and runs the application. */ public static void main(String args[]) { GLART_6_displayList app = new GLART_6_displayList(); displayWidth = 800; displayHeight = 600; app.run(); } /** * Initialize OpenGL * */ public void setup() { // color of overall scene lighting float ambient[] = { .2f, .2f, .2f, 1f }; // color of light source float lightDiffuse[] = { .7f, .7f, .65f, 1f }; // direct light float lightSpecular[] = { .7f, .7f, .65f, 1f }; // highlight float lightAmbient[] = { .7f, .7f, .7f, 1f }; // scattered light // light position: if last value is 0, then this describes light direction. // If 1, then light position. float lightPosition[] = { -4f, 4f, 6, 0f }; // color of material float mtlDiffuse[] = { .9f, .9f, .8f, 1f }; // warm gray float mtlAmbient[] = { .5f, .5f, .4f, 1f }; // darker warm gray float mtlSpecular[] = { .5f, .5f, .5f, 1f }; // medium reflective float mtlEmissive[] = { 0f, 0f, 0f, 1f}; // no glow float mtlShininess = 10f; // 0=no shine, 127=max shine // Select the Projection Matrix (controls perspective) gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); // Reset The Projection Matrix // Define perspective glu.gluPerspective( 55.0f, // Field Of View (float)getWidth() / (float)getHeight(), // aspect ratio 0.1f, // near Z clipping plane 1000.0f); // far Z clipping plane // Select The Modelview Matrix (controls model orientation) gl.glMatrixMode(GL.GL_MODELVIEW); // make sure OpenGL correctly layers objects gl.glEnable(GL.GL_DEPTH_TEST); // OpenGL won't draw backward facing triangles ("back faces") gl.glEnable(GL.GL_CULL_FACE); // Turn texturing on gl.glEnable(GL.GL_TEXTURE_2D); // turn lighting on (does not create a light) gl.glEnable(GL.GL_LIGHTING); // Create a light // diffuse is the color of direct light from this light source // specular is the hightlight color // ambient is the color of scattered light from this source // position is where the light is, or it's direction setLight( GL.GL_LIGHT1, lightDiffuse, lightAmbient, lightSpecular, lightPosition ); // no overall scene lighting setAmbientLight(ambient); // change the current material settings material.setDiffuse(mtlDiffuse); material.setAmbient(mtlAmbient); material.setSpecular(mtlSpecular); material.setShininess(mtlShininess); material.setGlowColor(mtlEmissive); // activate this material material.apply(); // set the background color gl.glClearColor(.2f, .2f, .23f, 1); // blending gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // Force normals to length 1 gl.glEnable(GL.GL_NORMALIZE); // Draw specular highlghts on top of textures (GL12.GL_SINGLE_COLOR to reset) gl.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL, GL.GL_SEPARATE_SPECULAR_COLOR ); // Create texture from image marbleTextureHandle = makeTexture("images/cement_stony.png"); // load the teapot mesh JOOBJImporter import3DS = new JOOBJImporter(); InputStream in3ds = getInputStream("models/teapotT.obj"); obj = import3DS.importFromStream(in3ds); // Create a "display list" of the teapot teapotDisplayList = gl.glGenLists(1); // allocate 1 display list gl.glNewList(teapotDisplayList, GL.GL_COMPILE); // start building the list renderMesh(obj,marbleTextureHandle); // glVertex() commands will go into list, not to screen gl.glEndList(); // done building the display list } /** * Render the scene. */ public void draw() { rotation += 2f; // Clear screen and depth buffer gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // reset the coordinate system to center of screen gl.glLoadIdentity(); // set viewpoint glu.gluLookAt( 0,6f,-8, 0,0,10, 0,1,0); // draw a grid of teapots for (int r=0; r < 20; r++) { for (int c=0; c < 20; c++) { gl.glPushMatrix(); { gl.glTranslatef(-50+(c*5), 0, r*5); gl.glRotatef(rotation, 0, .5f, 0); if (useDisplayList) { // draw the geometry that has been loaded into the GPU and pre-compiled gl.glCallList(teapotDisplayList); } else { // draw the geometry in "direct mode" renderMesh(obj,marbleTextureHandle); } } gl.glPopMatrix(); } } } float tileFactorHoriz = 1f; float tileFactorVert = 1f; /** * Render mesh with normals and texture coordinates. Loops through * all triangles in the mesh object. * * Several triangles may refer to the same vertex, but each face * can have different normals for that vertex. This allows for * sharp edges between faces. * * @param o mesh object to render */ public void renderMesh(JOMesh o, int textureHandle) { JOTriangle t; gl.glBindTexture(GL.GL_TEXTURE_2D,textureHandle); gl.glBegin(GL.GL_TRIANGLES); for (int j = 0; j < o.triangles.length; j++) { // draw all triangles in object t = o.triangles[j]; gl.glTexCoord2f(tileFactorHoriz*t.uvw1.x, tileFactorVert*t.uvw1.y); gl.glNormal3f(t.norm1.x, t.norm1.y, t.norm1.z); gl.glVertex3f( (float)t.p1.pos.x, (float)t.p1.pos.y, (float)t.p1.pos.z); gl.glTexCoord2f(tileFactorHoriz*t.uvw2.x, tileFactorVert*t.uvw2.y); gl.glNormal3f(t.norm2.x, t.norm2.y, t.norm2.z); gl.glVertex3f( (float)t.p2.pos.x, (float)t.p2.pos.y, (float)t.p2.pos.z); gl.glTexCoord2f(tileFactorHoriz*t.uvw3.x, tileFactorVert*t.uvw3.y); gl.glNormal3f(t.norm3.x, t.norm3.y, t.norm3.z); gl.glVertex3f( (float)t.p3.pos.x, (float)t.p3.pos.y, (float)t.p3.pos.z); } gl.glEnd(); } /** * Cleanup all the resources. */ public void exit() { // de-allocate display list if (teapotDisplayList != -1) { gl.glDeleteLists(teapotDisplayList,1); teapotDisplayList = -1; } super.exit(); } public void keyUp(int keycode) { if (keycode == KeyEvent.VK_SPACE) { useDisplayList = !useDisplayList; } } }