Jump to content
  • Advertisement
Sign in to follow this  
simotix

Building my physics solution

This topic is 3337 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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);
}

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!