Game Development Community

dev|Pro Game Development Curriculum

Rigid Shape Class

by Thomas \"Man of Ice\" Lund · 04/07/2004 (9:57 am) · 256 comments

Download Code File

History
2005-09-08 Updated with performance fix from XoCluTch

What is this?
For my game I needed a boulder that rolls down a hill, and that one needs to evade. Initial attempts to use the existing classes (items, shapes and especially projectiles) fail because of too simple physics and/or lack of collision box support. I was faced with either implementing collision boxes in the projectile class, look into ODE or try to code my own rigid body class.

Thanks to Ben Garney I didnt have to do any of these (thanks ;-) ), as there already exists rigid physics in the engine. The rigid.cc/h files have everything needed, but they are only available as con/net objects using the vehicle classes.

So I simply took the base vehicle class and the hover vehicle class, merged them together and removed most of the unneeded code. The result is actually fantastic, and I cant believe this isnt standard part of Torque.

As the code basically is a hover vehicle there might be parts of the code that should be removed further. If you spot any of those, then post here and I'll update the codebase.

What does it look like?
No resource without a movie :-)
Here is the final result from a tech demo level in my upcomming action adventure game.

www.codejar.com/rigidshape4.wmv

I also did a few early tests and I've included the movies here. The lack of realism is totally due to way too much impulse applied with a large vertical factor + low mass for the chests.

www.codejar.com/rigidshape.wmv
www.codejar.com/rigidshape2.wmv
www.codejar.com/rigidshape3.wmv

All movies are approx 3 MB

How to add
First thing is to add the 2 attached files in the zip to your engine\game dir and to your project. Then open the shapebase.h and find this

class ShapeBaseConvex : public Convex
{
   typedef Convex Parent;
   friend class ShapeBase;
   friend class Vehicle;

and add

friend class RigidShape;

Also in the same file down the bottom find this

#define StaticShape_GenericShadowLevel 2.0f
#define StaticShape_NoShadowLevel 2.0f

and add

#define RigidShape_GenericShadowLevel 0.7f
#define RigidShape_NoShadowLevel 0.2f

Recompile your engine and thats it.

If you want to do this "for real", then one also needs to define a new objectType. I have reused the ShapeBaseObjectType - change that if you want or go through tons of code and add a RigidShapeObjectType.

How to use
From script you now got access to a RigidShapeData datablock and a RigidShape object type. Your DTS object is required to have a mass node, but nothing else. The code still includes dusttrail and splash emitters from the vehicle code, as well as impact + water sound. This example does not use any of those.

An example datablock for a rigid shape is included below

datablock RigidShapeData( BouncingBoulder )
{	

   category = "RigidShape";
	
   shapeFile = "~/data/shapes/boulder/boulder.dts";
   emap = true;

   // Rigid Body
   mass = 500;
   massCenter = "0 0 0";    // Center of mass for rigid body
   massBox = "0 0 0";         // Size of box used for moment of inertia,
                              // if zero it defaults to object bounding box
   drag = 0.2;                // Drag coefficient
   bodyFriction = 0.2;
   bodyRestitution = 0.1;
   minImpactSpeed = 5;        // Impacts over this invoke the script callback
   softImpactSpeed = 5;       // Play SoftImpact Sound
   hardImpactSpeed = 15;      // Play HardImpact Sound
   integration = 4;           // Physics integration: TickSec/Rate
   collisionTol = 0.1;        // Collision distance tolerance
   contactTol = 0.1;          // Contact velocity tolerance
   
   minRollSpeed = 10;
   
   maxDrag = 0.5;
   minDrag = 0.01;

   triggerDustHeight = 1;
   dustHeight = 10;

   dragForce = 0.05;
   vertFactor = 0.05;

   normalForce = 0.05;
   restorativeForce = 0.05;
   rollForce = 0.05;
   pitchForce = 0.05;
};

By including the category="" it now shows up in the world editor under the Shapes, and its fully working. Spawn the object on a hilltop and see it roll down :-)

For the mission editor to work you will need to add a create() function that hooks into the mission editor. You can either put this into a rigidShape.cs file (dont forget to load it from game.cs) or put it into any .cs file in the server\script

// Hook into the mission editor.

function RigidShapeData::create(%data)
{
   // The mission editor invokes this method when it wants to create
   // an object of the given datablock type.
   %obj = new RigidShape() {
      dataBlock = %data;
   };
   return %obj;
}

If you want to have a little fun pushing things around then add this to your player onCollision:

function Armor::onCollision(%this,%obj,%col)
{

...

if (%col.getDataBlock().getName() $= "BouncingBoulder") {
	 // Apply an impulse to the object we collided with
	 %eye = %obj.getEyeVector();
         %vec = vectorScale(%eye, 10);
	 
        // Add a vertical component to give the item a better arc
	%dot = vectorDot("0 0 1",%eye);
	if (%dot < 0)
		%dot = -%dot;
	%vec = vectorAdd(%vec,vectorScale("0 0 2",1 - %dot));

	// Set the object's position and initial velocity
	%trans = %col.getTransform();
   
   // Heres the position and rotation.
   %pos = getWords(%trans, 0, 2);
	%col.applyImpulse(%pos,%vec);	 
}

...

}

I've done a few tests with forces, masses and such - and as you saw from my movies with varying results.

The objects are fully network aware, and I bet this code can replace ODE for most purposes if you dont need total realism.

As I wrote earlier, the code can be stripped down further. There are various pieces of the physics that I do not understand fully and left in. I would be very happy if someone could run through those parts and see if any of it can be taken out.

Regarding performance, I've tried to add approx 20 shapes to a scene and then letting all collide with each other (its in one of the movies actually). I noticed no performance degradation at all with those simple shapes (they had a 6 sided box as collision mesh.

The boulders in the last movie have an approx 25 faced hedra inside it as a collision mesh. I think I had 15 of those in an scene without performance degradation.

These shapes do have 1 problem though, and that is the collision detection that sometimes fails - exactly as vehicles. If they gain too much speed they will dip into the terrain or go through it. I think a lot of people are looking into that problem at the moment here www.garagegames.com/mg/forums/result.thread.php?qt=17384

Enjoy ;-)
#81
09/08/2005 (12:08 pm)
OK - resource updated with patch from XoCluTch!

Test and report back.

And remember that there is an integration variable that you can tweak too to gain performance
#82
09/11/2005 (11:03 am)
What is the general upper limit to the integration variable? You had said something about a engine crash if it's too high.
#83
09/11/2005 (11:13 am)
Wont compile rigidshape.cc(514) : error C2039: 'vRigidShape' : is not a member of 'RigidShape'
#84
09/23/2005 (11:48 am)
Couple more things:
I added
RigidShape::onRemove(%this,%obj)
{
Parent::onRemove(); // also tried Parent::onRemove(%this,%obj)
}

console says unknown function at this line Parent::onRemove(); so it has no parent ?

Also when I call %obj.delete() while the rock is in flight it crashes the engine at bool RigidShape::updateCollision(F32 dt) it's like the C++ class is trying to update an object that doesn't exist anymore.

Any help?
#85
09/23/2005 (2:48 pm)
You have to define the parent first before it will know what you mean. See below example.

class GuiCursor : public SimObject
{
private:
typedef SimObject Parent;


Regarding the delete, perhaps you are only deleting the client instance? Are you calling delete from within client or server script?
#86
09/23/2005 (3:49 pm)
This is how is is defined:
class RigidShapeData : public ShapeBaseData
{
typedef ShapeBaseData Parent;


and it's a server delete call.
#87
09/23/2005 (5:56 pm)
I don't see a onRemove method in ShapeBaseData
#88
09/24/2005 (5:12 am)
Around line 580

void RigidShape::onRemove()
{
scriptOnRemove();
removeFromScene();
#89
09/25/2005 (1:38 am)
Howard what did you do about this?

Wont compile rigidshape.cc(514) : error C2039: 'vRigidShape' : is not a member of 'RigidShape'
#90
09/25/2005 (2:17 pm)
is there a way to turn the rigid shape into a player? and what did everybody do about the error "vridgedshape is not a member of 'rigid shape'" it sounds like I'm not the only one with a problem. I just commented out the line and it compiled but surely this isn't the best solution.
#91
09/26/2005 (5:43 am)
@Ron, I just went back to the old version till someone figures it out.
@Master if you comment that line out does it still work?
#92
09/26/2005 (8:05 am)
Well I commented it out and it seems to work fine. Next question is I want to see how to get it to respond to a vehicle mounted by a player. The code above that is added to the player's collision doesn't work of course so any ideas?
#93
10/06/2005 (10:38 pm)
Hey I just tried using this with the newest download from CVS. This is what I got.

\Torque\engine\game\rigidShape.cc(122) : error C2065: 'RigidShape_GenericShadowLevel' : undeclared identifier
\Torque\engine\game\rigidShape.cc(123) : error C2065: 'RigidShape_NoShadowLevel' : undeclared identifier
\Torque\engine\game\rigidShape.cc(563) : error C2248: 'Convex::mObject' : cannot access protected member declared in class 'Convex'
../engine\collision\convex.h(161) : see declaration of 'Convex::mObject'
../engine\collision\convex.h(139) : see declaration of 'Convex'
\Torque\engine\game\rigidShape.cc(564) : error C2248: 'ShapeBaseConvex::pShapeBase' : cannot access protected member declared in class 'ShapeBaseConvex'
../engine\game\shapeBase.h(75) : see declaration of 'ShapeBaseConvex::pShapeBase'
../engine\game\shapeBase.h(68) : see declaration of 'ShapeBaseConvex'

Guess I can look into it to see whats up but if someone beats me to it, that would be really nice too heheh.
#94
10/07/2005 (6:43 am)
RigidShape and interior ramps seems to have a bit of a bug. If you have a ramp from one level to another the boulder will get stuck at the top. Make a simple interior with a ramp and place the bolder at the top and push it, rather than rolling down the ramp right away it hangs up at the top for a while till gravity moves it far enough down the ramp then it rolls. I've modified the ramp and floor to be solid, thick, thin, matched surfaces, penetrated and nothing changes. Im sure it has to do with the angle but dont know where in the code it's being affected.
#95
10/16/2005 (11:31 pm)
hmm...how hard would it be to make this work so Vehicles can push them around?Edit: Also, do you just make the mesh like a Vehicles mesh?
#96
10/17/2005 (12:26 am)
Really easy. With the use of apply impulse I was doing it just fine until for some reason the newer update to 1.4 doesn't like RigidShape. If you find a fix for it please let me know. I have several things to do besides this.
#97
10/17/2005 (1:14 am)
hmm can you give me your code? i dont 100% understand how the applyImpulse function works...iv had the function explained to me, but i just cant seem to get it.. iv got it to work alittle...but it doesnt look very good at all, it just seems to fly in a random direction.

function WheeledVehicleData::onCollision(%this,%obj,%col,%vec,%speed)
{
   // Collision with other objects, including items
   if (%col.getDataBlock().category $= "RigidShape")
   {
       %pos = %col.getWorldBoxCenter();
       %col.applyImpulse(%pos,%vec);
   }
}
#98
10/17/2005 (8:50 am)
Try this.

// Apply an impulse to the object we collided with
      %eye = %obj.getEyeVector();
      %vec = vectorScale(%eye, 3000);
    
      // Add a vertical component to give the item a better arc
      %dot = vectorDot("0 0 1",%eye);
      if (%dot < 0)
         %dot = -%dot;
      %vec = vectorAdd(%vec,vectorScale("0 0 2",1 - %dot));

      // Set the objects position and initial velocity
      %trans = %col.getTransform();

      // Heres the position and rotation.
      %pos = getWords(%trans, 0, 2);
      %col.applyImpulse(%pos,%vec);

Change the 3000 to whatever you want it to be. Its obviously pretty high. I was having some fun.
#99
10/20/2005 (7:09 am)
Ignore what I said earlier about it not working. That's what happens when you copy over the shapebase.h file. Yup feeling like an idiot.
#100
10/23/2005 (5:10 pm)
Hello all,

This is a great resource. I have a rigid shape (a chair) in my scene that moves around and whatnot. It