Inheriting btRigidBody

Trioxin
Posts: 7
Joined: Mon Aug 15, 2011 4:58 am

Inheriting btRigidBody

Post by Trioxin »

I have a question that I suspect is a bit general C++, but thought someone here might have encountered it and would give a more succinct answer to the problem.

I would like my class to inherit btRigidBody, but without all the constructor variables.
For example, I just want to be able to call

Code: Select all

terrain = new Terrain();
Then have the terrain constructor worry about mass, state, CollisionShape, and inertia.

For example, something like this:

Code: Select all

Terrain::Terrain(Game* p_Game) {
	[color=#FF0000]/*Terrain specific variable setting etc*/[/color]


	/*Bullet specific things*/
	BtOgre::StaticMeshToShapeConverter converter(m_Entity);
	btCollisionShape* colShape = converter.createTrimesh();
	btScalar mass(0);
	btVector3 inertia;

	BtOgre::RigidBodyState *state = new BtOgre::RigidBodyState( m_3DNode );
	this = new btRigidBody(mass, state, colShape, inertia);
	p_Game->m_PhysicsWorld->addRigidBody(this);
}
The problem of course is that C++ doesn't like this. And even if it could I can forsee problems n creating "this = new..."



Incase I can get some better suggestions to the specific problem, what I want to be able to do is cast a ray and return RayCallback.m_CollisionObject which I can then cast as an (Actor*) object to interact with, using a stored enum to decide whether to then cast it to a terrain, building, vehicle, etc.

After all, if I put my CollisionObject* as a variable inside Terrain, the ray will tell me which CollisionObject was hit, but not which terrain, player, ship, vehicle, etc that pointer belongs to.

Is there a better way of achieving this than inheriting the collision object?
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Inheriting btRigidBody

Post by TheKing »

I highly recommend you against inheriting any of your game logic classes from bullet for multiple reasons. A rigid body is a rigid body, a player isn't a rigid body object at all. A player should have a pointer to a rigid body and not be one itself. And if you want to switch physics libary, you'd have to rewrite your terrain, player, etc classes. Bottom line, graphics - physics - gamelogic shpuld always be split - you don't store healthpoints inside your mesh classes, do you?

One way to keep track of which rigid body belongs to which object would be to have a std::map<btRigidBody*, CObject*> in your collision/physics class where you can simply access any object by using a rigid bodys pointer. You'r familiar with maps, aren't you?

As an alternative, you could extend the btRigidBody-class with an int m_ID - variable and a SetID/GetID method. That way, using the collision-flag you can say fur sure which object the rigid body belongs to (e.g. Collision-Flag: VEHICLE, m_ID : 3 -> Rigid body belongs to third vehicle).

Hope this helped!
User avatar
Yann
Posts: 52
Joined: Wed Sep 28, 2011 8:36 am
Location: France

Re: Inheriting btRigidBody

Post by Yann »

TheKing wrote: One way to keep track of which rigid body belongs to which object would be to have a std::map<btRigidBody*, CObject*> in your collision/physics class where you can simply access any object by using a rigid bodys pointer. You'r familiar with maps, aren't you?
That would be my suggestion too
TheKing wrote: As an alternative, you could extend the btRigidBody-class with an int m_ID - variable and a SetID/GetID method. That way, using the collision-flag you can say fur sure which object the rigid body belongs to (e.g. Collision-Flag: VEHICLE, m_ID : 3 -> Rigid body belongs to third vehicle).
You do'nt even have to extend the btRigidBody-class, you can use the collision groups for that (if you dontt already use them for anything else). Just set all of your Terrain in a specific collision group, and when you get a collision, if the collision group is the one you choosed for the terrain, then it is one. Note that by default, Bullet put dynamic objects in group 1 (btBroadphaseProxy::DefaultFilter), and static objects in group 2 (btBroadphaseProxy::StaticFilter).
Trioxin
Posts: 7
Joined: Mon Aug 15, 2011 4:58 am

Re: Inheriting btRigidBody

Post by Trioxin »

Hi guys, thanks for the quick responses!
With regards to using a map, doesn't it potentially slow my program down significantly?
My application needs speed at the expense of good practice, and my previous experience with maps and hashmaps is that they're substantially slower than a cast. (cutting a map out of a random generator and replacing it with an array accessor turned a 53 second program into a 7 second program!)
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Inheriting btRigidBody

Post by TheKing »

Potentially, yes, maps can be kind of slow. Bit unless you have tousands of map-acesses per frame, you will barely even notice any impact on performance. If your world is rather static where rigid bodys are not added and removed regularly, you could simply use arrays, which are faster but harder to use (instead map<btRigidBody,X> its btRigidBody* array = new btRigidBody[Count]), and you need to be confident in the use of new, delete, memcy etc.
User avatar
Yann
Posts: 52
Joined: Wed Sep 28, 2011 8:36 am
Location: France

Re: Inheriting btRigidBody

Post by Yann »

Well, then you still could inherit from the btRigidBody, using default values for the construction, and changing them later using the protected btRigidBody::setupRigidBody method.
I never tried it, but you should give it a try...

Would looks like:

Code: Select all

Terrain::Terrain(Game* p_Game) 
: btRigidBody(/*put default values here...*/)
{/*Terrain specific variable setting etc*/


   /*Bullet specific things*/
   BtOgre::StaticMeshToShapeConverter converter(m_Entity);
   btCollisionShape* colShape = converter.createTrimesh();
   btScalar mass(0);
   btVector3 inertia;

   BtOgre::RigidBodyState *state = new BtOgre::RigidBodyState( m_3DNode );
   btRigidBody::btRigidBodyConstructionInfo constructionInfo(mass, state, colShape, inertia);
  setupRigidBody(constructionInfo);
   p_Game->m_PhysicsWorld->addRigidBody(this);
}
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: Inheriting btRigidBody

Post by Mako_energy02 »

Incase I can get some better suggestions to the specific problem, what I want to be able to do is cast a ray and return RayCallback.m_CollisionObject which I can then cast as an (Actor*) object to interact with, using a stored enum to decide whether to then cast it to a terrain, building, vehicle, etc.

After all, if I put my CollisionObject* as a variable inside Terrain, the ray will tell me which CollisionObject was hit, but not which terrain, player, ship, vehicle, etc that pointer belongs to.
Use the SetUserPointer() function on the collision object. I personally have a struct that stores an enum and a void pointer so I know what it's representing. Slightly hacky as it requires two casts...but it works well without any extra steps. You really, really should never inherit such a complicated class from bullet. Just store pointers.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Inheriting btRigidBody

Post by Flix »

TheKing wrote:I highly recommend you against inheriting any of your game logic classes from bullet for multiple reasons.
Yann wrote: You really, really should never inherit such a complicated class from bullet. Just store pointers.
Well, I just wanted to say that I've always used inheritance in my Bullet integrations without any big problem...
I can agree that there are reasons against it (in favour of composition plus user pointer nesting), but there is some advantage too: you don't need to "wrap" the body physic methods in your class (or you simply write less code if you're not doing it), you can mimic more closely the API used in the Bullet Demos (since your classes are inherited from the Bullet main classes), and you can probably compile against Bullet SVN a bit easily in my opinion (if you used to wrap Bullet methods into your own class using composition), since you inherit the code changes.
Not a big deal, but for lazy programmers like me it makes a difference...

In both cases you can still add some methods that "wrap" inheritance/composition a bit (like some static pseudo-upcast methods that return your main body class from a btCollisionObject in both cases).

Of course I'm not saying anything against the composition approach, I just wanted to say that one is free to choose its own strategy, as long as he knows what he's doing...
For sure if you want to support more than one physic library you'd better stick to compoisition :) .