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 ;-)
#121
02/23/2006 (5:16 am)
@Everyone - yeah. The latest patch of the resource has an extra/unused/uneeded vRigidShape. I'll remove that later if I update this again.

@Drexel uni - its most likely a matter of your collision mesh. Remember that this resource uses the underlying collision mesh to test the actual movement of the shape.

So if the shape doesnt have enough momentum to flip onto the next poly in the mesh, they will sway back.
#122
03/22/2006 (4:13 am)
Thats more realistic for Body2Body collision:

function RigidShapeData::onCollision(%data, %obj, %col, %vec, %speed)
{
if (%col.getDataBlock().getName() $= "RigidShapeBoulder") {
echo(%obj@"/"@%col@" "@%speed);
%col.applyImpulse(getWords(%col.getTransform(), 0, 2),vectorScale(vectorNormalize(VectorSub(getWords(%col.getTransform(), 0, 2),getWords(%obj.getTransform(), 0, 2))), %speed/2));
}
}
#123
04/18/2006 (12:55 pm)
I have try this with TLK 1.4, I got this error

rigidShape.cc(514) : error C2039: 'vRigidShape' : is not a member of 'RigidShape'
../engine\game/rigidShape.h(131) : see declaration of 'RigidShape'
Error executing cl.exe.
#124
04/18/2006 (2:20 pm)
I fix the error problem. Everything look good but when add the lines to player on::collision, I cannot push the boulder. It will roll down hill find.
#125
04/19/2006 (10:01 pm)
Michael did you add it as a Static Shape by accident? It must be from the Shapes categorey
#126
04/20/2006 (3:55 am)
Most likely your forces are not powerful enough. Try to up the amount of force you are using when trying to push it
#127
04/20/2006 (6:14 am)
you talking about the player force,what cs file would this be.
#128
04/20/2006 (8:07 am)
I got to work, I guess I should read more. I saw where if you shoot the boulder with a weapon it will react. I have try this and nothing happen, do you need to add something to the code or change something. It work great with TLK 1.4. Thanks for code and help.
#129
04/20/2006 (11:18 am)
Does minRollSpeed in the datablock have any affect on the RigidShape?
#130
04/27/2006 (7:01 am)
OK, afterr many trials and tribulations, I got it to work. Now, I may need something else, but what I am doing for our prototype game is soccer essentially. How can I stop the "ball" from hopping around. See video here.

http://www.minimax.net/ckampf/downloads/Videos/GFS-Demo0001.avi
(Divx Format)

I have reduced the speed, and it helps, but I need that. I changed the integration value up to 1000 and that didn't help much.

Any help would be greatly appreciated.
#131
04/29/2006 (11:55 am)
"Michael Prewer (Apr 18, 2006 at 22:20)
I fix the error problem. Everything look good but when add the lines to player on::collision, I cannot push the boulder. It will roll down hill find."

Hi

I am having the same problem and am new to Torque. It would be very helpful if you mentioned how you fixed the problem so others don't have to post the same quiestion again. So how did you do it?

Thanks
#132
04/29/2006 (12:05 pm)
I also have another question. If I use a shape like the crossbow or lantern as a rigid shape Torque crashes. It's looks as though it doesn't handle complex objects very well.

How could I fix this?

Thanks
#133
04/29/2006 (12:30 pm)
You are not allowed to use convex (or is it concave - can never remember) collision meshes. Thats 99% your problem
#134
04/29/2006 (12:32 pm)
Damn. Is there any other way to have a rigid body on a convex or concave shape then?
#135
04/29/2006 (12:38 pm)
Nope - the collision mesh always has to be convex. But the mesh for the actual shape can be anything.

So make your crosbow as always, and create a simple rectangle collision mesh - unless you need ultra realistic collision, then you should be able to create something that is usable
#136
04/29/2006 (1:46 pm)
In the datablock RigidShapeData( BouncingBoulder ) go down to the seven line.
Decrease the mass from 500 to 100 (you can play around with this ), the lower you go the easier it is to push the rigidshape.
In the function Armor::onCollision(%this,%obj,%col) for the player the code you put in there, go down to the fourth line decrease force of the impulse by changing %vec = vectorScale(%eye, 10); to 100 or so.
Now you should be able to push the rigidshape. Becarefull when changing these numbers you will get very unrealize looks.
I am play around datablock right now to see what I can get.

For the compile error. Open rigidShape.cc, go down line 514 this->vRigidShape = true; and comment it out . like this
// this->vRigidShape = true;
I m not if this is correct but fix the compile error and it work good.
#137
04/29/2006 (2:19 pm)
Thanks Thomas

Yeah, thats wht I did Michael. But I wasn't sure if it referenced something higher up.
#138
04/29/2006 (2:34 pm)
Thomas you mentioned I can just have a normal collison mesh and it should work. How certain are you about this because I tried to add the ammo object it it still crashed, and that it just a plain square bounding box.
#139
04/29/2006 (2:43 pm)
might as well link to this lan about convex and concave shapes.
http://www.garagegames.com/blogs/985/10361
#140
04/29/2006 (6:09 pm)
Ok, I now know about convex etc. The ammo and crossbow bounding boxes look fine so I don't see why they shouldn't work. The ammo actually loads and then I get the 'Don't Send' crash. Any ideas?