@@ -109,7 +109,7 @@ BtPhysTest::BtPhysTest(bool editor) | |||
if (USE_PLATFORM) | |||
{ | |||
quat NewRotation = quat::fromeuler_xyz(5.f, 0.f, 0.f); | |||
quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
vec3 NewPosition = pos_offset + vec3(5.0f, -25.0f, -15.0f); | |||
PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
@@ -119,8 +119,32 @@ BtPhysTest::BtPhysTest(bool editor) | |||
NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f); | |||
NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
PhysicsObject* BasePhyobj = NewPhyobj; | |||
m_platform_list << NewPhyobj; | |||
Ticker::Ref(NewPhyobj); | |||
NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f); | |||
NewPosition = pos_offset + vec3(-25.0f, -25.0f, 5.0f); | |||
NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, true); | |||
m_platform_list << NewPhyobj; | |||
Ticker::Ref(NewPhyobj); | |||
NewPosition += vec3(-0.0f, .0f, .0f); | |||
NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, false); | |||
m_platform_list << NewPhyobj; | |||
Ticker::Ref(NewPhyobj); | |||
NewPosition += vec3(-2.0f, .0f, .0f); | |||
NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false); | |||
m_platform_list << NewPhyobj; | |||
Ticker::Ref(NewPhyobj); | |||
} | |||
@@ -128,7 +152,7 @@ BtPhysTest::BtPhysTest(bool editor) | |||
if (USE_CHARACTER) | |||
{ | |||
quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
vec3 NewPosition = pos_offset + vec3(.0f, 20.0f, .0f); | |||
vec3 NewPosition = pos_offset + vec3(-15.0f, 20.0f, .0f); | |||
PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2); | |||
@@ -180,151 +204,6 @@ BtPhysTest::BtPhysTest(bool editor) | |||
} | |||
} | |||
} | |||
#if 0 | |||
//init Physics | |||
{ | |||
m_bt_ccd_mode = USE_CCD; | |||
//collision configuration contains default setup for memory, collision setup | |||
m_bt_collision_config = new btDefaultCollisionConfiguration(); | |||
//use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) | |||
m_bt_dispatcher = new btCollisionDispatcher(m_bt_collision_config); | |||
m_bt_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE, | |||
BOX_SHAPE_PROXYTYPE, | |||
m_bt_collision_config->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE, | |||
CONVEX_SHAPE_PROXYTYPE)); | |||
m_bt_broadphase = new btDbvtBroadphase(); | |||
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) | |||
m_bt_solver = new btSequentialImpulseConstraintSolver; | |||
m_bt_world = new btDiscreteDynamicsWorld(m_bt_dispatcher, m_bt_broadphase, m_bt_solver, m_bt_collision_config); | |||
//m_bt_world->setDebugDrawer(&sDebugDrawer); | |||
m_bt_world->getSolverInfo().m_splitImpulse = true; | |||
m_bt_world->getSolverInfo().m_numIterations = 20; | |||
m_bt_world->getDispatchInfo().m_useContinuous = (m_bt_ccd_mode == USE_CCD); | |||
m_bt_world->setGravity(btVector3(0,-10,0)); | |||
///create a few basic rigid bodies | |||
btBoxShape* box = new btBoxShape(btVector3(btScalar(110.),btScalar(1.),btScalar(110.))); | |||
btCollisionShape* groundShape = box; | |||
m_bt_collision_shapes << groundShape; | |||
m_ground_mesh.Compile("[sc#ddd afcb220 2 220 -1]"); | |||
//m_bt_collision_shapes << new btCylinderShape(btVector3(.5f,.5f,.5f)); | |||
btTransform groundTransform; | |||
groundTransform.setIdentity(); | |||
//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: | |||
{ | |||
btScalar mass(0.); | |||
//rigidbody is dynamic if and only if mass is non zero, otherwise static | |||
bool isDynamic = (mass != 0.f); | |||
btVector3 localInertia(0,0,0); | |||
if (isDynamic) | |||
groundShape->calculateLocalInertia(mass,localInertia); | |||
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects | |||
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); | |||
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); | |||
btRigidBody* body = new btRigidBody(rbInfo); | |||
//add the body to the dynamics world | |||
m_bt_world->addRigidBody(body); | |||
} | |||
//Adding Shapes | |||
{ | |||
//create a few dynamic rigidbodies | |||
// Re-using the same collision is better for memory usage and performance | |||
btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1)); | |||
m_rigid_mesh[0].Compile("[sc#add afcb2 2 2 -.1]"); | |||
m_rigid_mesh[1].Compile("[sc#dad afcb2 2 2 -.1]"); | |||
m_rigid_mesh[2].Compile("[sc#dda afcb2 2 2 -.1]"); | |||
m_rigid_mesh[3].Compile("[sc#daa afcb2 2 2 -.1]"); | |||
m_rigid_mesh[4].Compile("[sc#ada afcb2 2 2 -.1]"); | |||
m_rigid_mesh[5].Compile("[sc#aad afcb2 2 2 -.1]"); | |||
m_bt_collision_shapes << colShape; | |||
m_bt_dynamic_shapes << colShape; | |||
/// Create Dynamic Objects | |||
btTransform startTransform; | |||
startTransform.setIdentity(); | |||
btScalar mass(1.f); | |||
//rigidbody is dynamic if and only if mass is non zero, otherwise static | |||
bool isDynamic = (mass != 0.f); | |||
btVector3 localInertia(0,0,0); | |||
if (isDynamic) | |||
colShape->calculateLocalInertia(mass,localInertia); | |||
int i; | |||
for (i=0;i<gNumObjects;i++) | |||
{ | |||
btCollisionShape* shape = colShape; | |||
btTransform trans; | |||
trans.setIdentity(); | |||
//stack them | |||
int colsize = 10; | |||
int row = int(((float)i*CUBE_HALF_EXTENTS*2.0f)/((float)colsize*2.0f*CUBE_HALF_EXTENTS)); | |||
int row2 = row; | |||
int col = (i)%(colsize)-colsize/2; | |||
if (col>3) | |||
{ | |||
col=11; | |||
row2 |=1; | |||
} | |||
btVector3 pos(((row+col+row2) % 4)*CUBE_HALF_EXTENTS, | |||
20.0f + row*8*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT, | |||
col*8*CUBE_HALF_EXTENTS + 2 * (row2%2)*CUBE_HALF_EXTENTS); | |||
trans.setOrigin(pos); | |||
float mass = 1.f; | |||
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE)); | |||
//rigidbody is dynamic if and only if mass is non zero, otherwise static | |||
bool isDynamic = (mass != 0.f); | |||
btVector3 localInertia(0,0,0); | |||
if (isDynamic) | |||
shape->calculateLocalInertia(mass,localInertia); | |||
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects | |||
btDefaultMotionState* myMotionState = new btDefaultMotionState(trans); | |||
btRigidBody::btRigidBodyConstructionInfo cInfo(mass,myMotionState,shape,localInertia); | |||
btRigidBody* body = new btRigidBody(cInfo); | |||
body->setContactProcessingThreshold(BT_LARGE_FLOAT); | |||
m_bt_world->addRigidBody(body); | |||
///when using m_ccdMode | |||
if (m_bt_ccd_mode == USE_CCD) | |||
{ | |||
body->setCcdMotionThreshold(CUBE_HALF_EXTENTS); | |||
body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS); | |||
} | |||
} | |||
} | |||
} | |||
#endif | |||
} | |||
void BtPhysTest::TickGame(float seconds) | |||
@@ -334,6 +213,10 @@ void BtPhysTest::TickGame(float seconds) | |||
if (Input::GetButtonState(27 /*SDLK_ESCAPE*/)) | |||
Ticker::Shutdown(); | |||
m_loop_value += seconds; | |||
if (m_loop_value > M_PI * 2.0f) | |||
m_loop_value -= M_PI * 2.0f; | |||
vec3 GroundBarycenter = vec3(.0f); | |||
vec3 PhysObjBarycenter = vec3(.0f); | |||
float factor = .0f; | |||
@@ -395,11 +278,10 @@ void BtPhysTest::TickGame(float seconds) | |||
GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds)); | |||
PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
} | |||
else | |||
else if (i == 1) | |||
{ | |||
GroundMat = GroundMat * mat4::translate(vec3(.0f, .0f, 10.0f) * seconds); | |||
if (GroundMat.v3.z > 40.0f) | |||
GroundMat = GroundMat * mat4::translate(vec3(.0f, .0f, -80.0f)); | |||
GroundMat = mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) * | |||
mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * 20.f, .0f))); | |||
PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
} | |||
} | |||
@@ -458,17 +340,6 @@ void BtPhysTest::TickGame(float seconds) | |||
m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f); | |||
} | |||
#if 0 | |||
///step the simulation | |||
if (m_bt_world) | |||
{ | |||
//int steps = (int)(seconds / 0.005f); | |||
//for (int i = 0; i < steps; i++) | |||
m_bt_world->stepSimulation(seconds /*/ steps*/); | |||
//optional but useful: debug drawing | |||
//m_bt_world->debugDrawWorld(); | |||
} | |||
#endif | |||
} | |||
void BtPhysTest::TickDraw(float seconds) | |||
@@ -477,59 +348,12 @@ void BtPhysTest::TickDraw(float seconds) | |||
if (!m_ready) | |||
{ | |||
#if 0 | |||
m_ground_mesh.MeshConvert(); | |||
m_rigid_mesh[0].MeshConvert(); | |||
m_rigid_mesh[1].MeshConvert(); | |||
m_rigid_mesh[2].MeshConvert(); | |||
m_rigid_mesh[3].MeshConvert(); | |||
m_rigid_mesh[4].MeshConvert(); | |||
m_rigid_mesh[5].MeshConvert(); | |||
#endif | |||
/* FIXME: this object never cleans up */ | |||
m_ready = true; | |||
} | |||
//Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f)); | |||
#if 0 | |||
vec3 BarycenterLocation = vec3(.0f); | |||
float BarycenterFactor = 0.0f; | |||
for(int i=0;i<gNumObjects;i++) | |||
{ | |||
mat4 m(1.0f); | |||
btMatrix3x3 rot; rot.setIdentity(); | |||
btCollisionObject* colObj = m_bt_world->getCollisionObjectArray()[i]; | |||
btRigidBody* body = btRigidBody::upcast(colObj); | |||
if(body && body->getMotionState()) | |||
{ | |||
btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState(); | |||
myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(&m[0][0]); | |||
rot = myMotionState->m_graphicsWorldTrans.getBasis(); | |||
} | |||
else | |||
{ | |||
colObj->getWorldTransform().getOpenGLMatrix(&m[0][0]); | |||
rot = colObj->getWorldTransform().getBasis(); | |||
} | |||
if (i > 0) | |||
{ | |||
BarycenterLocation += m.v3.xyz; | |||
BarycenterFactor += 1.0f; | |||
} | |||
if (i == 0) | |||
m_ground_mesh.Render(m); | |||
else | |||
m_rigid_mesh[i % 6].Render(m); | |||
} | |||
if (BarycenterFactor > .0f) | |||
{ | |||
BarycenterLocation /= BarycenterFactor; | |||
m_camera->SetTarget(BarycenterLocation); | |||
m_camera->SetPosition(BarycenterLocation + vec3(-20.0f, 8.0f, .0f)); | |||
} | |||
#endif | |||
} | |||
BtPhysTest::~BtPhysTest() | |||
@@ -573,37 +397,6 @@ BtPhysTest::~BtPhysTest() | |||
} | |||
Ticker::Unref(m_simulation); | |||
#if 0 | |||
//Exit Physics | |||
{ | |||
//cleanup in the reverse order of creation/initialization | |||
//remove the rigidbodies from the dynamics world and delete them | |||
for (int i = m_bt_world->getNumCollisionObjects() - 1; i >= 0 ;i--) | |||
{ | |||
btCollisionObject* obj = m_bt_world->getCollisionObjectArray()[i]; | |||
btRigidBody* body = btRigidBody::upcast(obj); | |||
if (body && body->getMotionState()) | |||
delete body->getMotionState(); | |||
m_bt_world->removeCollisionObject(obj); | |||
delete obj; | |||
} | |||
//delete collision shapes | |||
for (int j = 0; j < m_bt_collision_shapes.Count(); j++) | |||
{ | |||
btCollisionShape* shape = m_bt_collision_shapes[j]; | |||
delete shape; | |||
} | |||
m_bt_collision_shapes.Empty(); | |||
delete m_bt_world; | |||
delete m_bt_solver; | |||
delete m_bt_broadphase; | |||
delete m_bt_dispatcher; | |||
delete m_bt_collision_config; | |||
} | |||
#endif | |||
} | |||
int main(int argc, char **argv) | |||
@@ -31,25 +31,7 @@ private: | |||
Array<PhysicsObject*> m_platform_list; | |||
Array<PhysicsObject*> m_character_list; | |||
#if 0 | |||
EasyMesh m_ground_mesh; | |||
EasyMesh m_rigid_mesh[6]; | |||
//Bullet Physics Datas | |||
enum | |||
{ | |||
USE_CCD=1, | |||
USE_NO_CCD | |||
}; | |||
int m_bt_ccd_mode; | |||
btDefaultCollisionConfiguration* m_bt_collision_config; | |||
btCollisionDispatcher* m_bt_dispatcher; | |||
btDbvtBroadphase* m_bt_broadphase; | |||
btSequentialImpulseConstraintSolver* m_bt_solver; | |||
btDiscreteDynamicsWorld* m_bt_world; | |||
Array<btCollisionShape*> m_bt_collision_shapes; | |||
Array<btCollisionShape*> m_bt_dynamic_shapes; | |||
#endif | |||
float m_loop_value; | |||
}; | |||
#endif // __BTPHYSTEST_H__ | |||
@@ -26,32 +26,37 @@ public: | |||
PhysicsObject(Simulation* new_sim, const vec3 &base_location, const quat &base_rotation) | |||
: m_ready(false), m_should_render(true), m_is_character(false) | |||
{ | |||
m_physics = new EasyPhysic(this); | |||
m_mesh.Compile("[sc#ddd afcb60 1 60 -.1]"); | |||
vec3 BoxSize = vec3(60.f, 1.f, 60.f); | |||
m_physics.SetCollisionChannel(0, 0xFF); | |||
m_physics.SetShapeToBox(BoxSize); | |||
m_physics.SetMass(.0f); | |||
m_physics.SetTransform(base_location, base_rotation); | |||
m_physics.InitBodyToRigid(true); | |||
m_physics.AddToSimulation(new_sim); | |||
m_physics->SetCollisionChannel(0, 0xFF); | |||
m_physics->SetShapeToBox(BoxSize); | |||
m_physics->SetMass(.0f); | |||
m_physics->SetTransform(base_location, base_rotation); | |||
m_physics->InitBodyToRigid(true); | |||
m_physics->AddToSimulation(new_sim); | |||
} | |||
PhysicsObject(Simulation* new_sim, const vec3 &base_location, const quat &base_rotation, int dummy) | |||
: m_ready(false), m_should_render(true), m_is_character(false) | |||
{ | |||
if (dummy == 1) //for Rope purpose | |||
if (dummy == 1) //for platform purpose | |||
{ | |||
m_physics = new EasyPhysic(this); | |||
m_mesh.Compile("[sc#ddd afcb20 1 20 -.1]"); | |||
vec3 BoxSize = vec3(20.f, 1.f, 20.f); | |||
m_physics.SetCollisionChannel(0, 0xFF); | |||
m_physics.SetShapeToBox(BoxSize); | |||
m_physics.SetMass(.0f); | |||
m_physics.SetTransform(base_location, base_rotation); | |||
m_physics.InitBodyToRigid(true); | |||
m_physics.AddToSimulation(new_sim); | |||
m_physics->SetCollisionChannel(0, 0xFF); | |||
m_physics->SetShapeToBox(BoxSize); | |||
m_physics->SetMass(.0f); | |||
m_physics->SetTransform(base_location, base_rotation); | |||
m_physics->InitBodyToRigid(true); | |||
m_physics->AddToSimulation(new_sim); | |||
} | |||
else if (dummy == 2) //for character purpose | |||
{ | |||
m_character = new EasyCharacterController(this); | |||
m_is_character = true; | |||
//m_mesh.Compile("[sc#f00 afcb10 10 10 -.1]"); | |||
m_mesh.Compile( | |||
@@ -77,12 +82,12 @@ public: | |||
" ty-.1 tx.05]" | |||
); | |||
vec3 BoxSize = vec3(.5f, 2.f, .5f); | |||
m_character.SetCollisionChannel(0, 0xFF); | |||
m_character.SetShapeToCapsule(BoxSize.x, BoxSize.y); | |||
m_character.SetMass(.0f); | |||
m_character.SetTransform(base_location, base_rotation); | |||
m_character.InitBodyToGhost(); | |||
m_character.AddToSimulation(new_sim); | |||
m_character->SetCollisionChannel(0, 0xFF); | |||
m_character->SetShapeToCapsule(BoxSize.x, BoxSize.y); | |||
m_character->SetMass(.0f); | |||
m_character->SetTransform(base_location, base_rotation); | |||
m_character->InitBodyToGhost(); | |||
m_character->AddToSimulation(new_sim); | |||
} | |||
} | |||
@@ -167,57 +172,67 @@ public: | |||
} | |||
} | |||
m_physics = new EasyPhysic(this); | |||
m_mesh.Compile(MeshRand[RandValue]); | |||
vec3 BoxSize = vec3(2.0f); | |||
int ColGroup = 1; | |||
if (RandValue < SphereLimit) | |||
{ | |||
m_physics.SetShapeToBox(BoxSize); | |||
m_physics->SetShapeToBox(BoxSize); | |||
ColGroup += 0; | |||
} | |||
else if (RandValue < ConeLimit) | |||
{ | |||
m_physics.SetShapeToSphere(BoxSize.x * 2.f); | |||
m_physics->SetShapeToSphere(BoxSize.x * 2.f); | |||
ColGroup += 1; | |||
} | |||
else if (RandValue < CylLimit) | |||
{ | |||
m_physics.SetShapeToCone(BoxSize.x, BoxSize.y); | |||
m_physics->SetShapeToCone(BoxSize.x, BoxSize.y); | |||
ColGroup += 2; | |||
} | |||
else if (RandValue < CapsLimit) | |||
{ | |||
m_physics.SetShapeToCylinder(BoxSize); | |||
m_physics->SetShapeToCylinder(BoxSize); | |||
ColGroup += 3; | |||
} | |||
else | |||
{ | |||
m_physics.SetShapeToCapsule(BoxSize.x, BoxSize.y); | |||
m_physics->SetShapeToCapsule(BoxSize.x, BoxSize.y); | |||
ColGroup += 4; | |||
} | |||
m_physics.SetCollisionChannel(0, 0xFF); | |||
//m_physics.SetCollisionChannel(ColGroup, (1<<ColGroup)|(1)); | |||
m_physics.SetMass(base_mass); | |||
m_physics.SetTransform(base_location); | |||
m_physics.InitBodyToRigid(); | |||
m_physics.AddToSimulation(new_sim); | |||
m_physics->SetCollisionChannel(0, 0xFF); | |||
//m_physics->SetCollisionChannel(ColGroup, (1<<ColGroup)|(1)); | |||
m_physics->SetMass(base_mass); | |||
m_physics->SetTransform(base_location); | |||
m_physics->InitBodyToRigid(); | |||
m_physics->AddToSimulation(new_sim); | |||
} | |||
void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))) | |||
{ | |||
if (m_is_character) | |||
m_character.SetTransform(base_location, base_rotation); | |||
m_character->SetTransform(base_location, base_rotation); | |||
else | |||
m_physics.SetTransform(base_location, base_rotation); | |||
m_physics->SetTransform(base_location, base_rotation); | |||
} | |||
void SetLinearVelocity(const lol::vec3& NewVelocity, bool bIsLocal=false) | |||
{ | |||
//if (m_is_character) | |||
// m_character->SetLinearVelocity(NewVelocity); | |||
//else | |||
// m_physics->SetLinearVelocity(NewVelocity); | |||
} | |||
lol::mat4 GetTransform() | |||
{ | |||
if (m_is_character) | |||
return m_character.GetTransform(); | |||
return m_character->GetTransform(); | |||
else | |||
return m_physics.GetTransform(); | |||
return m_physics->GetTransform(); | |||
} | |||
void SetRender(bool should_render) | |||
@@ -226,8 +241,8 @@ public: | |||
} | |||
EasyMesh *GetMesh() { return &m_mesh; } | |||
EasyPhysic *GetPhysic() { return &m_physics; } | |||
EasyPhysic *GetCharacter() { return &m_character; } | |||
EasyPhysic *GetPhysic() { return m_physics; } | |||
EasyPhysic *GetCharacter() { return m_character; } | |||
~PhysicsObject() | |||
{ | |||
@@ -254,21 +269,21 @@ protected: | |||
if (m_should_render) | |||
{ | |||
if (m_is_character) | |||
m_mesh.Render(m_character.GetTransform()); | |||
m_mesh.Render(m_character->GetTransform()); | |||
else | |||
m_mesh.Render(m_physics.GetTransform()); | |||
m_mesh.Render(m_physics->GetTransform()); | |||
} | |||
} | |||
private: | |||
//Base datas | |||
EasyMesh m_mesh; | |||
EasyPhysic m_physics; | |||
EasyCharacterController m_character; | |||
EasyMesh m_mesh; | |||
EasyPhysic* m_physics; | |||
EasyCharacterController* m_character; | |||
bool m_ready; | |||
bool m_should_render; | |||
bool m_is_character; | |||
bool m_ready; | |||
bool m_should_render; | |||
bool m_is_character; | |||
}; | |||
#endif /* __PHYSICOBJECT_H__ */ | |||
@@ -35,8 +35,8 @@ class EasyCharacterController : public EasyPhysic | |||
#ifdef HAVE_PHYS_USE_BULLET | |||
public: | |||
EasyCharacterController() : | |||
EasyPhysic(), | |||
EasyCharacterController(WorldEntity* NewOwnerEntity) : | |||
EasyPhysic(NewOwnerEntity), | |||
m_character(NULL) | |||
{ | |||
m_up_axis = 1; | |||
@@ -38,7 +38,7 @@ class EasyPhysic | |||
#ifdef HAVE_PHYS_USE_BULLET | |||
public: | |||
EasyPhysic(); | |||
EasyPhysic(WorldEntity* NewOwnerEntity); | |||
~EasyPhysic(); | |||
virtual void SetShapeToBox(lol::vec3& box_size); | |||
@@ -49,6 +49,9 @@ public: | |||
virtual bool CanChangeCollisionChannel() { return (m_rigid_body == NULL); } | |||
virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))); | |||
private: | |||
virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | |||
public: | |||
virtual void SetMass(float mass); | |||
virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false); | |||
virtual void InitBodyToGhost(); | |||
@@ -76,7 +79,7 @@ protected: | |||
#else // NO PHYSIC IMPLEMENTATION | |||
public: | |||
EasyPhysic() { } | |||
EasyPhysic(WorldEntity* NewOwnerEntity) { m_owner_entity = NewOwnerEntity; } | |||
virtual void SetShapeToBox(lol::vec3& BoxSize) { } | |||
virtual void SetShapeToSphere(float radius) { } | |||
@@ -86,6 +89,9 @@ public: | |||
virtual bool CanChangeCollisionChannel() { return true; } | |||
virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))) { } | |||
private: | |||
virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | |||
public: | |||
virtual void SetMass(float mass) { } | |||
virtual void InitBodyToRigid() { } | |||
virtual void InitBodyToGhost() { } | |||
@@ -113,11 +119,48 @@ public: | |||
int GetCollisionGroup() { return m_collision_group; } | |||
int GetCollisionMask() { return m_collision_mask; } | |||
//Base/Attachment logic | |||
virtual void AttachTo(EasyPhysic* NewBase, bool NewBaseLockLocation = true, bool NewBaseLockRotation = true) | |||
{ | |||
if (NewBase == this || NewBase->m_base_physic == this) | |||
return; | |||
if (NewBase) | |||
{ | |||
bool bAlreadyExists = false; | |||
for (int i = 0; i < NewBase->m_based_physic_list.Count(); ++i) | |||
if (NewBase->m_based_physic_list[i] == this) | |||
bAlreadyExists = true; | |||
if (!bAlreadyExists) | |||
NewBase->m_based_physic_list << this; | |||
m_base_physic = NewBase; | |||
m_base_lock_location = NewBaseLockLocation; | |||
m_base_lock_rotation = NewBaseLockRotation; | |||
} | |||
else | |||
{ | |||
for (int i = 0; i < NewBase->m_based_physic_list.Count(); ++i) | |||
if (NewBase->m_based_physic_list[i] == this) | |||
NewBase->m_based_physic_list.Remove(i--); | |||
m_base_physic = NULL; | |||
} | |||
} | |||
protected: | |||
lol::mat4 m_local_to_world; | |||
float m_mass; | |||
int m_collision_group; | |||
int m_collision_mask; | |||
WorldEntity* m_owner_entity; | |||
//Base/Attachment logic | |||
Array<EasyPhysic*> m_based_physic_list; //List of objects based on this : this object moves, its based object move with it. | |||
EasyPhysic* m_base_physic; //Base for this object : The base moves, the object moves with it. | |||
bool m_base_lock_location; //when this is TRUE, location moves with rotation change. | |||
bool m_base_lock_rotation; //when this is TRUE, rotation moves with rotation change. | |||
//Touch logic | |||
Array<EasyPhysic*> m_touching_physic; //Maintained by ghost objects | |||
}; | |||
} /* namespace phys */ | |||
@@ -29,7 +29,7 @@ namespace phys | |||
//EASY_PHYSIC | |||
//-- | |||
EasyPhysic::EasyPhysic() : | |||
EasyPhysic::EasyPhysic(WorldEntity* NewOwnerEntity) : | |||
m_collision_object(NULL), | |||
m_ghost_object(NULL), | |||
m_rigid_body(NULL), | |||
@@ -39,7 +39,8 @@ EasyPhysic::EasyPhysic() : | |||
m_motion_state(NULL), | |||
m_mass(.0f), | |||
m_collision_group(1), | |||
m_collision_mask(1) | |||
m_collision_mask(1), | |||
m_owner_entity(NewOwnerEntity) | |||
{ | |||
} | |||
@@ -113,7 +114,8 @@ void EasyPhysic::SetShapeToCapsule(float radius, float height) | |||
//-- | |||
void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | |||
{ | |||
m_local_to_world = lol::mat4::translate(base_location) * mat4(base_rotation); | |||
lol::mat4 PreviousMatrix = m_local_to_world; | |||
m_local_to_world = lol::mat4::translate(base_location) * lol::mat4(base_rotation); | |||
if (m_ghost_object) | |||
m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||
@@ -124,6 +126,28 @@ void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& b | |||
else | |||
m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||
} | |||
for (int i = 0; i < m_based_physic_list.Count(); i++) | |||
if (m_based_physic_list[i]) | |||
m_based_physic_list[i]->BaseTransformChanged(PreviousMatrix, m_local_to_world); | |||
else | |||
m_based_physic_list.Remove(i--); | |||
} | |||
//Internal callback when Base transform has changed. | |||
void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) | |||
{ | |||
mat4 PreviousMatrixLoc = ((m_base_lock_location)?(PreviousMatrix):(lol::mat4::translate(PreviousMatrix.v3.xyz))); | |||
mat4 PreviousMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(PreviousMatrix))):(lol::mat4(1.f))); | |||
mat4 NewMatrixLoc = ((m_base_lock_location)?(NewMatrix):(lol::mat4::translate(NewMatrix.v3.xyz))); | |||
mat4 NewMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(NewMatrix))):(lol::mat4(1.f))); | |||
if (m_ghost_object || (m_rigid_body->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT)) | |||
{ | |||
mat4 ThisMatrixLoc = NewMatrixLoc * inverse(PreviousMatrixLoc) * lol::mat4::translate(m_local_to_world.v3.xyz); | |||
mat4 ThisMatrixRot = NewMatrixRot * inverse(PreviousMatrixRot) * lol::mat4(lol::quat(m_local_to_world)); | |||
SetTransform(ThisMatrixLoc.v3.xyz, lol::mat4(lol::quat(ThisMatrixRot))); | |||
} | |||
} | |||
//------------------------------------------------------------------------- | |||