A small weekend trip to Bullet ... and for now back to ODE

noisy
Posts: 10
Joined: Thu May 24, 2007 7:57 pm

A small weekend trip to Bullet ... and for now back to ODE

Post by noisy »

Hi,

this weekend I took some time to integrate Bullet into my project. Coming from ODE I have to say I really like Bullet, it has a good C++ interface and already great features. But I have a few problems with it:

1. My ragdolls aren't working, which is probably because I don't really understand the Bullet constraints.
2. The heightfield implementation is not as good as that in ODE. In ODE objects falling beneath the ground are still detected, but in Bullet it seams that there are only triangles so that fast moving (or deep falling) objects can move through the terrain.

@1: I would find it very helpful if there were a HOWTO (for example on the Wiki) were Bullet's constraints are explained (like the joints are in the ODE wiki). I mean the only way to get information about them is looking into the Bullet source code (and I don't really understand this part), puzzling informations giving in some posts here or looking into the demos, which isn't enough (at least for those who don't understand all the maths behind it).

@2: I think the continous collision detection would solve this problem. So what's the progress about it?

Thanks,
noisy
User avatar
projectileman
Posts: 109
Joined: Thu Dec 14, 2006 4:27 pm
Location: Colombia

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by projectileman »

1. My ragdolls aren't working, which is probably because I don't really understand the Bullet constraints.
Have you ever looked the GenericJointDemo code??
2. The heightfield implementation is not as good as that in ODE. In ODE objects falling beneath the ground are still detected, but in Bullet it seams that there are only triangles so that fast moving (or deep falling) objects can move through the terrain.
I haven't tried this feature before, so I can't tell you if it is working. Could you considering working with trimeshes ?
In the past I've worked with ODE too, but its Heightmap implementation seems to me SLOW and inefficient. So for terrains I've decided working with trimeshes which have a very efficient way for handle large scale collisions (thanks to GIMPACT).

please try GIMPACT meshes or btBvhTriangleMeshShape.
@1: I would find it very helpful if there were a HOWTO (for example on the Wiki) were Bullet's constraints are explained (like the joints are in the ODE wiki). I mean the only way to get information about them is looking into the Bullet source code (and I don't really understand this part), puzzling informations giving in some posts here or looking into the demos, which isn't enough (at least for those who don't understand all the maths behind it).
Actually Bullet has two constraint implementations: one works similar to ODE (quickstep) and the other is based on sequencial impulses (Gauss-Seidel ??).

If you want to see how Quickstep implementation works, take a look to the OdeConstraintSolver class and OdeTypedJoint class in the quickstep folder in Extras.

The code for the Joints in sequencial impulse implementation is more simple to understand. Take a look to the btGeneric6DofConstraint class.
@2: I think the continous collision detection would solve this problem. So what's the progress about it?
I haven't tried continous collision detection, but most simulations should work in discrete collision detection mode.

PD: Sorry for my English :oops:
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by Erwin Coumans »

Hi,

I agree more documentation and better samples would help. I try to get some more resources into documentation/tools.

How do you author your ragdoll constraints? Can you help providing some description and code snippets how you currently specify a ragdoll using ODE?

Have you tried to compare it with the RagdollDemo and/or GenericJointDemo? You can either use the btConeTwistConstraint or btGenericD6Constraint to create ragdolls.

The heightfield is currently indeed infinitely thin. This can be fixed either giving the terrain some thickness, or by CCD.

Thanks,
Erwin
noisy
Posts: 10
Joined: Thu May 24, 2007 7:57 pm

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by noisy »

thanks for the fast answers.

For my ragdolls I'm using this code in ODE:

hinges:

Code: Select all

j = dJointCreateHinge (getGameWorld()->getWorld(), jointGroup);
dJointSetHingeAnchor (j, anchorPos.x, anchorPos.y, anchorPos.z);
dJointSetHingeAxis (j, axis.x, axis.y, axis.z);
dJointSetHingeParam (j, dParamLoStop, minA);
dJointSetHingeParam (j, dParamHiStop, maxA);
universal:

Code: Select all

j = dJointCreateUniversal (getGameWorld()->getWorld(), jointGroup);
dJointSetUniversalAnchor (j, anchorPos.x, anchorPos.y, anchorPos.z);
dJointSetUniversalAxis1 (j, axis.x, axis.y, axis.z);
dJointSetUniversalAxis2 (j, axis2.x, axis2.y, axis2.z);
dJointSetUniversalParam (j, dParamLoStop, minA);
dJointSetUniversalParam (j, dParamHiStop, maxA);
dJointSetUniversalParam (j, dParamLoStop2, minA2);
dJointSetUniversalParam (j, dParamHiStop2, maxA2);
My problem is that I don't know how to calculate the pivotInA, pivotInB, axisInA and axisInB transformations for the hinge constraint and the frameInA, frameInB and useLinearReferenceFrameA parameter for 6DOF constraint. Another problem is the fixed joint implementation: This can be done using 6DOF constraint and then locking any DOF, right? But what to pass then for frameInA, frameInB?

How can I give the terrain thickness? I don't see any function in btHeightfieldTerrainShape for doing this.

Another question:
In ODE I used several spaces for my ragdolls, so that at first the AABBs for the entire ragdolls are checked for colliding and only when overlapping the bones of them are checked. Now in bullet I put everything into one world. Is this really faster in one "magic" AxisSweep world than in several ODE hash-spaces?
noisy
Posts: 10
Joined: Thu May 24, 2007 7:57 pm

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by noisy »

I'm creating my ragdolls (see demo1 or demo2) using the data from an OGRE skeleton. Then I have an aditional XML file which descripes shapes and joints, see attached skeleton.zip

Now I create a body for each bone and the joints. Creating the bodies is not the problem with bullet. Only one thing: I'm not sure wheter this is the right code to create a ODE like capsule going along the Z-axis:

Code: Select all

// creating capsule along Z-axis
assert (length>radius*2);
float l = length*0.5-radius;
btVector3 positions[] = { btVector3(0, 0, -l), btVector3(0, 0, l) };
btScalar radi[] = { radius, radius };
g = new btMultiSphereShape (btVector3(radius, radius, length*2+radius), positions, radi, 2);
So I can calculate the resulting anchorPos and axis (in world space) for each joint and in ODE just pass it to the function. So my question again (hopefully a bit preciser): How do I calculate the pivotInA, pivotInB, axisInA, axisInB I have to pass to the btHingeConstraint to make it work like the ODE one? How to implement a fixed joint? And how to calculate the frameInA, frameInB parameter for the 6DOF constraint (I'll remove the 2 axis given to universal joint and use per-axis locking parameters)?

Thanks,
noisy
You do not have the required permissions to view the files attached to this post.
User avatar
projectileman
Posts: 109
Joined: Thu Dec 14, 2006 4:27 pm
Location: Colombia

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by projectileman »

For setting the frames in btGeneric6DofConstraint joints, just think about that ODE universal joint uses the X axis from one body and the Z axis from the other and then ODE calculates the relative orientation between bodies. In ODE the X and Z axis must be given in global coordinates.

btGeneric6DofConstraint does it in a more general approach, and the connection axes and connection points must be assigned in relative coordinates. The axes must be set in the transformation matrices (those present in the frames), just like setting the column values as if they were axes. The points are the origin attribute from each transform frame.
noisy
Posts: 10
Joined: Thu May 24, 2007 7:57 pm

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by noisy »

thank you, this was exactly the type of explanation I was looking for.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by Erwin Coumans »

It would be really nice if we can map the ODE joint interface into Bullet constraints, I'm sure others would find this helpful too. Could you help with this?

This is related to authoring. Bullet uses COLLADA Physics, which allows to specify the ragdoll using generic 6dof constraints.

You seem to use XML too, did you come up with the spec yourself? What exporter/authoring tool do you use?
Thanks,
Erwin

By the way, you can better attached zipped .txt or .xml or .cpp files, instead of copy/paste huge amounts of text. I modified the posting for you.
noisy
Posts: 10
Joined: Thu May 24, 2007 7:57 pm

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by noisy »

i have just implemented a ODE like fixed joint:

Code: Select all

btGeneric6DofConstraint *btJointCreateFixed (btRigidBody *body0, btRigidBody *body1)
{
	btGeneric6DofConstraint * joint6DOF;
	btTransform localA, localB;
	localA.setIdentity();
	localB = body1->getCenterOfMassTransform().inverse() * body0->getCenterOfMassTransform();

	joint6DOF = new btGeneric6DofConstraint(*body0, *body1, localA, localB, true);

	joint6DOF->setAngularLowerLimit(btVector3(-SIMD_EPSILON,-SIMD_EPSILON,-SIMD_EPSILON));
	joint6DOF->setAngularUpperLimit(btVector3(SIMD_EPSILON,SIMD_EPSILON,SIMD_EPSILON));
	return joint6DOF;
}
Other joint types will follow.
My XML files are custom ones, and handwritten. I just created them for ragdolls in combinition with the skeleton data I read from OGRE.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by Erwin Coumans »

That looks good. Does the fixed joint only fix the translation? It looks like you allow for rotation.

This would be really useful, to cover some of the other constraints. If you have any doubts of conversion, please ask.

Hope you can spend another weekend or holiday in Bullet land ;-)
Thanks,
Erwin
noisy
Posts: 10
Joined: Thu May 24, 2007 7:57 pm

Re: A small weekend trip to Bullet ... and for now back to ODE

Post by noisy »

I implemented another joint type:

Code: Select all

btHingeConstraint *btJointCreateHinge (btRigidBody *body0, btRigidBody *body1, const btVector3 &anchorPos, const btVector3 &axis)
{
	btTransform frameInA, frameInB;
	frameInA.setIdentity (); frameInB.setIdentity();
	
	frameInA.setOrigin (body0->getCenterOfMassTransform().inverse() * anchorPos);
	frameInB.setOrigin (body1->getCenterOfMassTransform().inverse() * anchorPos);
	
	btVector3 zAxis = axis;
	btVector3 xAxis = btVector3(0,1,0).cross(zAxis);
	assert (xAxis.normalized());
	btVector3 yAxis = zAxis.cross(xAxis);
	btMatrix3x3 basis(xAxis.x(), xAxis.y(), xAxis.z(), yAxis.x(), yAxis.y(), yAxis.z(), zAxis.x(), zAxis.y(), zAxis.z());
	frameInA.setBasis(body0->getCenterOfMassTransform().getBasis().inverse() * basis);
	frameInB.setBasis(body1->getCenterOfMassTransform().getBasis().inverse() * basis);
	
	return new btHingeConstraint (*body0, *body1, frameInA, frameInB);
}
After creating a hinge with this function you can set the limits with btHingeConstraint::setLimit like in ODE.
The fixed joint is just like that in ODE. It doesn't allow rotation, I set it to SIMD_EPSILON because I saw this in the GenericJointDemo fixed joint implementation (when setting RIGID to 1) and I hope there is a reason for this (maybe stability).