Reputation: 306
I am trying to battle my way through learning Java and bullet physics all in one go. Quite possible a little too much to do all at once but I like a challenge.
So far, I've learned how to import g3db objects, apply bullet physics to them and interact with them on the screen by using the following code:
assets = new AssetManager();
assets.load("globe.g3db", Model.class);
assets.load("crate.g3db", Model.class);
assets.finishLoading();
Model model = assets.get("globe.g3db", Model.class);
ModelInstance inst = new ModelInstance(model);
inst.transform.trn(0, 20, 0);
btRigidBody body;
btSphereShape sh = new btSphereShape(1);
sh.calculateLocalInertia(1, new Vector3(0,0,0));
body = new btRigidBody(new btRigidBody.btRigidBodyConstructionInfo(3, new btDefaultMotionState(inst.transform), sh));
body.setUserValue(Minstances.size);
body.proceedToTransform(inst.transform);
motionState = new MyMotionState();
motionState.transform = inst.transform;
body.setMotionState(motionState);
dynamicsWorld.addRigidBody(body );
Minstances.add(inst);
This works fine, if I set it above the ground it falls and comes to rest on the ground, however when it moves about it slides rather than rolls. Is there an easy fix?
Upvotes: 2
Views: 858
Reputation: 888
To allow rolling of a physical body, you need to calculate its local inertia and provide it to the construction info. In your code you're almost doing it right.
The method
btCollisionShape.calculateLocalInertia(float mass, Vector3 inertia)
indeed calculates local inertia but stores it in its second argument 'Vector3 inertia'. No changes are applied to btCollisionShape
itself.
After obtaining the vector of inertia you need to pass it to
btRigidBodyConstructionInfo(float mass, btMotionState motionState, btCollisionShape collisionShape, Vector3 localInertia)
as the last argument.
The correct code should look like this:
btRigidBody body;
btSphereShape sh = new btSphereShape(1);
Vector3 inertia = new Vector3(0,0,0);
sh.calculateLocalInertia(1, inertia);
body = new btRigidBody(new btRigidBody.btRigidBodyConstructionInfo(3, new btDefaultMotionState(inst.transform), sh, inertia));
Local inertia is not required to perform the simulation, but without it, all forces applied to bodies are treated as central forces and therefore cannot affect angular speed.
Upvotes: 2
Reputation: 1011
You need to read out and set the rotation as well, right now you are just reading \ applying the translation.
Create a new quaternion and get the xyzw values and apply them to your object.
something like this (c++ code, but you can easily do the same in java):
btTransform trans;
Quat myquat;
yourBulletDynamicObject->getMotionState()->getWorldTransform(trans);
btQuaternion rot = trans.getRotation();
myquat.w = rot.w();
myquat.x = rot.x();
myquat.y = rot.z();
myquat.z = rot.y();
set myquat back on your object.
Upvotes: 0