package classwork; import java.nio.*; import javax.media.opengl.*; import jocode.*; import jomodel.*; /** * GLART_6_alphaZsort.java * * Render the Teapot model with alpha blending. See render() for * special handling for drawing the model with a translucent effect. * * This app calls JOMesh.projectVerts() to "project" the vertices of * the mesh as if they were being drawn to the screen. Nothing is actually * drawn, but the positions of the vertices are recorded in the * mesh (GL_Vertex.posS holds the screen position) * so that we know the Z depth of every vertex. * * Then we call JOMesh.sortTriangles() to sort the triangles by * their Z depth value, from back to front. * * Then renderMesh() draws the sorted triangles from back to front and they * appear correctly layered on screen. */ public class GLART_6_alphaZsort extends JOApp { private float rotation = 0; private JOMesh obj; // Material object will hold color values JOMaterial clearMtl = new JOMaterial(); JOMaterial opaqueMtl = new JOMaterial(); // texture handle (a number that refers to an allocated texture) int marbleTextureHandle = 0; // Buffers to hold matrices for projectVerts() operation. // For memory efficiency, instantiate these once and reuse them. // see getModelviewMatrix(), getProjectionMatrix(), getViewport() and JOMesh.projectVerts(). public static DoubleBuffer modelViewMatrix; public static DoubleBuffer projectionMatrix; public static IntBuffer viewport; /** * Main function just creates and runs the application. */ public static void main(String args[]) { GLART_6_alphaZsort app = new GLART_6_alphaZsort(); displayWidth = 800; displayHeight = 600; app.run(); } /** * Initialize OpenGL */ public void setup() { // color of overall scene lighting float ambient[] = { 0f, 0f, 0f, 1f }; // color of light source float lightDiffuse[] = { 1f, 1f, 1f, 1f }; // direct light float lightSpecular[] = { 1f, 1f, 1f, 1f }; // highlight float lightAmbient[] = { .2f, .2f, .2f, 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, 1f }; // Create sphere texture marbleTextureHandle = makeTexture("images/marble.jpg"); JOOBJImporter importOBJ = new JOOBJImporter(); obj = importOBJ.load("models/teapotT.obj"); // Get the current projection and viewport matrices // for use in projectVerts(). Modelview matrix will change // every frame, so we'll get that in render(). projectionMatrix = getProjectionMatrix(); viewport = getViewport(); // Select the Projection Matrix (controls perspective) gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); // Reset The Projection Matrix // Define perspective glu.gluPerspective( 45.0f, // Field Of View (float)getWidth() / (float)getHeight(), // aspect ratio 0.1f, // near Z clipping plane 1000.0f); // far Z clipping plane // 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 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); // make the transparent material clearMtl.setDiffuse( new float[] { 1f, 1f, 1f, .7f }); // white .5f in the fourth position is ALPHA value clearMtl.setAmbient( new float[] { .7f, .7f, .7f, 1f }); // light gray clearMtl.setSpecular( new float[] { .5f, .5f, .5f, 1f }); // almost white: very reflective clearMtl.setShininess(50f); // 0=no shine, 127=max shine // make the opaque material opaqueMtl.setDiffuse(new float[] { 1f, .2f, .2f, 1f }); // reddish opaqueMtl.setAmbient(new float[] { .8f, .2f, .2f, 1f }); // reddish // set the background color gl.glClearColor(.5f, .5f, .6f, 1); // turn blending on (for transparency) 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 ); } /** * Render the scene. */ public void draw() { rotation += .3f; // Clear screen and depth buffer gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // Select The Modelview Matrix (controls model orientation) gl.glMatrixMode(GL.GL_MODELVIEW); // reset the coordinate system to center of screen gl.glLoadIdentity(); // Where is the 'eye' glu.gluLookAt( 0f, 4f, 8f, // eye position 0f, 1.5f, 0f, // target to look at 0f, 1f, 0f); // which way is up // rotate scene gl.glRotatef(rotation, 0,1,0); opaqueMtl.apply(); // set the opaque material gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // reset to the default blank texture (0) gl.glPushMatrix(); { gl.glRotatef(-90, 1,0,0); renderPlane(10,10); } gl.glPopMatrix(); // get the current modelView Matrix (right before we draw the model) modelViewMatrix = getModelviewMatrix(); // "project" the mesh vertices into the screen space. This doesn't // actually draw anything, it just creates the screen-space xyz // coordinate for each vert. From those values sortTriangles() // can sort the mesh triangles[] by Z depth (back to front). obj.projectVerts(obj, modelViewMatrix, projectionMatrix, viewport); obj.sortTriangles(); // make depth buffer read-only before drawing translucent objects gl.glDepthMask(false); // draw the mesh (will draw back to front if triangles are sorted by Z) gl.glEnable(GL.GL_TEXTURE_2D); clearMtl.apply(); renderMesh(obj,marbleTextureHandle); // make depth buffer writable gl.glDepthMask(true); } /** * 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(t.uvw1.x, 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(t.uvw2.x, 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(t.uvw3.x, 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(); } }