Added RayCastResult & a naïve integration for EasyCharacterController. Enjoy !legacy
| @@ -45,8 +45,10 @@ protected: | |||||
| { | { | ||||
| GAMEGROUP_BEFORE = 0, | GAMEGROUP_BEFORE = 0, | ||||
| GAMEGROUP_DEFAULT, | GAMEGROUP_DEFAULT, | ||||
| GAMEGROUP_AFTER, | |||||
| // Must be the last element | |||||
| GAMEGROUP_AFTER, | |||||
| GAMEGROUP_AFTER_POST, | |||||
| // Must be the last element | |||||
| GAMEGROUP_END | GAMEGROUP_END | ||||
| } | } | ||||
| m_gamegroup; | m_gamegroup; | ||||
| @@ -16,6 +16,7 @@ | |||||
| #if !defined __LOL_INPUT_INPUT_H__ | #if !defined __LOL_INPUT_INPUT_H__ | ||||
| #define __LOL_INPUT_INPUT_H__ | #define __LOL_INPUT_INPUT_H__ | ||||
| #include <cstring> | |||||
| #include "lol/math/vector.h" | #include "lol/math/vector.h" | ||||
| #include "input/stick.h" | #include "input/stick.h" | ||||
| @@ -108,7 +109,7 @@ struct ActionSetting | |||||
| ActionSetting(int NewActionId) | ActionSetting(int NewActionId) | ||||
| { | { | ||||
| //memset(this, 0, sizeof(ActionSetting)); | |||||
| memset(this, 0, sizeof(ActionSetting)); | |||||
| ActionId = NewActionId; | ActionId = NewActionId; | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -122,7 +123,7 @@ struct ButtonSetting | |||||
| ButtonSetting(int NewRawButtonId) | ButtonSetting(int NewRawButtonId) | ||||
| { | { | ||||
| //memset(this, 0, sizeof(ButtonSetting)); | |||||
| memset(this, 0, sizeof(ButtonSetting)); | |||||
| RawButtonId = NewRawButtonId; | RawButtonId = NewRawButtonId; | ||||
| } | } | ||||
| int GetActionSettingIdx(int ActionId) | int GetActionSettingIdx(int ActionId) | ||||
| @@ -51,13 +51,15 @@ int gNumObjects = 64; | |||||
| #define USE_WALL 1 | #define USE_WALL 1 | ||||
| #define USE_PLATFORM 1 | #define USE_PLATFORM 1 | ||||
| #define USE_ROPE 1 | |||||
| #define USE_BODIES 1 | |||||
| #define USE_ROPE 0 | |||||
| #define USE_BODIES 0 | |||||
| #define USE_ROTATION 0 | #define USE_ROTATION 0 | ||||
| #define USE_CHARACTER 1 | #define USE_CHARACTER 1 | ||||
| BtPhysTest::BtPhysTest(bool editor) | BtPhysTest::BtPhysTest(bool editor) | ||||
| { | { | ||||
| m_loop_value = .0f; | |||||
| /* Create a camera that matches the settings of XNA BtPhysTest */ | /* Create a camera that matches the settings of XNA BtPhysTest */ | ||||
| m_camera = new Camera(vec3(0.f, 600.f, 0.f), | m_camera = new Camera(vec3(0.f, 600.f, 0.f), | ||||
| vec3(0.f, 0.f, 0.f), | vec3(0.f, 0.f, 0.f), | ||||
| @@ -107,6 +109,7 @@ BtPhysTest::BtPhysTest(bool editor) | |||||
| } | } | ||||
| } | } | ||||
| PhysicsObject* BasePhyobj = NULL; | |||||
| if (USE_PLATFORM) | if (USE_PLATFORM) | ||||
| { | { | ||||
| quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | ||||
| @@ -117,16 +120,16 @@ BtPhysTest::BtPhysTest(bool editor) | |||||
| m_platform_list << NewPhyobj; | m_platform_list << NewPhyobj; | ||||
| Ticker::Ref(NewPhyobj); | Ticker::Ref(NewPhyobj); | ||||
| NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f); | |||||
| NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f); | |||||
| NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | ||||
| PhysicsObject* BasePhyobj = NewPhyobj; | |||||
| BasePhyobj = NewPhyobj; | |||||
| m_platform_list << NewPhyobj; | m_platform_list << NewPhyobj; | ||||
| Ticker::Ref(NewPhyobj); | Ticker::Ref(NewPhyobj); | ||||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f); | NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f); | ||||
| NewPosition = pos_offset + vec3(-25.0f, -25.0f, 5.0f); | |||||
| NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f); | |||||
| NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | ||||
| @@ -134,30 +137,32 @@ BtPhysTest::BtPhysTest(bool editor) | |||||
| m_platform_list << NewPhyobj; | m_platform_list << NewPhyobj; | ||||
| Ticker::Ref(NewPhyobj); | Ticker::Ref(NewPhyobj); | ||||
| NewPosition += vec3(-0.0f, .0f, .0f); | |||||
| NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||||
| //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); | |||||
| //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); | |||||
| //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); | |||||
| //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false); | |||||
| //m_platform_list << NewPhyobj; | |||||
| //Ticker::Ref(NewPhyobj); | |||||
| } | } | ||||
| if (USE_CHARACTER) | if (USE_CHARACTER) | ||||
| { | { | ||||
| quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | ||||
| vec3 NewPosition = pos_offset + vec3(-15.0f, 20.0f, .0f); | |||||
| vec3 NewPosition = pos_offset + vec3(-15.0f, -10.0f, .0f); | |||||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2); | PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2); | ||||
| m_character_list << NewPhyobj; | m_character_list << NewPhyobj; | ||||
| Ticker::Ref(NewPhyobj); | Ticker::Ref(NewPhyobj); | ||||
| //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true); | |||||
| } | } | ||||
| if (USE_BODIES) | if (USE_BODIES) | ||||
| @@ -280,8 +285,9 @@ void BtPhysTest::TickGame(float seconds) | |||||
| } | } | ||||
| else if (i == 1) | else if (i == 1) | ||||
| { | { | ||||
| 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))); | |||||
| 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)); | PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | ||||
| } | } | ||||
| } | } | ||||
| @@ -293,12 +299,20 @@ void BtPhysTest::TickGame(float seconds) | |||||
| { | { | ||||
| PhysicsObject* PhysObj = m_character_list[i]; | PhysicsObject* PhysObj = m_character_list[i]; | ||||
| EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter(); | EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter(); | ||||
| mat4 CtlrMx = Character->GetTransform(); | |||||
| int HMovement = Input::GetButtonState(275 /*SDLK_RIGHT*/) - Input::GetButtonState(276 /*SDLK_LEFT*/); | int HMovement = Input::GetButtonState(275 /*SDLK_RIGHT*/) - Input::GetButtonState(276 /*SDLK_LEFT*/); | ||||
| int VMovement = Input::GetButtonState(273 /*SDLK_UP*/) - Input::GetButtonState(274 /*SDLK_DOWN*/); | int VMovement = Input::GetButtonState(273 /*SDLK_UP*/) - Input::GetButtonState(274 /*SDLK_DOWN*/); | ||||
| int RMovement = Input::GetButtonState(280 /*SDLK_PAGEUP*/) - Input::GetButtonState(281 /*SDLK_PAGEDOWN*/); | int RMovement = Input::GetButtonState(280 /*SDLK_PAGEUP*/) - Input::GetButtonState(281 /*SDLK_PAGEDOWN*/); | ||||
| vec3 CharMove = vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f); | |||||
| Character->SetMovementForFrame(CharMove); | |||||
| Character->SetMovementForFrame(vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f)); | |||||
| RayCastResult HitResult; | |||||
| if (m_simulation->RayHits(HitResult, ERT_Closest, Character->GetTransform().v3.xyz, (Character->GetTransform().v3.xyz + vec3(.0f, -1.f, .0f)), Character)) | |||||
| Character->AttachTo(HitResult.m_collider_list[0], true, true); | |||||
| else | |||||
| Character->AttachTo(NULL); | |||||
| } | } | ||||
| } | } | ||||
| @@ -319,8 +333,8 @@ void BtPhysTest::TickGame(float seconds) | |||||
| PhysObjBarycenter /= factor; | PhysObjBarycenter /= factor; | ||||
| m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget())); | m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget())); | ||||
| vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 20.0f, .0f); | |||||
| m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 5.0f); | |||||
| vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f); | |||||
| m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -219,14 +219,6 @@ public: | |||||
| 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() | lol::mat4 GetTransform() | ||||
| { | { | ||||
| if (m_is_character) | if (m_is_character) | ||||
| @@ -29,7 +29,8 @@ namespace lol | |||||
| namespace phys | namespace phys | ||||
| { | { | ||||
| class EasyCharacterController : public EasyPhysic | |||||
| class EasyCharacterController : public EasyPhysic, | |||||
| public Entity | |||||
| { | { | ||||
| #ifdef HAVE_PHYS_USE_BULLET | #ifdef HAVE_PHYS_USE_BULLET | ||||
| @@ -37,8 +38,14 @@ class EasyCharacterController : public EasyPhysic | |||||
| public: | public: | ||||
| EasyCharacterController(WorldEntity* NewOwnerEntity) : | EasyCharacterController(WorldEntity* NewOwnerEntity) : | ||||
| EasyPhysic(NewOwnerEntity), | EasyPhysic(NewOwnerEntity), | ||||
| m_character(NULL) | |||||
| m_pair_caching_object(NULL), | |||||
| m_character(NULL), | |||||
| m_step_height(.0f), | |||||
| m_base_is_updating(false), | |||||
| m_base_cached_movement(vec3(0.f)), | |||||
| m_frame_cached_movement(vec3(0.f)) | |||||
| { | { | ||||
| m_gamegroup = GAMEGROUP_EZP_CHAR_CTRLR; | |||||
| m_up_axis = 1; | m_up_axis = 1; | ||||
| } | } | ||||
| ~EasyCharacterController() | ~EasyCharacterController() | ||||
| @@ -52,15 +59,24 @@ public: | |||||
| virtual void RemoveFromSimulation(class Simulation* current_simulation); | virtual void RemoveFromSimulation(class Simulation* current_simulation); | ||||
| virtual void SetMovementForFrame(vec3 const &MoveQuantity); | virtual void SetMovementForFrame(vec3 const &MoveQuantity); | ||||
| virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation); | |||||
| protected: | |||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | |||||
| public: | |||||
| virtual void TickGame(float seconds); | |||||
| protected: | protected: | ||||
| virtual btGhostObject* GetGhostObject(); | |||||
| virtual btGhostObject* GetGhostObjectInstance(); | |||||
| btPairCachingGhostObject* m_pair_caching_object; | btPairCachingGhostObject* m_pair_caching_object; | ||||
| btKinematicCharacterController* m_character; | btKinematicCharacterController* m_character; | ||||
| float m_step_height; | float m_step_height; | ||||
| int m_up_axis; | int m_up_axis; | ||||
| bool m_base_is_updating; | |||||
| vec3 m_base_cached_movement; | |||||
| vec3 m_frame_cached_movement; | |||||
| #else // NO PHYSIC IMPLEMENTATION | #else // NO PHYSIC IMPLEMENTATION | ||||
| @@ -34,6 +34,7 @@ class EasyPhysic | |||||
| { | { | ||||
| friend class EasyConstraint; | friend class EasyConstraint; | ||||
| friend class Simulation; | |||||
| #ifdef HAVE_PHYS_USE_BULLET | #ifdef HAVE_PHYS_USE_BULLET | ||||
| @@ -48,8 +49,9 @@ public: | |||||
| virtual void SetShapeToCapsule(float radius, float height); | virtual void SetShapeToCapsule(float radius, float height); | ||||
| virtual bool CanChangeCollisionChannel() { return (m_rigid_body == NULL); } | virtual bool CanChangeCollisionChannel() { return (m_rigid_body == NULL); } | ||||
| virtual mat4 GetTransform(); | |||||
| virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))); | virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))); | ||||
| private: | |||||
| protected: | |||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | ||||
| public: | public: | ||||
| virtual void SetMass(float mass); | virtual void SetMass(float mass); | ||||
| @@ -57,13 +59,12 @@ public: | |||||
| virtual void InitBodyToGhost(); | virtual void InitBodyToGhost(); | ||||
| virtual void AddToSimulation(class Simulation* current_simulation); | virtual void AddToSimulation(class Simulation* current_simulation); | ||||
| virtual void RemoveFromSimulation(class Simulation* current_simulation); | virtual void RemoveFromSimulation(class Simulation* current_simulation); | ||||
| virtual mat4 GetTransform(); | |||||
| protected: | protected: | ||||
| virtual void SetLocalInertia(float mass); | virtual void SetLocalInertia(float mass); | ||||
| virtual void SetShapeTo(btCollisionShape* collision_shape); | virtual void SetShapeTo(btCollisionShape* collision_shape); | ||||
| virtual btGhostObject* GetGhostObject(); | |||||
| virtual btGhostObject* GetGhostObjectInstance(); | |||||
| btCollisionObject* m_collision_object; | btCollisionObject* m_collision_object; | ||||
| @@ -88,6 +89,7 @@ public: | |||||
| virtual void SetShapeToCapsule(float radius, float height) { } | virtual void SetShapeToCapsule(float radius, float height) { } | ||||
| virtual bool CanChangeCollisionChannel() { return true; } | virtual bool CanChangeCollisionChannel() { return true; } | ||||
| virtual mat4 GetTransform() { return mat4(1.0f); } | |||||
| virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))) { } | virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f))) { } | ||||
| private: | private: | ||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | ||||
| @@ -97,7 +99,6 @@ public: | |||||
| virtual void InitBodyToGhost() { } | virtual void InitBodyToGhost() { } | ||||
| virtual void AddToSimulation(class Simulation* current_simulation) { } | virtual void AddToSimulation(class Simulation* current_simulation) { } | ||||
| virtual void RemoveFromSimulation(class Simulation* current_simulation) { } | virtual void RemoveFromSimulation(class Simulation* current_simulation) { } | ||||
| virtual mat4 GetTransform() { return mat4(1.0f); } | |||||
| virtual void InitBodyToGhost() { } | virtual void InitBodyToGhost() { } | ||||
| @@ -122,7 +123,7 @@ public: | |||||
| //Base/Attachment logic | //Base/Attachment logic | ||||
| virtual void AttachTo(EasyPhysic* NewBase, bool NewBaseLockLocation = true, bool NewBaseLockRotation = true) | virtual void AttachTo(EasyPhysic* NewBase, bool NewBaseLockLocation = true, bool NewBaseLockRotation = true) | ||||
| { | { | ||||
| if (NewBase == this || NewBase->m_base_physic == this) | |||||
| if (NewBase == this || (NewBase && NewBase->m_base_physic == this)) | |||||
| return; | return; | ||||
| if (NewBase) | if (NewBase) | ||||
| @@ -137,11 +138,11 @@ public: | |||||
| m_base_lock_location = NewBaseLockLocation; | m_base_lock_location = NewBaseLockLocation; | ||||
| m_base_lock_rotation = NewBaseLockRotation; | m_base_lock_rotation = NewBaseLockRotation; | ||||
| } | } | ||||
| else | |||||
| else if (m_base_physic) | |||||
| { | { | ||||
| 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--); | |||||
| for (int i = 0; i < m_base_physic->m_based_physic_list.Count(); ++i) | |||||
| if (m_base_physic->m_based_physic_list[i] == this) | |||||
| m_base_physic->m_based_physic_list.Remove(i--); | |||||
| m_base_physic = NULL; | m_base_physic = NULL; | ||||
| } | } | ||||
| } | } | ||||
| @@ -19,6 +19,13 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| //Override Gamegroups names for Physic-useage | |||||
| //"_ENT_" means that this is a group for Entities that use EasyPhysic primitives. | |||||
| //"_EZP_" means that this is a group for EasyPhysic primitives. | |||||
| #define GAMEGROUP_ENT_PLATFORM GAMEGROUP_BEFORE | |||||
| #define GAMEGROUP_ENT_MAIN GAMEGROUP_DEFAULT | |||||
| #define GAMEGROUP_EZP_CHAR_CTRLR GAMEGROUP_AFTER | |||||
| #define GAMEGROUP_SIMULATION GAMEGROUP_AFTER_POST | |||||
| #ifdef HAVE_PHYS_USE_BULLET | #ifdef HAVE_PHYS_USE_BULLET | ||||
| @@ -31,6 +38,10 @@ namespace lol | |||||
| #define LOL2BT_VEC3(ELEMENT) btVector3((ELEMENT).x, (ELEMENT).y, (ELEMENT).z) | #define LOL2BT_VEC3(ELEMENT) btVector3((ELEMENT).x, (ELEMENT).y, (ELEMENT).z) | ||||
| #define BT2LOL_VEC3(ELEMENT) (*(lol::vec3*)(&(ELEMENT))) | #define BT2LOL_VEC3(ELEMENT) (*(lol::vec3*)(&(ELEMENT))) | ||||
| //Same as above with Unit taken into account | |||||
| #define LOL2BTU_VEC3(ELEMENT) btVector3((ELEMENT).x * LOL2BT_UNIT, (ELEMENT).y * LOL2BT_UNIT, (ELEMENT).z * LOL2BT_UNIT) | |||||
| #define BT2LOLU_VEC3(ELEMENT) (*(lol::vec3*)(&(ELEMENT))) * BT2LOL_UNIT | |||||
| #define LOL2BT_QUAT(ELEMENT) btQuaternion((ELEMENT).x, (ELEMENT).y, (ELEMENT).z, (ELEMENT).w) | #define LOL2BT_QUAT(ELEMENT) btQuaternion((ELEMENT).x, (ELEMENT).y, (ELEMENT).z, (ELEMENT).w) | ||||
| #define BT2LOL_QUAT(ELEMENT) lol::quat((ELEMENT).getW(), BT2LOL_VEC3((ELEMENT).getAxis()) | #define BT2LOL_QUAT(ELEMENT) lol::quat((ELEMENT).getW(), BT2LOL_VEC3((ELEMENT).getAxis()) | ||||
| @@ -9,8 +9,10 @@ | |||||
| #define __LOLPHYSICS_H__ | #define __LOLPHYSICS_H__ | ||||
| #ifdef HAVE_PHYS_USE_BULLET | #ifdef HAVE_PHYS_USE_BULLET | ||||
| #include <cstring> | |||||
| #include <bullet/btBulletDynamicsCommon.h> | #include <bullet/btBulletDynamicsCommon.h> | ||||
| #include <bullet/btBulletCollisionCommon.h> | #include <bullet/btBulletCollisionCommon.h> | ||||
| #include <BulletDynamics/Character/btKinematicCharacterController.h> | |||||
| #include "LolBtPhysicsIntegration.h" | #include "LolBtPhysicsIntegration.h" | ||||
| #include "EasyPhysics.h" | #include "EasyPhysics.h" | ||||
| #include "EasyConstraint.h" | #include "EasyConstraint.h" | ||||
| @@ -22,6 +24,42 @@ namespace lol | |||||
| namespace phys | namespace phys | ||||
| { | { | ||||
| enum eRaycastType | |||||
| { | |||||
| ERT_Closest, | |||||
| ERT_AllHit, | |||||
| ERT_AnyHit, //Will stop at the first hit. Hit data are supposed to be irrelevant | |||||
| ERT_MAX | |||||
| }; | |||||
| struct RayCastResult | |||||
| { | |||||
| RayCastResult(int CollisionFilterGroup=1, int CollisionFilterMask=(0xFF)) | |||||
| { | |||||
| memset(this, 0, sizeof(RayCastResult)); | |||||
| m_collision_filter_group = CollisionFilterGroup; | |||||
| m_collision_filter_mask = CollisionFilterMask; | |||||
| } | |||||
| void Reset() | |||||
| { | |||||
| m_collider_list.Empty(); | |||||
| m_hit_normal_list.Empty(); | |||||
| m_hit_point_list.Empty(); | |||||
| m_hit_fraction_list.Empty(); | |||||
| } | |||||
| Array<EasyPhysic*> m_collider_list; | |||||
| Array<vec3> m_hit_normal_list; | |||||
| Array<vec3> m_hit_point_list; | |||||
| Array<float> m_hit_fraction_list; | |||||
| short int m_collision_filter_group; | |||||
| short int m_collision_filter_mask; | |||||
| unsigned int m_flags; //??? | |||||
| }; | |||||
| class Simulation : public Entity | class Simulation : public Entity | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -33,6 +71,7 @@ public: | |||||
| m_dynamics_world(0), | m_dynamics_world(0), | ||||
| m_timestep(1.f/60.f) | m_timestep(1.f/60.f) | ||||
| { | { | ||||
| m_gamegroup = GAMEGROUP_SIMULATION; | |||||
| } | } | ||||
| ~Simulation() | ~Simulation() | ||||
| { | { | ||||
| @@ -79,6 +118,111 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| //Reap-Off of the btKinematicClosestNotMeRayResultCallback | |||||
| class LolClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback | |||||
| { | |||||
| public: | |||||
| LolClosestNotMeRayResultCallback(btCollisionObject* Me, const btVector3& rayFromWorld, const btVector3& rayToWorld) : | |||||
| btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld) | |||||
| { | |||||
| m_me = Me; | |||||
| } | |||||
| virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) | |||||
| { | |||||
| if (rayResult.m_collisionObject == m_me) | |||||
| return 1.0; | |||||
| return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); | |||||
| } | |||||
| protected: | |||||
| btCollisionObject* m_me; | |||||
| }; | |||||
| //Will stop at the first hit. Hit data are supposed to be irrelevant | |||||
| class AnyHitRayResultCallback : public btCollisionWorld::ClosestRayResultCallback | |||||
| { | |||||
| public: | |||||
| AnyHitRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld) : | |||||
| btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld) | |||||
| { | |||||
| } | |||||
| virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) | |||||
| { | |||||
| return .0f; | |||||
| } | |||||
| }; | |||||
| //Returns true when hitting something. If SourceCaster is set, it will be ignored by Raycast. | |||||
| bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL) | |||||
| { | |||||
| bool bResult = false; | |||||
| btCollisionWorld::RayResultCallback* BtRayResult = NULL; | |||||
| btCollisionWorld::ClosestRayResultCallback* BtRayResult_Closest; | |||||
| btCollisionWorld::AllHitsRayResultCallback* BtRayResult_AllHits; | |||||
| switch (RaycastType) | |||||
| { | |||||
| case ERT_Closest: | |||||
| { | |||||
| if (SourceCaster) | |||||
| BtRayResult_Closest = new LolClosestNotMeRayResultCallback(SourceCaster->m_collision_object, LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo)); | |||||
| else | |||||
| BtRayResult_Closest = new btCollisionWorld::ClosestRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo)); | |||||
| BtRayResult = BtRayResult_Closest; | |||||
| break; | |||||
| } | |||||
| case ERT_AllHit: | |||||
| { | |||||
| BtRayResult_AllHits = new btCollisionWorld::AllHitsRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo)); | |||||
| BtRayResult = BtRayResult_AllHits; | |||||
| break; | |||||
| } | |||||
| case ERT_AnyHit: | |||||
| { | |||||
| BtRayResult_Closest = new AnyHitRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo)); | |||||
| BtRayResult = BtRayResult_Closest; | |||||
| break; | |||||
| } | |||||
| } | |||||
| m_dynamics_world->rayTest(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo), *BtRayResult); | |||||
| if (BtRayResult->hasHit()) | |||||
| { | |||||
| bResult = true; | |||||
| switch (RaycastType) | |||||
| { | |||||
| case ERT_Closest: | |||||
| { | |||||
| HitResult.m_collider_list << (EasyPhysic*)BtRayResult_Closest->m_collisionObject->getUserPointer(); | |||||
| HitResult.m_hit_normal_list << BT2LOLU_VEC3(BtRayResult_Closest->m_hitNormalWorld); | |||||
| HitResult.m_hit_point_list << BT2LOLU_VEC3(BtRayResult_Closest->m_hitPointWorld); | |||||
| HitResult.m_hit_fraction_list << BtRayResult_Closest->m_closestHitFraction; | |||||
| break; | |||||
| } | |||||
| case ERT_AllHit: | |||||
| { | |||||
| for (int i = 0; i < BtRayResult_AllHits->m_collisionObjects.size(); i++) | |||||
| { | |||||
| HitResult.m_collider_list << (EasyPhysic*)BtRayResult_AllHits->m_collisionObjects[i]->getUserPointer(); | |||||
| HitResult.m_hit_normal_list << BT2LOLU_VEC3(BtRayResult_AllHits->m_hitNormalWorld[i]); | |||||
| HitResult.m_hit_point_list << BT2LOLU_VEC3(BtRayResult_AllHits->m_hitPointWorld[i]); | |||||
| HitResult.m_hit_fraction_list << BtRayResult_AllHits->m_hitFractions[i]; | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| delete BtRayResult; | |||||
| return bResult; | |||||
| } | |||||
| void Exit() | void Exit() | ||||
| { | { | ||||
| delete m_dynamics_world; | delete m_dynamics_world; | ||||
| @@ -128,6 +272,7 @@ private: | |||||
| public: | public: | ||||
| void Init() { } | void Init() { } | ||||
| void TickGame(float seconds) { } | void TickGame(float seconds) { } | ||||
| bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL) { return false; } | |||||
| void Exit() { } | void Exit() { } | ||||
| private: | private: | ||||
| void CustomSetContinuousDetection(bool ShouldUseCCD) { } | void CustomSetContinuousDetection(bool ShouldUseCCD) { } | ||||
| @@ -36,7 +36,7 @@ void EasyCharacterController::InitBodyToRigid(bool ZeroMassIsKinematic) | |||||
| } | } | ||||
| //Return correct Ghost Object | //Return correct Ghost Object | ||||
| btGhostObject* EasyCharacterController::GetGhostObject() | |||||
| btGhostObject* EasyCharacterController::GetGhostObjectInstance() | |||||
| { | { | ||||
| return new btPairCachingGhostObject(); | return new btPairCachingGhostObject(); | ||||
| } | } | ||||
| @@ -63,6 +63,7 @@ void EasyCharacterController::AddToSimulation(class Simulation* current_simulati | |||||
| m_character = new btKinematicCharacterController(m_pair_caching_object, m_convex_shape, m_step_height, m_up_axis); | m_character = new btKinematicCharacterController(m_pair_caching_object, m_convex_shape, m_step_height, m_up_axis); | ||||
| dynamics_world->addAction(m_character); | dynamics_world->addAction(m_character); | ||||
| Ticker::Ref(this); | |||||
| } | } | ||||
| } | } | ||||
| @@ -75,14 +76,50 @@ void EasyCharacterController::RemoveFromSimulation(class Simulation* current_sim | |||||
| if (dynamics_world) | if (dynamics_world) | ||||
| { | { | ||||
| if (m_character) | if (m_character) | ||||
| { | |||||
| dynamics_world->removeAction(m_character); | dynamics_world->removeAction(m_character); | ||||
| Ticker::Unref(this); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| //Set movement for this frame | //Set movement for this frame | ||||
| void EasyCharacterController::SetMovementForFrame(vec3 const &MoveQuantity) | void EasyCharacterController::SetMovementForFrame(vec3 const &MoveQuantity) | ||||
| { | { | ||||
| m_character->setWalkDirection(LOL2BT_VEC3(MoveQuantity)); | |||||
| m_frame_cached_movement = MoveQuantity; | |||||
| } | |||||
| //------------------------------------------------------------------------- | |||||
| //Base Location/Rotation setup | |||||
| //-- | |||||
| void EasyCharacterController::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | |||||
| { | |||||
| if (m_base_is_updating) | |||||
| { | |||||
| m_base_cached_movement = base_location - m_local_to_world.v3.xyz; | |||||
| m_local_to_world = lol::mat4::translate(m_local_to_world.v3.xyz) * lol::mat4(base_rotation); | |||||
| if (m_ghost_object) | |||||
| m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * m_local_to_world.v3.xyz))); | |||||
| } | |||||
| else | |||||
| EasyPhysic::SetTransform(base_location, base_rotation); | |||||
| } | |||||
| //Internal callback when Base transform has changed. | |||||
| void EasyCharacterController::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) | |||||
| { | |||||
| m_base_is_updating = true; | |||||
| EasyPhysic::BaseTransformChanged(PreviousMatrix, NewMatrix); | |||||
| m_base_is_updating = false; | |||||
| } | |||||
| //Physic Tick | |||||
| void EasyCharacterController::TickGame(float seconds) | |||||
| { | |||||
| Entity::TickGame(seconds); | |||||
| m_character->setVelocityForTimeInterval(LOL2BT_VEC3(LOL2BT_UNIT * /*0.1f **/ (m_base_cached_movement + m_frame_cached_movement)) / seconds, seconds); | |||||
| //m_character->setWalkDirection(); | |||||
| } | } | ||||
| #endif // HAVE_PHYS_USE_BULLET | #endif // HAVE_PHYS_USE_BULLET | ||||
| @@ -40,7 +40,8 @@ EasyPhysic::EasyPhysic(WorldEntity* NewOwnerEntity) : | |||||
| m_mass(.0f), | m_mass(.0f), | ||||
| m_collision_group(1), | m_collision_group(1), | ||||
| m_collision_mask(1), | m_collision_mask(1), | ||||
| m_owner_entity(NewOwnerEntity) | |||||
| m_owner_entity(NewOwnerEntity), | |||||
| m_base_physic(NULL) | |||||
| { | { | ||||
| } | } | ||||
| @@ -112,26 +113,45 @@ void EasyPhysic::SetShapeToCapsule(float radius, float height) | |||||
| //------------------------------------------------------------------------- | //------------------------------------------------------------------------- | ||||
| //Base Location/Rotation setup | //Base Location/Rotation setup | ||||
| //-- | //-- | ||||
| //Getter | |||||
| mat4 EasyPhysic::GetTransform() | |||||
| { | |||||
| m_local_to_world = lol::mat4(1.0f); | |||||
| if (m_rigid_body && m_motion_state) | |||||
| { | |||||
| btTransform CurTransform; | |||||
| m_motion_state->getWorldTransform(CurTransform); | |||||
| CurTransform.getOpenGLMatrix(&m_local_to_world[0][0]); | |||||
| } | |||||
| else if (m_collision_object) | |||||
| m_collision_object->getWorldTransform().getOpenGLMatrix(&m_local_to_world[0][0]); | |||||
| return m_local_to_world; | |||||
| } | |||||
| //Setter | |||||
| void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | ||||
| { | { | ||||
| lol::mat4 PreviousMatrix = m_local_to_world; | lol::mat4 PreviousMatrix = m_local_to_world; | ||||
| m_local_to_world = lol::mat4::translate(base_location) * lol::mat4(base_rotation); | m_local_to_world = lol::mat4::translate(base_location) * lol::mat4(base_rotation); | ||||
| if (m_ghost_object) | if (m_ghost_object) | ||||
| m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||||
| m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location))); | |||||
| else | else | ||||
| { | { | ||||
| if (m_motion_state) | if (m_motion_state) | ||||
| m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||||
| m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location))); | |||||
| else | else | ||||
| m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT))); | |||||
| m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location))); | |||||
| } | } | ||||
| for (int i = 0; i < m_based_physic_list.Count(); i++) | for (int i = 0; i < m_based_physic_list.Count(); i++) | ||||
| { | |||||
| if (m_based_physic_list[i]) | if (m_based_physic_list[i]) | ||||
| m_based_physic_list[i]->BaseTransformChanged(PreviousMatrix, m_local_to_world); | m_based_physic_list[i]->BaseTransformChanged(PreviousMatrix, m_local_to_world); | ||||
| else | else | ||||
| m_based_physic_list.Remove(i--); | m_based_physic_list.Remove(i--); | ||||
| } | |||||
| } | } | ||||
| //Internal callback when Base transform has changed. | //Internal callback when Base transform has changed. | ||||
| @@ -196,7 +216,7 @@ void EasyPhysic::InitBodyToRigid(bool SetToKinematic) | |||||
| } | } | ||||
| //Return correct Ghost Object | //Return correct Ghost Object | ||||
| btGhostObject* EasyPhysic::GetGhostObject() | |||||
| btGhostObject* EasyPhysic::GetGhostObjectInstance() | |||||
| { | { | ||||
| return new btGhostObject(); | return new btGhostObject(); | ||||
| } | } | ||||
| @@ -207,7 +227,7 @@ void EasyPhysic::InitBodyToGhost() | |||||
| if (m_collision_object) | if (m_collision_object) | ||||
| delete m_collision_object; | delete m_collision_object; | ||||
| m_ghost_object = GetGhostObject(); | |||||
| m_ghost_object = GetGhostObjectInstance(); | |||||
| m_ghost_object->setCollisionShape(m_collision_shape); | m_ghost_object->setCollisionShape(m_collision_shape); | ||||
| m_collision_object = m_ghost_object; | m_collision_object = m_ghost_object; | ||||
| m_collision_object->setUserPointer(this); | m_collision_object->setUserPointer(this); | ||||
| @@ -294,24 +314,6 @@ void EasyPhysic::RemoveFromSimulation(class Simulation* current_simulation) | |||||
| } | } | ||||
| } | } | ||||
| //------------------------------------------------------------------------- | |||||
| //Getter functons | |||||
| //-- | |||||
| mat4 EasyPhysic::GetTransform() | |||||
| { | |||||
| m_local_to_world = lol::mat4(1.0f); | |||||
| if (m_rigid_body && m_motion_state) | |||||
| { | |||||
| btTransform CurTransform; | |||||
| m_motion_state->getWorldTransform(CurTransform); | |||||
| CurTransform.getOpenGLMatrix(&m_local_to_world[0][0]); | |||||
| } | |||||
| else if (m_collision_object) | |||||
| m_collision_object->getWorldTransform().getOpenGLMatrix(&m_local_to_world[0][0]); | |||||
| return m_local_to_world; | |||||
| } | |||||
| //Set Local Inertia | //Set Local Inertia | ||||
| void EasyPhysic::SetLocalInertia(float mass) | void EasyPhysic::SetLocalInertia(float mass) | ||||
| { | { | ||||