From 7334bb2ec1503147f1e6c4707c8c1ce1b2043d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20=E2=80=98Touky=E2=80=99=20Huet?= Date: Thu, 16 Aug 2012 17:14:07 +0000 Subject: [PATCH] Added Base/Attachment Logic, works with Kinematic & Ghost. --- test/BtPhysTest.cpp | 273 +++--------------- test/BtPhysTest.h | 20 +- test/PhysicObject.h | 103 ++++--- .../Physics/Include/EasyCharacterController.h | 4 +- test/Physics/Include/EasyPhysics.h | 47 ++- test/Physics/Src/EasyPhysics.cpp | 30 +- 6 files changed, 167 insertions(+), 310 deletions(-) diff --git a/test/BtPhysTest.cpp b/test/BtPhysTest.cpp index 6d863a49..379ffdac 100644 --- a/test/BtPhysTest.cpp +++ b/test/BtPhysTest.cpp @@ -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;i3) - { - 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;igetCollisionObjectArray()[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) diff --git a/test/BtPhysTest.h b/test/BtPhysTest.h index 3c515be3..8d5afa31 100644 --- a/test/BtPhysTest.h +++ b/test/BtPhysTest.h @@ -31,25 +31,7 @@ private: Array m_platform_list; Array 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 m_bt_collision_shapes; - Array m_bt_dynamic_shapes; -#endif + float m_loop_value; }; #endif // __BTPHYSTEST_H__ diff --git a/test/PhysicObject.h b/test/PhysicObject.h index cfef2973..7aba56dc 100644 --- a/test/PhysicObject.h +++ b/test/PhysicObject.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<SetCollisionChannel(0, 0xFF); + //m_physics->SetCollisionChannel(ColGroup, (1<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__ */ diff --git a/test/Physics/Include/EasyCharacterController.h b/test/Physics/Include/EasyCharacterController.h index 0af018e1..812d5526 100644 --- a/test/Physics/Include/EasyCharacterController.h +++ b/test/Physics/Include/EasyCharacterController.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; diff --git a/test/Physics/Include/EasyPhysics.h b/test/Physics/Include/EasyPhysics.h index 2cd770ae..a494c49a 100644 --- a/test/Physics/Include/EasyPhysics.h +++ b/test/Physics/Include/EasyPhysics.h @@ -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 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 m_touching_physic; //Maintained by ghost objects }; } /* namespace phys */ diff --git a/test/Physics/Src/EasyPhysics.cpp b/test/Physics/Src/EasyPhysics.cpp index 54a64a5a..8fe6fdd5 100644 --- a/test/Physics/Src/EasyPhysics.cpp +++ b/test/Physics/Src/EasyPhysics.cpp @@ -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))); + } } //-------------------------------------------------------------------------