/*
|
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
|
*
|
* 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<RagDoll> ragdolls = new ObjectArrayList<RagDoll>();
|
|
// 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)
|
{
|
RagDoll ragDoll = new RagDoll(null, new Vector3f(0f, 0f, 0f), 0.45f, walk); // Math.random() > 0.5/*true*/); // true);
|
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<Transform> initialmatrices;
|
|
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), 0.45f, walk);
|
|
bRep = null;
|
}
|
|
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) // FUCK
|
{
|
// 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 == 2) // 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<Transform>();
|
|
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<std::string, hidden::ProfileBlock*>::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<Transform> transformsPool = ObjectPool.get(Transform.class);
|
ObjectPool<Vector3f> 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<const btUniformScalingShape*>(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<const btConeShape*>(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<Vector3f> vtx = hull.getVertexPointer();
|
ObjectArrayList<Vector3f> 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<bRep.startvertices[currentobject]; i++)
|
{
|
Vertex v = bRep.GetVertex(i);
|
Vector3f v1 = vtx.getQuick(v.supportindex);
|
Vector3f normal = normals.getQuick(v.supportindex);
|
|
tmp1.set(v1);
|
trans.transform(tmp1);
|
|
v.x = tmp1.x;
|
v.y = tmp1.y;
|
v.z = tmp1.z;
|
|
averagex += v.x;
|
averagey += v.y;
|
averagez += v.z;
|
count++;
|
|
tmp1.set(normal);
|
trans.basis.transform(tmp1);
|
|
v.norm.x = tmp1.x;
|
v.norm.y = tmp1.y;
|
v.norm.z = tmp1.z;
|
}
|
// for (int i = 0; i < hull.numVertices(); i++)
|
// {
|
//
|
// }
|
|
int index3 = currentobject-1;
|
index3 *= 3;
|
|
bRep.averagepoints[index3] = averagex/count;
|
bRep.averagepoints[index3+1] = averagey/count;
|
bRep.averagepoints[index3+2] = averagez/count;
|
|
double mindist2 = 1E10f;
|
double maxdist2 = -1E10f;
|
|
for (int i=bRep.startvertices[currentobject-1]; i<bRep.startvertices[currentobject]; i++)
|
{
|
Vertex v = bRep.GetVertex(i);
|
|
double x = v.x - bRep.averagepoints[index3];
|
double y = v.y - bRep.averagepoints[index3+1];
|
double z = v.z - bRep.averagepoints[index3+2];
|
|
double dist2 = x*x + y*y + z*z;
|
|
if (mindist2 > 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<Vector3f> 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;i<polyshape->getNumVertices();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;i<polyshape->getNumPlanes();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<SphereKey, Integer> sphereDisplayLists = new HashMap<SphereKey, Integer>();
|
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<CylinderKey, Integer> cylinderDisplayLists = new HashMap<CylinderKey, Integer>();
|
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();
|
}
|
}
|
}
|