Simple Physics Engine |  |

For latest version, please visit: http://spehome.com/document.php

What's new in SPE SDK 3.00
- New interface ISPEPhysicsState and ISPEConstraint and ISPEContact to access the new solver and building custom joints.
- New APIs for Physics Filter in ISPERigidBody and ISPEWorld.
- New Individual APIs for detect collisions for characters etc. in ISPEWorld.
- ISPEShape::SetMassCenter() avaible now to move the center of mass after shape been initialized.
- Old ISPERigidBody::SetPosition()/SetOrientation() changed to SetPositionMesh()/SetOrientationMesh() which are refer to mesh frame, and current SetPosition()/SetOrientation() are refer to the center of mass(body frame). Set/GetTransform() also changed to Set/GetTransformMesh().
- Remove the functions use single float as parameters like SetPosition(float x, float y, float z) in ISPERigidBody and ISPEParticle.
- New APIs to access the sleep status of rigid body: SetSleeping(), GetSleeping(), SetSleepFactor(), GetSleepFactor().
- New APIs to set or get AngularDamping of rigid body: Set/GetAngularDamping().
- New APIs to filter collision for a single rigid body: AddCollisionException()/BeInCollisionException()/DeleteCollisionException, and Set/GetGroupId() for group filter.
- Functions for Point and Vector transfer: BodyPoint()/WorldPoint()/BodyVector()/WorldVector() moved to ISPEPhysicsState form ISPERigidBody.
- ISPERigidBody::AddWorldImpulse()/AddBodyTorque() changed to ISPERigidBody::ApplyWorldImpulse()/ApplyBodyTorque().
- ISPERigidBody::GetContact had the new form, you must use ISPEContact interface.
- Spring and friction in Joint not support any more, you must maintain them yourself.
- ISPEWorld::Set/GetMaxSubStep() changed to Set/GetMaxStepPerUpdate().
- ISPEWorld::DirectStep() avaible now to call single Step() directly.
- ISPEWorld::GetBreakList() avaible now to get list of rigid bodies that need to break.
- New APIs to config the precision and speed of new solver in ISPEWorld: SetSolverCacheFactor()/SetSolverPrecision().
- ISPEWorld::Set/GetNumThreads() not avaible now in public SDK.
- New APIs to clear the physics world: ISPEWorld::Clear(), and ISPEWorld::ClearGarbage() to release unused memory.
- New tutorials in SDK: Physics and AI, CustomJoint.

Introduction : |

How does SPE work!? | Constraint in SPE

Tutorials : |

Get Start | Joint | Break | Contact Query | Fluid | Physics Filter | Collision Detection

References : |

ISPEShape | ISPEPhysicsState | ISPERigidBody | ISPEJoint | ISPEConstraint
ISPEContact | ISPEParticle | ISPEFluid | ISPEWorld

How does SPE work?

Constraint in SPE
- Introduction of SPEConstraintData.
  struct SPEConstraintData
  {
  SPEVector r[2]; // vector from center of mass to constraint point
  SPEVector n; // normal
  float dv; // desired relative velocity in normal
  float u; // friction coefficient in tangent space
  float low, high; // low and high bound of normal impulse
  };
// To solve collisions, we set constraint data this way: LPSPECONTACT pContact = pWorld->AddContact(); // Create contact // specify rigid bodies pContact->SetRigidBody(RigidBody0, RigidBody1); // then enable the contact
pContact->SetEnabled(true);
LPSPECONSTRAINT pConstraint = pContact->AddConstraint();
SPEConstraintData data;
data.r[0] = r0;
data.r[1] = r1;
data.n = n;
// note that the relative velocity is defined as v0-v1 in SPE.
data.dv = -e * ( ( Velocity0(p) - Velocity1(p) ) * n );
data.u = 0.5f * ( u0 + u1); // artificial formula
data.low = 0.0f;
data.high = SPE_POSITIVE_INFINITE;
// submit data
pConstraint->SetData(data);
// To solve ball joint, we set constraint data this way:
LPSPECONTACT pContact = pWorld->AddContact();
// specify rigid bodies
pContact->SetRigidBody(RigidBody0, RigidBody1);
// then enable the contact
pContact->SetEnabled(true);
LPSPECONSTRAINT pConstraint = pContact->AddConstraint();
SPEConstraintData data;
data.r[0] = r0;
data.r[1] = r1;
data.n = n; // p1-p0
// correct positions
data.dv = (p1-p0).Length()/StepTime;
// use infinite friction to avoid sliding in tangent space
data.u = SPE_POSITIVE_INFINITE;
// need not to clamp impulse in this case
data.low = SPE_NEGATIVE_INFINITE;
data.high = SPE_POSITIVE_INFINITE;
// submit data
pConstraint->SetData(data);
// This is only the basic idea of ball joint solving,
//for a more reliable implementation, see CustomJoint in the SDK.

Get Start
- Import the Library. Configure your IDE to make sure the compiler and linker can find "SPE.lib" and "SPE.h".
- Include the header file of SPE, "SPE.h" is the only file you need to include.
  #include "SPE.h"
- Define some global variables.
  LPSPEWORLD pWorld; // interface of physics world
  LPSPERIGIDBODY pBody; // interface of a rigidbody
  LPD3DXMESH pBoxMesh;
- Ready for physics simulation.
  // Function to initialize a shape from D3DXMesh
  void InitShape(ISPEShape* pShape, ID3DXMesh* pMesh)
  {
  BYTE *pVB;
  void *pIB;
  pMesh->LockVertexBuffer(D3DLOCK_NOSYSLOCK, (void**)&pVB);
  pMesh->LockIndexBuffer (D3DLOCK_NOSYSLOCK, (void**)&pIB);
  if(pMesh->GetOptions() & D3DXMESH_32BIT) // 32BIT index
  {
  pShape->Initialize (pVB, pMesh->GetNumBytesPerVertex (),
  (int*)pIB, pMesh->GetNumFaces ());
  }
  else // 16BIT index
  {
  pShape->Initialize (pVB, pMesh->GetNumBytesPerVertex (),
  (WORD*)pIB, pMesh->GetNumFaces ());
  }
  pMesh->UnlockVertexBuffer ();
  pMesh->UnlockIndexBuffer ();
  }
  void InitApp()
  {
  D3DXLoadMeshFromX ("box.x", &pBoxMesh); // load a model from x file
  pWorld = CreateSPEWorld(); // create a instance of physics world
  pWorld->SetGravity (SPEVector(0, -9.8f, 0)); // set the gravity
  LPSPESHAPE pShape = pWorld->CreateShape(); // create a shape instance
  InitShape(pShape, pBoxMesh); // initialize the shape
  pBody = pWorld->AddRigidBody (pShape); // add a rigid body to SPEWorld with this shape
  pBody->SetPosition (SPEVector(0.0f, 2.0f, 0.0f)); // set position of rigid body
  pBody->SetVelocity (SPEVector(0.0f, 0.0f, -5.0f)); // set velocity
  pBody->SetAngularVelocity (SPEVector(0.0f, 25.0f, 0.0f));
  pWorld->ReleaseShape(pShape); // release the shape
  // another way to add a rigid body is to use "Shape" which is a member of pWorld, it had
  // been created when the pWorld was created. e.g.
  // InitShape(pWorld->Shape, pBoxMesh);
  // pBody = pWorld->AddRigidBody ();
  // you needn't pass any parameter if you want to add a rigid body by "Shape" , and needn't release it
  // it can be Re-Initialize too.
  }
- Update the physics world.
  void CALLBACK OnFrameMove(float fElapsedTime )
  {
  pWorld->Update(fElapsedTime);
  }
- Get physics result from engine.
  void CALLBACK OnFrameRender( IDirect3DDevice9* m_pd3dDevice )
  {
  D3DXMATRIX matWorld;
  pBody->GetTransformMesh (&matWorld); // get the world matrix of a rigid body
  pd3dDevice->SetTransform (D3DTS_WORLD, &matWorld);
  pBoxMesh->DrawSubset (0);
  }
- Release all resources.
  void CALLBACK OnDestroyDevice( void* pUserContext )
  {
  SAFE_RELEASE( pBoxMesh );
  ReleaseSPEWorld( pWorld ); // release physics world
  }

Joint
void InitApp() { LPSPESHAPE pShape = pWorld->CreateShape(); // create a shape instance D3DXLoadMeshFromX ("cask.x", &pCaskMesh); // load a model from x file InitShape(pShape, pCaskMesh);
// add 4 rigid bodies to the physics world using same shape
for(int i=0; i<4; i++)
{
pBody[i]=pWorld->AddRigidBody (pShape);
pBody[i]->SetPosition (SPEVector(0, (float)i+2, 0));
}
pWorld->ReleaseShape(pShape);
SPEJointDesc jd; // define a joint desc
jd.Default(); // set to default
jd.Body[0]=pBody[0]; // first body to be linked by the joint
jd.Body[1]=pBody[1]; // second body to be linked by the joint
jd.CreateByWorldAnchor=true; // create by world anchor
jd.WorldAnchor=SPEVector(0, 2.5f, 0); // specify the world position of anchor
pJoint[0]=pWorld->AddJoint(jd); // add joint to the physics world
pBody[3]->SetBeStatic(true);
jd.Default();
jd.Body[0]=pBody[3];
jd.Body[1]=pBody[2];
jd.CreateByWorldAnchor=false; // create by body anchor
jd.BodyAnchor[0]=SPEVector(0,-0.5f,0); // specify the position in the first body's frame
jd.BodyAnchor[1]=SPEVector(0,0,1); // specify the position in the second body's frame
pJoint[1]=pWorld->AddJoint(jd);
}

Break
SPEArray<LPSPERIGIDBODY> Bodies; // use an array to save dynamic increasing rigid bodies // function to create a SPEMesh from D3DXMesh void InitMesh(SPEMesh &speMesh, LPD3DXMESH pMesh) { DXVERTEX *dxvb;
int *dxib;
pMesh->LockVertexBuffer(D3DLOCK_NOSYSLOCK, (void**)&dxvb);
pMesh->LockIndexBuffer (D3DLOCK_NOSYSLOCK, (void**)&dxib);
int nBytes=pMesh->GetNumBytesPerVertex ();
speMesh.Initialize ((BYTE*)dxvb, nBytes, (BYTE*)&dxvb[0].t,
nBytes, dxib, pMesh->GetNumFaces ());
pMesh->UnlockVertexBuffer ();
pMesh->UnlockIndexBuffer ();
}
void InitApp()
{
LPSPESHAPE pShape = pWorld->CreateShape(); // create a shape instance
// add a normal rigid body
D3DXLoadMeshFromX ("cask.x", &pBoxMesh); // load a model from x file
InitShape(pShape, pBoxMesh);
pbody=pWorld->AddRigidBody (pShape);
pbody->SetPosition (SPEVector(-5, 3, 0));
pbody->SetVelocity (SPEVector(10,0,0));
pbody->UserData=pBoxMesh; // use UserData as flag for rendering.
Bodies.push(pbody);
// add a breakable rigid body
D3DXMatrixScaling(&mat, 1.0f, 1.0f, 1.0f);
LoadMesh(pd3dDevice, pMesh[3], L"media/bone.x", mat);
// to make a breakable rigid body, shape initializing from SPEMesh is necessary!
SPEMesh speMesh;
InitMesh(speMesh, pMesh[3]); // create a SPEMesh first
pShape->Initialize(speMesh); // Initialize a shape from SPEMesh
pbody=pWorld->AddRigidBody (pShape);
pbody->SetPosition (SPEVector(-1, 3, 0));
pbody->SetAngularVelocity (SPEVector(10,0,0));
pbody->SetBreakForce(30.0f); // positive value make the body be breakable
pbody->UserData=0; // use UserData as flag for rendering
Bodies.push(pbody);
pWorld->ReleaseShape(pShape);
D3DXCreateTextureFromFile(pd3dDevice, L"media/spehome.bmp", &spe); // texture for original surface
D3DXCreateTextureFromFile(pd3dDevice, L"media/section.bmp", §ion); // texture for sections
}
// function to break a rigid body into pieces
void CheckBreak()
{
for(int i=0; i<Bodies.size; i++)
{
if(Bodies[i]->WantBreak()) // if a force greater than "BreakForce" had just applied to body
{
SPEContactInfo ci;
Bodies[i]->GetBreakContact(ci); // get the contact which make the body break
srand(timeGetTime());
SPEVector n(rnd(1),rnd(1),rnd(1)); // generate a rand normal direction
// create a plane by rand normal and contact info as a knife to carve the body
SPEPlane pl(n, ci.Position);
pWorld->Carve(Bodies[i], pl); // carve the body and the result is saved in ISPEWorld::Meshes
LPSPERIGIDBODY pbody;
for(int j=0; j<pWorld->Meshes.size; j++)
{
pWorld->Shape->Initialize(pWorld->Meshes[j]); // initialize shape from piece mesh
if(pWorld->Shape->GetVolume()<0.0005f) continue; // ignore the too small pieces
pbody=pWorld->AddRigidBody(); // add a rigid body to SPEWorld by ISPEWorld::Shape
// if the volume is greater than 0.05f, then make it breakable too
if(pWorld->Shape->GetVolume()>0.05f)
{
pbody->SetBreakForce(30.0f);
}
// compute states to make all pieces looks like a real part from the old body
pbody->PatternState (Bodies[i]);
pbody->UserData=0; // set the render flag
Bodies.push(pbody); // add to body list
}
pWorld->DeleteRigidBody(Bodies[i]); // delete the old broken body from SPEWorld
Bodies.del(i); // delete the pointer from local body list
i--;
}
}
}
void CALLBACK OnFrameMove(float fElapsedTime)
{
pWorld->Update(fElapsedTime);
CheckBreak(); // check break every frame
}
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice)
{
D3DXMATRIX matWorld;
for(int i=0; i<Bodies.size; i++)
{
Bodies[i]->GetTransform (&matWorld);
pd3dDevice->SetTransform (D3DTS_WORLD, &matWorld);
if(Bodies[i]->UserData)
{
LPD3DXMESH pMesh=(LPD3DXMESH)(Bodies[i]->UserData);
pd3dDevice->SetTexture(0, spe);
pMesh->DrawSubset (0);
}
else // render objects by SPEMesh
{
SPEMesh* pMesh=Bodies[i]->GetShape()->GetMesh();
// render the original surface
pd3dDevice->SetTexture(0, spe);
pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST,
pMesh->GetNum(0), pMesh->GetData(0), sizeof(SPEVertex));
// render the section
pd3dDevice->SetTexture(0, section);
pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST,
pMesh->GetNum(1), pMesh->GetData(1), sizeof(SPEVertex));
}
}
}

ContactQuery
LPSPECONTACT pContact; int num=pBody[1]->GetNumContacts(); for(int i=0; i<num; i++) { pContact=pBody[1]->GetContact(i);
float sign = pBody[1]==pContact->GetRigidBody(0) ? 1.0f : -1.0f; // normal and impulse in Constraint is for the first rigid body
int numConstraints=pContact->GetNumConstraints();
for(int j=0; j<numConstraints; j++)
{
LPSPECONSTRAINT pConstraint=pContact->GetConstraint(j);
SPEVector position=pConstraint->GetPosition();
SPEVector normal=pConstraint->GetNormal()*sign;
SPEVector impulse=pConstraint->GetImpulse()*sign;
DrawLine(pd3dDevice, position, position+normal, 0);
DrawLine(pd3dDevice, position, position+impulse*0.05f, 0xffffff00);
}
}

Fluid
LPSPEWORLD pWorld; LPSPEFLUID pFluid; void InitApp() { pFluid=pWorld->AddFluid(); // add a Fluid to SPEWorld
pFluid->SetMaterial(SPE_WATER); // set material
//pFluid->SetMaterial(SPE_SMOKE);
pFluid->SetMeshGeneration(true); // generate surface mesh for rendering
float step=0.08f;
SPEVector velocity(0, 0, 0);
for(float y=0.0f; y<1.0f; y+=step)
{
for(float x=0.0f; x<step*9.5f; x+=step)
{
for(float z=0.0f; z<step*9.5f; z+=step)
{
pFluid->AddParticle(SPEVector(x, y+1.0f, z), velocity); // add particle to Fluid
}
}
}
}
void RenderFluid()
{
D3DXMatrixIdentity(&matWorld); // all the vertices of fluid mesh are in world frame
pd3dDevice->SetTransform (D3DTS_WORLD, &matWorld);
pd3dDevice->SetFVF(DXFVF);
pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST,pFluid->GetMesh()->Triangle.size,
&pFluid->GetMesh()->Triangle[0],sizeof(SPEVertex));
// to render Fluid as particles, use ISPEFluid::GetParticlePosition, and do not forget to turn mesh generation off.
}

Physics Filter
- There are 2 ways to disable collision detection.
  LPSPEWORLD pWorld;
  LPSPERIGIDBODY pBody0, pBody1;
  // 1) Using collision exception list of rigid body:
  pBody0->AddCollisionException(pBody1);
  // or
  pBody1->AddCollisionException(pBody0);
  // 2) Use group filter.
  pBody0->SetGroupId(2);
  pBody1->SetGroupId(3);
  pWorld->AddGroupPhysicsFlag(2, 3, SPE_PHYSICS_NONE);
  // the order of GroupId is arbitrary so it is equal to:
  pWorld->AddGroupPhysicsFlag(3, 2, SPE_PHYSICS_NONE);
- You can only use group filter to disable solving.

Collision Detection
- 1) Create rigid body first using ISPEWorld::CreateRigidBody():
  LPSPERIGIDBODY pBody0, pBody1;
  pBody0=pWorld->CreateRigidBody(pShape);
  pBody1=pWorld->CreateRigidBody(pShape);
- 2) Specify the position and new position to the State and NewState for each rigid body:
  pBody0->GetState()->SetPosition(pos);
  pBody0->GetNewState()->SetPosition(npos);
  pBody1->GetState()->SetPosition(pos);
  pBody1->GetNewState()->SetPosition(npos);
- 3) Push the rigid bodies to an array and call DetectCollisions().
  SPEArray list;
  list.push(pBody0);
  list.push(pBody1);
  pWorld->DetectCollisions(list);
- 4) Then you can get the collision information by contact query interfaces of ISPERigidBody.
- Note:
  [1]You can also change the orientation on step 2);
  [2]SPE do not generate a full swept volume to detect collisions, so if the distance from position to new position is too long and make broad phase skiped, you may miss some collisions.
  [3]Contact information is stored in a temporary list, you must use it before you call ISPEWorld::DetectCollisions() next time.
  [4]Physics filter is also effective here.

ISPEShape Reference
- Applications use the methods of the ISPEShape interface to create collision shapes and ready for create rigid bodies.
  struct ISPEShape
  {
  virtual SPERESULT Initialize(BYTE *pVertex, int StrideSize, int *pIndex, int NumTriangles) = 0;

  | Create a shape from tri-mesh data.

  Parameters
  pVertex
  [in] Pointer to vertex buffer.
  StrideSize
  [in] Stride of one vertex, in bytes.
  pIndex
  [in] Pointer to index buffer, index must be 32BIT.
  NumTriangles
  [in] Number of triangles.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks

  virtual SPERESULT Initialize(BYTE *pVertex, int StrideSize, WORD *pIndex, int NumTriangles) = 0;

  | Create a shape from tri-mesh data.

  Parameters
  pVertex
  [in] Pointer to vertex buffer.
  StrideSize
  [in] Stride of one vertex, in bytes.
  pIndex
  [in] Pointer to index buffer, index must be 16BIT.
  NumTriangles
  [in] Number of triangles.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks

  virtual SPERESULT InitializeForStatic(BYTE *pVertex, int StrideSize, int *pIndex, int NumTriangles) = 0;

  | Create a shape from tri-mesh data for static rigid body.

  Parameters
  pVertex
  [in] Pointer to vertex buffer.
  StrideSize
  [in] Stride of one vertex, in bytes.
  pIndex
  [in] Pointer to index buffer, index must be 32BIT.
  NumTriangles
  [in] Number of triangles.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks
  Shape Initializing by this function can only be static, you can not use SetBeStatic(false) to active it. This function is just a little faster than the general initializing.

  virtual SPERESULT Initialize(BYTE *pVertex, int StrideSize, int NumVertices) = 0;

  | Create a convex hull by giving vertices.

  Parameters
  pVertex
  [in] Pointer to vertex buffer.
  StrideSize
  [in] Stride of one vertex, in bytes.
  NumVertices
  [in] Number of vertices.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks

  virtual SPERESULT Initialize(SPEMesh &speMesh) = 0;

  | Create a shape from a SPEMesh object.

  Parameters
  speMesh
  [in] reference of a SPEMesh object.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks

  virtual SPERESULT InitializeAsSphere(float r) = 0;

  | Create a sphere shape.

  Parameters
  r
  [in] radius of sphere.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks

  virtual SPERESULT InitializeAsCapsule(float length, float r) = 0;

  | Create a capsule shape.

  Parameters
  length
  [in] length of capsule.
  r
  [in] radius of capsule.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks
  The axis of capsule is align on Z, length must be greater than 2*r.

  virtual float GetVolume() = 0;

  | Get the volume of shape.

  Parameters
  Return
  The volume of shape.
  Remarks
  The volume is computed while the shape be initialized.

  virtual SPERESULT SetMassCenter(const SPEVector &cm) = 0;

  | Set the center of mass of shape.

  Parameters
  cm
  [in] center of mass.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks
  This function is only valid after initializing and before creating rigid body, if you try to change the center of mass using interface from the ISPERigidBody::GetShape(), it would failed.

  virtual SPEVector GetMassCenter(void *pv=0) = 0;

  | Get the mass center of shape.

  Parameters
  pv
  [out] If pv is not null, mass center value will be copied to.
  Return
  The mass center of shape.
  Remarks
  The mass center is computed while the shape be initialized.

  virtual SPEMesh* GetMesh() = 0;

  | Get the pointer of SPEMesh contained in the shape.

  Parameters
  Return
  The pointer of SPEMesh.
  Remarks
  If the shape is not initialize from SPEMesh, the return valume is 0.

  virtual SPERESULT CloneTo(ISPEShape** ppIShape) = 0;

  | Clone the shape instance to another interface.

  Parameters
  ppIShape
  [out] Address of a pointer to an ISPEShape interface, representing the destination shape.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks
  An initialized shape must be released before get the new shape data.

  protected:
  ISPEShape(){}
  virtual ~ISPEShape(){}
  };

ISPEPhysicsState Reference
- Applications use the methods of the ISPEPhysicsState interface to query of modify the physics state of rigid body.
  struct ISPEPhysicsState
  {
  // Set or Get member of State for body frame
  virtual void SetPosition(const SPEVector pos) = 0;
  virtual SPEVector GetPosition() = 0;
  virtual void SetOrientation(const SPEMatrix ort) = 0;
  virtual SPEMatrix GetOrientation() = 0;
  virtual void SetVelocity(const SPEVector vel) = 0;
  virtual SPEVector GetVelocity() = 0;
  virtual void SetAngularVelocity(const SPEVector& av) = 0;
  virtual SPEVector GetAngularVelocity() = 0;
  // Set or Get member of State for mesh frame
  virtual void SetPositionMesh(const SPEVector pos) = 0;
  virtual SPEVector GetPositionMesh() = 0;
  virtual void SetOrientationMesh(const SPEMatrix ort) = 0;
  virtual SPEMatrix GetOrientationMesh() = 0;
  // Transform a point or a vector between body frame and world frame
  virtual SPEVector PointBodyToWorld(const SPEVector &p) = 0;
  virtual SPEVector PointWorldToBody(const SPEVector &p) = 0;
  virtual SPEVector VectorBodyToWorld(const SPEVector &p) = 0;
  virtual SPEVector VectorWorldToBody(const SPEVector &p) = 0;
  // Get the velocity at a point in world frame
  virtual SPEVector GetVelocityAtWorldPoint(const SPEVector &p) = 0;
  protected:
  ISPEPhysicsState(){}
  virtual ~ISPEPhysicsState(){}
  };

ISPERigidBody Reference
- Applications use the methods of the ISPERigidBody interface to manipulate and query rigid body.
  struct ISPERigidBody
  {
  virtual void SetMass(float mass) = 0;

  | Set the mass of rigid body.

  Parameters
  mass
  [in] mass of rigid body.
  Return
  Remarks
  The default mass of a rigid body is 1000 * ShapeVolume.

  virtual float GetMass() = 0;

  | Get the mass of rigid body.

  Parameters
  Return
  The mass of rigid body.
  Remarks
  The default mass of a rigid body is 1000 * ShapeVolume.

  virtual void SetDensity(float density=1000) = 0;

  | Set the density of rigid body.

  Parameters
  density
  [in] density of rigid body.
  Return
  Remarks
  The default density of rigid body is 1000. New mass of rigid body would be density * ShapeVolume.

  virtual float GetDensity() = 0;

  | Get the density of rigid body.

  Parameters
  Return
  The density of rigid body.
  Remarks
  The default density of rigid body is 1000.

  virtual void SetInertia(const SPEMatrix &inertia) = 0;

  | Set the inertia tensor.

  Parameters
  inertia
  [in] inertia tensor.
  Return
  Remarks
  The inertia tensor is computed automatically by system. Note that inertia would be restored while you call SetMass()/SetDensity().

  virtual SPEMatrix GetInertia() = 0;

  | Get the inertia tensor.

  Parameters
  Return
  The inertia tensor of rigid body.
  Remarks
  The inertia tensor is computed automatically by system. Note that inertia would be restored while you call SetMass()/SetDensity().

  virtual SPEMatrix GetWorldInertia() = 0;

  | Get the inertia tensor in world frame by current orientation.

  Parameters
  Return
  The inertia tensor of rigid body.
  Remarks
  The inertia tensor is computed automatically by system. Note that inertia would be restored while you call SetMass()/SetDensity().

  virtual ISPEPhysicsState* GetState() = 0;

  | Get the interface of "State" of rigid body.

  Parameters
  Return
  interface of "State".
  Remarks

  virtual ISPEPhysicsState* GetNewState() = 0;

  | Get the interface of "New State" of rigid body.

  Parameters
  Return
  interface of "New State".
  Remarks

  virtual void SetPosition(SPEVector& pos) = 0;

  | Set the position of rigid body.

  Parameters
  pos
  [in] position.
  Return
  Remarks
  The default position of rigid body is SPEVector(0,0,0).

  virtual SPEVector GetPosition() = 0;

  | Get the position of rigid body.

  Parameters
  Return
  Position of rigid body.
  Remarks

  virtual void SetOrientation(SPEMatrix& ort) = 0;

  | Set the Orientation of rigid body.

  Parameters
  ort
  [in] Orientation.
  Return
  Remarks
  The default Orientation of rigid body is SPEMatrix::Identity().

  virtual SPEMatrix GetOrientation() = 0;

  | Get the Orientation of rigid body.

  Parameters
  Return
  orientation of rigid body.
  Remarks
  The default Orientation of rigid body is SPEMatrix::Identity().

  virtual void SetVelocity(SPEVector& v) = 0;

  | Set the velocity of rigid body.

  Parameters
  v
  [in] velocity.
  Return
  Remarks
  The default velocity of rigid body is SPEVector(0,0,0).

  virtual SPEVector GetVelocity() = 0;

  | Get the velocity of rigid body.

  Parameters
  Return
  Remarks
  The default velocity of rigid body is SPEVector(0,0,0).

  virtual void SetAngularVelocity(SPEVector& av) = 0;

  | Set the angular velocity of rigid body.

  Parameters
  av
  [in] angular velocity.
  Return
  Remarks
  The default angular velocity of rigid body is SPEVector(0,0,0).

  virtual SPEVector GetAngularVelocity() = 0;

  | Get the angular velocity of rigid body.

  Parameters
  Return
  Remarks
  The default angular velocity of rigid body is SPEVector(0,0,0).

  virtual void SetPositionMesh(const SPEVector& pos) = 0;

  | Set the position of rigid body for mesh frame.

  Parameters
  pos
  [in] position.
  Return
  Remarks
  The default position of rigid body is SPEVector(0,0,0), hence the default position for mesh frame is -MassCenter.

  virtual SPEVector GetPositionMesh() = 0;

  | Get the position of rigid body for mesh frame.

  Parameters
  Return
  position.
  Remarks
  The default position of rigid body is SPEVector(0,0,0), hence the default position for mesh frame is -MassCenter.

  virtual void SetOrientationMesh(const SPEMatrix& ort) = 0;

  | Set the Orientation of rigid body for mesh frame.

  Parameters
  ort
  [in] Orientation.
  Return
  Remarks
  The default Orientation of rigid body is SPEMatrix::Identity(). Changing the orientation for mesh frame may also caused the position of body frame change.

  virtual SPEMatrix GetOrientationMesh() = 0;

  | Get the Orientation of rigid body.

  Parameters
  Return
  orientation of rigid body.
  Remarks
  The default Orientation of rigid body is SPEMatrix::Identity().

  virtual void SetTransformMesh(SPEMatrix& trans) = 0;

  | Set the Transform of rigid body for mesh frame, include position and orientation.

  Parameters
  trans
  [in] Transform.
  Return
  Remarks
  The default Transform of rigid body is SPEMatrix::Identity(), hence the default transform matrix for mesh frame is SPEMatrix::Translate(-MassCenter);

  virtual void SetTransformMesh(void* pmat) = 0;

  | Set the Transform of rigid body using other data type, include position and orientation.

  Parameters
  pmat
  [in] address of a matrix.
  Return
  Remarks
  The default Transform of rigid body is SPEMatrix::Identity(), hence the default transform matrix for mesh frame is SPEMatrix::Translate(-MassCenter);

  virtual SPEMatrix GetTransformMesh(void* pmat=0) = 0;

  | Get the Transform of rigid body, include position and orientation.

  Parameters
  pmat
  [out] address of a matrix or NULL.
  Return
  Remarks
  If pamt is not 0, Transform data would copied to. The default Transform of rigid body is SPEMatrix::Identity(), hence the default transform matrix for mesh frame is SPEMatrix::Translate(-MassCenter);

  virtual void SetBeStatic(bool bs) = 0;

  | Set if the rigid body be static.

  Parameters
  bs
  [in] bool.
  Return
  Remarks
  If the rigid body had been set to be static, it would not move and the mass is infinite. The default is false.

  virtual bool GetBeStatic() = 0;

  | Get if the rigid body be static.

  Parameters
  Return
  true if the rigid body be static, else return false.
  Remarks
  If the rigid body had been set to be static, it would not move and the mass is infinite. The default is false.

  virtual SPERESULT SetSleeping(bool sleeping) = 0;

  | Force to sleep or wake up the rigid body.

  Parameters
  sleeping
  [in] (true)sleep or (false)wake up.
  Return
  Remarks

  virtual bool GetSleeping() = 0;

  | Get the state of sleeping of a rigid body.

  Parameters
  Return
  true if is sleeping, else return false.
  Remarks

  virtual void SetSleepFactor(float factor) = 0;

  | Set the factor of sleep threshold which would determine how fast a rigid body go to sleep.

  Parameters
  factor
  [in] factor.
  Return
  Remarks
  The default factor is 1.0f;

  virtual float GetSleepFactor() = 0;

  | Get the factor of sleep threshold which would determine how fast a rigid body go to sleep.

  Parameters
  Return
  factor.
  Remarks
  The default factor is 1.0f;

  virtual void SetDynamicGeneration(bool dg) = 0;

  | Set if the rigid body would be controled by manual.

  Parameters
  dg
  [in] bool.
  Return
  Remarks
  If the rigid body had been set to generate dynamic, Velocity and AngularVelocity is generated while you call SetTransform or SetPosition or SetOrientation, making ragdoll interact with other bodies. The default is false.

  virtual bool GetDynamicGeneration() = 0;

  | Get if the rigid body would be controled by manual.

  Parameters
  Return
  true if the rigid body had been set to generate dynamic, else return false.
  Remarks
  If the rigid body had been set to generate dynamic, Velocity and AngularVelocity is generated while you call SetTransform or SetPosition or SetOrientation, making ragdoll interact with other bodies. The default is false.

  virtual void SetExternForceField(SPEVector &force) = 0; // this function can used for particles

  | Set extern force field influence to rigid body.

  Parameters
  force
  [in] a vector reprenting the force field.
  Return
  Remarks
  This is a dedicate function design for particle simulation. The default is SPEVector(0,0,0).

  virtual SPEVector GetExternForceField() = 0;

  | Get extern force field influence to rigid body.

  Parameters
  Return
  Extern force field.
  Remarks
  The default is SPEVector(0,0,0).

  virtual void SetDamping(float damping) = 0;

  | Set damping of rigid body.

  Parameters
  damping
  [in] damping.
  Return
  Remarks
  The default is 0.0f.

  virtual float GetDamping() = 0;

  | Get damping of rigid body.

  Parameters
  Return
  damping of rigid body.
  Remarks
  The default is 0.0f.

  virtual void SetAngularDamping(float angulardamping) = 0;

  | Set angular damping of rigid body.

  Parameters
  angulardamping
  [in] angular damping.
  Return
  Remarks
  The default is 0.0f.

  virtual float GetAngularDamping() = 0;

  | Get angular damping of rigid body.

  Parameters
  Return
  angular damping of rigid body.
  Remarks
  The default is 0.0f.

  virtual void SetFriction(float friction) = 0;

  | Set friction coefficient of rigid body.

  Parameters
  friction
  [in] friction coefficient.
  Return
  Remarks
  When two rigid bodies collide, the finally friction coefficient between two surfaces is: (body0.friction+body1.friction)/2 . The default is 0.5f.

  virtual float GetFriction() = 0;

  | Get friction coefficient of rigid body.

  Parameters
  Return
  Friction coefficient of rigid body.
  Remarks
  When two rigid bodies collide, the finally friction coefficient between two surfaces is: (body0.friction+body1.friction)/2 . The default is 0.5f.

  virtual void SetElasticity(float elasticity) = 0;

  | Set elasticity coefficient of rigid body.

  Parameters
  elasticity
  [in] elasticity coefficient.
  Return
  Remarks
  When two rigid bodies collide, the finally elasticity coefficient between two surfaces is: body0.elasticity*body1.elasticity . The default is 0.1f.

  virtual float GetElasticity() = 0;

  | Get elasticity coefficient of rigid body.

  Parameters
  Return
  Elasticity coefficient of rigid body.
  Remarks
  When two rigid bodies collide, the finally elasticity coefficient between two surfaces is: body0.elasticity*body1.elasticity . The default is 0.1f.

  virtual void ApplyWorldImpulse(SPEVector &impulse, SPEVector &position) = 0;

  | Apply a impulse to the rigid body.

  Parameters
  impulse
  [in] a vector representing the impulse, include direction and scalar, in world frame.
  position
  [in] position where impulse to applied, in world frame.
  Return
  Remarks
  Impulse would applied into the NewState.

  virtual void ApplyBodyTorque(SPEVector &torque) = 0;

  | Add a Torque to the rigid body.

  Parameters
  torque
  [in] a vector representing the torque, include direction and scalar, in body frame.
  Return
  Remarks
  Impulse would applied into the NewState.

  virtual int GetNumContacts() = 0;

  | Get number of the contacts of rigid body.

  Parameters
  Return
  Number of the contacts of rigid body.
  Remarks

  virtual ISPEContact* GetContact(int index) = 0;

  | Get index'th contact.

  Parameters
  index
  [in] index.
  Return
  the index'th contact.
  Remarks

  virtual bool CastRay(SPEVector &RayPos, SPEVector &RayDir, SPECastRayInfo &Info) = 0;

  | Test if a ray intersect this rigid body.

  Parameters
  RayPos
  [in] Start position of the ray.
  RayDir
  [in] Direction of the ray.
  Info
  [out] Intersect information of this test.
  Return
  true if the ray intersect this rigid body, else return false.
  Remarks
  To find the nearest intersection in the whole world, use SPEWorld::CastRay(...).

  virtual void AddCollisionException(ISPERigidBody *pIBody) = 0;

  | Add a rigid body to collision exception list to avoid collision detection.

  Parameters
  pIBody
  [in] interface of a rigid body.
  Return
  Remarks

  virtual bool BeInCollisionException(ISPERigidBody *pIBody) = 0;

  | Check if a rigid body is in the collision exception list.

  Parameters
  Return
  true if in, else false.
  Remarks

  virtual void DeleteCollisionException(ISPERigidBody *pIBody=0) = 0;

  | Delete a rigid body to collision exception list.

  Parameters
  pIBody
  [in] interface of a rigid body. if pIBody==0, all rigid body in the list would be deleted.
  Return
  Remarks

  virtual void SetGroupId(int id) = 0;

  | Set the group Id of a rigid body.

  Parameters
  id
  [in] Id.
  Return
  Remarks
  Group Id is used for physics filter.

  virtual int GetGroupId() = 0;

  | Get the group Id of a rigid body.

  Parameters
  Return
  Id.
  Remarks
  Group Id is used for physics filter.

  virtual void SetBreakForce(float force) = 0;

  | Set the tolerance force of rigid body.

  Parameters
  force
  [in] tolerance force.
  Return
  Remarks
  While a force greater than BreakForce had applied to the rigid body, WantBreak() would return true. Negative value means unbreakable. The default is -1.

  virtual float GetBreakForce() = 0;

  | Get the tolerance force of rigid body.

  Parameters
  Return
  Tolerance force.
  Remarks
  While a force greater than BreakForce had applied to the rigid body, WantBreak() would return true. Negative value means unbreakable. The default is -1.

  virtual bool WantBreak() = 0;

  | Get the state whether a rigid body can break.

  Parameters
  Return
  true if a force greater than BreakForce had applied to the rigid body, else return false.
  Remarks

  virtual void GetBreakContact(SPEContactInfo &Contact) = 0;

  | Get the information of contact which break the rigid body.

  Parameters
  Contact
  [out] Reference of a SPEContactInfo.
  Return
  Remarks

  virtual void PatternState(ISPERigidBody* ibody) = 0;

  | Set all the states of the child pieces patterned from parent body.

  Parameters
  ibody
  [in] parent body.
  Return
  Remarks
  A dedicated function to implement breakable rigid bodies. It computes and sets new position, orientation, velocity, angular velocity to make pieces looks like a real part from the parent body.

  virtual ISPEShape* GetShape() = 0;

  | Get the shape interface of rigid body.

  Parameters
  Return
  Shape interface of rigid body.
  Remarks
  Shape in the rigid body had been locked and can not be initialized.

  void* UserData;
  int iUserData;
  float fUserData;
  protected:
  ISPERigidBody()
  {
  UserData=0;
  iUserData=0;
  fUserData=0.0f;
  }
  virtual ~ISPERigidBody(){}
  };

ISPEJoint Reference
- Applications use the methods of the ISPEJoint interface to control joints.
  struct ISPEJoint
  {
  virtual ISPERigidBody* GetBody(int index) = 0;

  | Get one of rigid body linked by this joint.

  Parameters
  index
  [in] Rigid body index, 0 or 1.
  Return
  Interface of the rigid body.
  Remarks

  virtual SPEVector GetWorldAnchor() = 0;

  | Get the world anchor of joint.

  Parameters
  Return
  World anchor of joint.
  Remarks

  virtual void SetBodyAnchor(int index, SPEVector &anchor) = 0;

  | Change the body anchor of joint.

  Parameters
  index
  [in] index of two bodies, 0 or 1.
  anchor
  [in] new position of body anchor, in body frame.
  Return
  Remarks
  Body anchor had been determined when the joint been created, this function allow user to change position of anchor.

  virtual SPEVector GetBodyAnchor(int index) = 0;

  | Get the body anchor of joint.

  Parameters
  index
  [in] index of two bodies, 0 or 1.
  Return
  Remarks
  Body anchor had been determined when the joint been created.

  virtual bool IsBroken() = 0;

  | Get the state that whether the joint is broken.

  Parameters
  Return
  true if the joint is broken, else return false.
  Remarks
  A joint been breakable only when the member of SPEJointDesc named BreakForce had been asigned a positive value when create the joint.

  virtual ISPEContact* GetContact() = 0;

  | Get the contact interface for this joint.

  Parameters
  Return
  interface of contact.
  Remarks

  };

ISPEConstraint Reference
- Applications use the methods of the ISPEConstraint interface to get collision information or build custom joints.
  struct ISPEConstraint
  {
  virtual SPERESULT SetData(const SPEConstraintData &data) = 0;

  | Feed data to constraint.

  Parameters
  data
  [in] data.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks
  If the length of n in data is less than 1.0e-6, the method would failed.

  virtual void GetData(SPEConstraintData &data) = 0;

  | Get data of this constraint.

  Parameters
  data
  [out] data.
  Return
  Remarks

  virtual void SetEnabled(bool enabled) = 0;

  | Enable of disable a constraint.

  Parameters
  enabled
  [in] value.
  Return
  Remarks
  The default is true.

  virtual bool GetEnabled() = 0;

  | Get the state of the constraint.

  Parameters
  Return
  true if enabled, else return false.
  Remarks
  The default is true.

  virtual SPEVector GetPosition() = 0;

  | Get the position of the constraint.

  Parameters
  Return
  position.
  Remarks
  Only the constraint generated by collision detection had a valid position.

  virtual SPEVector GetNormal() = 0;

  | Get the normal of the constraint.

  Parameters
  Return
  normal.
  Remarks
  The direction of normal is for the first rigid body of a contact pair, If you want to get the normal for the second rigid body, just reverse it(multply -1.0f).
  The return value is equal to the SPEConstraintData.n.

  virtual SPEVector GetImpulse() = 0;

  | Get the Impulse work out by solver.

  Parameters
  Return
  impulse.
  Remarks
  The direction of impulse is for the first rigid body of a contact pair, If you want to get the impulse for the second rigid body, just reverse it(multply -1.0f).
  You can't get valid impulse in the CallBack function PreSolve() because the solver had not run.

  protected:
  ISPEConstraint(){}
  virtual ~ISPEConstraint(){}
  };

ISPEContact Reference
- Applications use the methods of the ISPEContact interface to manage the constraints.
  struct ISPEContact
  {
  virtual void SetRigidBody(ISPERigidBody* pIBody0, ISPERigidBody* pIBody1) = 0;

  | Specify the rigid body of contact pair.

  Parameters
  pIBody0, pIBody1
  [in] two rigid bodies.
  Return
  Remarks
  If you had not specify the rigid bodies, you can not enable this contact.

  virtual ISPERigidBody* GetRigidBody(int index) = 0; // index must be 0 or 1

  | Get the rigid body of contact pair.

  Parameters
  index
  [in] index of two rigid body, must be 0 or 1.
  Return
  Remarks

  virtual ISPEConstraint* AddConstraint() = 0;

  | Add a constraint to contact.

  Parameters
  Return
  interface of a constraint.
  Remarks
  You can also retrieve the interface by it's index.

  virtual SPERESULT DeleteConstraint(ISPEConstraint* pIConstraint=0) = 0;

  | Delete a constraint or all constraints from contact.

  Parameters
  pIConstraint
  [in] interface of a constraint, it it's null, all constraints would be deleted.
  Return
  SPE_OK if pIConstraint is valid, else return SPE_FAILED.
  Remarks

  virtual SPERESULT SetEnabled(bool enabled) = 0;

  | Enable or disable all constraints belong to the contact.

  Parameters
  enabled
  [in] value.
  Return
  SPE_OK if succeed, else return SPE_FAILED.
  Remarks
  If you had not specify the rigid bodies, you can not enable this contact. The default is false.

  virtual bool GetEnabled() = 0;

  | Get the state of the contact.

  Parameters
  Return
  true if enabled, else return false.
  Remarks
  The default is false.

  virtual int GetNumConstraints() = 0;

  | Get the numble of constraints.

  Parameters
  Return
  numble of constraints.
  Remarks

  virtual ISPEConstraint* GetConstraint(int index) = 0;

  | Get the constraint by index.

  Parameters
  Return
  interface of constraint, if index is not valid, return 0.
  Remarks

  virtual ISPEConstraint* GetVirtualConstraint() = 0;

  | Get the virtual constraint.

  Parameters
  Return
  interface of constraint.
  Remarks
  Virtual constraint is generated by collision detection system, generally, it is the center of all contact point,
  and it's normal is get from a contact point which had the deepest penetrate. Virtual constraint is used to process impact.

  virtual SPECONTACTTYPE GetType() = 0;

  | Get the type of contact.

  Parameters
  Return
  type of contact.
  Remarks
  The type would be COLLISION, JOINT or CUSTOM.

  virtual SPEVector GetSumImpulse(int index) = 0; // index must be 0 or 1

  | Get the sum of impulses of all constraint for index'th rigid body.

  Parameters
  Return
  sum of impulses.
  Remarks

  virtual SPEVector GetSumTorque(int index) = 0; // index must be 0 or 1

  | Get the sum of torque of all constraint for index'th rigid body.

  Parameters
  Return
  sum of torques.
  Remarks

  protected:
  ISPEContact(){}
  virtual ~ISPEContact(){}
  };

ISPEParticle Reference
- Applications use the methods of the ISPEParticle interface to access particles in Fluid.
  struct ISPEParticle
  {
  virtual void SetPosition(const SPEVector& pos) = 0;

  | Set the position of particle.

  Parameters
  pos
  [in] position
  Return
  Remarks

  virtual SPEVector GetPosition() = 0;

  | Get the position of particle.

  Parameters
  Return
  Position of particle.
  Remarks
  If pos is not 0, position data would copied to.

  virtual void SetVelocity(const SPEVector& v) = 0;

  | Set the velocity of particle.

  Parameters
  v
  [in] velocity
  Return
  Remarks

  virtual SPEVector GetVelocity() = 0;

  | Get the velocity of particle.

  Parameters
  Return
  Velocity of particle.
  Remarks

  protected:
  ISPEParticle(){}
  virtual ~ISPEParticle(){}
  };

ISPEFluid Reference
- Applications use the methods of the ISPEFluid interface to control the simulation of Fluid.
  struct ISPEFluid
  {
  virtual void SetMaterial(SPEFLUIDMATERIAL material) = 0;

  | Set the material of fluid.

  Parameters
  material
  [in] material, SPE_WATER or SPE_SMOKE.
  Return
  Remarks
  SPE hide any parameters of SPH algorithm to make the engine easy to use and to keep the engine be stable.

  virtual ISPEParticle* AddParticle(const SPEVector &position) = 0;

  | Add a particle with zero velocity to fluid.

  Parameters
  position
  [in] position.
  Return
  Remarks

  virtual ISPEParticle* AddParticle(const SPEVector &position, const SPEVector &velocity) = 0;

  | Add a particle to fluid.

  Parameters
  position
  [in] position.
  velocity
  [in] velocity.
  Return
  Remarks

  virtual void DeleteParticle(ISPEParticle* pIParticle=0) = 0;

  | Delete a particle or all particles from Fluid.

  Parameters
  pIParticle
  [in] interface of a Fluid or NULL.
  Return
  Remarks
  If pIParticle is not NULL, pIParticle would be deleted, otherwise all Particles in the Fluid would be deleted.

  virtual int GetNumParticles() = 0;

  | Get the number of particles in Fluid.

  Parameters
  Return
  Number of particles.
  Remarks

  virtual void GetParticlePosition(void* pData, int StrideSize) = 0;

  | Get the position of all particles in Fluid.

  Parameters
  pData
  [in] address of a buffer to store positions.
  StrideSize
  [in] stride of buffer, in bytes.
  Return
  Remarks

  virtual void GetParticleVelocity(void* pData, int StrideSize) = 0;

  | Get the velocity of all particles in Fluid.

  Parameters
  pData
  [in] address of a buffer to store positions.
  StrideSize
  [in] stride of buffer, in bytes.
  Return
  Remarks

  virtual void SetMeshGeneration(bool mg) = 0;

  | Set if to generate surface mesh of Fluid.

  Parameters
  mg
  [in] bool.
  Return
  Remarks
  The reason SPE does not provide a function like GenerateMesh() is that the system only generate mesh at proper time.

  virtual bool GetMeshGeneration() = 0;

  | Get if to generate surface mesh of Fluid.

  Parameters
  Return
  true if the system generate mesh, else return false.
  Remarks
  The reason SPE does not provide a function like GenerateMesh() is that the system only generate mesh at proper time.

  virtual SPEMesh* GetMesh() = 0;

  | Get the surface mesh of Fluid.

  Parameters
  Return
  Pointer of surface mesh.
  Remarks

  protected:
  ISPEFluid(){}
  virtual ~ISPEFluid(){}
  };

ISPEWorld Reference
- Applications use the methods of the ISPEWorld interface to control physics world.
  struct ISPEWorld
  {
  virtual void SetGravity(const SPEVector &g) = 0;

  | Set the gravity of the physics world.

  Parameters
  g
  [in] gravity.
  Return
  Remarks
  The default is SPEVector(0, 0, -9.8f).

  virtual SPEVector GetGravity() = 0;

  | Get the gravity of the physics world.

  Parameters
  Return
  gravity.
  Remarks
  The default is SPEVector(0, 0, -9.8f).

  virtual void SetStepTime(float time=0.01f) = 0;

  | Set the step time to do physics simulation.

  Parameters
  time
  [in] step time.
  Return
  Remarks
  SPE use fixed time step to do physics simulation, small step time means more time to compute. The default is 0.01f.

  virtual float GetStepTime() = 0;

  | Get the step time to do physics simulation.

  Parameters
  Return
  step time.
  Remarks
  SPE use fixed time step to do physics simulation, small step time means more time would be take to compute. The default is 0.01f.

  virtual void SetMaxStepPerUpdate(int sub=2) = 0; // 2 is the default

  | Set the number of max step in a update.

  Parameters
  sub
  [in] number of max step.
  Return
  Remarks
  SPE use fixed time step to do physics simulation, when the elapsed time is greater than step time, SPE would do physics-computation more than once. The default is 2.

  virtual int GetMaxStepPerUpdate() = 0;

  | Get the number of max step in a update.

  Parameters
  Return
  number of max step.
  Remarks
  SPE use fixed time step to do physics simulation, when the elapsed time is greater than step time, SPE would do physics-computation more than once. The default is 2.

  virtual int Update(float dt) = 0;

  | Update the physics world, including integration, collision dection and collision resolve.

  Parameters
  dt
  [in] elapsed time.
  Return
  number of step ran during this update.
  Remarks

  virtual void DirectStep() = 0;

  | Update the physics world with a single step.

  Parameters
  Return
  Remarks

  virtual void SetSolverCacheFactor(float factor=0.2f) = 0; // 0.2 is the default

  | Set the percentage of cached results to be used as initialization value for solver.

  Parameters
  factor
  [in] percentage, must be in [0.0, 1.0].
  Return
  Remarks
  The default is 0.2(20%). Cache data is useful only when the solver precision is low and no large-scale impulse/force change in the simulation.

  virtual float GetSolverCacheFactor() = 0;

  | Get the percentage of cached results to be used as initialization value for solver.

  Parameters
  Return
  percentage
  Remarks
  The default is 0.2(20%). Cache data is useful only when the solver precision is low and no large-scale impulse/force change in the simulation.

  virtual void SetSolverPrecision(int precision=2) = 0; // 2 is the default

  | Set the Precision level of solver.

  Parameters
  precision
  [in] precision level, must be greater than 0.
  Return
  Remarks
  The default is 2.

  virtual int GetSolverPrecision() = 0;

  | Get the Precision level of solver.

  Parameters
  Return
  precision
  Remarks
  The default is 2.

  virtual void SetCallBackPreSolve(SPECallBackFunc pFunc, void *pParam) = 0;

  | Set the call back function which would be called before solver run.

  Parameters
  pFunc
  [in] a pointer to a function.
  pParam
  [in] parameter of your function.
  Return
  Remarks
  Call back function must defined like this: void* pFunc(void *pParam){...}. To disable call back function, set pFunc to 0.

  virtual void SetCallBackStepFinished(SPECallBackFunc pFunc, void *pParam) = 0;

  | Set the call back function which would be called after a step is finished.

  Parameters
  pFunc
  [in] a pointer to a function.
  pParam
  [in] parameter of your function.
  Return
  Remarks
  Call back function must defined like this: void* pFunc(void *pParam){...}. To disable call back function, set pFunc to 0.

  virtual void SetNumThreads(int n) = 0;

  | Set the number of threads to be use for each phase of physics computation. For Multi-Threads Library only.

  Parameters
  n
  [in] number of threads.
  Return
  Remarks
  The default is 1, means multi-thread is disabled. Do not try to use a number larger than the cores of CPU.

  virtual int GetNumThreads() = 0;

  | Get the number of threads using for each phase of physics computation. For Multi-Threads Library only.

  Parameters
  Return
  number of threads.
  Remarks
  The default is 1, means multi-thread is disabled.

  virtual ISPEShape* CreateShape() = 0;

  | Create a shape instance.

  Parameters
  Return
  Interface of a shape instance.
  Remarks
  SPEWorld::Shape is available as soon as the SPEWorld been created.

  virtual void ReleaseShape(ISPEShape *pIShape) = 0;

  | Release a shape instance.

  Parameters
  pIShape
  [in] interface of a shape instance.
  Return
  Remarks

  virtual ISPERigidBody* AddRigidBody(ISPEShape *pIShape=0) = 0;

  | Add a rigid body to the physics world by a shape.

  Parameters
  pIShape
  [in] interface of a shape instance or NULL.
  Return
  Interface of a rigid body.
  Remarks
  If pIShape==0, system would use SPEWorld::Shape to add a rigid body.

  virtual void DeleteRigidBody(ISPERigidBody *pIBody=0) = 0;

  | Delete a rigid body or delete all rigid bodies in the physics world.

  Parameters
  pIBody
  [in] interface of a rigid body or NULL.
  Return
  Remarks
  If pIBody is not NULL, pIBody would be deleted, otherwise all rigid bodies in the physics world would be deleted.

  virtual ISPEFluid* AddFluid() = 0;

  | Add a Fluid instance to the physics world.

  Parameters
  Return
  Interface of a Fluid.
  Remarks

  virtual void DeleteFluid(ISPEFluid* pIFluid=0) = 0;

  | Delete a Fluid or delete all Fluids in the physics world.

  Parameters
  pIFluid
  [in] interface of a Fluid or NULL.
  Return
  Remarks
  If pIFluid is not NULL, pIFluid would be deleted, otherwise all Fluids in the physics world would be deleted.

  virtual ISPEJoint* AddJoint(SPEJointDesc& joint) = 0;

  | Add a joint to the physics world by a joint desc.

  Parameters
  joint
  [in] reference of a SPEJointDesc structure.
  Return
  Interface of a joint.
  Remarks

  virtual void DeleteJoint(ISPEJoint* pIJoint=0) = 0;

  | Delete a joint or delete all joints in the physics world.

  Parameters
  pIJoint
  [in] interface of a joint or NULL.
  Return
  Remarks
  If pIJoint is not NULL, pIJoint would be deleted, otherwise all joints in the physics world would be deleted.

  virtual ISPEContact* AddCustomContact() = 0;

  | Add a custom contact to the physics world.

  Parameters
  Return
  Interface of a contact.
  Remarks

  virtual SPERESULT DeleteCustomContact(ISPEContact* pIContact=0) = 0;

  | Delete a custom contact or delete all custom contacts in the physics world.

  Parameters
  pIContact
  [in] interface of a contact or NULL.
  Return
  Remarks
  If pIContact is not NULL, pIContact would be deleted, otherwise all custom contact in the physics world would be deleted.

  virtual void Clear() = 0; // clear all above stuff

  | Delete all rigid bodies, fluids, joints, custom contacts in the physics world.

  Parameters
  Return
  Remarks

  virtual void ClearGarbage() = 0; // release all unused memory

  | Release all unused memory allocated by SPE.

  Parameters
  Return
  Remarks

  virtual ISPERigidBody* CreateRigidBody(ISPEShape* pIShape=0) = 0; // if pIShape==0, member "Shape" is used

  | Create a rigid body but not add to the list for simulation.

  Parameters
  pIShape
  [in] interface of a shape instance or NULL.
  Return
  Interface of a rigid body.
  Remarks
  If pIShape==0, system would use SPEWorld::Shape to create a rigid body.

  virtual SPERESULT ReleaseRigidBody(ISPERigidBody *pIBody) = 0;

  | Release a rigid body.

  Parameters
  pIBody
  [in] interface of a rigid body.
  Return
  SPE_OK if the method succeeds, else return SPE_FAILED.
  Remarks
  Only the interface returned by ISPEWorld::CreateRigidBody can be released.

  virtual void DetectCollisions(SPEArray &RigidBodyList) = 0;

  | Detect collisions for a set of rigid bodies.

  Parameters
  RigidBodyList
  [in] a set of rigid bodies.
  Return
  Remarks
  For more information, see tutorial section in this document.

  virtual void AddGroupPhysicsFlag(int id0, int id1, SPEGROUPPHYSICSFLAG flag) = 0;

  | Add a flag to physics world for physics filter.

  Parameters
  id0
  [in] the first group id.
  id0
  [in] the second group id.
  flag
  [in] physics filter flag.
  Return
  Remarks

  virtual SPEGROUPPHYSICSFLAG GetGroupPhysicsFlag(int id0, int id1) = 0;

  | Query the flag for a pair of group.

  Parameters
  id0
  [in] the first group id.
  id0
  [in] the second group id.
  Return
  physics filter flag.
  Remarks
  If no matched pair is found, return SPE_PHYSICS_FULL.

  virtual void DeleteGroupPhysicsFlag(int id0, int id1) = 0;

  | Delete a flag for a pair of group.

  Parameters
  id0
  [in] the first group id.
  id0
  [in] the second group id.
  Return
  Remarks

  virtual int GetNumGroupPhysicsFlags() = 0;

  | Get the number of flags in physics world.

  Parameters
  Return
  number of flags.
  Remarks

  virtual void ClearGroupPhysicsFlag() = 0;

  | Delete all flags.

  Parameters
  Return
  Remarks

  virtual int GetBreakList() = 0;

  | Get the list of rigid bodies that need to break.

  Parameters
  Return
  size of list.
  Remarks
  list is stored in the ISPEWorld::List.

  virtual void Carve(ISPERigidBody* ibody, SPEPlane &knife) = 0;

  | Carve a rigid body by a plane.

  Parameters
  ibody
  [in] interface of a rigid body to be carved.
  knife
  [in] a plane representing a knife.
  Return
  Remarks
  The result is a list of SPEMesh, which stored in the SPEWorld::Meshes.

  virtual void Carve(ISPERigidBody* ibody, SPEArray &knives) = 0;

  | Carve a rigid body by a collection of planes.

  Parameters
  ibody
  [in] interface of a rigid body to be carved.
  knives
  [in] a collection of planes.
  Return
  Remarks
  The result is a list of SPEMesh, which stored in the SPEWorld::Meshes.

  virtual bool CastRay(SPEVector &RayPos, SPEVector &RayDir, SPECastRayInfo &Info) = 0; // find the nearest intersection

  | Cast a ray to find the nearest intersection.

  Parameters
  RayPos
  [in] start position of the ray.
  RayDir
  [in] direction of the ray.
  Info
  [out] Intersect information of this test.
  Return
  true if the ray hits some thing, else return false.
  Remarks
  To test if a ray hits an appointed body, use SPERigidBody::CastRay(...).

  ISPEShape* Shape;

  | A shape interface to bring some conveniences while using SPE

  Parameters
  Return
  Remarks

  SPEArray<SPEMesh> Meshes;

  | A list of SPEMesh to store the result of Carve(...).

  Parameters
  Return
  Remarks

  SPEArray<ISPERigidBody*> List;

  | A list of rigid bodies to store the result of some functions.

  Parameters
  Return
  Remarks

  protected:
  ISPEWorld(){}
  virtual ~ISPEWorld(){}
  };

© 2006-2008, spehome.com, All rights reserved.