/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package automenta.spacenet.space.geom.physics; import automenta.spacenet.space.Repeat; import automenta.spacenet.space.Space; import automenta.spacenet.var.scalar.DoubleVar; import automenta.spacenet.var.vector.V3; import com.ardor3d.scenegraph.Spatial; import com.bulletphysics.collision.broadphase.AxisSweep3; import com.bulletphysics.collision.dispatch.CollisionDispatcher; import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration; import com.bulletphysics.collision.shapes.BoxShape; import com.bulletphysics.collision.shapes.CollisionShape; import com.bulletphysics.dynamics.DiscreteDynamicsWorld; import com.bulletphysics.dynamics.DynamicsWorld; import com.bulletphysics.dynamics.RigidBody; import com.bulletphysics.dynamics.RigidBodyConstructionInfo; import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver; import com.bulletphysics.linearmath.DefaultMotionState; import com.bulletphysics.linearmath.Transform; import java.util.Map; import java.util.WeakHashMap; import javax.vecmath.Vector3f; /** * * @author seh */ public class PhySpace extends Repeat { private final DoubleVar timeScale = new DoubleVar(1.0); public final DynamicsWorld dynamicsWorld; private int defaultSubSteps = 1; private final V3 gravity; private Vector3f va = new Vector3f(); private final static double updatePeriod = 0.01; private Map<RigidBody, Space> bodySpace = new WeakHashMap(); private final Vector3f worldAabbMax; private final Vector3f worldAabbMin; @Deprecated public PhySpace() { this(25.0); } public PhySpace(double worldDimension) { this(worldDimension, worldDimension, worldDimension); } //TODO make space dimensions necessary constructor parameter public PhySpace(double wx, double wy, double wz) { super(updatePeriod); float w = (float) wx; float h = (float) wy; float d = (float) wz; // collision configuration contains default setup for memory, collision // setup. Advanced users can create their own configuration. DefaultCollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration(); // use the default collision dispatcher. For parallel processing you // can use a diffent dispatcher (see Extras/BulletMultiThreaded) CollisionDispatcher dispatcher = new CollisionDispatcher(collisionConfiguration); // the maximum size of the collision world. Make sure objects stay // within these boundaries // Don't make the world AABB size too large, it will harm simulation // quality and performance worldAabbMin = new Vector3f(-w / 2.0f, -h / 2.0f, -d / 2.0f); worldAabbMax = new Vector3f(w / 2.0f, h / 2.0f, d / 2.0f); int maxProxies = 1024; AxisSweep3 overlappingPairCache = new AxisSweep3(worldAabbMin, worldAabbMax, maxProxies); //BroadphaseInterface overlappingPairCache = new SimpleBroadphase( // maxProxies); // the default constraint solver. For parallel processing you can use a // different solver (see Extras/BulletMultiThreaded) SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver(); dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration); //dynamicsWorld = new SimpleDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration); gravity = new V3(0, 0, 0) { @Override protected void notifyChanges() { super.notifyChanges(); updateGravity(this); } }; updateGravity(gravity); // // create a few basic rigid bodies // CollisionShape groundShape = new BoxShape(new Vector3f(50.f, 50.f, 50.f)); // // keep track of the shapes, we release memory at exit. // // make sure to re-use collision shapes among rigid bodies whenever // // possible! // List<CollisionShape> collisionShapes = new ArrayList<CollisionShape>(); // // collisionShapes.add(groundShape); } protected void updateGravity(V3 g) { va.set(g.getXf(), g.getYf(), g.getZf()); dynamicsWorld.setGravity(va); } @Override protected void update(double t, double dt, Spatial s) { double timeStep = getTimeScale().d() * dt; int subSteps = defaultSubSteps; //dynamicsWorld.stepSimulation((float)timeStep); dynamicsWorld.stepSimulation((float) timeStep, subSteps); dynamicsWorld.performDiscreteCollisionDetection(); // // print positions of all objects // for (int j = dynamicsWorld.getNumCollisionObjects() - 1; j >= 0; j--) { // CollisionObject obj = dynamicsWorld.getCollisionObjectArray().get(j); // RigidBody body = RigidBody.upcast(obj); // if (body != null && body.getMotionState() != null) { // Transform trans = new Transform(); // body.getMotionState().getWorldTransform(trans); // System.out.printf("world pos = %f,%f,%f\n", trans.origin.x, // trans.origin.y, trans.origin.z); // } // } } public DoubleVar getTimeScale() { return timeScale; } public V3 getGravity() { return gravity; } protected void addBoundPlane(Vector3f size, Vector3f center) { CollisionShape groundShape = new BoxShape(size); Transform groundTransform = new Transform(); groundTransform.setIdentity(); groundTransform.origin.set(center); float mass = 0f; Vector3f localInertia = new Vector3f(0, 0, 0); // using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects DefaultMotionState myMotionState = new DefaultMotionState(groundTransform); RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, groundShape, localInertia); RigidBody body = new RigidBody(rbInfo); // add the body to the dynamics world dynamicsWorld.addRigidBody(body); } protected void addBoundPlanes() { float minX = worldAabbMin.x; float minY = worldAabbMin.y; float minZ = worldAabbMin.z; float maxX = worldAabbMax.x; float maxY = worldAabbMax.y; float maxZ = worldAabbMax.z; float thick = 0.05f; //back plane at -z addBoundPlane(new Vector3f(maxX-minX, maxY-minY, thick), new Vector3f(0, 0, minZ)); //front plane at +z addBoundPlane(new Vector3f(maxX-minX, maxY-minY, thick), new Vector3f(0, 0, maxZ)); //left plane at -x addBoundPlane(new Vector3f(thick, maxY-minY, maxZ-minZ), new Vector3f(minX, 0, 0)); //right plane at +x addBoundPlane(new Vector3f(thick, maxY-minY, maxZ-minZ), new Vector3f(maxX, 0, 0)); //bottom plane at -y addBoundPlane(new Vector3f(maxX-minX, thick, maxZ-minZ), new Vector3f(0, minY, 0)); //top plane at +y addBoundPlane(new Vector3f(maxX-minX, thick, maxZ-minZ), new Vector3f(0, maxY, 0)); } public PhyBox add(PhyBox pb) { dynamicsWorld.addRigidBody(pb.getBody()); bodySpace.put(pb.getBody(), pb); return pb; } public PhyBox remove(PhyBox pb) { //TODO write return null; } public Space getSpace(RigidBody b) { return bodySpace.get(b); } }