Game Development Community

Wheeled Vehicle Moment of Inertia from Bounding Box

by David Wyand · in Torque Game Engine · 11/04/2002 (2:53 pm) · 13 replies

Greetings!

I've recently begun working with wheeled vehicles in the TGE, and have come across something I need an opinion on.

I've been having some troubles with my vehicles becoming unstable while travelling in a straight line at high speeds on perfectly flat terrain -- they starting bouncing on their own at an increasing rate until everything falls apart. I've modeled my LightWave car such that the origin is well below the body, which I believe defines the centre of mass.

The car itself is functioning as expected, other than the simulation failing over time. So, I moved onto comparing my LightWave built car with the racing mod buggy, and everything seems to be fine, except for the bounding box.

The reason, IMHO, that the bounding box is important is that the moment of inertia for the wheeled vehicle appears to be based on it. Within the WheeledVehicle::onNewDataBlock() function in wheeledVehicle.cc, the following exists:

// Set inertial tensor, default for the vehicle is sphere
mRigid.setObjectInertia(mObjBox.max - mObjBox.min);

And as far as I can discern, mObjBox is the object's bounding box.

Now, in the LightWave DTS exporter (as well as the Milkshape one, and any future ones that use the DTS SDK), the bounding box is defined as the smallest box that fits around the geometry. And with the moment of inertia being calculated based on this, its position would be quite high in the air (compared to the centre of mass).

Now, within 3DS Max, I understand that the bounding box in manually created (by putting an actual box around the object). This allows the modeler to extend the bounding box well below the vehicle and effectively move the moment of inertia lower. In the case of the racing mod buggy, it appears that the bounding box extends well below the ground when the buggy is viewed in-game.

To test my theory, I forced my LightWave vehicle to have the same bounding box dimensions as the racing buggy. With this code change (I forced it within the TGE), my own vehicle now behaves as expected and doesn't bounce away. Yay!

So, here's the issue. Originally I thought that the only thing to watch out for in a wheeled vehicle was where the origin was compared to the geometry. Based on my research, there is the added complexity of the bounding box. Based on this, there is the possibility that all LightWave, Milkshape, and DTS SDK wheeled vehicles will be unstable.

Now, I can change the LightWave DTS exporter to allow the option of a manually defined bounding box. I believe that this would get around the problem. However, is this the way we want the Torque Engine to work?

Here's the options I can think of:

1. Change the LightWave exporter, Milkshape exporter and DTS SDK to allow for manual bounding box definition.

2. Modify the moment of inertia calculation to be based on something other than the bounding box such as the centre of mass (or a named node).

So what do you think? Tim Gift, any thoughts? Or am I just bonkers?

- LightWave Dave

About the author

A long time Associate of the GarageGames' community. I run www.zworldo.com a free-to-play, browser based games site using Torque 3D technology.

Recent Threads


#1
11/04/2002 (8:52 pm)
Greetings!

After thinking about this for a bit (it's amazing what you think about in the shower), I've realized that the formula

mRigid.setObjectInertia(mObjBox.max - mObjBox.min);

actually uses the absolute size of the bounding box, rather than its volume around a position. In other words, it is the bounding box centred around the origin (hence the requirement to model a wheeled vehicle with the origin as the centre of mass).

What this means is that it didn't really matter at all that the bounding box extended well below the ground for the racing buggy. Just that the bounding box was of a sufficient size to provide stability for the moment of inertia.

In the end, though, we're still left with the problem of the reliance on the bounding box. One possible solution I've come up with is to make use of a bounds variable just like the Player class does. This way, the bounding box for the wheeled vehicle could be defined in script.

I'll see about making the appropriate changes and trying this out tomorrow. And I'm still considering the posibilities of allowing the user to optionally define the bounding box within the LightWave DTS exporter.

- LightWave Dave
#2
11/05/2002 (8:32 am)
I think you hit the best solution, allowing a single script variable to be defined and used as the absolute. That removes that max - min calculation also.

Simplifing code is almost always the best solution.
#3
11/05/2002 (9:00 am)
Greetings!

Well, that's actually what I've now done. And it appears to work great. So far, I've chosen to keep some backwards compatibility, so there is more code than a pure solution.

Here's what to do, for those that are interested:

In wheeledVehicle.h, within the struct WheeledVehicleData, add the following (I put it after int integration;):

Point3F moiSize; // Moment of inertia Width, depth, heigth

Now, in wheeledVehicle.cc, add the following to the WheeledVehicleData constructor (WheeledVehicleData::WheeledVehicleData() for those that don't know):

moiSize.x = -1.0;
moiSize.y = -1.0;
moiSize.z = -1.0;

I placed it after brakeLightSequence = -1;

Next, add this to the bottom of the WheeledVehicleData::initPersistFields() function:

addField("moiSize", TypePoint3F, Offset(moiSize, WheeledVehicleData));

Finally, within WheeledVehicle::onNewDataBlock(), replace:

mRigid.setObjectInertia(mObjBox.max - mObjBox.min);

with:

Con::errorf("Setting inertial tensor...");
   if (mDataBlock->moiSize.x > 0.0 && mDataBlock->moiSize.y > 0.0 && mDataBlock->moiSize.z > 0.0)
   {
      Con::errorf("moiSize (datablock) point (%f, %f, %f)",mDataBlock->moiSize.x,mDataBlock->moiSize.y,mDataBlock->moiSize.z);
      mRigid.setObjectInertia(mDataBlock->moiSize);
   } else
   {
	  Point3F temppnt = mObjBox.max - mObjBox.min;
      Con::errorf("Shape bounding box size (%f, %f, %f)",temppnt.x,temppnt.y,temppnt.z);
      mRigid.setObjectInertia(mObjBox.max - mObjBox.min);
   }

Note that the Con::errorf() calls are purely optional, as is the temppnt definition.

That's it for the code changes. Now, to make use of this new code, you'll need to add a variable definition to your scripted car datablock.

Find your datablock WheeledVehicleData() definition in your script (I defined mine in car.cs). Somewhere in there, add:

moiSize = "4.56 7.645329 4.196888";

I placed this line at the end of the rigid body definitions. Of course, you should change your numbers as appropriate. These are what the racing buggy uses, so I found them to be a good default.

Well, that should be it. Hope that helps someone out, and it would still be great to hear an official word on all this.

Enjoy!

- LightWave Dave
#4
11/05/2002 (6:48 pm)
Hey David, this is awesome ! My brother is the best I know that can play with car setups (sim and life) and that can tell you what is needed in a game to make it like real. He just tryed it (briefly cause he is a bit busy) with your new addition and he has now a big smile on his face. He was asking me for something like this (and other things) since long. Note that the front wheel and rear wheel are separated on the setups we just tryed and it's working pefectly.

Thanks much for this great ressources ! Take another shower like this anytime ! :)
#5
11/05/2002 (8:17 pm)
Greetings!

I'm glad that it helped you out. And it's good to hear that my directions could be followed and actually worked! :o)

I think I'll go ahead and post this as an actual resource, and point it out to Tim Gift to see if we can get this into the TGE Head. All assuming that there isn't a better solution, of course.

- LightWave Dave
#6
11/06/2002 (12:49 pm)
David,

After lot of testing, I've found that this is making the game lag, and even more during multiplayer sessions (even more on the client side). It's really annoying. I tryed removing all the other things that was sending request to server to see if I could find a way to keep this great code because we like it bad, but with the lag, it's not fun :( I then tryed removing it and everythings get back to normal. What is weird is that the FPS stay the same ?!?

My system is :
Pentium 4 1.6Mhz
768 megs Ram
ATI Radeon 32Megs DDR

My bro's system
AMD 1.33 MHz
256 Megs DDR
Asus Gforce2 64megs (can't remember the # but it's better then my Radeon in everything we try)

Both of these systems react the same with the inertie code. Do you have an idea what could cause that ?

Thanks
#7
11/07/2002 (7:07 am)
Greetings!

Well, I can't think of why you'd be getting any lag at all. All the code does is allow you to manually set the bounding box size, which only occurs when the vehicle is first created. It then never runs again.

My only thought is if the size of the bounding box you are defining is rather large for some calculation. Have you tried using the numbers I gave in my example above (which are the same as the racing buggy)?

During my testing, I didn't encounter any unusual lag, but I have yet to try it in multiplayer. If you're curious, my machine is:

Pentium III 667MHz
768 MB RAM
Asus Gefore 2 GTS (32 MB)

I'll see about trying this out with a friend to make sure that there isn't a problem with multiplayer.

- LightWave Dave
#8
11/07/2002 (8:02 am)
David,

Your completly right !

During the last night, I dreamed-thinked of it (some are doing this in shower, some in bed, hehe) and I wanted to clear this out this morning because like you said, it hasn't any sense that the prob was with your code. I was just testing this right now :

Because the FPS was the same, it was clear that the problem was with the car and not math's CPU or graphics probs. So I just did a test with my own car and TADA, no lags ! Yipee ! Seems that the buggy is "buggy" :) Yes I was using your numbers, but with a car setup really fast and drivable. The way the buggy is made (mass, etc) it can't take our setup. For it to take it, I only had to change the mass gravity center, like my own cars :)

So, I'm really sorry to have made you scratch your head and lose time with testing because of me. I feel really cheap not to have figured this before :(

Again, thanks really much for this great ressource. Definitly could make it to the CVS.

Gilles Jr.
#9
11/07/2002 (8:38 am)
Greetings!

No problem at all. I'm glad you were able to work everything out.

- LightWave Dave
#10
11/16/2002 (10:16 am)
Greetings!

Well, I've finally been able to try out my code changes in a multiplayer/dedicated server environment. And you know what? Gilles was right!

Symptom: When driving a vehicle and you are not playing on the server machine, the screen jerks around when you turn. It looks like you're getting a lot of lag (even on a dedicated LAN connection).

Actual Problem: There is movement prediction code on the client that attempts to match up your vehicle with the server. Its purpose is to smooth out your display between server updates to your client, and prevent your player from popping around the screen (especially when not moving in a straight line). For this to work, the client and server must have the same information about the player's (in this case, vehicle's) movement parameters. And there's the catch.

Silly me, I wasn't sending the moiSize variable information from the server to the client. This means that when the client uses the moiSize value to predict how the vehicle moves, it is basing this prediction on the wrong value. Hence, when a server update arrives, the client must correct the vehicle's motion and pop it into position. The result: your screen jumps around and it is nearly impossible to navigate, especially at high speeds.

The Solution: Fortunately, the solution is quite simple. All it takes is a few lines of code to transmit the moiSize from the server to the client.

In wheeledVehicle.cc, add the following to the end of the WheeledVehicleData::packData() function:

stream->write(moiSize.x);
stream->write(moiSize.y);
stream->write(moiSize.z);

And, add the following to the bottom of WheeledVehicleData::unpackData():

stream->read(&moiSize.x);
stream->read(&moiSize.y);
stream->read(&moiSize.z);

That should be everything. I've tested this out with a dedicated server and two clients, and the wheeled vehicle now turns smoothly.

- LightWave Dave
#11
11/16/2002 (11:08 am)
You took another shower ?!? hehe This is working nice in multi now. Wouhou ! You're genious.

As a sad note, I noticed that our "bad invisible bump" seems to have come back now ?!? Really weird because they where almost all gone with your code(the first part). But I suspect it is maybe a problem with our setup that we've worked on before this new addition as we where trying hardly to get rid of the lags :). I will try to get my brother to play with the setups to see if we can have both "lag" and "invisible bumps" gone. But you seems to have tested it roughly so I think you'd have noticed it too so it's probably our setups and that is a really good news. We played a lot with the collision and the bounds too in our models to get rid of the lags, so the problem is maybe there too. Maybe re-working the models the old way will fix this. We'll do testing and get back here to update what we've found. Probably a couples of days of testing again :)

Nice work, thanks really much again. Really appreciate

Gilles Jr
#12
11/16/2002 (2:23 pm)
Greetings!

Heh. Yup, a shower once a week -- whether I need it or not :o)

I actually came to this solution while I was scrambling to get a demo ready to try with a friend over the Internet. Without the above changes, my single-player vehicles were uncontrollable in multiplayer.

Now, as for your "invisible bumps", I had even come across those in single player, and even prior to any of my moiSize changes above. I seem to have solved it with a combination of changing the centre of gravity, the spring length and strength of the shocks, and lengthening and widening the wheel-base. It really came down to a lot of trial and error.

With all of the possible variables involved, it seems that with any new vehicle design, it takes a bit of playing around to get everything working just right. Which, I suppose, is quite similar to what would happen in real life :o)

- LightWave Dave
#13
11/17/2002 (1:03 pm)
Hehe yup, after working out our vehicles in torque, we could almost become vehicles engineers :)

Well, I reworked all my vehicles and all is working perfect. I had done a lot of modif to get rid of the lags and I had really weird collisions, etc ... for that purpose. With your fix, I now came back to normal modeling and settings. And bro didn't even touch the setups.

So ... Yipeee ! hehe

Thanks very much!

Gilles Jr