Building my physics solution

Started by
5 comments, last by bzroom 14 years, 5 months ago
I am trying to build me physics portion of my engine and I am stuck at deciding how I should solve a problem. Basically, my physics manager will hold an array of physics nodes (CPhysicsBase, or CRigidBody), then check for collision and return either NO_COLISSION, COLLISION or RESTING_CONTACT. However, it is not necessary for plain physics node to deal with RESTING_CONTACT, just typically a RigidBody node for applying friction. My question is, what is the best way to deal with the RESTING_CONTACT state? I could make an enum for the CPhysicsBase and CRigidBody, then make sure it is a RigidBody then just type cast it like

	case RESTING_CONTACT:
		/* Handle the resting contact */
		if(vPhysicsNodes[0]->GetCollisionType == RIGID_BODY)
		((CRigidBody *)vPhysicsNodes[0])->ApplyFriction(elapsedTime);

		break;

However, that just seems like a poorly hacked version. Or should I just drop the regular CPhysicsBase and just always use a CRigidBody so I do not have to worry about this? Idealy, I would like to be able to use a CPhysicsBase because it would hold less variables, functions and sometimes I do not need a RigidBody solution for the physics nodes (such as a typically wall that does not move). Here is a code example of my setup

#include <d3dx9.h>
#include <vector>
using std::vector;

typedef enum COLLISION_STATE{ NO_COLLISION ,COLLISION, RESTING_CONTACT };

class CCollisionSphere;
class CCollisionPlane;

class CCollisionBase
{
public:
	virtual COLLISION_STATE CheckCollision(CCollisionBase *pCollisionBase) = 0;
	virtual COLLISION_STATE DoCheckCollision(CCollisionPlane *pPlane) = 0;
	virtual COLLISION_STATE DoCheckCollision(CCollisionSphere *pSphere) = 0;
};

class CCollisionSphere : public CCollisionBase
{
public:
	COLLISION_STATE CheckCollision(CCollisionBase *pCollisionBase) { return pCollisionBase->DoCheckCollision(this); }
	COLLISION_STATE DoCheckCollision(CCollisionPlane *pPlane) { return NO_COLLISION; }
	COLLISION_STATE DoCheckCollision(CCollisionSphere *pSphere) { return NO_COLLISION; }
};

class CCollisionPlane : public CCollisionBase
{
public:
	COLLISION_STATE CheckCollision(CCollisionBase *pCollisionBase) { return pCollisionBase->DoCheckCollision(this); }
	COLLISION_STATE DoCheckCollision(CCollisionPlane *pPlane) { return NO_COLLISION; }
	COLLISION_STATE DoCheckCollision(CCollisionSphere *pSphere) { return NO_COLLISION; }
};

class CPhysicsBase
{
protected:
	CCollisionBase *m_pCollisionBounds;
public:
	CPhysicsBase(CCollisionBase *pCollisionBounds)
	{
		m_pCollisionBounds = pCollisionBounds;
	}

	CCollisionBase *GetCollisionBounds() { return m_pCollisionBounds; }
};

class CRigidBody : public CPhysicsBase
{
public:
	CRigidBody(CCollisionBase *pCollisionBounds) : CPhysicsBase(pCollisionBounds) { }
};


int main()
{
	vector<CPhysicsBase *> vPhysicsNodes;

	CCollisionBase *pCollisionSphere = new CCollisionSphere();
	CCollisionBase *pCollisionPlane = new CCollisionPlane();

	CRigidBody *pRigidBodySphere = new CRigidBody(pCollisionSphere);
	CRigidBody *pRigidBodyPlane = new CRigidBody(pCollisionPlane);

	vPhysicsNodes.push_back(pRigidBodySphere);
	vPhysicsNodes.push_back(pRigidBodyPlane);

	COLLISION_STATE collisionReponse = vPhysicsNodes[0]->GetCollisionBounds()->CheckCollision(vPhysicsNodes[1]->GetCollisionBounds());

	switch(check)
	{
	case NO_COLLISION:
		/* Compute Linear Velocity for vPhysicsNodes[0]*/

		break;
		
	case COLLISION:
		/* Handles the collision contact */

		break;

	case RESTING_CONTACT:
		/* Handle the resting contact */

		break;
	}


	return(0);
}

Advertisement
Does anyone have any opinions?
Quote:Original post by simotix
Does anyone have any opinions?
Any particular reason why you aren't reusing an existing physics solution?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by swiftcoder
Quote:Original post by simotix
Does anyone have any opinions?
Any particular reason why you aren't reusing an existing physics solution?



I was hoping to implement it my self for the sake of learning.
I would use the base, and only store the base in the list. Then, call the apply friction function for every base object who is set to resting. Then, dont set any walls to resting :)

void Physics::Update(float dt){  foreach (PhysBase p in objects)  {    switch (p->ContactState())    {      case Resting:        p->UpdatingRestingContactStuffSuch            AsApplyFrictionIfThatsTheSortOfThingYoureInto();      break;    }  }}


Incase a wall does get set to a resting state, the update resting function will not be derived for a static object and essentially a no op.

You may not be interested in all this virtual call overhead. You could store the objects in different lists by type, and then use a templated update function to update each type of object.

Note: I would have probably chose to put this switch statement inside the object itself, and let the derived type determine which cases are relevant and how to handle them.

My physics loops usually look like this:
void Physics::Update(float dt){  foreach (PhysBase p in objects)    p->PreStep();  foreach (PhysBase p in objects)    p->CollisionAndResolution();  foreach (PhysBase p in objects)    p->Integration();  foreach (PhysBase p in objects)    p->PostStep();}


Or something along those lines. I would do the resting contact stuff in PreStep of the RigidBody type, but PreStep for a StaticBody type may be blank, and entirely different for a ChacterBody or VehicleBody type.
Quote:Original post by bzroom
I would use the base, and only store the base in the list. Then, call the apply friction function for every base object who is set to resting. Then, dont set any walls to resting :)

void Physics::Update(float dt){  foreach (PhysBase p in objects)  {    switch (p->ContactState())    {      case Resting:        p->UpdatingRestingContactStuffSuch            AsApplyFrictionIfThatsTheSortOfThingYoureInto();      break;    }  }}



I really like this idea, sure there is a bit of virtual overhead though. I may also have to deal with a bit of double dispatching also. Do you happen to remember where you learned this idea?
No where in particular. Just lots of experimentation.

This topic is closed to new replies.

Advertisement