I'm trying to simulate a tank. I've got a basic box, then 6 cylinders as wheels, three for each side. I only want the wheels to rotate around the Z axis and but be fixed to the center box. To turn the object, all the wheels on one side will rotate +Z and the other side will use -Z.
Problem 1) Some versions appear to lock the center box from any rotation, others the center box works but the wheels don't follow center box rotation
Problem 2) For some reason I can only turn the wheels manually calling setAngularVelocity(), insead of applyTorque().
Here is an example of the shape I'm trying.
And here is the code I've got, please tell me where I'm going wrong. Either my entire object doesn't rotate on Y axis, or the center box does but the wheels stay locked to Y axis.
Bullet version 2.80-rev2531
Code: Select all
btCollisionShape *pShape = 0;
btMotionState* pState = 0;
btRigidBody* pBody = 0;
btScalar mass = 200;
pShape = new btBoxShape(btVector3(50,10,32));
btTransform localTrans;
localTrans.setIdentity();
localTrans.setOrigin( cvt(getPosition()) );
pState = new btDefaultMotionState(localTrans);
btVector3 inertia (0,0,0);
// Important, do not remove this or object won't rotate!
pShape->calculateLocalInertia(mass, inertia);
//Create the rigid body
pBody = new btRigidBody(mass, pState, pShape, inertia);
// Don't deativate when movement done
pBody->forceActivationState(DISABLE_DEACTIVATION);
// add the body to the physics world
mpBtWorld->addRigidBody(pBody);
mpBodies[TANK_HULL] = pBody;
//////// Wheels /////////////
btScalar mass = 50;
btVector3 interia(0,0,0);
btVector3 startPos = cvt(getPosition() + Vector3(0,10,0));
btVector3 endPos (0,0,0);
btRigidBody* pBody = 0;
int x,z;
int xOffset = 36; // spacing between wheels
// create 6 wheels
for (int i = 0; i < 6; i++)
{
if (i < 3)
z = -38;
else
z = 38;
if (i < 3)
x = i * xOffset;
else
x = (i - 3) * xOffset;
endPos = startPos + btVector3(x - xOffset, -20, z);
localTrans.setIdentity();
localTrans.setOrigin(endPos);
// width, radius, radius
btCollisionShape* pShape = new btCylinderShapeZ(btVector3(12, 5, 5));
mpShapes[TANK_WHEEL_1 + i] = pShape;
pShape->calculateLocalInertia(mass, interia);
btDefaultMotionState* state = new btDefaultMotionState(localTrans);
pBody = new btRigidBody(mass, state, pShape);
mpBodies[TANK_WHEEL_1 + i] = pBody;
pBody->forceActivationState(DISABLE_DEACTIVATION);
// add wheel to world
mpBtWorld->addRigidBody(pBody);
// add joint
/*
/////////// another attempt /////////////////////
btGeneric6DofSpringConstraint* pJoint = 0;
// this joint causes an explosion
pJoint = new btGeneric6DofSpringConstraint(*mpBodies[TANK_HULL],
*pBody,
hullTrans,
localTrans,
false);
////////////// another attempt ///////////////////
btHingeConstraint* pJoint = 0;
btVector3 axis1 (0,1,0); // Y
btVector3 axis2;
if (i < 3)
axis2 = btVector3(0,0,1); // Z
else
axis2 = btVector3(0,0,-1); // Z
pJoint = new btHingeConstraint(*mpBodies[TANK_HULL],
*pBody,
endPos, // pivotInA
endPos + axis2, // pivotInB
axis1, // axisInA
axis2, // axisInB
true);
*/ //////////// best match so far /////////////////////
btHinge2Constraint* pJoint = 0;
btVector3 axis1 (0,1,0); // Y
btVector3 axis2;
if (i < 3)
axis2 = btVector3(0,0,1); // Z
else
axis2 = btVector3(0,0,-1); // Z
pJoint = new btHinge2Constraint(*mpBodies[TANK_HULL],
*pBody,
endPos,
axis1,
axis2);
pJoint->setAngularLowerLimit(btVector3(1,-1, 1));
pJoint->setAngularUpperLimit(btVector3(0, 1, 0));
pJoint->setDbgDrawSize(btScalar(25.0f));
mpBtWorld->addConstraint(pJoint, true);
mpJoints[TANK_WHEEL_1 + i] = pJoint;
}