Physics Engines

Started by
10 comments, last by MrRowl 17 years, 10 months ago
Hey guys, I am wanting to implement a physics engine to work with my graphics engine. I know this is a very broad subject and there are infinite ways of doing this, but I just wanted some input on how this is typically done. One of my questions is how do you keep your physics engine separate from your graphics/game engine - like Havoc, etc does it. Does the physics engine work (collisions, positions, rotations, etc.) directly on the game objects or would you feed the physics engine bounded boxes (or whatever shapes), let it do the calculations, and receive the new positions/rotations to use on your objects? Like I said, this is a broad area, but I would like to know how some of you have done this - just to get me started. I have the physics (2 semesters of engineering physics) and math (4 semesters cal) background, but it's the actual implementation and integration I'm lost on. Thanks
---------------------My specs (because I always forget to post them)Intel P4 2.4 GHz640 MB system memoryRadeon 9700 PROWindows XPDirectX 9DirectX 8.1 SDK
Advertisement
I usually create an Entity class of some sort that stores physics relative stuff like velocities, bounding volumes etc...

In my Game engine I would use the Is-A-Rule and derive my game objects from both The render objects in my graphics and the entity object from the physics engine... I know, I know, multiple inheritance is bad... but not if you program to the interface and not implementation... and avoid the diamond of death in c++
I would have game objects inheriting from the physics-engine objects, generally, as most game objects will want to be dealt with directly in the physics engine. (Rockets, players, cars and what have you all have velocities, positions and collision mechanics to deal with.) They would also store the information needed to render themselves via an interface defined in the rendering module. That is:
// **** In physics moduleclass PhysicsObject { Vector Position, Velocity; Model CollisionVolume; abstract void Update(); // physics updates}// Different physics behaviours implemented via inheritanceclass GravityObject : PhysicsObject {  override void Update() { Velocity += new Vector(0, 0, -9.8); }}class Projectile : PhysicsObject { ... }// **** In rendering moduleinterface IRenderable { // probably actually provide methods to add textures, // models etc so the renderer can do things as efficiently // as possible, but for the sake of example void Render(RenderingEngine engine);}// **** In game codeclass Rocket : Projectile, IRenderable { Model model; void Render(RenderingEngine engine){ ... }} // ... etc


If you're using C++, you can store simple model and render code in a Renderable class and use multiple inheritance (shudder :P). The other option is to have a base GameObject class which implements IRenderable but contains a physics object instead of inheriting from it, viz:
class GameObject : IRenderable { void Render(RenderingEngine engine){ ... } PhysicsObject PhysicsObject;}
The advantage to not using inheritance is that the physics library is then free to manage the memory used by the rigid body class. For example, if the game object just contains a rigidBodyID (which could be like a smart-pointer using reference counting) then the physics engine is free to move the memory containing that rigid body data around as it likes. It might do this to make all the rigid bodies be stored in contiguous memory, thus improving cache hits when running the simulation - especially because then the game-data doesn't get in the way. Also, the physics engine is has more control over the deletion of memory - i.e. the game code might ask to free a rigidBodyID, but the implementation might actually wait until the next physics update to actually do it. With inheritance some of these things would be more awkward to implement - in the end the class you inherit from would just be a proxy anyway.

Next time I start from scratch I'll be doing it this way :)
Quote:Original post by MrRowl
The advantage to not using inheritance is that the physics library is then free to manage the memory used by the rigid body class. For example, if the game object just contains a rigidBodyID (which could be like a smart-pointer using reference counting) then the physics engine is free to move the memory containing that rigid body data around as it likes. It might do this to make all the rigid bodies be stored in contiguous memory, thus improving cache hits when running the simulation - especially because then the game-data doesn't get in the way. Also, the physics engine is has more control over the deletion of memory - i.e. the game code might ask to free a rigidBodyID, but the implementation might actually wait until the next physics update to actually do it. With inheritance some of these things would be more awkward to implement - in the end the class you inherit from would just be a proxy anyway.

Next time I start from scratch I'll be doing it this way :)


I agree with this reasoning completely and this is the way I do it. This kind of memory flexibility is especialy important if you ever plan to use your work on consoles since you usualy get an area of fast memory which doesn't tend to be that large, or in the case of PS3 you'll be wanting to do your processing on the SPU's which work on small local storages which you have to DMA to from main memory. In fact my console simulator simply assigns blocks of memory to work with at the start which it then distributes amongst the objects it contains to keep everything in contiguous lists. As objects status' are changed the simulator internally shuffles objects to maintain blocks of objects together which all want to be processed in the same way. This kind of approach makes it very easy to batch copy and tripple buffer groups of objects for processing. It also has the advantage that it lets you do away with on-the-fly memory assignements and deletions. When an object is freed its place is simply filled by moving the last object in the list to its position and adding the deleted objects ID to a pool of free objects for future object additions.
[size="1"] [size="4"]:: SHMUP-DEV ::
Mr. Rowl is spot on the money. I've seen engines that remove certain parts of a rigid body when it comes to rest or "sleep" - such as velocities, torques etc, as they're only required when the body is active. Great for memory lean systems, such as handhelds.
I agree with the basic idea, with exception of the point keeping bodies in a linear array just to have a more cache friendly memory layout. Do you think (or actually profiled) that the advantage of having you rigid bodies in a continuous block outweights the cost of copying your data around all the time in order to maintain this block? This might be correct in a scenario where you have a fixed number of bodies for the whole level, but I am not sure if this holds true when you are creating and destroying bodies very frequently.



-Dirk
Fixed sized memory allocators are pretty common to reduce cache issues.

PS2 was very notorious for memory fragmentation.

Quite commonly you'd employ the idea of maybe memory batches, where you'd for each level of your game, you'd allocate another batch ready for that level, and when finished it'd clean it up. A level being a menu, the global information, the game level itself.

Another common one is having a temporary memory block available for a few frames b4 destroyed.

Or having memory banks for different purposes, like a memory bank for graphics, another for AI.

This is all to avoid memory fragmentation, and hence why having a contingous array for memory can be useful.

In terms of cache misses, its a hit and miss affair and best done with profilers and looking at the memory structure of the app, to see if you can get your structure to align on the correct boundaries, and if you can shuffle variables around etc.
Thanks for all of the replies everyone.

So, for each object (lets say I just have crates and balls at the moment), I could send a bounding box/sphere to the physics engine which would keep track of and re-position each bounding box/sphere. Then the object itself would fetch its new position from the physics engine. Am I on the right track here?
---------------------My specs (because I always forget to post them)Intel P4 2.4 GHz640 MB system memoryRadeon 9700 PROWindows XPDirectX 9DirectX 8.1 SDK
I don't like the idea of using inheritance to define different behaviour at all, partly because I don't really like multiple inheritance, but mainly because it's inflexible any way you look at it. For every combination of physics and rendering behaviour(which are 2 completely distinct operations), I must derive a new class. And that's not all, because I could also have other types of behaviours, like AI and whatnot. And let's not mention that it's impossible to change the behaviour of an object at run-time.

In my game, I make a distinct difference between Objects and Handlers. Basically, think the difference between MFC and .NET. In MFC, they had virtual functions like OnClick() that would be overriden to define new behaviour. In .NET, they have Event Handlers that are treated like object properties. Objects are responsible to encapsulate their data, and some standard internal operations. Custom behaviour is implemented throught Handlers that operate on Objects. A Physics Handler moves the object, a Render Handler renders it, a Control Handler makes the control decisions(through AI,through keyboard input...).

class Handler{	virtual void Handle(Object *obj)=0;};class Mover:public Handler{};class Renderer:public Handler{};class GravityMover:public Mover{	virtual void Handle(Object *obj)	{		//Move object with gravity...	}};class UnderwaterMover:public Mover{	virtual void Handle(Object *obj)	{	//Move object when it's under water...	}};class PerVertexLightingRenderer:public Renderer{	virtual void Handle(Object *obj)	{	//Render object with per-vertex lighting	}};class PerPixelLightingRenderer:public Renderer{	virtual void Handle(Object *obj)	{	//Render object with per-pixel lighting	}};class Object{public:	Vec3 position,velocity;	Vec3* VertexData;	Renderer *renderer;	Mover *mover;        bool underwater;public:	Object()	{		renderer=NULL;		mover=NULL;                underwater=false;	}	virtual void Move()	{			if ((position.y<0)&&(!underwater))//Is it underwater?		{                        underwater=true;			delete mover;			mover=new UnderwaterMover();//BAM!Change physics 		}		if (mover) mover->Handle(this);	}	virtual void Render()	{		if (renderer) renderer->Handle(this);	}};//mainObject rock;rock.renderer=new PerPixelLightRenderer();rock.mover=new GravityMover();


[Edited by - mikeman on June 1, 2006 2:29:58 PM]

This topic is closed to new replies.

Advertisement