//jleblanc 3.6.06 //draws a "brain" inside a head //essentially the same as GLART_6_alphaZsort but modified //So you should be able to drop this in the folder where that is and it will run //Uses the womanhead.obj file Mark included. You may have to adjust the path to //that file import glmodel.GL_Mesh; import glmodel.GL_OBJ_Importer; import glmodel.GL_Triangle; import java.io.InputStream; import java.nio.*; // Native IO buffers: LWJGL uses these to efficiently exchange data with system memory import org.lwjgl.opengl.*; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.glu.*; import glmodel.*; /** * 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 GL_Mesh.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 GL_Mesh.sortTriangles() to sort the triangles by * their Z depth value, from back to front. * * Then renderMesh() draws the sorted triangles and they * appear correctly layered on screen. */ public class Head { private boolean done = false; private final String windowTitle = "Translucent Model with Z Sort"; private DisplayMode displayMode; private float rotation = 0; private GL_Mesh obj; // color of overall scene lighting float ambient[] = { 0f, 0f, 0f, 1f }; // color of light source float lightDiffuse[] = { .8f, .8f, .75f, 1f }; // direct light float lightSpecular[] = { .8f, .8f, .75f, 1f }; // highlight float lightAmbient[] = { .02f, .02f, .0f, 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 }; // color of material float mtlDiffuse[] = { .9f, .7f, .6f, .75f }; // light gray -- translucent float mtlAmbient[] = { .08f, .08f, .08f, 1f }; // dark gray float mtlSpecular[] = { .8f, .8f, .8f, 1f }; // almost white: very reflective float mtlEmissive[] = {.315f, .34f, .315f, 1f}; // slight glow color float mtlShininess = 127f; // 0=no shine, 127=max shine /* float mtlDiffuse[] = { .7f, .7f, .6f, .6f }; // light gray -- translucent float mtlAmbient[] = { .08f, .08f, .08f, 1f }; // dark gray float mtlSpecular[] = { .8f, .8f, .8f, 1f }; // almost white: very reflective float mtlEmissive[] = {.315f, .34f, .315f, 1f}; // slight glow color float mtlShininess = 127f; // 0=no shine, 127=max shine*/ // Material object will hold color values GLMaterial material = new GLMaterial(); // texture handle (a number that refers to an allocated texture) int marbleTextureHandle = 0; // Arrays to hold matrices for projectVerts() operation. // For memory efficiency, instantiate these once and reuse. // see getModelviewMatrixA(), getMatrixAsArray() and mesh.projectVerts(). public static float[][] modelViewMatrix = new float[4][4]; public static float[][] projectionMatrix = new float[4][4]; public static int[] viewport = new int[4]; /** * Main function just creates and runs the application. */ public static void main(String args[]) { Head app = new Head(); app.run(); } /** * Initialize the app, then sit in a render loop until done==true. */ public void run() { try { init(); while (!done) { mainloop(); render(); Display.update(); } cleanup(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } } /** * Initialize the environment * @throws Exception */ private void init() throws Exception { initDisplay(); initGL(); //////////////////////////////////// // Create sphere texture // Load the image as RGBA pixels GLImage textureImg = new GLImage("images/marble.jpg"); // Allocate and configure a texture based on the image marbleTextureHandle = makeTexture(textureImg); GL_OBJ_Importer importOBJ = new GL_OBJ_Importer(); InputStream in = FILE.getInputStream("models/womanhead.obj"); //"shark.obj" //"castle.obj" "venus.obj" obj = importOBJ.importFromStream(in); //GL_3DS_Importer import3DS = new GL_3DS_Importer(); //InputStream in3ds = FILE.getInputStream("models/teapotT.3DS"); //obj = import3DS.importFromStream(in3ds); // 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 = getProjectionMatrixA(); viewport = getViewportA(); } /** * Create an OpenGL display, in this case a fullscreen window. * @throws Exception */ private void initDisplay() throws Exception { // set to full screen, no chrome Display.setFullscreen(false); // get all possible display resolutions DisplayMode d[] = Display.getAvailableDisplayModes(); // find a resolution we like for (int i = 0; i < d.length; i++) { if (d[i].getWidth() == 800 && d[i].getHeight() == 600 && d[i].getBitsPerPixel() == 32) { displayMode = d[i]; break; } } // set the display to the resolution we picked Display.setDisplayMode(displayMode); Display.setTitle(windowTitle); // create the window Display.create(); } /** * Initialize OpenGL * */ private void initGL() { // Select the Projection Matrix (controls perspective) GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); // Reset The Projection Matrix // Define perspective GLU.gluPerspective( 50.0f, // Field Of View (float)displayMode.getWidth() / (float)displayMode.getHeight(), // aspect ratio 0.1f, // near Z clipping plane 1000.0f); // far Z clipping plane // Where is the 'eye' GLU.gluLookAt( 0f, 2f, 15f, // eye position 0f, 1.5f, 0f, // target to look at 0f, 1f, 0f); // which way is up // Select The Modelview Matrix (controls model orientation) GL11.glMatrixMode(GL11.GL_MODELVIEW); // make sure OpenGL correctly layers objects GL11.glEnable(GL11.GL_DEPTH_TEST); // OpenGL won't draw backward facing triangles ("back faces") GL11.glEnable(GL11.GL_CULL_FACE); /* // turn lighting on (does not create a light) GL11.glEnable(GL11.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( GL11.GL_LIGHT1, lightDiffuse, lightAmbient, lightSpecular, lightPosition ); // no overall scene lighting setAmbientLight(ambient); // change the current material settings material.setSurfaceColorLit(mtlDiffuse); material.setSurfaceColorShadow(mtlAmbient); material.setReflectionColor(mtlSpecular); material.setShininess(mtlShininess); material.setGlowColor(mtlEmissive); // activate this material material.apply(); // set the background color GL11.glClearColor(.2f, .2f, .23f, 1); // blending GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); // Force normals to length 1 GL11.glEnable(GL11.GL_NORMALIZE); // Draw specular highlghts on top of textures (GL12.GL_SINGLE_COLOR to reset) GL11.glLightModeli(GL12.GL_LIGHT_MODEL_COLOR_CONTROL, GL12.GL_SEPARATE_SPECULAR_COLOR ); */ } /** * Handle keyboard input. Just check for escape key or user * clicking to close the window. */ private void mainloop() { if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Escape is pressed done = true; } if(Display.isCloseRequested()) { // Window is closed done = true; } } /** * Render the scene. */ private void render() { rotation += .2f; // Clear screen and depth buffer GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // reset the coordinate system to center of screen GL11.glLoadIdentity(); // get the current modelView Matrix modelViewMatrix = getModelviewMatrixA(); // make depth buffer read-only before drawing translucent objects GL11.glDepthMask(false); //ROTATE THE SCENE GL11.glTranslatef(0,3,0); GL11.glRotatef(rotation, 0,1,0); System.out.println(rotation); //RENDER THE "BRAINS" GL11.glPushMatrix(); { GL11.glTranslatef(0,1,0); GL11.glScalef(1.2f,1.2f,1.4f); rendercluster(180,2); } GL11.glPopMatrix(); GL11.glPushMatrix(); { GL11.glTranslatef(0,-5,0); GL11.glScalef(1f,1.5f,1f); rendercluster(100,1); } GL11.glPopMatrix(); //ENABLE ALL THAT GUNK // draw the mesh (will draw back to front if triangles are sorted by Z) // "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(); //turn lighting on (does not create a light) GL11.glEnable(GL11.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( GL11.GL_LIGHT1, lightDiffuse, lightAmbient, lightSpecular, lightPosition ); // no overall scene lighting setAmbientLight(ambient); // change the current material settings material.setSurfaceColorLit(mtlDiffuse); material.setSurfaceColorShadow(mtlAmbient); material.setReflectionColor(mtlSpecular); material.setShininess(mtlShininess); material.setGlowColor(mtlEmissive); // activate this material material.apply(); // set the background color GL11.glClearColor(.2f, .2f, .23f, 1); // blending GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); // Force normals to length 1 GL11.glEnable(GL11.GL_NORMALIZE); // Draw specular highlghts on top of textures (GL12.GL_SINGLE_COLOR to reset) GL11.glLightModeli(GL12.GL_LIGHT_MODEL_COLOR_CONTROL, GL12.GL_SEPARATE_SPECULAR_COLOR ); //RENDER THE HEAD GL11.glEnable(GL11.GL_TEXTURE_2D); renderMesh(obj,marbleTextureHandle); // make depth buffer writable GL11.glDepthMask(true); //DISABLE TEXTURE AND LIGHTING GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_LIGHTING); } void rendercluster(float twist, int c) { rendertree(c,twist/3, .05f, 1, 1, 10); GL11.glRotatef(30, 0,0,1); GL11.glRotatef(120, 1,0,0); rendertree(c,twist/3, .05f, 1, 1, 10); GL11.glRotatef(120, 1,0,0); rendertree(c,twist/3, .05f, 1, 1, 10); GL11.glRotatef(120, 0,0,1); rendertree(c,twist/3, .05f, 1, 1, 10); } public void rendertree(int c, float turn, float width, float scale, float level, float maxlevel) { if(level *
* Params:
* an OpenGL light number (GL11.GL_LIGHT1),
* 'Diffuse': color of direct light from this source,
* 'Ambient': color of scattered light from this source
* 'Specular': color of this light reflected off a surface,
* position.
*/ public static void setLight( int GLLightHandle, float[] diffuseLightColor, float[] ambientLightColor, float[] specularLightColor, float[] position ) { FloatBuffer ltDiffuse = allocFloats(diffuseLightColor); FloatBuffer ltAmbient = allocFloats(ambientLightColor); FloatBuffer ltSpecular = allocFloats(specularLightColor); FloatBuffer ltPosition = allocFloats(position); GL11.glLight(GLLightHandle, GL11.GL_DIFFUSE, ltDiffuse); // color of the direct illumination GL11.glLight(GLLightHandle, GL11.GL_AMBIENT, ltAmbient); // color of the reflected light GL11.glLight(GLLightHandle, GL11.GL_SPECULAR, ltSpecular); // color of the highlight (same as direct light) GL11.glLight(GLLightHandle, GL11.GL_POSITION, ltPosition); GL11.glEnable(GLLightHandle); // Enable the light (GL_LIGHT1 - 7) //GL11.glLightf(GLLightHandle, GL11.GL_QUADRATIC_ATTENUATION, .005F); // how light beam drops off } /** * Set the color of the Global Ambient Light. Affects all objects in * scene regardless of their placement. */ public static void setAmbientLight(float[] ambientLightColor) { FloatBuffer ltAmbient = allocFloats(ambientLightColor); GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, ltAmbient); } public static final int SIZE_FLOAT = 4; public static FloatBuffer allocFloats(int howmany) { return ByteBuffer.allocateDirect(howmany * SIZE_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer(); } public static FloatBuffer allocFloats(float[] floatarray) { FloatBuffer fb = ByteBuffer.allocateDirect(floatarray.length * SIZE_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer(); fb.put(floatarray).flip(); return fb; } /** * Create a texture from the given image. */ public static int makeTexture(GLImage textureImg) { if ( textureImg == null ) { return 0; } else { return makeTexture(textureImg.pixelBuffer, textureImg.w, textureImg.h); } } /** * Create a texture from the given pixels in RGBA format. Set the texture * to repeat in both directions and use LINEAR for magnification. * @return the texture handle */ public static int makeTexture(ByteBuffer pixels, int w, int h) { // get a new empty texture int textureHandle = allocateTexture(); // 'select' the new texture by it's handle GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle); // set texture parameters GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); //GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); //GL11.GL_NEAREST); // Create the texture from pixels GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, w, h, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixels); return textureHandle; } /** * Allocate a texture (glGenTextures) and return the handle to it. */ public static int allocateTexture() { IntBuffer textureHandle = allocInts(1); GL11.glGenTextures(textureHandle); return textureHandle.get(0); } public static final int SIZE_INT = 4; public static IntBuffer allocInts(int howmany) { return ByteBuffer.allocateDirect(howmany * SIZE_INT).order(ByteOrder.nativeOrder()).asIntBuffer(); } public static FloatBuffer getModelviewMatrix() { FloatBuffer bufferModelviewMatrix = allocFloats(16); bufferModelviewMatrix.clear(); GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, bufferModelviewMatrix); return bufferModelviewMatrix; } public static FloatBuffer getProjectionMatrix() { FloatBuffer bufferProjectionMatrix = allocFloats(16); bufferProjectionMatrix.clear(); GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, bufferProjectionMatrix); return bufferProjectionMatrix; } public static IntBuffer getViewport() { IntBuffer bufferViewport = allocInts(16); bufferViewport.clear(); GL11.glGetInteger(GL11.GL_VIEWPORT, bufferViewport); return bufferViewport; } /** * Copy a FloatBuffer matrix to a 4x4 float array. The 4x4 float array * is passed in, not allocated inside the function, to reduce garbage * collection needs. * * @param fb source FloatBuffer containing 16 values of 4x4 matrix * @param fa target float[4][4] array will hold the matrix */ public static void getMatrixAsArray(FloatBuffer fb , float[][] fa) { fa[0][0] = fb.get(); fa[0][1] = fb.get(); fa[0][2] = fb.get(); fa[0][3] = fb.get(); fa[1][0] = fb.get(); fa[1][1] = fb.get(); fa[1][2] = fb.get(); fa[1][3] = fb.get(); fa[2][0] = fb.get(); fa[2][1] = fb.get(); fa[2][2] = fb.get(); fa[2][3] = fb.get(); fa[3][0] = fb.get(); fa[3][1] = fb.get(); fa[3][2] = fb.get(); fa[3][3] = fb.get(); //return fa; } /** * Return the modelview matrix as a 4x4 float array */ public static float[][] getModelviewMatrixA() { FloatBuffer b = getModelviewMatrix(); // get matrix in FloatBuffer getMatrixAsArray(b,modelViewMatrix); // copy into array return modelViewMatrix; // return the array } /** * Return the projection matrix as a 4x4 float array */ public static float[][] getProjectionMatrixA() { FloatBuffer b = getProjectionMatrix(); getMatrixAsArray(b,projectionMatrix); return projectionMatrix; } /** * Return the Viewport data as array of 4 floats */ public static int[] getViewportA() { IntBuffer ib = getViewport(); int[] viewport = new int[4]; viewport[0] = ib.get(0); viewport[1] = ib.get(1); viewport[2] = ib.get(2); viewport[3] = ib.get(3); return viewport; } }