I set up my framework with a generic IPhysicsManager, IPhysicsWorld and IPhysicsObject interface. I then created interfaces for each of the physics libraires that I wanted to test. this allowed me to create game objects that have physics attached, but the gaem objects do not know what physics library is being used. I have working libraries for Newton, Newton2, Physx, and ODE. I actuall recommend this style for everyone, because it allows me to change the physics engine at will, without changing the game itself.
example for gaem object
Code: Select all
class IrrObjectBox : public IrrObject
{
virtual void CreatePhysicsObject()
{
IRR_LOG(L"IrrObject_Box::CreatePhysicsObject()");
// make sure the object is available
DestroyPhysicsObject();
// make sure the node is valid
IRR_CHECK(m_Node,L"-- no node to create physics object from");
// create a physics object to represent this node
IPhysicsObjectData data;
data.type = POT_PRIMITIVE_BOX;
data.position = GetPosition();
data.rotation = GetRotation();
data.scale = GetScale()*2;
data.mass = GetMass();
data.gravity = true;
data.bboffset = GetBBOffset();
data.frozen = GetFrozen();
data.userdata = GetID();
m_PhysicsObject = GetLevel()->GetPhysicsWorld()->CreatePhysicsObject(data);
}
}
updating the node each frame requries a call to the physicsobject
Code: Select all
void IrrObject::Frame(float elapsedtime)
{
IrrObjectMessage msg;
if (next_state != state)
{
if (force_state_change)
{
msg.Create(MSG_RESERVED_Exit,0,0,0,0,0,stringw(L""));
ProcessStateMachine(&msg);
state = next_state;
next_state = state;
force_state_change = false;
msg.Create(MSG_RESERVED_Enter,0,0,0,0,0,stringw(L""));
ProcessStateMachine(&msg);
}
}
// match the nodes to the physics object position and rotation each frame
if (m_PhysicsObject)
{
SetNodePosition(m_PhysicsObject->GetPosition());
SetNodeRotation(m_PhysicsObject->GetRotation());
}
if (GetDebug()) DrawPhysicsBoundingBox();
msg.Create(MSG_RESERVED_Update,0,0,0,0,0,stringw(L""));
ProcessStateMachine(&msg);
}
the calls tot he physics object are handled behind the scenes, so that this call
Code: Select all
SetNodePosition(m_PhysicsObject->GetPosition());
SetNodeRotation(m_PhysicsObject->GetRotation());
is handlded internally by the IPhysicsObject_Newton2 class
Code: Select all
vector3df CPhysicsObject_Newton2::GetPosition()
{
if(!m_NewtonBody) return vector3df(0,0,0);
core::matrix4 temp_mat;
NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
core::vector3df pos=temp_mat.getTranslation()*NewtonToIrr;
return pos;
}
vector3df CPhysicsObject_Newton2::GetRotation()
{
if(!m_NewtonBody) return vector3df(0,0,0);
core::matrix4 temp_mat;
NewtonBodyGetMatrix(m_NewtonBody,GetMatrixPointer(temp_mat));
return temp_mat.getRotationDegrees();
}
Newton2 comes with a spendid set of tutorials. Also, Irrnewt is a phenomenol teaching tool. Take a look at Irrnewt to see how they did it in there. Most of the techniques are the same for Newton2.
generically speaking, for Newton2 you do this.
create the world
Code: Select all
// create the newton world
m_NewtonWorld = NewtonCreate (NULL,NULL);
create physics objects and add to the world
Code: Select all
IPhysicsObject* CPhysicsWorld_Newton2::CreatePhysicsObject(IPhysicsObjectData data)
{
NewtonCollision* collision = CreateCollision(data);
if (collision)
{
CPhysicsObject_Newton2* obj = new CPhysicsObject_Newton2(this);
obj->m_NewtonBody = NewtonCreateBody(m_NewtonWorld,collision);
NewtonBodySetUserData(obj->m_NewtonBody,obj);
NewtonBodySetForceAndTorqueCallback(obj->m_NewtonBody,defBodyForceAndTorqueCallback);
if(data.gravity) obj->AddContinuousForce(m_WorldData.gravity);
obj->SetMass(data.mass);
obj->SetPosition(data.position);
obj->SetRotation(data.rotation);
obj->SetLinearDamping(data.linearDamping);
obj->SetAngularDamping(data.angularDamping);
obj->SetFreeze(data.frozen);
obj->SetUserdata(data.userdata);
return obj;
}
return NULL;
}
NewtonCollision* CPhysicsWorld_Newton2::CreateCollision(IPhysicsObjectData data)
{
switch (data.type)
{
case POT_AUTO_DETECT : { } break;
case POT_PRIMITIVE_SPHERE : { return CreateCollision_Sphere(data); } break;
case POT_PRIMITIVE_BOX : { return CreateCollision_Cube(data); } break;
case POT_PRIMITIVE_CONE : { return CreateCollision_Cone(data); } break;
case POT_PRIMITIVE_CAPSULE : { return CreateCollision_Capsule(data); } break;
case POT_PRIMITIVE_CYLINDER : { return CreateCollision_Cylinder(data); } break;
case POT_PRIMITIVE_CHAMFERCYLINDER : { return CreateCollision_ChamferCylinder(data); } break;
case POT_CONVEXHULL : { return CreateCollision_ConvexHull(data); } break;
case POT_TREE : { return CreateCollision_Tree(data); } break;
}
return NULL;
}
Code: Select all
NewtonCollision* CPhysicsWorld_Newton2::CreateCollision_Sphere(IPhysicsObjectData data)
{
return NewtonCreateSphere(m_NewtonWorld, data.scale.X*IrrToNewton, data.scale.Y*IrrToNewton,data.scale.Z*IrrToNewton,0,0);
}
NewtonCollision* CPhysicsWorld_Newton2::CreateCollision_Cube(IPhysicsObjectData data)
{
data.scale += data.bboffset;
return NewtonCreateBox (m_NewtonWorld, data.scale.X*IrrToNewton, data.scale.Y*IrrToNewton,data.scale.Z*IrrToNewton,0,0);
}
NewtonCollision* CPhysicsWorld_Newton2::CreateCollision_Cone(IPhysicsObjectData data)
{
return NewtonCreateCone(m_NewtonWorld, data.scale.X*IrrToNewton, data.scale.Y*IrrToNewton,0,0);
}
and then update the world each frame
Code: Select all
void CPhysicsWorld_Newton2::Update(float elapsedtime)
{
if (m_NewtonWorld) NewtonUpdate (m_NewtonWorld, elapsedtime);
}