| @@ -100,17 +100,47 @@ BtPhysTest::BtPhysTest(bool editor) | |||
| m_ground_list << NewPhyobj; | |||
| } | |||
| for (int x=0; x < 6; x++) | |||
| if (1) | |||
| { | |||
| for (int y=0; y < 6; y++) | |||
| for (int x=0; x < 6; x++) | |||
| { | |||
| for (int z=0; z < 5; z++) | |||
| for (int y=0; y < 6; y++) | |||
| { | |||
| PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f, | |||
| vec3(-20.f, 15.f, -20.f) + | |||
| vec3(8.f * (float)x, 8.f * (float)y, 8.f * (float)z)); | |||
| m_physobj_list << new_physobj; | |||
| Ticker::Ref(new_physobj); | |||
| for (int z=0; z < 5; z++) | |||
| { | |||
| PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f, | |||
| vec3(-20.f, 15.f, -20.f) + | |||
| vec3(8.f * (float)x, 8.f * (float)y, 8.f * (float)z)); | |||
| m_physobj_list << new_physobj; | |||
| Ticker::Ref(new_physobj); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| if (1) | |||
| { | |||
| Array<PhysicsObject*> RopeElements; | |||
| for (int i = 0; i < 14; i++) | |||
| { | |||
| PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f, | |||
| vec3(0.f, 15.f, -20.f) + | |||
| vec3(0.f, 0.f, 2.f * (float)i), 1); | |||
| RopeElements << new_physobj; | |||
| m_physobj_list << new_physobj; | |||
| Ticker::Ref(new_physobj); | |||
| if (RopeElements.Count() > 1) | |||
| { | |||
| EasyConstraint* new_constraint = new EasyConstraint(); | |||
| vec3 A2B = .5f * (RopeElements[i]->GetPhysic()->GetTransform().v3.xyz - | |||
| RopeElements[i - 1]->GetPhysic()->GetTransform().v3.xyz); | |||
| new_constraint->SetPhysObjA(RopeElements[i - 1]->GetPhysic(), lol::mat4::translate(A2B)); | |||
| new_constraint->SetPhysObjB(RopeElements[i]->GetPhysic(), lol::mat4::translate(-A2B)); | |||
| new_constraint->InitConstraintToPoint2Point(); | |||
| new_constraint->DisableCollisionBetweenObjs(true); | |||
| new_constraint->AddToSimulation(m_simulation); | |||
| m_constraint_list << new_constraint; | |||
| } | |||
| } | |||
| } | |||
| @@ -298,17 +328,20 @@ void BtPhysTest::TickGame(float seconds) | |||
| PhysObj->SetRender(true); | |||
| } | |||
| for (int i = 0; i < m_ground_list.Count(); i++) | |||
| if (1) | |||
| { | |||
| PhysicsObject* PhysObj = m_ground_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| mat4 CenterMx = mat4::translate(GroundBarycenter); | |||
| GroundMat = inverse(CenterMx) * GroundMat; | |||
| GroundMat = CenterMx * | |||
| mat4(quat::fromeuler_xyz(vec3(.0f, 20.f, 20.0f) * seconds)) | |||
| * GroundMat; | |||
| PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
| for (int i = 0; i < m_ground_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_ground_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| mat4 CenterMx = mat4::translate(GroundBarycenter); | |||
| GroundMat = inverse(CenterMx) * GroundMat; | |||
| GroundMat = CenterMx * | |||
| mat4(quat::fromeuler_xyz(vec3(.0f, 20.f, 20.0f) * seconds)) | |||
| * GroundMat; | |||
| PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
| } | |||
| } | |||
| PhysObjBarycenter = vec3(.0f); | |||
| @@ -403,16 +436,26 @@ void BtPhysTest::TickDraw(float seconds) | |||
| BtPhysTest::~BtPhysTest() | |||
| { | |||
| Ticker::Unref(m_camera); | |||
| while (m_constraint_list.Count()) | |||
| { | |||
| EasyConstraint* CurPop = m_constraint_list.Last(); | |||
| m_constraint_list.Pop(); | |||
| CurPop->RemoveFromSimulation(m_simulation); | |||
| delete CurPop; | |||
| } | |||
| while (m_ground_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_ground_list.Last(); | |||
| m_ground_list.Pop(); | |||
| CurPop->GetPhysic()->RemoveFromSimulation(m_simulation); | |||
| Ticker::Unref(CurPop); | |||
| } | |||
| while (m_physobj_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_physobj_list.Last(); | |||
| m_physobj_list.Pop(); | |||
| CurPop->GetPhysic()->RemoveFromSimulation(m_simulation); | |||
| Ticker::Unref(CurPop); | |||
| } | |||
| Ticker::Unref(m_simulation); | |||
| @@ -25,6 +25,7 @@ private: | |||
| bool m_ready; | |||
| lol::phys::Simulation* m_simulation; | |||
| Array<EasyConstraint*> m_constraint_list; | |||
| Array<PhysicsObject*> m_physobj_list; | |||
| Array<PhysicsObject*> m_ground_list; | |||
| @@ -34,7 +34,7 @@ public: | |||
| m_physics.AddToSimulation(new_sim); | |||
| } | |||
| PhysicsObject(Simulation* new_sim, float base_mass, const vec3 &base_location) | |||
| PhysicsObject(Simulation* new_sim, float base_mass, const vec3 &base_location, int RandValue = -1) | |||
| : m_ready(false), m_should_render(true) | |||
| { | |||
| Array<char *> MeshRand; | |||
| @@ -82,7 +82,38 @@ public: | |||
| MeshRand << "[sc#ada scb#ada acap3 2 1]"; | |||
| MeshRand << "[sc#aad scb#aad acap3 2 1]"; | |||
| int RandValue = (int)(lol::RandF() * (MeshRand.Count() - 1)); | |||
| switch (RandValue) | |||
| { | |||
| case 0: | |||
| { | |||
| RandValue = (int)(lol::RandF() * (SphereLimit - 1)); | |||
| break; | |||
| } | |||
| case 1: | |||
| { | |||
| RandValue = SphereLimit + (int)(lol::RandF() * ((ConeLimit - SphereLimit) - 1)); | |||
| break; | |||
| } | |||
| case 2: | |||
| { | |||
| RandValue = ConeLimit + (int)(lol::RandF() * ((CylLimit - ConeLimit) - 1)); | |||
| break; | |||
| } | |||
| case 3: | |||
| { | |||
| RandValue = CylLimit + (int)(lol::RandF() * ((CapsLimit - CylLimit) - 1)); | |||
| break; | |||
| } | |||
| case 4: | |||
| { | |||
| RandValue = CapsLimit + (int)(lol::RandF() * ((MeshRand.Count() - CapsLimit) - 1)); | |||
| break; | |||
| } | |||
| default: | |||
| { | |||
| RandValue = (int)(lol::RandF() * (MeshRand.Count() - 1)); | |||
| } | |||
| } | |||
| m_mesh.Compile(MeshRand[RandValue]); | |||
| vec3 BoxSize = vec3(2.0f); | |||
| @@ -113,7 +144,8 @@ public: | |||
| ColGroup += 4; | |||
| } | |||
| m_physics.SetCollisionChannel(ColGroup, (1<<ColGroup)|(1)); | |||
| 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(); | |||
| @@ -135,6 +167,9 @@ public: | |||
| m_should_render = should_render; | |||
| } | |||
| EasyMesh *GetMesh() { return &m_mesh; } | |||
| EasyPhysic *GetPhysic() { return &m_physics; } | |||
| ~PhysicsObject() | |||
| { | |||
| } | |||
| @@ -10,11 +10,6 @@ | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| // | |||
| // The EasyMesh class | |||
| // ------------------ | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| @@ -30,6 +25,10 @@ namespace phys | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| //------------------------------------------------------------------------- | |||
| //EASY_PHYSIC | |||
| //-- | |||
| EasyPhysic::EasyPhysic() : | |||
| m_collision_object(NULL), | |||
| m_rigid_body(NULL), | |||
| @@ -108,9 +107,9 @@ void EasyPhysic::SetShapeToCapsule(float radius, float height) | |||
| void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | |||
| { | |||
| if (m_motion_state) | |||
| m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location))); | |||
| m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||
| else | |||
| m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location))); | |||
| m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -156,16 +155,31 @@ void EasyPhysic::InitBodyToRigid(bool SetToKinematic) | |||
| void EasyPhysic::AddToSimulation(class Simulation* current_simulation) | |||
| { | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (m_rigid_body) | |||
| if (dynamics_world) | |||
| { | |||
| dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask); | |||
| if (m_mass != .0f) | |||
| current_simulation->AddToDynamic(this); | |||
| if (m_rigid_body) | |||
| { | |||
| dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask); | |||
| if (m_mass != .0f) | |||
| current_simulation->AddToDynamic(this); | |||
| else | |||
| current_simulation->AddToStatic(this); | |||
| } | |||
| else | |||
| current_simulation->AddToStatic(this); | |||
| dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask); | |||
| } | |||
| } | |||
| void EasyPhysic::RemoveFromSimulation(class Simulation* current_simulation) | |||
| { | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_rigid_body) | |||
| dynamics_world->removeRigidBody(m_rigid_body); | |||
| else | |||
| dynamics_world->removeCollisionObject(m_collision_object); | |||
| } | |||
| else | |||
| dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask); | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -195,6 +209,27 @@ void EasyPhysic::SetLocalInertia(float mass) | |||
| m_local_inertia = btVector3(.0f, .0f, .0f); | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| //EASY_CONSTRAINT | |||
| //-- | |||
| void EasyConstraint::AddToSimulation(class Simulation* current_simulation) | |||
| { | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world && m_typed_constraint) | |||
| { | |||
| dynamics_world->addConstraint(m_typed_constraint, m_disable_a2b_collision); | |||
| current_simulation->AddToConstraint(this); | |||
| } | |||
| } | |||
| void EasyConstraint::RemoveFromSimulation(class Simulation* current_simulation) | |||
| { | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world, m_typed_constraint) | |||
| dynamics_world->removeConstraint(m_typed_constraint); | |||
| } | |||
| #endif // HAVE_PHYS_USE_BULLET | |||
| } /* namespace phys */ | |||
| @@ -32,6 +32,8 @@ namespace phys | |||
| class EasyPhysic | |||
| { | |||
| friend class EasyConstraint; | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| public: | |||
| @@ -49,6 +51,7 @@ public: | |||
| void SetMass(float mass); | |||
| void InitBodyToRigid(bool ZeroMassIsKinematic=false); | |||
| void AddToSimulation(class Simulation* current_simulation); | |||
| void RemoveFromSimulation(class Simulation* current_simulation); | |||
| mat4 GetTransform(); | |||
| protected: | |||
| @@ -79,6 +82,7 @@ public: | |||
| void SetMass(float mass) { } | |||
| void InitBodyToRigid() { } | |||
| void AddToSimulation(class Simulation* current_simulation) { } | |||
| void RemoveFromSimulation(class Simulation* current_simulation) { } | |||
| mat4 GetTransform() { return mat4(1.0f); } | |||
| #endif // PHYSIC IMPLEMENTATION | |||
| @@ -108,23 +112,176 @@ protected: | |||
| class EasyConstraint | |||
| { | |||
| EasyConstraint() | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| public: | |||
| EasyConstraint() : | |||
| m_typed_constraint(NULL), | |||
| m_p2p_constraint(NULL), | |||
| m_hinge_constraint(NULL), | |||
| m_slider_constraint(NULL), | |||
| m_cone_twist_constraint(NULL), | |||
| m_6dof_constraint(NULL), | |||
| m_a_physobj(NULL), | |||
| m_b_physobj(NULL), | |||
| m_a_transform(lol::mat4(1.f)), | |||
| m_b_transform(lol::mat4(1.f)), | |||
| m_using_ref_a(false), | |||
| m_disable_a2b_collision(false) | |||
| { | |||
| } | |||
| ~EasyConstraint() | |||
| { | |||
| //btPoint2PointConstraint(bA, bB, PivotA, PivotB) | |||
| //btHingeConstraint(bA, bB, TransfA, TransfB, UseRefA) | |||
| //btSliderConstraint(bA, bB, TransfA, TransfB, UseRefA) | |||
| //btConeTwistConstraint(bA, bB, TransfA, TransfB) | |||
| //btGeneric6DofConstraint(bA, bB, TransfA, TransfB, UseRefA) | |||
| delete m_typed_constraint; | |||
| m_p2p_constraint = NULL; | |||
| m_hinge_constraint = NULL; | |||
| m_slider_constraint = NULL; | |||
| m_cone_twist_constraint = NULL; | |||
| m_6dof_constraint = NULL; | |||
| } | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| void AddToSimulation(class Simulation* current_simulation); | |||
| void RemoveFromSimulation(class Simulation* current_simulation); | |||
| private: | |||
| //check if Init can be done | |||
| bool CanProceedWithInit() | |||
| { | |||
| if (!m_a_physobj || !m_b_physobj) | |||
| return false; | |||
| if (!m_a_physobj->m_rigid_body || !m_b_physobj->m_rigid_body) | |||
| return false; | |||
| return true; | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| //Init constraint functions | |||
| //-- | |||
| void CustomInitConstraintToPoint2Point() | |||
| { | |||
| m_p2p_constraint = new btPoint2PointConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body, | |||
| LOL2BT_VEC3(m_a_transform.v3.xyz * LOL2BT_UNIT), LOL2BT_VEC3(m_b_transform.v3.xyz * LOL2BT_UNIT)); | |||
| m_typed_constraint = m_p2p_constraint; | |||
| } | |||
| void CustomInitConstraintToHinge() | |||
| { | |||
| m_hinge_constraint = new btHingeConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body, | |||
| btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform.v3.xyz * LOL2BT_UNIT)), | |||
| btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform.v3.xyz * LOL2BT_UNIT)), | |||
| m_using_ref_a); | |||
| m_typed_constraint = m_hinge_constraint; | |||
| } | |||
| void CustomInitConstraintToSlider() | |||
| { | |||
| m_slider_constraint = new btSliderConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body, | |||
| btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform.v3.xyz * LOL2BT_UNIT)), | |||
| btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform.v3.xyz * LOL2BT_UNIT)), | |||
| m_using_ref_a); | |||
| m_typed_constraint = m_slider_constraint; | |||
| } | |||
| void CustomInitConstraintToConeTwist() | |||
| { | |||
| m_cone_twist_constraint = new btConeTwistConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body, | |||
| btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform.v3.xyz * LOL2BT_UNIT)), | |||
| btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform.v3.xyz * LOL2BT_UNIT))); | |||
| m_typed_constraint = m_cone_twist_constraint; | |||
| } | |||
| void CustomInitConstraintTo6Dof() | |||
| { | |||
| m_6dof_constraint = new btGeneric6DofConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body, | |||
| btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform.v3.xyz * LOL2BT_UNIT)), | |||
| btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform.v3.xyz * LOL2BT_UNIT)), | |||
| m_using_ref_a); | |||
| m_typed_constraint = m_6dof_constraint; | |||
| } | |||
| btTypedConstraint* m_typed_constraint; | |||
| btPoint2PointConstraint* m_p2p_constraint; | |||
| btHingeConstraint* m_hinge_constraint; | |||
| btSliderConstraint* m_slider_constraint; | |||
| btConeTwistConstraint* m_cone_twist_constraint; | |||
| btGeneric6DofConstraint* m_6dof_constraint; | |||
| #else // NO PHYSIC IMPLEMENTATION | |||
| public: | |||
| EasyConstraint() : | |||
| m_a_physobj(NULL), | |||
| m_b_physobj(NULL), | |||
| m_a_transform(lol::mat4(1.f)), | |||
| m_b_transform(lol::mat4(1.f)), | |||
| m_using_ref_a(false), | |||
| m_disable_a2b_collision(false) | |||
| { | |||
| } | |||
| private: | |||
| void AddToSimulation(class Simulation* current_simulation) { } | |||
| void RemoveFromSimulation(class Simulation* current_simulation) { } | |||
| //check if Init can be done | |||
| bool CanProceedWithInit() { return false; } | |||
| void CustomInitConstraintToPoint2Point() { } | |||
| void CustomInitConstraintToHinge() { } | |||
| void CustomInitConstraintToSlider() { } | |||
| void CustomInitConstraintToConeTwist() { } | |||
| void CustomInitConstraintTo6Dof() { } | |||
| #endif // PHYSIC IMPLEMENTATION | |||
| public: | |||
| void InitConstraintToPoint2Point() { if (CanProceedWithInit()) CustomInitConstraintToPoint2Point(); } | |||
| void InitConstraintToHinge() { if (CanProceedWithInit()) CustomInitConstraintToHinge(); } | |||
| void InitConstraintToSlider() { if (CanProceedWithInit()) CustomInitConstraintToSlider(); } | |||
| void InitConstraintToConeTwist() { if (CanProceedWithInit()) CustomInitConstraintToConeTwist(); } | |||
| void InitConstraintTo6Dof() { if (CanProceedWithInit()) CustomInitConstraintTo6Dof(); } | |||
| //Set given physic object to the proper slot. | |||
| void SetPhysObjA(EasyPhysic* NewPhysObj, lol::mat4 NewTransform) { SetPhysObj(false, NewPhysObj, NewTransform); } | |||
| void SetPhysObjB(EasyPhysic* NewPhysObj, lol::mat4 NewTransform) { SetPhysObj(true, NewPhysObj, NewTransform); } | |||
| void SetPhysObj(bool SetToB, EasyPhysic* NewPhysObj, lol::mat4 NewTransform) | |||
| { | |||
| if (SetToB) | |||
| { | |||
| m_b_physobj = NewPhysObj; | |||
| m_b_transform = NewTransform; | |||
| } | |||
| else | |||
| { | |||
| m_a_physobj = NewPhysObj; | |||
| m_a_transform = NewTransform; | |||
| } | |||
| } | |||
| //Set whether or not the physic engine should use the A object as the reference (most constraint transform are local). | |||
| void SetRefAsA(bool NewUseRefA) | |||
| { | |||
| m_using_ref_a = NewUseRefA; | |||
| } | |||
| //Set whether or not to disable the collision between the bodies | |||
| void DisableCollisionBetweenObjs(bool DisableCollision) | |||
| { | |||
| m_disable_a2b_collision = DisableCollision; | |||
| } | |||
| private: | |||
| EasyPhysic* m_a_physobj; | |||
| EasyPhysic* m_b_physobj; | |||
| lol::mat4 m_a_transform; | |||
| lol::mat4 m_b_transform; | |||
| bool m_using_ref_a; | |||
| bool m_disable_a2b_collision; | |||
| }; | |||
| } /* namespace phys */ | |||