/* * Java port of Bullet (c) 2008 Martin Dvorak * * Bullet Continuous Collision Detection and Physics Library * Ragdoll Demo * Copyright (c) 2007 Starbreeze Studios * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * Originally Written by: Marten Svanfeldt * ReWritten by: Francisco Le�n */ //package com.bulletphysics.demos.genericjoint; import com.bulletphysics.BulletGlobals; import com.bulletphysics.BulletStats; import com.bulletphysics.collision.dispatch.CollisionObject; import com.bulletphysics.util.ObjectArrayList; import com.bulletphysics.collision.broadphase.BroadphaseInterface; import com.bulletphysics.collision.broadphase.BroadphaseNativeType; import com.bulletphysics.collision.broadphase.DbvtBroadphase; import com.bulletphysics.collision.dispatch.CollisionDispatcher; import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration; import com.bulletphysics.collision.shapes.BoxShape; import com.bulletphysics.collision.shapes.SphereShape; import com.bulletphysics.collision.shapes.CollisionShape; import com.bulletphysics.collision.shapes.CompoundShape; import com.bulletphysics.collision.shapes.StaticPlaneShape; import com.bulletphysics.collision.shapes.CylinderShape; import com.bulletphysics.collision.shapes.ConvexShape; import com.bulletphysics.collision.shapes.ShapeHull; import com.bulletphysics.collision.shapes.PolyhedralConvexShape; import com.bulletphysics.collision.shapes.ConcaveShape; import com.bulletphysics.collision.shapes.TriangleCallback; import com.bulletphysics.collision.shapes.InternalTriangleIndexCallback; //import com.bulletphysics.demos.opengl.DemoApplication; //import com.bulletphysics.demos.opengl.GLDebugDrawer; //import com.bulletphysics.demos.opengl.IGL; //import com.bulletphysics.demos.opengl.LWJGL; import javax.media.opengl.GL; import javax.media.opengl.glu.GLU; import com.bulletphysics.dynamics.RigidBody; import com.bulletphysics.dynamics.RigidBodyConstructionInfo; import com.bulletphysics.dynamics.DynamicsWorld; import com.bulletphysics.dynamics.DiscreteDynamicsWorld; import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver; import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver; import com.bulletphysics.linearmath.DefaultMotionState; import com.bulletphysics.linearmath.DebugDrawModes; import com.bulletphysics.linearmath.Transform; import com.bulletphysics.linearmath.TransformUtil; import com.bulletphysics.linearmath.VectorUtil; import com.bulletphysics.linearmath.Clock; import com.bulletphysics.util.ObjectPool; import com.bulletphysics.util.IntArrayList; import javax.vecmath.Vector3f; import javax.vecmath.Color3f; //import org.lwjgl.LWJGLException; //import static com.bulletphysics.demos.opengl.IGL.*; import com.bulletphysics.linearmath.MiscUtil; //import com.bulletphysics.dynamics.constraintsolver.TypedConstraint; import com.bulletphysics.dynamics.constraintsolver.Generic6DofConstraint; import java.util.Map; import java.util.HashMap; //import org.lwjgl.util.glu.Cylinder; //import org.lwjgl.util.glu.Disk; //import org.lwjgl.util.glu.Sphere; /** * * @author jezek2 */ public class GenericJoint extends Object3D//extends DemoApplication { static final long serialVersionUID = -2574299047421149815L; boolean IsStatic() { return false; } int myoffset; int mysize; boolean walkdefined; boolean walk; // this is the most important class // static // protected // DynamicsWorld staticdynamicsWorld = null; //DynamicsWorld dynamicsWorld = null; private ObjectArrayList ragdolls = new ObjectArrayList(); // public GenericJointDemo(IGL gl) { // super(gl); // } void SetDynamics(DynamicsWorld d) { //for (int i=ragdolls.size(); --i>=0;) int i=0; { myoffset = d.getNumCollisionObjects() - 1; ragdolls.get(i).SetDynamics(d); mysize = d.getNumCollisionObjects() - myoffset; } } void ResetDynamics(DynamicsWorld d) { //for (int i=ragdolls.size(); --i>=0;) int i=0; { myoffset = d.getNumCollisionObjects() - 1; ragdolls.get(i).ResetDynamics(d); mysize = d.getNumCollisionObjects() - myoffset; } } DynamicsWorld GetDynamicsWorld() { Object3D ancestor = parent; while (parent != null && !(parent instanceof PhysicsNode)) { parent = parent.parent; } if (parent == null) return null; else return ((PhysicsNode)parent).GetDynamics(); } public GenericJoint(boolean walk) { super("RagDoll"); this.walk = walk; this.walkdefined = true; // initPhysics(); // // myoffset = GetDynamicWorld().getNumCollisionObjects() - 1; // // if (myoffset == 0) // clientResetScene(); spawnRagdoll(walk); // mysize = GetDynamicWorld().getNumCollisionObjects() - myoffset; CreateMaterial(); } public void spawnRagdoll() { spawnRagdoll(true); // false); } public void spawnRagdoll(boolean walk) // random) { // KIDS4 RagDoll ragDoll = new RagDoll(null, new Vector3f(0f, 0f, 0f), 0.45f/2, walk, myzoffset = zoffset); // Math.random() > 0.5/*true*/); // true); zoffset += 0.1f; ragdolls.add(ragDoll); bRep = null; } /* @Override public void clientMoveAndDisplay() { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // simple dynamics world doesn't handle fixed-time-stepping float ms = getDeltaTimeMicroseconds(); float minFPS = 1000000f / 60f; if (ms > minFPS) { ms = minFPS; } if (dynamicsWorld != null) { dynamicsWorld.stepSimulation(ms / 1000000.f); // optional but useful: debug drawing dynamicsWorld.debugDrawWorld(); } renderme(); //glFlush(); //glutSwapBuffers(); } @Override public void displayCallback() { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (dynamicsWorld != null) { dynamicsWorld.debugDrawWorld(); } renderme(); //glFlush(); //glutSwapBuffers(); } @Override public void keyboardCallback(char key, int x, int y, int modifiers) { switch (key) { case 'e': spawnRagdoll(true); break; default: super.keyboardCallback(key, x, y, modifiers); } } */ static protected Clock clock = new Clock(); static public float getDeltaTimeMicroseconds() { //#ifdef USE_BT_CLOCK float dt = clock.getTimeMicroseconds(); clock.reset(); return dt; //#else //return btScalar(16666.); //#endif } // public static void main(String[] args) //throws LWJGLException // { // GenericJointDemo demoApp = new GenericJointDemo(); //LWJGL.getGL()); // demoApp.initPhysics(); // for (;;) // { // float ms = getDeltaTimeMicroseconds(); // float minFPS = 1000000f / 60f; // if (ms > minFPS) // { // ms = minFPS; // } // // demoApp.dynamicsWorld.stepSimulation(ms / 1000000.f); // } // //demoApp.setCameraDistance(10f); // // //LWJGL.main(args, 800, 600, "Joint 6DOF - Sequencial Impulse Solver", demoApp); // } transient cVector minima = new cVector(); transient cVector maxima = new cVector(); // float totalms = 0; // void Step() // { // float ms = getDeltaTimeMicroseconds(); // // float minFPS = 1000000f / 60f; // if (ms > minFPS) // { // ms = minFPS; // } // // if (staticdynamicsWorld == null) // initPhysics(); // // staticdynamicsWorld.stepSimulation(ms / 1000000.f); // } // ObjectArrayList initialmatrices; float myzoffset; void Reset() { // int numObjects = dynamicsWorld.getNumCollisionObjects(); // // for (currentobject = 1; currentobject < numObjects; currentobject++) // { // int i = currentobject; // CollisionObject colObj = dynamicsWorld.getCollisionObjectArray().getQuick(i); // RigidBody body = RigidBody.upcast(colObj); // // if (body != null && body.getMotionState() != null) // { // DefaultMotionState myMotionState = (DefaultMotionState) body.getMotionState(); // myMotionState.graphicsWorldTrans.set(initialmatrices.getQuick(currentobject)); // } else // { //// colObj.getWorldTransform(m); // } // } // ragdolls.clear(); //?? initPhysics(); // spawnRagdoll(); // renderme(null); //RagDoll.tick = 7; assert(ragdolls.size() == 1); if (!this.walkdefined) { walk = true; walkdefined = true; } ragdolls.get(0).init(/*staticdynamicsWorld,*/ new Vector3f(0f, 0f, 0f), ragdolls.get(0).scale, walk, myzoffset); bRep = null; } static float zoffset = 0; void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? { // super.DrawNode(display,root,selected); // System.out.println("DrawNode " + this + "; " + dynamicsWorld + " : " + staticdynamicsWorld); //if (bRep == null) try { renderme(display); } catch(Exception e) { e.printStackTrace(); } //display.GetGL().glPushMatrix(); display.PushMatrix(LA.Identity, 1); Vector3f v = ragdolls.get(0).bodies[0].worldTransform.origin; // display.GetGL().glTranslatef(-v.x,0,-v.z); super.DrawNode(display, root, selected); //display.GetGL().glPopMatrix(); display.PopMatrix(LA.Identity); // assert(bRep != null); if (Globals.isLIVE() && live && display.DrawMode() == display.SHADOW) // SHADOW { // float ms = getDeltaTimeMicroseconds(); // float minFPS = 1000000f / 60f; // if (ms > minFPS) // { // ms = minFPS; // } // // if (CameraPane.CURRENTANTIALIAS > 0) // ms /= CameraPane.ACSIZE; // // totalms += ms; // // if (totalms > 2000000) // { // // spawnRagdoll(true); // totalms = 0; // } // //// assert (dynamicsWorld != null); //// // if (staticdynamicsWorld == null) //// staticdynamicsWorld = dynamicsWorld; // initPhysics(); //// //// assert(dynamicsWorld == staticdynamicsWorld); // // staticdynamicsWorld.stepSimulation(ms / 1000000.f); } } // GL gl0; private FontRender.GLFont font; public void initFont(GL gl, GLU glu) { try { //font = FontRender.createFont("Dialog", 11, false, true); font = new FontRender.GLFont(gl, Grafreed.class.getResourceAsStream("DejaVu_Sans_11.fnt")); } catch (java.io.IOException e) { e.printStackTrace(); } } public void drawString(GL gl, GLU glu, CharSequence s, int x, int y, float red, float green, float blue) { if (font == null) { initFont(gl, glu); } //if (font != null) { FontRender.drawString(gl, font, s, x, y, red, green, blue); } } public void drawString(GL gl, GLU glu, CharSequence s, int x, int y, Color3f color) { drawString(gl, glu, s, x, y, color.x, color.y, color.z); } protected int glutScreenWidth = 100; protected int glutScreenHeight = 100; public void setOrthographicProjection(GL gl) { // switch to projection mode gl.glMatrixMode(gl.GL_PROJECTION); // save previous matrix which contains the //settings for the perspective projection gl.glPushMatrix(); // reset matrix gl.glLoadIdentity(); // set a 2D orthographic projection // gl.gluOrtho2D(0, glutScreenWidth, 0, glutScreenHeight); gl.glOrtho(0, glutScreenWidth, 0, glutScreenHeight, 0.001, 1000); gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadIdentity(); // invert the y axis, down is positive gl.glScalef(1f, -1f, 1f); // mover the origin from the bottom left corner // to the upper left corner gl.glTranslatef(0f, -glutScreenHeight, 0f); } public void resetPerspectiveProjection(GL gl) { gl.glMatrixMode(gl.GL_PROJECTION); gl.glPopMatrix(); gl.glMatrixMode(gl.GL_MODELVIEW); // updateCamera(); } transient private /*final*/ Transform m; // = new Transform(); private Vector3f wireColor = new Vector3f(); protected Color3f TEXT_COLOR = new Color3f(0f, 0f, 0f); private StringBuilder buf = new StringBuilder(); protected int debugMode = 0; public int getDebugMode() { return debugMode; } boolean buildrep; int startvertex; int currentobject; public void renderme(iCameraPane display) { GL gl = display!=null?display.GetGL0():null; // gl0 = gl; if (GetDynamicsWorld() != null) { if (m == null) m = new Transform(); if (glMat == null) glMat = new float[16]; int numObjects = mysize; // dynamicsWorld.getNumCollisionObjects(); int numConstraints = GetDynamicsWorld().getNumConstraints(); Transform trans = new Transform(); if (gl != null) for (int c=0; c < numConstraints; c++) { Generic6DofConstraint tc = (Generic6DofConstraint)GetDynamicsWorld().getConstraint(c); CollisionObject colObj = tc.getRigidBodyB(); RigidBody body = RigidBody.upcast(colObj); if (body != null && body.getMotionState() != null) { DefaultMotionState myMotionState = (DefaultMotionState) body.getMotionState(); m.set(myMotionState.graphicsWorldTrans); } tc.getFrameOffsetB(trans); if (false) //c == 8) // DEBUG { gl.glDisable(gl.GL_LIGHTING); gl.glPushMatrix(); m.getOpenGLMatrix(glMat); gl.glMultMatrixf(glMat, 0); gl.glColor3f(0, 0, 1); gl.glBegin(gl.GL_LINES); gl.glVertex3f(0,0,-0.01f); gl.glVertex3f(0,0,0.01f); gl.glEnd(); gl.glColor3f(1, 0, 0); gl.glPushMatrix(); //m.getOpenGLMatrix(glMat); //gl.glMultMatrixf(glMat, 0); trans.getOpenGLMatrix(glMat); gl.glMultMatrixf(glMat, 0); gl.glBegin(gl.GL_LINES); gl.glVertex3f(-0.01f,0,0); gl.glVertex3f(0.01f,0,0); gl.glEnd(); gl.glPopMatrix(); //tc.getFrameOffsetB(trans); gl.glColor3f(0, 1, 0); gl.glPushMatrix(); //m.getOpenGLMatrix(glMat); //gl.glMultMatrixf(glMat, 0); trans.getOpenGLMatrix(glMat); gl.glMultMatrixf(glMat, 0); gl.glBegin(gl.GL_LINES); gl.glVertex3f(0,-0.01f,0); gl.glVertex3f(0,0.01f,0); gl.glEnd(); gl.glPopMatrix(); gl.glPopMatrix(); //cRigidBody gl.glColor3f(1, 1, 0); Vector3f pt = ((RagDoll.cRigidBody)body).anchor; // worldTransform.origin; gl.glBegin(gl.GL_LINES); gl.glVertex3f(pt.x,pt.y-0.01f,pt.z-0.01f); gl.glVertex3f(pt.x,pt.y+0.01f,pt.z+0.01f); gl.glEnd(); } } wireColor.set(1f, 0f, 0f); buildrep = false; startvertex = 0; if (bRep == null && numObjects != 0) { bRep = new BoundaryRep(); bRep.startvertices = new int[numObjects]; bRep.averagepoints = new float[(bRep.startvertices.length-1) * 3]; bRep.extremepoints = new float[(bRep.startvertices.length-1) * 3]; bRep.supportminsize = new float[(bRep.startvertices.length-1)]; bRep.supportmaxsize = new float[(bRep.startvertices.length-1)]; buildrep = true; initialmatrices = new ObjectArrayList(); MiscUtil.resize(initialmatrices, numObjects, Transform.class); } for (currentobject = 1; currentobject < numObjects; currentobject++) { int i = currentobject; CollisionObject colObj = GetDynamicsWorld().getCollisionObjectArray().getQuick(i+myoffset); RigidBody body = RigidBody.upcast(colObj); if (body != null && body.getMotionState() != null) { DefaultMotionState myMotionState = (DefaultMotionState) body.getMotionState(); m.set(myMotionState.graphicsWorldTrans); Vector3f v = ragdolls.get(0).bodies[0].worldTransform.origin; // m.origin.x -= v.x; // uses tween instead! // m.origin.z -= v.z; // if (buildrep) // initialmatrices.getQuick(currentobject).set(m); } else { colObj.getWorldTransform(m); } wireColor.set(1f, 1f, 0.5f); // wants deactivation if ((i & 1) != 0) { wireColor.set(0f, 0f, 1f); } // color differently for active, sleeping, wantsdeactivation states if (colObj.getActivationState() == 1) // active { if ((i & 1) != 0) { //wireColor.add(new Vector3f(1f, 0f, 0f)); wireColor.x += 1f; } else { //wireColor.add(new Vector3f(0.5f, 0f, 0f)); wireColor.x += 0.5f; } } if (colObj.getActivationState() == 2) // ISLAND_SLEEPING { if ((i & 1) != 0) { //wireColor.add(new Vector3f(0f, 1f, 0f)); wireColor.y += 1f; } else { //wireColor.add(new Vector3f(0f, 0.5f, 0f)); wireColor.y += 0.5f; } } /*GLShapeDrawer.*/ // System.out.print("x"); drawOpenGL(display, m, colObj.getCollisionShape(), wireColor, getDebugMode()); } // System.out.println(); float xOffset = 10f; float yStart = 20f; float yIncr = 20f; // gl.glDisable(gl.GL_LIGHTING); // gl.glColor3f(0f, 0f, 0f); if (false) // (debugMode & DebugDrawModes.NO_HELP_TEXT) == 0) { setOrthographicProjection(gl); // yStart = showProfileInfo(xOffset, yStart, yIncr); // #ifdef USE_QUICKPROF // if ( getDebugMode() & btIDebugDraw::DBG_ProfileTimings) // { // static int counter = 0; // counter++; // std::map::iterator iter; // for (iter = btProfiler::mProfileBlocks.begin(); iter != btProfiler::mProfileBlocks.end(); ++iter) // { // char blockTime[128]; // sprintf(blockTime, "%s: %lf",&((*iter).first[0]),btProfiler::getBlockTime((*iter).first, btProfiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT)); // glRasterPos3f(xOffset,yStart,0); // BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),blockTime); // yStart += yIncr; // // } // } // #endif //USE_QUICKPROF String s = "mouse to interact"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; // JAVA NOTE: added s = "LMB=drag, RMB=shoot box, MIDDLE=apply impulse"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = "space to reset"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = "cursor keys and z,x to navigate"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = "i to toggle simulation, s single step"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = "q to quit"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = ". to shoot box or trimesh (MovingConcaveDemo)"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; // not yet hooked up again after refactoring... s = "d to toggle deactivation"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = "g to toggle mesh animation (ConcaveDemo)"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; // JAVA NOTE: added s = "e to spawn new body (GenericJointDemo)"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; s = "h to toggle help text"; drawString(gl, null, s, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; //buf = "p to toggle profiling (+results to file)"; //drawString(gl,null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; //bool useBulletLCP = !(getDebugMode() & btIDebugDraw::DBG_DisableBulletLCP); //bool useCCD = (getDebugMode() & btIDebugDraw::DBG_EnableCCD); //glRasterPos3f(xOffset,yStart,0); //sprintf(buf,"1 CCD mode (adhoc) = %i",useCCD); //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); //yStart += yIncr; //glRasterPos3f(xOffset, yStart, 0); //buf = String.format(%10.2f", ShootBoxInitialSpeed); /* buf.setLength(0); buf.append("+- shooting speed = "); FastFormat.append(buf, ShootBoxInitialSpeed); drawString(gl,null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; //#ifdef SHOW_NUM_DEEP_PENETRATIONS buf.setLength(0); buf.append("gNumDeepPenetrationChecks = "); FastFormat.append(buf, BulletStats.gNumDeepPenetrationChecks); drawString(gl,null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; buf.setLength(0); buf.append("gNumGjkChecks = "); FastFormat.append(buf, BulletStats.gNumGjkChecks); drawString(gl,null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; buf.setLength(0); buf.append("gNumSplitImpulseRecoveries = "); FastFormat.append(buf, BulletStats.gNumSplitImpulseRecoveries); drawString(gl,null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; */ //buf = String.format("gNumAlignedAllocs = %d", BulletGlobals.gNumAlignedAllocs); // TODO: BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); //yStart += yIncr; //buf = String.format("gNumAlignedFree= %d", BulletGlobals.gNumAlignedFree); // TODO: BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); //yStart += yIncr; //buf = String.format("# alloc-free = %d", BulletGlobals.gNumAlignedAllocs - BulletGlobals.gNumAlignedFree); // TODO: BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); //yStart += yIncr; //enable BT_DEBUG_MEMORY_ALLOCATIONS define in Bullet/src/LinearMath/btAlignedAllocator.h for memory leak detection //#ifdef BT_DEBUG_MEMORY_ALLOCATIONS //glRasterPos3f(xOffset,yStart,0); //sprintf(buf,"gTotalBytesAlignedAllocs = %d",gTotalBytesAlignedAllocs); //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); //yStart += yIncr; //#endif //BT_DEBUG_MEMORY_ALLOCATIONS if (GetDynamicsWorld() != null) { buf.setLength(0); buf.append("# objects = "); FastFormat.append(buf, GetDynamicsWorld().getNumCollisionObjects()); drawString(gl, null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; buf.setLength(0); buf.append("# pairs = "); FastFormat.append(buf, GetDynamicsWorld().getBroadphase().getOverlappingPairCache().getNumOverlappingPairs()); drawString(gl, null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; } //#endif //SHOW_NUM_DEEP_PENETRATIONS // JAVA NOTE: added int free = (int) Runtime.getRuntime().freeMemory(); int total = (int) Runtime.getRuntime().totalMemory(); buf.setLength(0); buf.append("heap = "); FastFormat.append(buf, (float) (total - free) / (1024 * 1024)); buf.append(" / "); FastFormat.append(buf, (float) (total) / (1024 * 1024)); buf.append(" MB"); drawString(gl, null, buf, Math.round(xOffset), Math.round(yStart), TEXT_COLOR); yStart += yIncr; resetPerspectiveProjection(gl); } // gl.glEnable(gl.GL_LIGHTING); } } public void drawCube(iCameraPane display, float extent) { GL gl = display.GetGL0(); extent = extent * 0.5f; gl.glBegin(gl.GL_QUADS); gl.glNormal3f(1f, 0f, 0f); gl.glVertex3f(+extent, -extent, +extent); gl.glVertex3f(+extent, -extent, -extent); gl.glVertex3f(+extent, +extent, -extent); gl.glVertex3f(+extent, +extent, +extent); gl.glNormal3f(0f, 1f, 0f); gl.glVertex3f(+extent, +extent, +extent); gl.glVertex3f(+extent, +extent, -extent); gl.glVertex3f(-extent, +extent, -extent); gl.glVertex3f(-extent, +extent, +extent); gl.glNormal3f(0f, 0f, 1f); gl.glVertex3f(+extent, +extent, +extent); gl.glVertex3f(-extent, +extent, +extent); gl.glVertex3f(-extent, -extent, +extent); gl.glVertex3f(+extent, -extent, +extent); gl.glNormal3f(-1f, 0f, 0f); gl.glVertex3f(-extent, -extent, +extent); gl.glVertex3f(-extent, +extent, +extent); gl.glVertex3f(-extent, +extent, -extent); gl.glVertex3f(-extent, -extent, -extent); gl.glNormal3f(0f, -1f, 0f); gl.glVertex3f(-extent, -extent, +extent); gl.glVertex3f(-extent, -extent, -extent); gl.glVertex3f(+extent, -extent, -extent); gl.glVertex3f(+extent, -extent, +extent); gl.glNormal3f(0f, 0f, -1f); gl.glVertex3f(-extent, -extent, -extent); gl.glVertex3f(-extent, +extent, -extent); gl.glVertex3f(+extent, +extent, -extent); gl.glVertex3f(+extent, -extent, -extent); gl.glEnd(); } private /*static*/ float[] glMat = new float[16]; public void drawOpenGL(iCameraPane display, Transform trans, CollisionShape shape, Vector3f color, int debugMode) { GL gl = null; // display.getGL(); ObjectPool transformsPool = ObjectPool.get(Transform.class); ObjectPool vectorsPool = ObjectPool.get(Vector3f.class); //System.out.println("shape="+shape+" type="+BroadphaseNativeTypes.forValue(shape.getShapeType())); trans.getOpenGLMatrix(glMat); //// display.PushMatrix(glMat); // gl.glPushMatrix(); // gl.glMultMatrixf(glMat, 0); // if (shape.getShapeType() == BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE.getValue()) // { // const btUniformScalingShape* scalingShape = static_cast(shape); // const btConvexShape* convexShape = scalingShape->getChildShape(); // float scalingFactor = (float)scalingShape->getUniformScalingFactor(); // { // btScalar tmpScaling[4][4]={{scalingFactor,0,0,0}, // {0,scalingFactor,0,0}, // {0,0,scalingFactor,0}, // {0,0,0,1}}; // // drawOpenGL( (btScalar*)tmpScaling,convexShape,color,debugMode); // } // glPopMatrix(); // return; // } if (shape.getShapeType() == BroadphaseNativeType.COMPOUND_SHAPE_PROXYTYPE) { new Exception().printStackTrace(); System.exit(0); CompoundShape compoundShape = (CompoundShape) shape; Transform childTrans = transformsPool.get(); for (int i = compoundShape.getNumChildShapes() - 1; i >= 0; i--) { compoundShape.getChildTransform(i, childTrans); CollisionShape colShape = compoundShape.getChildShape(i); drawOpenGL(display, childTrans, colShape, color, debugMode); } transformsPool.release(childTrans); } else { //drawCoordSystem(); //glPushMatrix(); // gl.glEnable(gl.GL_COLOR_MATERIAL); // gl.glColor3f(color.x, color.y, color.z); boolean useWireframeFallback = true; if ((debugMode & DebugDrawModes.DRAW_WIREFRAME) == 0) { // you can comment out any of the specific cases, and use the default // the benefit of 'default' is that it approximates the actual collision shape including collision margin switch (shape.getShapeType()) { case BOX_SHAPE_PROXYTYPE: { new Exception().printStackTrace(); System.exit(0); BoxShape boxShape = (BoxShape) shape; Vector3f halfExtent = boxShape.getHalfExtentsWithMargin(vectorsPool.get()); gl.glScalef(2f * halfExtent.x, 2f * halfExtent.y, 2f * halfExtent.z); drawCube(display, 1f); vectorsPool.release(halfExtent); useWireframeFallback = false; break; } case SPHERE_SHAPE_PROXYTYPE: { new Exception().printStackTrace(); System.exit(0); SphereShape sphereShape = (SphereShape) shape; float radius = sphereShape.getMargin(); // radius doesn't include the margin, so draw with margin // TODO: glutSolidSphere(radius,10,10); //sphere.draw(radius, 8, 8); drawSphere(display, radius, 10, 10); /* glPointSize(10f); glBegin(GL_POINTS); glVertex3f(0f, 0f, 0f); glEnd(); glPointSize(1f); */ useWireframeFallback = false; break; } // case CONE_SHAPE_PROXYTYPE: // { // const btConeShape* coneShape = static_cast(shape); // int upIndex = coneShape->getConeUpIndex(); // float radius = coneShape->getRadius();//+coneShape->getMargin(); // float height = coneShape->getHeight();//+coneShape->getMargin(); // switch (upIndex) // { // case 0: // glRotatef(90.0, 0.0, 1.0, 0.0); // break; // case 1: // glRotatef(-90.0, 1.0, 0.0, 0.0); // break; // case 2: // break; // default: // { // } // }; // // glTranslatef(0.0, 0.0, -0.5*height); // glutSolidCone(radius,height,10,10); // useWireframeFallback = false; // break; // // } case STATIC_PLANE_PROXYTYPE: { new Exception().printStackTrace(); System.exit(0); StaticPlaneShape staticPlaneShape = (StaticPlaneShape) shape; float planeConst = staticPlaneShape.getPlaneConstant(); Vector3f planeNormal = staticPlaneShape.getPlaneNormal(vectorsPool.get()); Vector3f planeOrigin = vectorsPool.get(); planeOrigin.scale(planeConst, planeNormal); Vector3f vec0 = vectorsPool.get(); Vector3f vec1 = vectorsPool.get(); TransformUtil.planeSpace1(planeNormal, vec0, vec1); float vecLen = 100f; Vector3f pt0 = vectorsPool.get(); pt0.scaleAdd(vecLen, vec0, planeOrigin); Vector3f pt1 = vectorsPool.get(); pt1.scale(vecLen, vec0); pt1.sub(planeOrigin, pt1); Vector3f pt2 = vectorsPool.get(); pt2.scaleAdd(vecLen, vec1, planeOrigin); Vector3f pt3 = vectorsPool.get(); pt3.scale(vecLen, vec1); pt3.sub(planeOrigin, pt3); gl.glBegin(gl.GL_LINES); gl.glVertex3f(pt0.x, pt0.y, pt0.z); gl.glVertex3f(pt1.x, pt1.y, pt1.z); gl.glVertex3f(pt2.x, pt2.y, pt2.z); gl.glVertex3f(pt3.x, pt3.y, pt3.z); gl.glEnd(); vectorsPool.release(planeNormal); vectorsPool.release(planeOrigin); vectorsPool.release(vec0); vectorsPool.release(vec1); vectorsPool.release(pt0); vectorsPool.release(pt1); vectorsPool.release(pt2); vectorsPool.release(pt3); break; } case CYLINDER_SHAPE_PROXYTYPE: { new Exception().printStackTrace(); System.exit(0); CylinderShape cylinder = (CylinderShape) shape; int upAxis = cylinder.getUpAxis(); float radius = cylinder.getRadius(); Vector3f halfVec = vectorsPool.get(); float halfHeight = VectorUtil.getCoord(cylinder.getHalfExtentsWithMargin(halfVec), upAxis); drawCylinder(display, radius, halfHeight, upAxis); vectorsPool.release(halfVec); break; } default: { if (shape.isConvex()) { ConvexShape convexShape = (ConvexShape) shape; if (shape.getUserPointer() == null) { // create a hull approximation ShapeHull hull = new ShapeHull(convexShape); // JAVA NOTE: not needed ///// cleanup memory //m_shapeHulls.push_back(hull); float margin = shape.getMargin(); hull.buildHull(margin); convexShape.setUserPointer(hull); //printf("numTriangles = %d\n", hull->numTriangles ()); //printf("numIndices = %d\n", hull->numIndices ()); //printf("numVertices = %d\n", hull->numVertices ()); } if (shape.getUserPointer() != null) { //glutSolidCube(1.0); ShapeHull hull = (ShapeHull) shape.getUserPointer(); ObjectArrayList vtx = hull.getVertexPointer(); ObjectArrayList normals = hull.getNormalPointer(); Vector3f center = vectorsPool.get(); Vector3f tmp1 = vectorsPool.get(); // Vector3f normal = vectorsPool.get(); // Vector3f tmp2 = vectorsPool.get(); if (buildrep) // bRep == null || bRep.FaceCount() != hull.numTriangles()) { center.x = center.y = center.z = 0; for (int i = 0; i < vtx.size(); i++) { Vector3f v = vtx.getQuick(i); // tmp1.set(v); // trans.transform(tmp1); center.x += v.x; center.y += v.y; center.z += v.z; } center.x /= vtx.size(); center.y /= vtx.size(); center.z /= vtx.size(); //bRep = new BoundaryRep(); Vertex vert = new Vertex(true); int totalvertices = 0; int index = 0; IntArrayList idx = hull.getIndexPointer(); for (int i = 0; i < hull.numTriangles(); i++) { int i1 = index++; int i2 = index++; int i3 = index++; assert (i1 < hull.numIndices() && i2 < hull.numIndices() && i3 < hull.numIndices()); int index1 = idx.get(i1); int index2 = idx.get(i2); int index3 = idx.get(i3); assert (index1 < hull.numVertices() && index2 < hull.numVertices() && index3 < hull.numVertices()); Vector3f v1 = vtx.getQuick(index1); Vector3f v2 = vtx.getQuick(index2); Vector3f v3 = vtx.getQuick(index3); // tmp1.sub(v3, v1); // tmp2.sub(v2, v1); // normal.cross(tmp2, tmp1); // normal.normalize(); // gl.glNormal3f(normal.x, normal.y, normal.z); // gl.glVertex3f(v1.x, v1.y, v1.z); // gl.glVertex3f(v2.x, v2.y, v2.z); // gl.glVertex3f(v3.x, v3.y, v3.z); //Applet3D.tracein("appendTriangle", p + "; " + q + "; " + r); int qx; int rx; int px; // = qx = rx = -1; //LA.vecCopy(p, vert/*.pos*/); //LA.vecCopy(p.norm, vert.norm); tmp1.set(v1); Vector3f normal = normals.getQuick(index1); //normal.set(tmp1); //normal.sub(center); //normal.normalize(); trans.transform(tmp1); vert.x = tmp1.x; vert.y = tmp1.y; vert.z = tmp1.z; vert.norm.x = normal.x; vert.norm.y = normal.y; vert.norm.z = normal.z; vert.supportindex = index1+startvertex; Vertex in = bRep.GetCache(vert); if (in != null) { px = in.index; } else { totalvertices += 1; Vertex vert2 = new Vertex(true); LA.vecCopy(vert/*.pos*/, vert2/*.pos*/); LA.vecCopy(vert.norm, vert2.norm); px = bRep.VertexCount(); vert2.index = px; vert2.supportindex = vert.supportindex; //bRep.AddVertex(vert2); bRep.Remember(vert2); } // LA.vecCopy(q, vert/*.pos*/); // LA.vecCopy(q.norm, vert.norm); tmp1.set(v2); normal = normals.getQuick(index2); //normal.set(tmp1); //normal.sub(center); //normal.normalize(); trans.transform(tmp1); vert.x = tmp1.x; vert.y = tmp1.y; vert.z = tmp1.z; vert.norm.x = normal.x; vert.norm.y = normal.y; vert.norm.z = normal.z; vert.supportindex = index2+startvertex; in = bRep.GetCache(vert); if (in != null) { qx = in.index; } else { totalvertices += 1; Vertex vert2 = new Vertex(true); LA.vecCopy(vert/*.pos*/, vert2/*.pos*/); LA.vecCopy(vert.norm, vert2.norm); qx = bRep.VertexCount(); // vertices.size(); vert2.index = qx; vert2.supportindex = vert.supportindex; //bRep.AddVertex(vert2); bRep.Remember(vert2); // vertextable.put(vert2, vert2); } // LA.vecCopy(r, vert/*.pos*/); // LA.vecCopy(r.norm, vert.norm); tmp1.set(v3); normal = normals.getQuick(index3); //normal.set(tmp1); //normal.sub(center); //normal.normalize(); trans.transform(tmp1); vert.x = tmp1.x; vert.y = tmp1.y; vert.z = tmp1.z; vert.norm.x = normal.x; vert.norm.y = normal.y; vert.norm.z = normal.z; vert.supportindex = index3+startvertex; in = bRep.GetCache(vert); if (in != null) { rx = in.index; } else { totalvertices += 1; Vertex vert2 = new Vertex(true); LA.vecCopy(vert/*.pos*/, vert2/*.pos*/); LA.vecCopy(vert.norm, vert2.norm); rx = bRep.VertexCount(); vert2.index = rx; vert2.supportindex = vert.supportindex; //bRep.AddVertex(vert2); bRep.Remember(vert2); } bRep.AddFace(px, qx, rx); } //startvertex += totalvertices; bRep.startvertices[currentobject] = bRep.startvertices[currentobject-1] + totalvertices; } else { if (bRep.averagepoints == null || bRep.extremepoints == null || bRep.supportminsize == null || bRep.supportmaxsize == null) { bRep.averagepoints = new float[(bRep.startvertices.length-1) * 3]; bRep.extremepoints = new float[(bRep.startvertices.length-1) * 3]; bRep.supportminsize = new float[(bRep.startvertices.length-1)]; bRep.supportmaxsize = new float[(bRep.startvertices.length-1)]; } float averagex = 0; float averagey = 0; float averagez = 0; int count = 0; for (int i=bRep.startvertices[currentobject-1]; i dist2) mindist2 = dist2; if (maxdist2 < dist2) { maxdist2 = dist2; bRep.extremepoints[index3] = (float)v.x; bRep.extremepoints[index3+1] = (float)v.y; bRep.extremepoints[index3+2] = (float)v.z; } } bRep.supportminsize[currentobject-1] = (float)Math.sqrt(mindist2); bRep.supportmaxsize[currentobject-1] = (float)Math.sqrt(maxdist2); } // if (hull.numTriangles() > 0) // { // int index = 0; // IntArrayList idx = hull.getIndexPointer(); // ObjectArrayList vtx = hull.getVertexPointer(); // // gl.glBegin(gl.GL_TRIANGLES); // // for (int i = 0; i < hull.numTriangles(); i++) // { // int i1 = index++; // int i2 = index++; // int i3 = index++; // assert (i1 < hull.numIndices() && // i2 < hull.numIndices() && // i3 < hull.numIndices()); // // int index1 = idx.get(i1); // int index2 = idx.get(i2); // int index3 = idx.get(i3); // assert (index1 < hull.numVertices() && // index2 < hull.numVertices() && // index3 < hull.numVertices()); // // Vector3f v1 = vtx.getQuick(index1); // Vector3f v2 = vtx.getQuick(index2); // Vector3f v3 = vtx.getQuick(index3); // tmp1.sub(v3, v1); // tmp2.sub(v2, v1); // normal.cross(tmp2, tmp1); // normal.normalize(); // // gl.glNormal3f(normal.x, normal.y, normal.z); // gl.glVertex3f(v1.x, v1.y, v1.z); // gl.glVertex3f(v2.x, v2.y, v2.z); // gl.glVertex3f(v3.x, v3.y, v3.z); // // } // gl.glEnd(); // } // vectorsPool.release(normal); vectorsPool.release(tmp1); // vectorsPool.release(tmp2); } } else { // printf("unhandled drawing\n"); } } } } if (useWireframeFallback) { // for polyhedral shapes if (shape.isPolyhedral()) { new Exception().printStackTrace(); System.exit(0); PolyhedralConvexShape polyshape = (PolyhedralConvexShape) shape; gl.glBegin(gl.GL_LINES); Vector3f a = vectorsPool.get(), b = vectorsPool.get(); int i; for (i = 0; i < polyshape.getNumEdges(); i++) { polyshape.getEdge(i, a, b); gl.glVertex3f(a.x, a.y, a.z); gl.glVertex3f(b.x, b.y, b.z); } gl.glEnd(); vectorsPool.release(a); vectorsPool.release(b); // if (debugMode==btIDebugDraw::DBG_DrawFeaturesText) // { // glRasterPos3f(0.0, 0.0, 0.0); // //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),polyshape->getExtraDebugInfo()); // // glColor3f(1.f, 1.f, 1.f); // for (i=0;igetNumVertices();i++) // { // btPoint3 vtx; // polyshape->getVertex(i,vtx); // glRasterPos3f(vtx.x(), vtx.y(), vtx.z()); // char buf[12]; // sprintf(buf," %d",i); // BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); // } // // for (i=0;igetNumPlanes();i++) // { // btVector3 normal; // btPoint3 vtx; // polyshape->getPlane(normal,vtx,i); // btScalar d = vtx.dot(normal); // // glRasterPos3f(normal.x()*d, normal.y()*d, normal.z()*d); // char buf[12]; // sprintf(buf," plane %d",i); // BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); // // } // } } } // #ifdef USE_DISPLAY_LISTS // // if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) // { // GLuint dlist = OGL_get_displaylist_for_shape((btCollisionShape * )shape); // if (dlist) // { // glCallList(dlist); // } // else // { // #else if (shape.isConcave())//>getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE||shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) // if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) { new Exception().printStackTrace(); System.exit(0); ConcaveShape concaveMesh = (ConcaveShape) shape; //btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); //btVector3 aabbMax(100,100,100);//btScalar(1e30),btScalar(1e30),btScalar(1e30)); //todo pass camera, for some culling Vector3f aabbMax = vectorsPool.get(); aabbMax.set(1e30f, 1e30f, 1e30f); Vector3f aabbMin = vectorsPool.get(); aabbMin.set(-1e30f, -1e30f, -1e30f); GlDrawcallback drawCallback = new GlDrawcallback(gl); drawCallback.wireframe = (debugMode & DebugDrawModes.DRAW_WIREFRAME) != 0; concaveMesh.processAllTriangles(drawCallback, aabbMin, aabbMax); vectorsPool.release(aabbMax); vectorsPool.release(aabbMin); } //#endif //#ifdef USE_DISPLAY_LISTS // } // } //#endif // if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) // { // btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; // // //todo: pass camera for some culling // btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); // btVector3 aabbMin(-btScalar(1e30),-btScalar(1e30),-btScalar(1e30)); // TriangleGlDrawcallback drawCallback; // convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); // // } // TODO: error in original sources GL_DEPTH_BUFFER_BIT instead of GL_DEPTH_TEST //gl.glDisable(GL_DEPTH_TEST); //glRasterPos3f(0, 0, 0);//mvtx.x(), vtx.y(), vtx.z()); if ((debugMode & DebugDrawModes.DRAW_TEXT) != 0) { // TODO: BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->getName()); } if ((debugMode & DebugDrawModes.DRAW_FEATURES_TEXT) != 0) { //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),shape->getExtraDebugInfo()); } //gl.glEnable(GL_DEPTH_TEST); //glPopMatrix(); } // gl.glPopMatrix(); } //////////////////////////////////////////////////////////////////////////// //private static final Cylinder cylinder = new Cylinder(); //private static final Disk disk = new Disk(); //private static final Sphere sphere = new Sphere(); Superellipsoid sphere = new Superellipsoid(); Cone cylinder = new Cone(); private static class SphereKey { public float radius; public SphereKey() { } public SphereKey(SphereKey key) { radius = key.radius; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof SphereKey)) { return false; } SphereKey other = (SphereKey) obj; return radius == other.radius; } @Override public int hashCode() { return Float.floatToIntBits(radius); } } private static Map sphereDisplayLists = new HashMap(); private static SphereKey sphereKey = new SphereKey(); public void drawSphere(iCameraPane display, float radius, int slices, int stacks) { GL gl = display.GetGL0(); sphereKey.radius = radius; Integer glList = sphereDisplayLists.get(sphereKey); if (glList == null) { glList = gl.glGenLists(1); gl.glNewList(glList, gl.GL_COMPILE); sphere.DrawNode(display, null, false); // radius, 8, 8); gl.glEndList(); sphereDisplayLists.put(new SphereKey(sphereKey), glList); } gl.glCallList(glList); } //////////////////////////////////////////////////////////////////////////// private static class CylinderKey { public float radius; public float halfHeight; public CylinderKey() { } public CylinderKey(CylinderKey key) { radius = key.radius; halfHeight = key.halfHeight; } public void set(float radius, float halfHeight) { this.radius = radius; this.halfHeight = halfHeight; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof CylinderKey)) { return false; } CylinderKey other = (CylinderKey) obj; if (radius != other.radius) { return false; } if (halfHeight != other.halfHeight) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 23 * hash + Float.floatToIntBits(radius); hash = 23 * hash + Float.floatToIntBits(halfHeight); return hash; } } private static Map cylinderDisplayLists = new HashMap(); private static CylinderKey cylinderKey = new CylinderKey(); public void drawCylinder(iCameraPane display, float radius, float halfHeight, int upAxis) { GL gl = display.GetGL0(); gl.glPushMatrix(); switch (upAxis) { case 0: gl.glRotatef(-90f, 0.0f, 1.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, -halfHeight); break; case 1: gl.glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, -halfHeight); break; case 2: gl.glTranslatef(0.0f, 0.0f, -halfHeight); break; default: { assert (false); } } // The gluCylinder subroutine draws a cylinder that is oriented along the z axis. // The base of the cylinder is placed at z = 0; the top of the cylinder is placed at z=height. // Like a sphere, the cylinder is subdivided around the z axis into slices and along the z axis into stacks. cylinderKey.set(radius, halfHeight); Integer glList = cylinderDisplayLists.get(cylinderKey); if (glList == null) { glList = gl.glGenLists(1); gl.glNewList(glList, gl.GL_COMPILE); // disk.setDrawStyle(GLU_FILL); // disk.setNormals(GLU_SMOOTH); // disk.draw(0, radius, 15, 10); // cylinder.setDrawStyle(GLU_FILL); // cylinder.setNormals(GLU_SMOOTH); // cylinder.draw(radius, radius, 2f * halfHeight, 15, 10); cylinder.DrawNode(display, null, false); // radius, radius, 2f * halfHeight, 15, 10); gl.glTranslatef(0f, 0f, 2f * halfHeight); gl.glRotatef(-180f, 0f, 1f, 0f); //disk.draw(0, radius, 15, 10); gl.glEndList(); cylinderDisplayLists.put(new CylinderKey(cylinderKey), glList); } gl.glCallList(glList); gl.glPopMatrix(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private static class TriMeshKey { public CollisionShape shape; public int dlist; // OpenGL display list } private static class GlDisplaylistDrawcallback extends TriangleCallback { private GL gl; private final Vector3f diff1 = new Vector3f(); private final Vector3f diff2 = new Vector3f(); private final Vector3f normal = new Vector3f(); public GlDisplaylistDrawcallback(GL gl) { this.gl = gl; } public void processTriangle(Vector3f[] triangle, int partId, int triangleIndex) { diff1.sub(triangle[1], triangle[0]); diff2.sub(triangle[2], triangle[0]); normal.cross(diff1, diff2); normal.normalize(); gl.glBegin(gl.GL_TRIANGLES); gl.glColor3f(0, 1, 0); gl.glNormal3f(normal.x, normal.y, normal.z); gl.glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z); gl.glColor3f(0, 1, 0); gl.glNormal3f(normal.x, normal.y, normal.z); gl.glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z); gl.glColor3f(0, 1, 0); gl.glNormal3f(normal.x, normal.y, normal.z); gl.glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z); gl.glEnd(); /*glBegin(GL_LINES); glColor3f(1, 1, 0); glNormal3d(normal.getX(),normal.getY(),normal.getZ()); glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); glNormal3d(normal.getX(),normal.getY(),normal.getZ()); glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); glColor3f(1, 1, 0); glNormal3d(normal.getX(),normal.getY(),normal.getZ()); glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); glNormal3d(normal.getX(),normal.getY(),normal.getZ()); glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ()); glColor3f(1, 1, 0); glNormal3d(normal.getX(),normal.getY(),normal.getZ()); glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ()); glNormal3d(normal.getX(),normal.getY(),normal.getZ()); glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ()); glEnd();*/ } } private static class GlDrawcallback extends TriangleCallback { private GL gl; public boolean wireframe = false; public GlDrawcallback(GL gl) { this.gl = gl; } public void processTriangle(Vector3f[] triangle, int partId, int triangleIndex) { if (wireframe) { gl.glBegin(gl.GL_LINES); gl.glColor3f(1, 0, 0); gl.glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z); gl.glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z); gl.glColor3f(0, 1, 0); gl.glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z); gl.glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z); gl.glColor3f(0, 0, 1); gl.glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z); gl.glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z); gl.glEnd(); } else { gl.glBegin(gl.GL_TRIANGLES); gl.glColor3f(1, 0, 0); gl.glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z); gl.glColor3f(0, 1, 0); gl.glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z); gl.glColor3f(0, 0, 1); gl.glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z); gl.glEnd(); } } } private static class TriangleGlDrawcallback extends InternalTriangleIndexCallback { private GL gl; public TriangleGlDrawcallback(GL gl) { this.gl = gl; } public void internalProcessTriangleIndex(Vector3f[] triangle, int partId, int triangleIndex) { gl.glBegin(gl.GL_TRIANGLES);//LINES); gl.glColor3f(1, 0, 0); gl.glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z); gl.glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z); gl.glColor3f(0, 1, 0); gl.glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z); gl.glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z); gl.glColor3f(0, 0, 1); gl.glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z); gl.glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z); gl.glEnd(); } } }