I forgot to shape.calculateLocalInertia(mass, new Vector3d(0,0,0));
ok leave this for obscurity now
------------
ok, so I update jBullet to the current version on the main website http://jbullet.advel.cz/. Update the import calls since mine was considerable old. Ran my program and. No rotation. I thought maybe I made some mistakes in my CustomMotionState and just needed to fix that up. No good. I started print the rotation matrix. Nothing. it's a pure [ 1 0 0 ][ 0 1 0][ 0 0 1] ie no rotation. I thought maybe I need to access the matrix differently. no success.
So I started to prototype a test. Result. Precarious stacked boxes will never tip/lean/fall. They bounce and move just fine and behave perfectly in a world of no rotation.
Heres my test code, it's a big minimal copy and paste from JPCT HelloWorld and jBullet HelloWorld.
Code: Select all
import com.threed.jpct.*;
import com.threed.jpct.util.Light;
import sregame.hgkad.physics.*;
import java.util.Vector;
import java.util.List;
import java.util.ArrayList;
import javax.vecmath.Vector3f;
import javax.swing.*;
import java.awt.*;
import javax.vecmath.Matrix3f;
import javax.vecmath.Matrix4f;
import com.bulletphysics.BulletGlobals;
import com.bulletphysics.collision.broadphase.AxisSweep3;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.dispatch.CollisionWorld;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.dynamics.DynamicsWorld;
import com.bulletphysics.dynamics.constraintsolver.Point2PointConstraint;
import com.bulletphysics.dynamics.constraintsolver.TypedConstraint;
import com.bulletphysics.linearmath.*;
import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.broadphase.SimpleBroadphase;
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.collision.shapes.StaticPlaneShape;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
public class BulletTest {
private World world;
private FrameBuffer buffer;
private Object3D box;
private JFrame frame;
public DiscreteDynamicsWorld dynamicWorld;
public int maxSubSteps;
public float timeStep, fixedTimeStep;
protected Clock clock = new Clock();
private List<CollisionShape> collisionShapes = new ArrayList<CollisionShape>();
private BroadphaseInterface overlappingPairCache;
private CollisionDispatcher dispatcher;
private ConstraintSolver solver;
private DefaultCollisionConfiguration collisionConfiguration;
private Vector<RigidBody> boxList;
public static void main(String[] args) throws Exception {
new BulletTest().loop();
}
public BulletTest() throws Exception {
boxList = new Vector();
frame=new JFrame("Bullet Test");
frame.setSize(800, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
world = new World();
world.setAmbientLight(120, 120, 120);
TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));
box = Primitives.getBox(1f, 1f);
box.setTexture("box");
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);
world.getCamera().setPosition(150, -50, -5);
world.getCamera().lookAt(box.getTransformedCenter());
Light light = new Light(world);
light.setPosition(new SimpleVector(-200, -50 , 80));
light.setIntensity(150,140,150);
collisionConfiguration = new DefaultCollisionConfiguration();
dispatcher = new CollisionDispatcher(collisionConfiguration);
Vector3f worldAabbMin = new Vector3f(-10000,-10000,-10000);
Vector3f worldAabbMax = new Vector3f(10000,10000,10000);
AxisSweep3 overlappingPairCache = new AxisSweep3(worldAabbMin, worldAabbMax);
SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver();
dynamicWorld = new DiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicWorld.setGravity(new Vector3f(0,-10,0));
CollisionShape groundShape = new BoxShape(new Vector3f(50.f, 50.f, 50.f));
Transform groundTransform = new Transform();
groundTransform.setIdentity();
groundTransform.origin.set(new Vector3f(0.f, -56.f, 0.f));
float mass = 0f;
Vector3f localInertia = new Vector3f(0, 0, 0);
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
dynamicWorld.addRigidBody(body);
initTestObects();
}
private void loop() throws Exception {
buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);
Canvas canvas=buffer.enableGLCanvasRenderer();
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
frame.add(canvas);
RigidBody body;
Object3D gfx;
DefaultMotionState dms;
SimpleVector pos;
Matrix4f rotMatrix = new Matrix4f();
while (frame.isShowing()) {
float ms = clock.getTimeMicroseconds();
clock.reset();
dynamicWorld.stepSimulation(ms / 1000000f);
for(int i = 0; i < boxList.size(); i++){
body = boxList.get(i);
gfx = (Object3D)body.getUserPointer();
dms = (DefaultMotionState)body.getMotionState();
dms.graphicsWorldTrans.getMatrix(rotMatrix);
//System.out.println(dms.graphicsWorldTrans.basis.toString());
System.out.println(rotMatrix.toString());
pos = gfx.getTransformedCenter();
gfx.translate(
dms.graphicsWorldTrans.origin.x - pos.x,
(-dms.graphicsWorldTrans.origin.y) - pos.y,
(-dms.graphicsWorldTrans.origin.z) - pos.z );
}
box.rotateY(0.01f);
buffer.clear(java.awt.Color.BLUE);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
canvas.repaint();
Thread.sleep(10);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
frame.dispose();
System.exit(0);
}
public void initTestObects(){
Transform transform;
Object3D boxgfx;
Vector3f size = new Vector3f(2,2,2);
BoxShape shape = new BoxShape(size);
//JPCTBulletMotionState ms;
MotionState ms;
Vector3f localInertia = new Vector3f(0,0,0);
RigidBodyConstructionInfo rbInfo;
RigidBody body;
for(int i = 1; i < 30; i++){
boxgfx = Primitives.getCube(2);
boxgfx.setTexture("box");
boxgfx.setEnvmapped(Object3D.ENVMAP_ENABLED);
boxgfx.build();
world.addObject(boxgfx);
transform = new Transform();
transform.setIdentity();
transform.origin.set(0, (i * 4), i*2);
ms = new DefaultMotionState(transform);
//ms = new JPCTBulletMotionState(transform);
//ms.setObject(boxgfx);
rbInfo = new RigidBodyConstructionInfo(500, ms, shape, localInertia);
body = new RigidBody(rbInfo);
body.setRestitution(0.1f);
body.setFriction(0.01f);
body.setDamping(0.0f, 0.0f);
body.setUserPointer(boxgfx);
boxList.add(body);
dynamicWorld.addRigidBody(body);
} // end for loop
}
}