//http://www.aorensoftware.com/blog/2011/06/01/when-bullets-move-too-fast/
package com.bitwaffle.spaceguts.physics;
import javax.vecmath.Vector3f;
import com.bitwaffle.spaceguts.entities.DynamicEntity;
import com.bitwaffle.spaceguts.input.KeyBindings;
import com.bitwaffle.spaceguts.util.QuaternionHelper;
import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.broadphase.DbvtBroadphase;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionWorld;
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
import com.bulletphysics.collision.shapes.ConvexShape;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
import com.bulletphysics.linearmath.Clock;
import com.bulletphysics.linearmath.Transform;
/**
* This class handles the dynamics world and everything related
*
* @author TranquilMarmot
*
*/
public class Physics {
/** maximum number of substeps to do on each tick */
private final static int SUBSTEPS = 10;
/** the discrete dynamics world */
public static DiscreteDynamicsWorld dynamicsWorld;
/** broadphase interface */
public static BroadphaseInterface broadphase;
/** collision dispatcher */
public static CollisionDispatcher dispatcher;
/** impulse constraint solver */
public static SequentialImpulseConstraintSolver solver;
/** clock to use for framerate independence */
private static Clock clock = new Clock();
/** to keep the debug key from being held */
private static boolean debugDown = false;
/** whether or not to draw physics debug info */
public static boolean drawDebug = false;
/**
* Initializes the physics engine
*/
public static void initPhysics() {
// broadphase interface
broadphase = new DbvtBroadphase();
// collision configuration and dispatcher
DefaultCollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration();
dispatcher = new CollisionDispatcher(collisionConfiguration);
// wat
solver = new SequentialImpulseConstraintSolver();
// the world everything is in
dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase,
solver, collisionConfiguration);
// no gravity, we're in space!
dynamicsWorld.setGravity(new Vector3f(0, 0, 0));
// see the PhysicsDebugDrawer class
dynamicsWorld.setDebugDrawer(new PhysicsDebugDrawer());
Physics.dynamicsWorld.setInternalTickCallback(new DynamicEntityCallback(), null);
}
/**
* Updates the dynamics world
*/
public static void update() {
dynamicsWorld.stepSimulation(getDeltaTimeMicroseconds() / 1000000.0f,
SUBSTEPS);
// handle the physics debug key
if (KeyBindings.SYS_DEBUG_PHYSICS.isPressed() && !debugDown) {
drawDebug = !drawDebug;
debugDown = true;
}
if (!KeyBindings.SYS_DEBUG_PHYSICS.isPressed()) {
debugDown = false;
}
}
/**
* Cleans up all the physics stuff
*/
public static void cleanup() {
dynamicsWorld.destroy();
dynamicsWorld = null;
broadphase = null;
dispatcher = null;
solver = null;
}
/**
* @return Change in time in microseconds
*/
private static float getDeltaTimeMicroseconds() {
float delta = clock.getTimeMicroseconds();
clock.reset();
return delta;
}
public static void convexSweepTest(DynamicEntity origin, org.lwjgl.util.vector.Vector3f distance, ConvexShape shape, CollisionWorld.ConvexResultCallback callback){
// grab current world transform
Transform from = new Transform(), to = new Transform();
origin.rigidBody.getWorldTransform(to);
origin.rigidBody.getWorldTransform(from);
// set 'to' transform to be in front of the player
org.lwjgl.util.vector.Vector3f forward = QuaternionHelper.rotateVectorByQuaternion(distance, origin.rotation);
from.origin.add(new javax.vecmath.Vector3f(forward.x, forward.y, forward.z));
dynamicsWorld.convexSweepTest(shape, to, from, callback);
}
}