- fixed 1270 CR characters - fixed 56 trailing spaces - fixed 5085 tabslegacy
| @@ -240,45 +240,45 @@ void EasyMesh::Rotate(float t, vec3 const &axis) | |||
| void EasyMesh::RadialJitter(float r) | |||
| { | |||
| Array<int> Welded; | |||
| Welded.Push(-1); | |||
| Welded.Push(-1); | |||
| for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++) | |||
| { | |||
| int j, k; | |||
| for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++) | |||
| { | |||
| if(Welded[k] < 0) | |||
| { | |||
| vec3 diff = m_vert[i].m1 - m_vert[j].m1; | |||
| if(diff.x > 0.1f || diff.x < -0.1f) | |||
| continue; | |||
| if(diff.y > 0.1f || diff.y < -0.1f) | |||
| continue; | |||
| if(diff.z > 0.1f || diff.z < -0.1f) | |||
| continue; | |||
| break; | |||
| } | |||
| } | |||
| if(j == i) | |||
| Welded.Push(-1); | |||
| else | |||
| Welded.Push(j); | |||
| } | |||
| int i, j; | |||
| { | |||
| int j, k; | |||
| for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++) | |||
| { | |||
| if(Welded[k] < 0) | |||
| { | |||
| vec3 diff = m_vert[i].m1 - m_vert[j].m1; | |||
| if(diff.x > 0.1f || diff.x < -0.1f) | |||
| continue; | |||
| if(diff.y > 0.1f || diff.y < -0.1f) | |||
| continue; | |||
| if(diff.z > 0.1f || diff.z < -0.1f) | |||
| continue; | |||
| break; | |||
| } | |||
| } | |||
| if(j == i) | |||
| Welded.Push(-1); | |||
| else | |||
| Welded.Push(j); | |||
| } | |||
| int i, j; | |||
| for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++) | |||
| { | |||
| if(Welded[j] == -1) | |||
| m_vert[i].m1 *= 1.0f + RandF(r); | |||
| else | |||
| m_vert[i].m1 = m_vert[Welded[j]].m1; | |||
| } | |||
| { | |||
| if(Welded[j] == -1) | |||
| m_vert[i].m1 *= 1.0f + RandF(r); | |||
| else | |||
| m_vert[i].m1 = m_vert[Welded[j]].m1; | |||
| } | |||
| ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2); | |||
| ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2); | |||
| } | |||
| void EasyMesh::TaperX(float y, float z, float xoff) | |||
| @@ -361,10 +361,10 @@ void EasyMesh::AppendCylinder(int nsides, float h, float r1, float r2, | |||
| vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n; | |||
| /* Construct normal */ | |||
| if (r2 != .0f) | |||
| n = vec3(r2, h * .5f, 0.f); | |||
| else | |||
| n = vec3(r1, h * .5f, 0.f); | |||
| if (r2 != .0f) | |||
| n = vec3(r2, h * .5f, 0.f); | |||
| else | |||
| n = vec3(r1, h * .5f, 0.f); | |||
| n.y = r1 * (r1 - r2) / h; | |||
| if (!smooth) | |||
| n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n; | |||
| @@ -850,7 +850,7 @@ void EasyMesh::Chamfer(float f) | |||
| for (int i = 0; i < ilen / 3; i++) | |||
| { | |||
| } | |||
| /* Fun shit: reduce all triangles */ | |||
| @@ -45,11 +45,11 @@ protected: | |||
| { | |||
| GAMEGROUP_BEFORE = 0, | |||
| GAMEGROUP_DEFAULT, | |||
| GAMEGROUP_AFTER, | |||
| GAMEGROUP_AFTER_0, | |||
| GAMEGROUP_AFTER_1, | |||
| GAMEGROUP_AFTER, | |||
| GAMEGROUP_AFTER_0, | |||
| GAMEGROUP_AFTER_1, | |||
| // Must be the last element | |||
| // Must be the last element | |||
| GAMEGROUP_END | |||
| } | |||
| m_gamegroup; | |||
| @@ -31,7 +31,7 @@ namespace lol | |||
| * Input implementation class | |||
| */ | |||
| InputTracker* Input::m_input_tracker = NULL; | |||
| InputTracker* Input::m_input_tracker = NULL; | |||
| static class InputData | |||
| { | |||
| @@ -66,10 +66,10 @@ static InputData * const data = &inputdata; | |||
| int ButtonSetting::GetActionSettingIdx(ACTION_TYPE SearchAction) | |||
| { | |||
| for (int i = 0; i < m_associated_action_list.Count(); i++) | |||
| if (ACTION_CMP(m_associated_action_list[i].m_action, SearchAction)) | |||
| return i; | |||
| return -1; | |||
| for (int i = 0; i < m_associated_action_list.Count(); i++) | |||
| if (ACTION_CMP(m_associated_action_list[i].m_action, SearchAction)) | |||
| return i; | |||
| return -1; | |||
| } | |||
| /* | |||
| @@ -78,37 +78,37 @@ int ButtonSetting::GetActionSettingIdx(ACTION_TYPE SearchAction) | |||
| InputTracker::InputTracker() | |||
| { | |||
| m_gamegroup = GAMEGROUP_BEFORE; | |||
| m_gamegroup = GAMEGROUP_BEFORE; | |||
| for (int i = 0; i < Key::Last * 2; ++i) | |||
| m_input_status << 0; | |||
| for (int i = 0; i < Key::Last * 2; ++i) | |||
| m_input_status << 0; | |||
| Ticker::Ref(this); | |||
| Ticker::Ref(this); | |||
| } | |||
| //Internal | |||
| int InputTracker::GetButtonSettingIdx(Key Button) | |||
| { | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| if (m_input_assocation_list[i].m_raw_button == Button) | |||
| return i; | |||
| return -1; | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| if (m_input_assocation_list[i].m_raw_button == Button) | |||
| return i; | |||
| return -1; | |||
| } | |||
| //----- | |||
| int InputTracker::GetCurrentButtonStatus(Key Button) | |||
| { | |||
| if (Button < m_input_status.Count()) | |||
| return m_input_status[Button]; | |||
| return 0; | |||
| if (Button < m_input_status.Count()) | |||
| return m_input_status[Button]; | |||
| return 0; | |||
| } | |||
| //----- | |||
| int InputTracker::GetPreviousButtonStatus(Key Button) | |||
| { | |||
| if (Button < m_input_status.Count()) | |||
| return m_input_status[(int)Button + (int)Key::Last]; | |||
| return 0; | |||
| if (Button < m_input_status.Count()) | |||
| return m_input_status[(int)Button + (int)Key::Last]; | |||
| return 0; | |||
| } | |||
| //Internal : Updates the action status & timers | |||
| @@ -116,146 +116,146 @@ void InputTracker::UpdateActionStatus(float seconds) | |||
| { | |||
| #if defined USE_SDL | |||
| #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION >= 3 | |||
| Uint8 *keystate = SDL_GetKeyboardState(NULL); | |||
| Uint8 *keystate = SDL_GetKeyboardState(NULL); | |||
| #else | |||
| Uint8 *keystate = SDL_GetKeyState(NULL); | |||
| Uint8 *keystate = SDL_GetKeyState(NULL); | |||
| #endif | |||
| //SOOOoooo ugly. | |||
| for (int i = 0; i < Key::Last; ++i) | |||
| { | |||
| m_input_status[i + Key::Last] = m_input_status[i]; | |||
| m_input_status[i] = keystate[i]; | |||
| } | |||
| //SOOOoooo ugly. | |||
| for (int i = 0; i < Key::Last; ++i) | |||
| { | |||
| m_input_status[i + Key::Last] = m_input_status[i]; | |||
| m_input_status[i] = keystate[i]; | |||
| } | |||
| #endif | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| for (int j = 0; j < CurIT.m_associated_action_list.Count(); j++) | |||
| { | |||
| ActionSetting &CurAS = CurIT.m_associated_action_list[j]; | |||
| for (int j = 0; j < CurIT.m_associated_action_list.Count(); j++) | |||
| { | |||
| ActionSetting &CurAS = CurIT.m_associated_action_list[j]; | |||
| if (CurAS.m_buffered_since <= CurAS.m_buffering_time) | |||
| CurAS.m_buffered_since += seconds; | |||
| if (CurAS.m_buffered_since <= CurAS.m_buffering_time) | |||
| CurAS.m_buffered_since += seconds; | |||
| if (GetCurrentButtonStatus(CurIT.m_raw_button) && | |||
| CurAS.m_buffering_time >= .0f) | |||
| CurAS.m_buffered_since = .0f; | |||
| } | |||
| } | |||
| if (GetCurrentButtonStatus(CurIT.m_raw_button) && | |||
| CurAS.m_buffering_time >= .0f) | |||
| CurAS.m_buffered_since = .0f; | |||
| } | |||
| } | |||
| } | |||
| //Helps link a software input Action-Id to an hardware input Button-Id. | |||
| void InputTracker::LinkActionToKey(ACTION_TYPE Action, Key Button) | |||
| { | |||
| int ITIdx = GetButtonSettingIdx(Button); | |||
| if (ITIdx == -1) | |||
| { | |||
| ITIdx = m_input_assocation_list.Count(); | |||
| m_input_assocation_list << ButtonSetting(Button); | |||
| } | |||
| int ITIdx = GetButtonSettingIdx(Button); | |||
| if (ITIdx == -1) | |||
| { | |||
| ITIdx = m_input_assocation_list.Count(); | |||
| m_input_assocation_list << ButtonSetting(Button); | |||
| } | |||
| ButtonSetting &CurIT = m_input_assocation_list[ITIdx]; | |||
| ButtonSetting &CurIT = m_input_assocation_list[ITIdx]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx == -1) | |||
| { | |||
| ASIdx = CurIT.m_associated_action_list.Count(); | |||
| CurIT.m_associated_action_list << ActionSetting(Action); | |||
| } | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx == -1) | |||
| { | |||
| ASIdx = CurIT.m_associated_action_list.Count(); | |||
| CurIT.m_associated_action_list << ActionSetting(Action); | |||
| } | |||
| } | |||
| //Helps unlink a software input Action-Id to an hardware input Button-Id. | |||
| void InputTracker::UnlinkAction(ACTION_TYPE Action) | |||
| { | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| CurIT.m_associated_action_list.Remove(ASIdx); | |||
| } | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| CurIT.m_associated_action_list.Remove(ASIdx); | |||
| } | |||
| } | |||
| //Returns the current status of a given action | |||
| int InputTracker::GetStatus(ACTION_TYPE Action) | |||
| { | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| { | |||
| ActionSetting &CurAS = CurIT.m_associated_action_list[ASIdx]; | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| { | |||
| ActionSetting &CurAS = CurIT.m_associated_action_list[ASIdx]; | |||
| if (CurAS.m_buffering_time >= .0f && CurAS.m_buffered_since <= CurAS.m_buffering_time) | |||
| return 1; | |||
| return 0; | |||
| } | |||
| } | |||
| return 0; | |||
| if (CurAS.m_buffering_time >= .0f && CurAS.m_buffered_since <= CurAS.m_buffering_time) | |||
| return 1; | |||
| return 0; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| //Returns TRUE if action status went from Active to Inactive this frame | |||
| bool InputTracker::WasReleased(ACTION_TYPE Action) | |||
| { | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| { | |||
| if (GetPreviousButtonStatus(CurIT.m_raw_button) && | |||
| !GetCurrentButtonStatus(CurIT.m_raw_button)) | |||
| return true; | |||
| return false; | |||
| } | |||
| } | |||
| return false; | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| { | |||
| if (GetPreviousButtonStatus(CurIT.m_raw_button) && | |||
| !GetCurrentButtonStatus(CurIT.m_raw_button)) | |||
| return true; | |||
| return false; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| //Returns TRUE if action status went from Inactive to Active this frame | |||
| bool InputTracker::WasPressed(ACTION_TYPE Action) | |||
| { | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| { | |||
| if (!GetPreviousButtonStatus(CurIT.m_raw_button) && | |||
| GetCurrentButtonStatus(CurIT.m_raw_button)) | |||
| return true; | |||
| return false; | |||
| } | |||
| } | |||
| return false; | |||
| for (int i = 0; i < m_input_assocation_list.Count(); i++) | |||
| { | |||
| ButtonSetting &CurIT = m_input_assocation_list[i]; | |||
| int ASIdx = CurIT.GetActionSettingIdx(Action); | |||
| if (ASIdx != -1) | |||
| { | |||
| if (!GetPreviousButtonStatus(CurIT.m_raw_button) && | |||
| GetCurrentButtonStatus(CurIT.m_raw_button)) | |||
| return true; | |||
| return false; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| //Returns the current status of a given action | |||
| int InputTracker::GetStatus(Key Button) | |||
| { | |||
| return GetCurrentButtonStatus(Button); | |||
| return GetCurrentButtonStatus(Button); | |||
| } | |||
| //Returns TRUE if action status went from Active to Inactive this frame | |||
| bool InputTracker::WasReleased(Key Button) | |||
| { | |||
| if (GetPreviousButtonStatus(Button) && | |||
| !GetCurrentButtonStatus(Button)) | |||
| return true; | |||
| return false; | |||
| if (GetPreviousButtonStatus(Button) && | |||
| !GetCurrentButtonStatus(Button)) | |||
| return true; | |||
| return false; | |||
| } | |||
| //Returns TRUE if action status went from Inactive to Active this frame | |||
| bool InputTracker::WasPressed(Key Button) | |||
| { | |||
| if (!GetPreviousButtonStatus(Button) && | |||
| GetCurrentButtonStatus(Button)) | |||
| return true; | |||
| return false; | |||
| if (!GetPreviousButtonStatus(Button) && | |||
| GetCurrentButtonStatus(Button)) | |||
| return true; | |||
| return false; | |||
| } | |||
| /* | |||
| @@ -316,63 +316,63 @@ int Input::GetButtonState(int button) | |||
| //Helps link a software input Action-Id to an hardware input Button-Id. | |||
| void Input::LinkActionToKey(ACTION_TYPE Action, struct Key Button) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| Input::m_input_tracker->LinkActionToKey(Action, Button); | |||
| if (CheckInputTrackerInit()) | |||
| Input::m_input_tracker->LinkActionToKey(Action, Button); | |||
| } | |||
| //Helps unlink a software input Action-Id to an hardware input Button-Id. | |||
| void Input::UnlinkAction(ACTION_TYPE Action) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| Input::m_input_tracker->UnlinkAction(Action); | |||
| if (CheckInputTrackerInit()) | |||
| Input::m_input_tracker->UnlinkAction(Action); | |||
| } | |||
| //Returns the current status of a given action | |||
| int Input::GetStatus(ACTION_TYPE Action) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->GetStatus(Action); | |||
| return 0; | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->GetStatus(Action); | |||
| return 0; | |||
| } | |||
| //Returns TRUE if action status when from Active to Inactive this frame | |||
| bool Input::WasPressed(ACTION_TYPE Action) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasPressed(Action); | |||
| return false; | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasPressed(Action); | |||
| return false; | |||
| } | |||
| //Returns TRUE if action status when from Active to Inactive this frame | |||
| bool Input::WasReleased(ACTION_TYPE Action) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasReleased(Action); | |||
| return false; | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasReleased(Action); | |||
| return false; | |||
| } | |||
| //Returns the current status of a given action | |||
| int Input::GetStatus(Key Button) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->GetStatus(Button); | |||
| return 0; | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->GetStatus(Button); | |||
| return 0; | |||
| } | |||
| //Returns TRUE if action status when from Active to Inactive this frame | |||
| bool Input::WasPressed(Key Button) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasPressed(Button); | |||
| return false; | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasPressed(Button); | |||
| return false; | |||
| } | |||
| //Returns TRUE if action status when from Active to Inactive this frame | |||
| bool Input::WasReleased(Key Button) | |||
| { | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasReleased(Button); | |||
| return false; | |||
| if (CheckInputTrackerInit()) | |||
| return Input::m_input_tracker->WasReleased(Button); | |||
| return false; | |||
| } | |||
| //-- | |||
| @@ -409,7 +409,7 @@ public: | |||
| static ivec2 GetMousePos(); | |||
| static ivec3 GetMouseButtons(); | |||
| //BH : Shouldn't use this | |||
| //BH : Shouldn't use this | |||
| static int GetButtonState(int button); | |||
| /* Action management */ | |||
| @@ -66,11 +66,11 @@ static inline void sincos(float const &x, float *s, float *c) | |||
| static inline double lerp(double const &a, double const &b, double const &x) | |||
| { | |||
| return a + (b - a) * x; | |||
| return a + (b - a) * x; | |||
| } | |||
| static inline float lerp(float const &a, float const &b, float const &x) | |||
| { | |||
| return a + (b - a) * x; | |||
| return a + (b - a) * x; | |||
| } | |||
| @@ -55,8 +55,8 @@ template <typename T> static inline T PotUp(T val) | |||
| //Lerp for float | |||
| template <typename T1, typename T2, typename Tf> static inline T1 damp(const T1 &a, const T2 &b, const Tf &x, const Tf &dt) | |||
| { | |||
| if (dt <= .0f) | |||
| return a; | |||
| if (dt <= .0f) | |||
| return a; | |||
| return lol::lerp(a, b, dt / (dt + x)); | |||
| } | |||
| @@ -28,7 +28,7 @@ WorldEntity::WorldEntity() | |||
| m_position = vec3(0); | |||
| m_rotation = quat(1); | |||
| m_velocity = vec3(0); | |||
| m_rotation_velocity = vec3(0); | |||
| m_rotation_velocity = vec3(0); | |||
| m_bbox[0] = m_bbox[1] = vec3(0); | |||
| m_mousepos = ivec2(0); | |||
| @@ -49,25 +49,25 @@ using namespace lol::phys; | |||
| int gNumObjects = 64; | |||
| #define USE_WALL 1 | |||
| #define USE_PLATFORM 1 | |||
| #define USE_ROPE 0 | |||
| #define USE_BODIES 1 | |||
| #define USE_ROTATION 0 | |||
| #define USE_CHARACTER 1 | |||
| #define USE_STAIRS 1 | |||
| #define IPT_MOVE_FORWARD "Move_Forward" | |||
| #define IPT_MOVE_BACKWARD "Move_Backward" | |||
| #define IPT_MOVE_LEFT "Move_Left" | |||
| #define IPT_MOVE_RIGHT "Move_Right" | |||
| #define IPT_MOVE_UP "Move_Up" | |||
| #define IPT_MOVE_DOWN "Move_Down" | |||
| #define IPT_MOVE_JUMP "Move_Jump" | |||
| #define USE_WALL 1 | |||
| #define USE_PLATFORM 1 | |||
| #define USE_ROPE 0 | |||
| #define USE_BODIES 1 | |||
| #define USE_ROTATION 0 | |||
| #define USE_CHARACTER 1 | |||
| #define USE_STAIRS 1 | |||
| #define IPT_MOVE_FORWARD "Move_Forward" | |||
| #define IPT_MOVE_BACKWARD "Move_Backward" | |||
| #define IPT_MOVE_LEFT "Move_Left" | |||
| #define IPT_MOVE_RIGHT "Move_Right" | |||
| #define IPT_MOVE_UP "Move_Up" | |||
| #define IPT_MOVE_DOWN "Move_Down" | |||
| #define IPT_MOVE_JUMP "Move_Jump" | |||
| BtPhysTest::BtPhysTest(bool editor) | |||
| { | |||
| m_loop_value = .0f; | |||
| m_loop_value = .0f; | |||
| /* Create a camera that matches the settings of XNA BtPhysTest */ | |||
| m_camera = new Camera(vec3(0.f, 600.f, 0.f), | |||
| @@ -75,191 +75,191 @@ BtPhysTest::BtPhysTest(bool editor) | |||
| vec3(0, 1, 0)); | |||
| m_camera->SetRotation(quat::fromeuler_xyz(0.f, 0.f, 0.f)); | |||
| m_camera->SetPerspective(45.f, 1280.f, 960.f, .1f, 1000.f); | |||
| //m_camera->SetOrtho(1280.f / 6, 960.f / 6, -1000.f, 1000.f); | |||
| //m_camera->SetOrtho(1280.f / 6, 960.f / 6, -1000.f, 1000.f); | |||
| Ticker::Ref(m_camera); | |||
| m_ready = false; | |||
| m_simulation = new Simulation(); | |||
| m_simulation->SetWorldLimit(vec3(-1000.0f, -1000.0f, -1000.0f), vec3(1000.0f, 1000.0f, 1000.0f)); | |||
| m_simulation->Init(); | |||
| vec3 NewGravity = vec3(.0f, -10.0f, .0f); | |||
| m_simulation->SetGravity(NewGravity); | |||
| m_simulation->SetContinuousDetection(true); | |||
| m_simulation->SetTimestep(1.f / 120.f); | |||
| m_simulation = new Simulation(); | |||
| m_simulation->SetWorldLimit(vec3(-1000.0f, -1000.0f, -1000.0f), vec3(1000.0f, 1000.0f, 1000.0f)); | |||
| m_simulation->Init(); | |||
| vec3 NewGravity = vec3(.0f, -10.0f, .0f); | |||
| m_simulation->SetGravity(NewGravity); | |||
| m_simulation->SetContinuousDetection(true); | |||
| m_simulation->SetTimestep(1.f / 120.f); | |||
| Ticker::Ref(m_simulation); | |||
| float offset = 29.5f; | |||
| vec3 pos_offset = vec3(.0f, 30.f, .0f); | |||
| if (USE_STAIRS) | |||
| { | |||
| vec3 new_offset = vec3(1.0f, .125f, .0f); | |||
| quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
| vec3 NewPosition = pos_offset + vec3(5.0f, -29.f, 15.0f); | |||
| { | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 30.f); | |||
| NewPosition += vec3(4.0f, .0f, -4.0f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_stairs_list << NewPhyobj; | |||
| } | |||
| { | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 40.f); | |||
| NewPosition += vec3(4.0f, .0f, -4.0f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_stairs_list << NewPhyobj; | |||
| } | |||
| NewPosition = pos_offset + vec3(5.0f, -29.5f, 15.0f); | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
| for (int i=0; i < 15; i++) | |||
| { | |||
| NewPosition += new_offset; | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_stairs_list << NewPhyobj; | |||
| } | |||
| } | |||
| if (USE_WALL) | |||
| { | |||
| for (int i=0; i < 6; i++) | |||
| { | |||
| vec3 NewPosition = vec3(.0f); | |||
| quat NewRotation = quat(1.f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation); | |||
| int idx = i/2; | |||
| NewPosition = pos_offset; | |||
| NewPosition[idx] += offset; | |||
| offset *= -1.f; | |||
| if (idx != 1) | |||
| { | |||
| vec3 NewAxis = vec3(.0f); | |||
| NewAxis[2 - idx] = 1; | |||
| NewRotation = quat::rotate(90.f, NewAxis); | |||
| } | |||
| NewPhyobj->SetTransform(NewPosition, NewRotation); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_ground_list << NewPhyobj; | |||
| } | |||
| } | |||
| PhysicsObject* BasePhyobj = NULL; | |||
| if (USE_PLATFORM) | |||
| { | |||
| 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); | |||
| m_platform_list << NewPhyobj; | |||
| Ticker::Ref(NewPhyobj); | |||
| NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f); | |||
| NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
| BasePhyobj = NewPhyobj; | |||
| m_platform_list << NewPhyobj; | |||
| Ticker::Ref(NewPhyobj); | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f); | |||
| NewPosition = pos_offset + vec3(-20.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); | |||
| } | |||
| if (USE_CHARACTER) | |||
| { | |||
| quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
| vec3 NewPosition = pos_offset + vec3(-5.0f, -10.0f, 15.0f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2); | |||
| m_character_list << NewPhyobj; | |||
| Ticker::Ref(NewPhyobj); | |||
| Input::LinkActionToKey(IPT_MOVE_FORWARD, Key::Up); | |||
| Input::LinkActionToKey(IPT_MOVE_BACKWARD, Key::Down); | |||
| Input::LinkActionToKey(IPT_MOVE_LEFT, Key::Left); | |||
| Input::LinkActionToKey(IPT_MOVE_RIGHT, Key::Right); | |||
| Input::LinkActionToKey(IPT_MOVE_JUMP, Key::Space); | |||
| Input::LinkActionToKey(IPT_MOVE_UP, Key::PageUp); | |||
| Input::LinkActionToKey(IPT_MOVE_DOWN, Key::PageDown); | |||
| //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true); | |||
| } | |||
| if (USE_BODIES) | |||
| { | |||
| for (int x=0; x < 6; x++) | |||
| { | |||
| for (int y=0; y < 6; y++) | |||
| { | |||
| 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 (USE_ROPE) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| float offset = 29.5f; | |||
| vec3 pos_offset = vec3(.0f, 30.f, .0f); | |||
| if (USE_STAIRS) | |||
| { | |||
| vec3 new_offset = vec3(1.0f, .125f, .0f); | |||
| quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
| vec3 NewPosition = pos_offset + vec3(5.0f, -29.f, 15.0f); | |||
| { | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 30.f); | |||
| NewPosition += vec3(4.0f, .0f, -4.0f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_stairs_list << NewPhyobj; | |||
| } | |||
| { | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 40.f); | |||
| NewPosition += vec3(4.0f, .0f, -4.0f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_stairs_list << NewPhyobj; | |||
| } | |||
| NewPosition = pos_offset + vec3(5.0f, -29.5f, 15.0f); | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
| for (int i=0; i < 15; i++) | |||
| { | |||
| NewPosition += new_offset; | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_stairs_list << NewPhyobj; | |||
| } | |||
| } | |||
| if (USE_WALL) | |||
| { | |||
| for (int i=0; i < 6; i++) | |||
| { | |||
| vec3 NewPosition = vec3(.0f); | |||
| quat NewRotation = quat(1.f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation); | |||
| int idx = i/2; | |||
| NewPosition = pos_offset; | |||
| NewPosition[idx] += offset; | |||
| offset *= -1.f; | |||
| if (idx != 1) | |||
| { | |||
| vec3 NewAxis = vec3(.0f); | |||
| NewAxis[2 - idx] = 1; | |||
| NewRotation = quat::rotate(90.f, NewAxis); | |||
| } | |||
| NewPhyobj->SetTransform(NewPosition, NewRotation); | |||
| Ticker::Ref(NewPhyobj); | |||
| m_ground_list << NewPhyobj; | |||
| } | |||
| } | |||
| PhysicsObject* BasePhyobj = NULL; | |||
| if (USE_PLATFORM) | |||
| { | |||
| 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); | |||
| m_platform_list << NewPhyobj; | |||
| Ticker::Ref(NewPhyobj); | |||
| NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f); | |||
| NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1); | |||
| BasePhyobj = NewPhyobj; | |||
| m_platform_list << NewPhyobj; | |||
| Ticker::Ref(NewPhyobj); | |||
| NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f); | |||
| NewPosition = pos_offset + vec3(-20.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); | |||
| } | |||
| if (USE_CHARACTER) | |||
| { | |||
| quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f); | |||
| vec3 NewPosition = pos_offset + vec3(-5.0f, -10.0f, 15.0f); | |||
| PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2); | |||
| m_character_list << NewPhyobj; | |||
| Ticker::Ref(NewPhyobj); | |||
| Input::LinkActionToKey(IPT_MOVE_FORWARD, Key::Up); | |||
| Input::LinkActionToKey(IPT_MOVE_BACKWARD, Key::Down); | |||
| Input::LinkActionToKey(IPT_MOVE_LEFT, Key::Left); | |||
| Input::LinkActionToKey(IPT_MOVE_RIGHT, Key::Right); | |||
| Input::LinkActionToKey(IPT_MOVE_JUMP, Key::Space); | |||
| Input::LinkActionToKey(IPT_MOVE_UP, Key::PageUp); | |||
| Input::LinkActionToKey(IPT_MOVE_DOWN, Key::PageDown); | |||
| //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true); | |||
| } | |||
| if (USE_BODIES) | |||
| { | |||
| for (int x=0; x < 6; x++) | |||
| { | |||
| for (int y=0; y < 6; y++) | |||
| { | |||
| 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 (USE_ROPE) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void BtPhysTest::TickGame(float seconds) | |||
| @@ -269,143 +269,143 @@ void BtPhysTest::TickGame(float seconds) | |||
| if (Input::WasReleased(Key::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; | |||
| if (USE_WALL) | |||
| { | |||
| for (int i = 0; i < m_ground_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_ground_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| GroundBarycenter += GroundMat.v3.xyz; | |||
| factor += 1.f; | |||
| } | |||
| GroundBarycenter /= factor; | |||
| for (int i = 0; i < m_ground_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_ground_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| vec3 CenterToGround = GroundMat.v3.xyz - GroundBarycenter; | |||
| vec3 CenterToCam = m_camera->m_position - GroundBarycenter; | |||
| if (dot(normalize(CenterToCam - CenterToGround), | |||
| normalize(CenterToGround)) > 0.f) | |||
| PhysObj->SetRender(false); | |||
| else | |||
| PhysObj->SetRender(true); | |||
| } | |||
| } | |||
| if (USE_ROTATION) | |||
| { | |||
| 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)); | |||
| } | |||
| } | |||
| if (USE_PLATFORM) | |||
| { | |||
| for (int i = 0; i < m_platform_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_platform_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| if (i == 0) | |||
| { | |||
| GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds)); | |||
| PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
| } | |||
| 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))); | |||
| PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
| } | |||
| } | |||
| } | |||
| if (USE_CHARACTER) | |||
| { | |||
| for (int i = 0; i < m_character_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_character_list[i]; | |||
| EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter(); | |||
| mat4 CtlrMx = Character->GetTransform(); | |||
| int HMovement = Input::GetStatus(IPT_MOVE_RIGHT) - Input::GetStatus(IPT_MOVE_LEFT); | |||
| int VMovement = Input::GetStatus(IPT_MOVE_FORWARD) - Input::GetStatus(IPT_MOVE_BACKWARD); | |||
| int RMovement = Input::GetStatus(IPT_MOVE_UP) - Input::GetStatus(IPT_MOVE_DOWN); | |||
| vec3 CharMove = vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f); | |||
| if (Input::WasReleased(IPT_MOVE_JUMP)) | |||
| Character->Jump(); | |||
| Character->SetMovementForFrame(CharMove); | |||
| 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); | |||
| } | |||
| } | |||
| if (USE_CHARACTER) | |||
| { | |||
| PhysObjBarycenter = vec3(.0f); | |||
| factor = .0f; | |||
| for (int i = 0; i < m_character_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_character_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| PhysObjBarycenter += GroundMat.v3.xyz; | |||
| factor += 1.f; | |||
| } | |||
| PhysObjBarycenter /= factor; | |||
| m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget())); | |||
| vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f); | |||
| m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f); | |||
| } | |||
| else | |||
| { | |||
| PhysObjBarycenter = vec3(.0f); | |||
| for (int i = 0; i < m_physobj_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_physobj_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| PhysObjBarycenter += GroundMat.v3.xyz; | |||
| factor += 1.f; | |||
| } | |||
| PhysObjBarycenter /= factor; | |||
| m_camera->SetTarget(PhysObjBarycenter); | |||
| m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f); | |||
| } | |||
| 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; | |||
| if (USE_WALL) | |||
| { | |||
| for (int i = 0; i < m_ground_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_ground_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| GroundBarycenter += GroundMat.v3.xyz; | |||
| factor += 1.f; | |||
| } | |||
| GroundBarycenter /= factor; | |||
| for (int i = 0; i < m_ground_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_ground_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| vec3 CenterToGround = GroundMat.v3.xyz - GroundBarycenter; | |||
| vec3 CenterToCam = m_camera->m_position - GroundBarycenter; | |||
| if (dot(normalize(CenterToCam - CenterToGround), | |||
| normalize(CenterToGround)) > 0.f) | |||
| PhysObj->SetRender(false); | |||
| else | |||
| PhysObj->SetRender(true); | |||
| } | |||
| } | |||
| if (USE_ROTATION) | |||
| { | |||
| 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)); | |||
| } | |||
| } | |||
| if (USE_PLATFORM) | |||
| { | |||
| for (int i = 0; i < m_platform_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_platform_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| if (i == 0) | |||
| { | |||
| GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds)); | |||
| PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
| } | |||
| 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))); | |||
| PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat)); | |||
| } | |||
| } | |||
| } | |||
| if (USE_CHARACTER) | |||
| { | |||
| for (int i = 0; i < m_character_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_character_list[i]; | |||
| EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter(); | |||
| mat4 CtlrMx = Character->GetTransform(); | |||
| int HMovement = Input::GetStatus(IPT_MOVE_RIGHT) - Input::GetStatus(IPT_MOVE_LEFT); | |||
| int VMovement = Input::GetStatus(IPT_MOVE_FORWARD) - Input::GetStatus(IPT_MOVE_BACKWARD); | |||
| int RMovement = Input::GetStatus(IPT_MOVE_UP) - Input::GetStatus(IPT_MOVE_DOWN); | |||
| vec3 CharMove = vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f); | |||
| if (Input::WasReleased(IPT_MOVE_JUMP)) | |||
| Character->Jump(); | |||
| Character->SetMovementForFrame(CharMove); | |||
| 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); | |||
| } | |||
| } | |||
| if (USE_CHARACTER) | |||
| { | |||
| PhysObjBarycenter = vec3(.0f); | |||
| factor = .0f; | |||
| for (int i = 0; i < m_character_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_character_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| PhysObjBarycenter += GroundMat.v3.xyz; | |||
| factor += 1.f; | |||
| } | |||
| PhysObjBarycenter /= factor; | |||
| m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget())); | |||
| vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f); | |||
| m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f); | |||
| } | |||
| else | |||
| { | |||
| PhysObjBarycenter = vec3(.0f); | |||
| for (int i = 0; i < m_physobj_list.Count(); i++) | |||
| { | |||
| PhysicsObject* PhysObj = m_physobj_list[i]; | |||
| mat4 GroundMat = PhysObj->GetTransform(); | |||
| PhysObjBarycenter += GroundMat.v3.xyz; | |||
| factor += 1.f; | |||
| } | |||
| PhysObjBarycenter /= factor; | |||
| m_camera->SetTarget(PhysObjBarycenter); | |||
| m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f); | |||
| } | |||
| } | |||
| @@ -425,50 +425,50 @@ 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_stairs_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_stairs_list.Last(); | |||
| m_stairs_list.Pop(); | |||
| CurPop->GetPhysic()->RemoveFromSimulation(m_simulation); | |||
| Ticker::Unref(CurPop); | |||
| } | |||
| while (m_character_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_character_list.Last(); | |||
| m_character_list.Pop(); | |||
| CurPop->GetCharacter()->RemoveFromSimulation(m_simulation); | |||
| Ticker::Unref(CurPop); | |||
| } | |||
| while (m_platform_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_platform_list.Last(); | |||
| m_platform_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_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_stairs_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_stairs_list.Last(); | |||
| m_stairs_list.Pop(); | |||
| CurPop->GetPhysic()->RemoveFromSimulation(m_simulation); | |||
| Ticker::Unref(CurPop); | |||
| } | |||
| while (m_character_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_character_list.Last(); | |||
| m_character_list.Pop(); | |||
| CurPop->GetCharacter()->RemoveFromSimulation(m_simulation); | |||
| Ticker::Unref(CurPop); | |||
| } | |||
| while (m_platform_list.Count()) | |||
| { | |||
| PhysicsObject* CurPop = m_platform_list.Last(); | |||
| m_platform_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); | |||
| } | |||
| @@ -21,18 +21,18 @@ protected: | |||
| virtual void TickDraw(float seconds); | |||
| private: | |||
| Camera* m_camera; | |||
| bool m_ready; | |||
| lol::phys::Simulation* m_simulation; | |||
| Array<EasyConstraint*> m_constraint_list; | |||
| Array<PhysicsObject*> m_physobj_list; | |||
| Array<PhysicsObject*> m_ground_list; | |||
| Array<PhysicsObject*> m_platform_list; | |||
| Array<PhysicsObject*> m_character_list; | |||
| Array<PhysicsObject*> m_stairs_list; | |||
| float m_loop_value; | |||
| Camera* m_camera; | |||
| bool m_ready; | |||
| lol::phys::Simulation* m_simulation; | |||
| Array<EasyConstraint*> m_constraint_list; | |||
| Array<PhysicsObject*> m_physobj_list; | |||
| Array<PhysicsObject*> m_ground_list; | |||
| Array<PhysicsObject*> m_platform_list; | |||
| Array<PhysicsObject*> m_character_list; | |||
| Array<PhysicsObject*> m_stairs_list; | |||
| float m_loop_value; | |||
| }; | |||
| #endif // __BTPHYSTEST_H__ | |||
| @@ -23,279 +23,279 @@ using namespace lol::phys; | |||
| class PhysicsObject : public WorldEntity | |||
| { | |||
| 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); | |||
| } | |||
| 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 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); | |||
| } | |||
| 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( | |||
| "[sc#000 scb#000" | |||
| //"[sc#aaa scb#aaa" | |||
| "[ad8 2 0 rx180 ty-1]" | |||
| "[asph8 .5 .5 .5 ty1]" | |||
| "[ac32 2 .5 .5 0 0]" | |||
| "[asph6 .1 .1 .1 ty.9 tx.5 tz.15]" | |||
| "[asph6 .1 .1 .1 ty.9 tx.5 tz-.15]" | |||
| "[asph8 .05 .5 .05 ty.6 tz.5]" | |||
| "[asph8 .05 .5 .05 ty.6 tz-.5]" | |||
| "]" | |||
| "[sc#fd0 scb#fd0" | |||
| "[ac8 .4 .1 0 0 0 ty.25 rz-90 ty.7 tx.5]" | |||
| "]" | |||
| "[" | |||
| "[sc#fff scb#fff" | |||
| "[ad8 2 0 rx180 ty-1]" | |||
| "[asph8 .5 .5 .5 ty1]" | |||
| "[ac32 1.9 .5 .5 0 0]" | |||
| "]" | |||
| " ty-.1 tx.05]" | |||
| ); | |||
| vec3 BoxSize = vec3(1.f, 2.f, 1.f); | |||
| m_character->SetCollisionChannel(0, 0xFF); | |||
| m_character->SetShapeToCapsule(BoxSize.x, BoxSize.y); | |||
| m_character->SetMass(.0f); | |||
| //m_character->SetStepHeight(1.f); | |||
| m_character->SetTransform(base_location, base_rotation); | |||
| m_character->InitBodyToGhost(); | |||
| m_character->AddToSimulation(new_sim); | |||
| } | |||
| else if (dummy == 3) //for Stairs purpose | |||
| { | |||
| m_physics = new EasyPhysic(this); | |||
| m_mesh.Compile("[sc#aae afcb4 .25 4 -.01]"); | |||
| vec3 BoxSize = vec3(4.f, .25f, 4.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); | |||
| } | |||
| } | |||
| PhysicsObject(Simulation* new_sim, float base_mass, const vec3 &base_location, int RandValue = -1) | |||
| : m_ready(false), m_should_render(true), m_is_character(false) | |||
| { | |||
| Array<char const *> MeshRand; | |||
| //MeshRand << "[sc#add afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#dad afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#dda afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#daa afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#ada afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#aad afcb2 2 2 -.1]"; | |||
| MeshRand << "[sc#add afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#dad afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#dda afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#daa afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#ada afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#aad afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| int SphereLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add asph1 2 2 2]"; | |||
| MeshRand << "[sc#dad asph1 2 2 2]"; | |||
| MeshRand << "[sc#dda asph1 2 2 2]"; | |||
| MeshRand << "[sc#daa asph1 2 2 2]"; | |||
| MeshRand << "[sc#ada asph1 2 2 2]"; | |||
| MeshRand << "[sc#aad asph1 2 2 2]"; | |||
| int ConeLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add scb#add ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#dad scb#dad ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#dda scb#dda ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#daa scb#daa ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#ada scb#ada ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#aad scb#aad ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| int CylLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add scb#add ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#dad scb#dad ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#dda scb#dda ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#daa scb#daa ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#ada scb#ada ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#aad scb#aad ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| int CapsLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add scb#add acap1 2 1]"; | |||
| MeshRand << "[sc#dad scb#dad acap1 2 1]"; | |||
| MeshRand << "[sc#dda scb#dda acap1 2 1]"; | |||
| MeshRand << "[sc#daa scb#daa acap1 2 1]"; | |||
| MeshRand << "[sc#ada scb#ada acap1 2 1]"; | |||
| MeshRand << "[sc#aad scb#aad acap1 2 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_physics = new EasyPhysic(this); | |||
| m_mesh.Compile(MeshRand[RandValue]); | |||
| vec3 BoxSize = vec3(2.0f); | |||
| int ColGroup = 1; | |||
| if (RandValue < SphereLimit) | |||
| { | |||
| m_physics->SetShapeToBox(BoxSize); | |||
| ColGroup += 0; | |||
| } | |||
| else if (RandValue < ConeLimit) | |||
| { | |||
| m_physics->SetShapeToSphere(BoxSize.x * 2.f); | |||
| ColGroup += 1; | |||
| } | |||
| else if (RandValue < CylLimit) | |||
| { | |||
| m_physics->SetShapeToCone(BoxSize.x, BoxSize.y); | |||
| ColGroup += 2; | |||
| } | |||
| else if (RandValue < CapsLimit) | |||
| { | |||
| m_physics->SetShapeToCylinder(BoxSize); | |||
| ColGroup += 3; | |||
| } | |||
| else | |||
| { | |||
| 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); | |||
| } | |||
| 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); | |||
| else | |||
| m_physics->SetTransform(base_location, base_rotation); | |||
| } | |||
| lol::mat4 GetTransform() | |||
| { | |||
| if (m_is_character) | |||
| return m_character->GetTransform(); | |||
| else | |||
| return m_physics->GetTransform(); | |||
| } | |||
| void SetRender(bool should_render) | |||
| { | |||
| m_should_render = should_render; | |||
| } | |||
| EasyMesh *GetMesh() { return &m_mesh; } | |||
| EasyPhysic *GetPhysic() { return m_physics; } | |||
| EasyCharacterController *GetCharacter() { return m_character; } | |||
| ~PhysicsObject() | |||
| { | |||
| } | |||
| char const *GetName() { return "<PhysicsObject>"; } | |||
| 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); | |||
| } | |||
| 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 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); | |||
| } | |||
| 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( | |||
| "[sc#000 scb#000" | |||
| //"[sc#aaa scb#aaa" | |||
| "[ad8 2 0 rx180 ty-1]" | |||
| "[asph8 .5 .5 .5 ty1]" | |||
| "[ac32 2 .5 .5 0 0]" | |||
| "[asph6 .1 .1 .1 ty.9 tx.5 tz.15]" | |||
| "[asph6 .1 .1 .1 ty.9 tx.5 tz-.15]" | |||
| "[asph8 .05 .5 .05 ty.6 tz.5]" | |||
| "[asph8 .05 .5 .05 ty.6 tz-.5]" | |||
| "]" | |||
| "[sc#fd0 scb#fd0" | |||
| "[ac8 .4 .1 0 0 0 ty.25 rz-90 ty.7 tx.5]" | |||
| "]" | |||
| "[" | |||
| "[sc#fff scb#fff" | |||
| "[ad8 2 0 rx180 ty-1]" | |||
| "[asph8 .5 .5 .5 ty1]" | |||
| "[ac32 1.9 .5 .5 0 0]" | |||
| "]" | |||
| " ty-.1 tx.05]" | |||
| ); | |||
| vec3 BoxSize = vec3(1.f, 2.f, 1.f); | |||
| m_character->SetCollisionChannel(0, 0xFF); | |||
| m_character->SetShapeToCapsule(BoxSize.x, BoxSize.y); | |||
| m_character->SetMass(.0f); | |||
| //m_character->SetStepHeight(1.f); | |||
| m_character->SetTransform(base_location, base_rotation); | |||
| m_character->InitBodyToGhost(); | |||
| m_character->AddToSimulation(new_sim); | |||
| } | |||
| else if (dummy == 3) //for Stairs purpose | |||
| { | |||
| m_physics = new EasyPhysic(this); | |||
| m_mesh.Compile("[sc#aae afcb4 .25 4 -.01]"); | |||
| vec3 BoxSize = vec3(4.f, .25f, 4.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); | |||
| } | |||
| } | |||
| PhysicsObject(Simulation* new_sim, float base_mass, const vec3 &base_location, int RandValue = -1) | |||
| : m_ready(false), m_should_render(true), m_is_character(false) | |||
| { | |||
| Array<char const *> MeshRand; | |||
| //MeshRand << "[sc#add afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#dad afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#dda afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#daa afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#ada afcb2 2 2 -.1]"; | |||
| //MeshRand << "[sc#aad afcb2 2 2 -.1]"; | |||
| MeshRand << "[sc#add afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#dad afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#dda afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#daa afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#ada afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| MeshRand << "[sc#aad afcb1.7 1.7 1.7 0][sc#000 afcb1.9 1.9 1.9 0 sx-1 sy-1 sz-1]"; | |||
| int SphereLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add asph1 2 2 2]"; | |||
| MeshRand << "[sc#dad asph1 2 2 2]"; | |||
| MeshRand << "[sc#dda asph1 2 2 2]"; | |||
| MeshRand << "[sc#daa asph1 2 2 2]"; | |||
| MeshRand << "[sc#ada asph1 2 2 2]"; | |||
| MeshRand << "[sc#aad asph1 2 2 2]"; | |||
| int ConeLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add scb#add ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#dad scb#dad ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#dda scb#dda ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#daa scb#daa ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#ada scb#ada ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| MeshRand << "[sc#aad scb#aad ad1 2 0 rx180 ty-1 ac4 2 2 0 0 0]"; | |||
| int CylLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add scb#add ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#dad scb#dad ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#dda scb#dda ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#daa scb#daa ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#ada scb#ada ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| MeshRand << "[sc#aad scb#aad ad1 2 0 rx180 ty-1 my ac4 2 2 2 0 0]"; | |||
| int CapsLimit = MeshRand.Count(); | |||
| MeshRand << "[sc#add scb#add acap1 2 1]"; | |||
| MeshRand << "[sc#dad scb#dad acap1 2 1]"; | |||
| MeshRand << "[sc#dda scb#dda acap1 2 1]"; | |||
| MeshRand << "[sc#daa scb#daa acap1 2 1]"; | |||
| MeshRand << "[sc#ada scb#ada acap1 2 1]"; | |||
| MeshRand << "[sc#aad scb#aad acap1 2 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_physics = new EasyPhysic(this); | |||
| m_mesh.Compile(MeshRand[RandValue]); | |||
| vec3 BoxSize = vec3(2.0f); | |||
| int ColGroup = 1; | |||
| if (RandValue < SphereLimit) | |||
| { | |||
| m_physics->SetShapeToBox(BoxSize); | |||
| ColGroup += 0; | |||
| } | |||
| else if (RandValue < ConeLimit) | |||
| { | |||
| m_physics->SetShapeToSphere(BoxSize.x * 2.f); | |||
| ColGroup += 1; | |||
| } | |||
| else if (RandValue < CylLimit) | |||
| { | |||
| m_physics->SetShapeToCone(BoxSize.x, BoxSize.y); | |||
| ColGroup += 2; | |||
| } | |||
| else if (RandValue < CapsLimit) | |||
| { | |||
| m_physics->SetShapeToCylinder(BoxSize); | |||
| ColGroup += 3; | |||
| } | |||
| else | |||
| { | |||
| 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); | |||
| } | |||
| 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); | |||
| else | |||
| m_physics->SetTransform(base_location, base_rotation); | |||
| } | |||
| lol::mat4 GetTransform() | |||
| { | |||
| if (m_is_character) | |||
| return m_character->GetTransform(); | |||
| else | |||
| return m_physics->GetTransform(); | |||
| } | |||
| void SetRender(bool should_render) | |||
| { | |||
| m_should_render = should_render; | |||
| } | |||
| EasyMesh *GetMesh() { return &m_mesh; } | |||
| EasyPhysic *GetPhysic() { return m_physics; } | |||
| EasyCharacterController *GetCharacter() { return m_character; } | |||
| ~PhysicsObject() | |||
| { | |||
| } | |||
| char const *GetName() { return "<PhysicsObject>"; } | |||
| protected: | |||
| virtual void TickGame(float seconds) | |||
| { | |||
| WorldEntity::TickGame(seconds); | |||
| } | |||
| virtual void TickDraw(float seconds) | |||
| { | |||
| WorldEntity::TickDraw(seconds); | |||
| if (!m_ready) | |||
| { | |||
| m_mesh.MeshConvert(); | |||
| m_ready = true; | |||
| } | |||
| if (m_should_render) | |||
| { | |||
| if (m_is_character) | |||
| m_mesh.Render(m_character->GetTransform()); | |||
| else | |||
| m_mesh.Render(m_physics->GetTransform()); | |||
| } | |||
| } | |||
| virtual void TickGame(float seconds) | |||
| { | |||
| WorldEntity::TickGame(seconds); | |||
| } | |||
| virtual void TickDraw(float seconds) | |||
| { | |||
| WorldEntity::TickDraw(seconds); | |||
| if (!m_ready) | |||
| { | |||
| m_mesh.MeshConvert(); | |||
| m_ready = true; | |||
| } | |||
| if (m_should_render) | |||
| { | |||
| if (m_is_character) | |||
| m_mesh.Render(m_character->GetTransform()); | |||
| else | |||
| m_mesh.Render(m_physics->GetTransform()); | |||
| } | |||
| } | |||
| private: | |||
| //Base datas | |||
| EasyMesh m_mesh; | |||
| EasyPhysic* m_physics; | |||
| EasyCharacterController* m_character; | |||
| bool m_ready; | |||
| bool m_should_render; | |||
| bool m_is_character; | |||
| //Base datas | |||
| EasyMesh m_mesh; | |||
| EasyPhysic* m_physics; | |||
| EasyCharacterController* m_character; | |||
| bool m_ready; | |||
| bool m_should_render; | |||
| bool m_is_character; | |||
| }; | |||
| #endif /* __PHYSICOBJECT_H__ */ | |||
| @@ -29,259 +29,259 @@ | |||
| namespace lol | |||
| { | |||
| namespace phys | |||
| { | |||
| namespace phys | |||
| { | |||
| #ifdef USE_LOL_CTRLR_CHARAC | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| //SweepCallback used for Swweep Tests. | |||
| class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback | |||
| { | |||
| public: | |||
| ClosestNotMeConvexResultCallback(btCollisionObject* NewMe, const vec3& NewUp, float MinSlopeDot) : | |||
| btCollisionWorld::ClosestConvexResultCallback(LOL2BTU_VEC3(vec3(.0f)), LOL2BTU_VEC3(vec3(.0f))), | |||
| m_me(NewMe), | |||
| m_up(NewUp), | |||
| m_min_slope_dot(MinSlopeDot) { } | |||
| virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& ConvexResult, bool NormalInWorld) | |||
| { | |||
| //We hit ourselves, FAIL | |||
| if (ConvexResult.m_hitCollisionObject == m_me) | |||
| return btScalar(1.f); | |||
| vec3 WorldHitNomal(.0f); | |||
| if (NormalInWorld) | |||
| WorldHitNomal = BT2LOL_VEC3(ConvexResult.m_hitNormalLocal); | |||
| else //need to transform Normal into worldspace | |||
| { | |||
| btVector3 TmpWorldHitNormal = ConvexResult.m_hitCollisionObject->getWorldTransform().getBasis() * ConvexResult.m_hitNormalLocal; | |||
| WorldHitNomal = BT2LOL_VEC3(TmpWorldHitNormal); | |||
| } | |||
| float DotUp = dot(m_up, WorldHitNomal); | |||
| //We hit below the accepted slope_dot, FAIL | |||
| if (DotUp < m_min_slope_dot) | |||
| return btScalar(1.f); | |||
| //Continue to next. | |||
| return ClosestConvexResultCallback::addSingleResult(ConvexResult, NormalInWorld); | |||
| } | |||
| protected: | |||
| btCollisionObject* m_me; | |||
| const vec3 m_up; | |||
| float m_min_slope_dot; | |||
| }; | |||
| ///BulletKinematicCharacterController is an object that supports a sliding motion in a world. | |||
| ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. | |||
| ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. | |||
| class BulletKinematicCharacterController : public btActionInterface | |||
| { | |||
| public: | |||
| BulletKinematicCharacterController(btPairCachingGhostObject* NewGhostObject, btConvexShape* NewConvexShape, float NewStepHeight, int NewUpAxis=1) | |||
| { | |||
| m_convex_shape = NewConvexShape; | |||
| m_i_up_axis = NewUpAxis; | |||
| m_ghost_object = NewGhostObject; | |||
| m_step_height = NewStepHeight; | |||
| m_added_margin = 0.02f; | |||
| m_walk_direction = vec3(.0f, .0f, .0f); | |||
| m_do_gobject_sweep_test = true; | |||
| m_turn_angle = .0f; | |||
| m_use_walk_direction = false; // Should remove walk direction, this doesn't work correctly. | |||
| m_velocity_time_interval = .0f; | |||
| m_vertical_velocity = .0f; | |||
| m_vertical_offset = .0f; | |||
| m_f_gravity = 9.8f * 3.f; // 3G acceleration. | |||
| m_fall_speed = 55.f; // Terminal velocity of a sky diver in m/s. | |||
| m_jump_speed = 10.f; // ? | |||
| m_was_on_ground = false; | |||
| m_was_jumping = false; | |||
| SetMaxSlope(45.f); | |||
| } | |||
| ~BulletKinematicCharacterController() { } | |||
| protected: | |||
| static vec3* GetUpAxisDirections() | |||
| { | |||
| static vec3 sUpAxisDirection[3] = { vec3(1.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f) }; | |||
| return sUpAxisDirection; | |||
| } | |||
| //-------------------------- | |||
| //CONVENIENCE FUNCTIONS | |||
| //-- | |||
| //Returns the reflection Direction of a ray going 'Direction' hitting a surface with Normal 'Normal' from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html | |||
| vec3 GetReflectedDir(const vec3& Direction, const vec3& Normal) | |||
| { | |||
| return Direction - (2.f * dot(Direction, Normal) * Normal); | |||
| } | |||
| //Returns the portion of 'direction' that is parallel to 'normal' | |||
| vec3 ProjectDirOnNorm(const vec3& Direction, const vec3& Normal) | |||
| { | |||
| return Normal * dot(Direction, Normal); | |||
| } | |||
| //Returns the portion of 'Direction' that is perpindicular to 'Normal' | |||
| vec3 ProjectDirOnNormPerpindicular(const vec3& Direction, const vec3& Normal) | |||
| { | |||
| return Direction - ProjectDirOnNorm(Direction, Normal); | |||
| } | |||
| //Returns Ghost Object. -duh- | |||
| btPairCachingGhostObject* GetGhostObject() | |||
| { | |||
| return m_ghost_object; | |||
| } | |||
| //"Real" war functions | |||
| bool RecoverFromPenetration(btCollisionWorld* CollisionWorld); | |||
| void UpdateTargetOnHit(const vec3& hit_normal, float TangentMag = .0f, float NormalMag = 1.f); | |||
| void DoMove(btCollisionWorld* CollisionWorld, const vec3& MoveStep, float DeltaTime); | |||
| public: | |||
| ///btActionInterface interface : KEEP IN camelCase | |||
| virtual void updateAction(btCollisionWorld* CollisionWorld, float deltaTime) | |||
| { | |||
| PreStep(CollisionWorld); | |||
| PlayerStep(CollisionWorld, deltaTime); | |||
| } | |||
| //not in the interface, but called above | |||
| void PreStep(btCollisionWorld* CollisionWorld); | |||
| void PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime); | |||
| ///btActionInterface interface : KEEP IN camelCase | |||
| void debugDraw(btIDebugDraw* debugDrawer) { } | |||
| void SetUpAxis(int NewAxis) | |||
| { | |||
| if (NewAxis < 0) | |||
| NewAxis = 0; | |||
| if (NewAxis > 2) | |||
| NewAxis = 2; | |||
| m_i_up_axis = NewAxis; | |||
| } | |||
| //!!!!!! SHOULD DITCH THAT !!!!!! | |||
| //This should probably be called setPositionIncrementPerSimulatorStep. | |||
| //This is neither a Direction nor a velocity, but the amount to | |||
| //increment the position each simulation iteration, regardless | |||
| //of DeltaTime. | |||
| //This call will Reset any velocity set by SetVelocityForTimeInterval(). | |||
| virtual void SetWalkDirection(const vec3& walkDirection) | |||
| { | |||
| m_use_walk_direction = true; | |||
| m_walk_direction = walkDirection; | |||
| m_normalized_direction = normalize(m_walk_direction); | |||
| } | |||
| //Caller provides a velocity with which the character should MoveStep for | |||
| //the given time period. After the time period, velocity is Reset | |||
| //to zero. | |||
| //This call will Reset any walk Direction set by SetWalkDirection(). | |||
| //Negative time intervals will result in no motion. | |||
| virtual void SetVelocityForTimeInterval(const vec3& velocity, float timeInterval) | |||
| { | |||
| m_use_walk_direction = false; | |||
| m_walk_direction = velocity; | |||
| m_normalized_direction = normalize(m_walk_direction); | |||
| m_velocity_time_interval = timeInterval; | |||
| } | |||
| //Usefulness ? | |||
| void Reset() { } | |||
| void Warp(const vec3& NewOrigin) | |||
| { | |||
| btTransform NewTransform; | |||
| NewTransform.setIdentity(); | |||
| NewTransform.setOrigin(LOL2BTU_VEC3(NewOrigin)); | |||
| m_ghost_object->setWorldTransform(NewTransform); | |||
| } | |||
| //External Setup | |||
| //-- | |||
| void SetFallSpeed(float NewFallSpeed) { m_fall_speed = NewFallSpeed; } | |||
| void SetJumpSpeed(float NewJumpSpeed) { m_jump_speed = NewJumpSpeed; } | |||
| void SetMaxJumpHeight(float NewMaxJumpHeight) { m_max_jump_height = NewMaxJumpHeight; } | |||
| //Jump logic will go in EasyCC | |||
| bool CanJump() const { return OnGround(); } | |||
| void Jump(); | |||
| //NewGravity functions | |||
| void SetGravity(float NewGravity) { m_f_gravity = NewGravity; } | |||
| float GetGravity() const { return m_f_gravity; } | |||
| //The max slope determines the maximum angle that the controller can walk up. | |||
| //The slope angle is measured in radians. | |||
| void SetMaxSlope(float NewSlopeRadians) { m_max_slope_radians = NewSlopeRadians; m_max_slope_cosine = lol::cos(NewSlopeRadians); } | |||
| float GetMaxSlope() const { return m_max_slope_radians; } | |||
| void SetUseGhostSweepTest(bool UseGObjectSweepTest) { m_do_gobject_sweep_test = UseGObjectSweepTest; } | |||
| bool OnGround() const { return m_vertical_velocity == .0f && m_vertical_offset == .0f; } | |||
| private: | |||
| btPairCachingGhostObject* m_ghost_object; | |||
| btConvexShape* m_convex_shape; //is also in m_ghost_object, but it needs to be convex, so we store it here to avoid upcast | |||
| //keep track of the contact manifolds | |||
| btManifoldArray m_manifold_array; | |||
| float m_half_height; | |||
| float m_velocity_time_interval; | |||
| float m_vertical_velocity; | |||
| float m_vertical_offset; | |||
| float m_fall_speed; | |||
| float m_jump_speed; | |||
| float m_max_jump_height; | |||
| float m_max_slope_radians; // Slope angle that is set (used for returning the exact value) | |||
| float m_max_slope_cosine; // Cosine equivalent of m_max_slope_radians (calculated once when set, for optimization) | |||
| float m_f_gravity; | |||
| float m_turn_angle; | |||
| float m_step_height; | |||
| float m_added_margin;//@todo: remove this and fix the code | |||
| ///this is the desired walk Direction, set by the user | |||
| vec3 m_walk_direction; | |||
| vec3 m_normalized_direction; | |||
| //some internal variables | |||
| vec3 m_current_position; | |||
| float m_current_step_offset; | |||
| vec3 m_target_position; | |||
| vec3 m_touching_normal; | |||
| bool m_touching_contact; | |||
| bool m_was_on_ground; | |||
| bool m_was_jumping; | |||
| bool m_do_gobject_sweep_test; | |||
| bool m_use_walk_direction; | |||
| int m_i_up_axis; | |||
| //--------------------------------------------------------------------- | |||
| //NEW INTERNAL VARS | |||
| //--------------------------------------------------------------------- | |||
| //Gravity in vec3 | |||
| vec3 m_gravity; | |||
| //Current Velocity | |||
| vec3 m_velocity; | |||
| }; | |||
| //SweepCallback used for Swweep Tests. | |||
| class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback | |||
| { | |||
| public: | |||
| ClosestNotMeConvexResultCallback(btCollisionObject* NewMe, const vec3& NewUp, float MinSlopeDot) : | |||
| btCollisionWorld::ClosestConvexResultCallback(LOL2BTU_VEC3(vec3(.0f)), LOL2BTU_VEC3(vec3(.0f))), | |||
| m_me(NewMe), | |||
| m_up(NewUp), | |||
| m_min_slope_dot(MinSlopeDot) { } | |||
| virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& ConvexResult, bool NormalInWorld) | |||
| { | |||
| //We hit ourselves, FAIL | |||
| if (ConvexResult.m_hitCollisionObject == m_me) | |||
| return btScalar(1.f); | |||
| vec3 WorldHitNomal(.0f); | |||
| if (NormalInWorld) | |||
| WorldHitNomal = BT2LOL_VEC3(ConvexResult.m_hitNormalLocal); | |||
| else //need to transform Normal into worldspace | |||
| { | |||
| btVector3 TmpWorldHitNormal = ConvexResult.m_hitCollisionObject->getWorldTransform().getBasis() * ConvexResult.m_hitNormalLocal; | |||
| WorldHitNomal = BT2LOL_VEC3(TmpWorldHitNormal); | |||
| } | |||
| float DotUp = dot(m_up, WorldHitNomal); | |||
| //We hit below the accepted slope_dot, FAIL | |||
| if (DotUp < m_min_slope_dot) | |||
| return btScalar(1.f); | |||
| //Continue to next. | |||
| return ClosestConvexResultCallback::addSingleResult(ConvexResult, NormalInWorld); | |||
| } | |||
| protected: | |||
| btCollisionObject* m_me; | |||
| const vec3 m_up; | |||
| float m_min_slope_dot; | |||
| }; | |||
| ///BulletKinematicCharacterController is an object that supports a sliding motion in a world. | |||
| ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. | |||
| ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. | |||
| class BulletKinematicCharacterController : public btActionInterface | |||
| { | |||
| public: | |||
| BulletKinematicCharacterController(btPairCachingGhostObject* NewGhostObject, btConvexShape* NewConvexShape, float NewStepHeight, int NewUpAxis=1) | |||
| { | |||
| m_convex_shape = NewConvexShape; | |||
| m_i_up_axis = NewUpAxis; | |||
| m_ghost_object = NewGhostObject; | |||
| m_step_height = NewStepHeight; | |||
| m_added_margin = 0.02f; | |||
| m_walk_direction = vec3(.0f, .0f, .0f); | |||
| m_do_gobject_sweep_test = true; | |||
| m_turn_angle = .0f; | |||
| m_use_walk_direction = false; // Should remove walk direction, this doesn't work correctly. | |||
| m_velocity_time_interval = .0f; | |||
| m_vertical_velocity = .0f; | |||
| m_vertical_offset = .0f; | |||
| m_f_gravity = 9.8f * 3.f; // 3G acceleration. | |||
| m_fall_speed = 55.f; // Terminal velocity of a sky diver in m/s. | |||
| m_jump_speed = 10.f; // ? | |||
| m_was_on_ground = false; | |||
| m_was_jumping = false; | |||
| SetMaxSlope(45.f); | |||
| } | |||
| ~BulletKinematicCharacterController() { } | |||
| protected: | |||
| static vec3* GetUpAxisDirections() | |||
| { | |||
| static vec3 sUpAxisDirection[3] = { vec3(1.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f) }; | |||
| return sUpAxisDirection; | |||
| } | |||
| //-------------------------- | |||
| //CONVENIENCE FUNCTIONS | |||
| //-- | |||
| //Returns the reflection Direction of a ray going 'Direction' hitting a surface with Normal 'Normal' from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html | |||
| vec3 GetReflectedDir(const vec3& Direction, const vec3& Normal) | |||
| { | |||
| return Direction - (2.f * dot(Direction, Normal) * Normal); | |||
| } | |||
| //Returns the portion of 'direction' that is parallel to 'normal' | |||
| vec3 ProjectDirOnNorm(const vec3& Direction, const vec3& Normal) | |||
| { | |||
| return Normal * dot(Direction, Normal); | |||
| } | |||
| //Returns the portion of 'Direction' that is perpindicular to 'Normal' | |||
| vec3 ProjectDirOnNormPerpindicular(const vec3& Direction, const vec3& Normal) | |||
| { | |||
| return Direction - ProjectDirOnNorm(Direction, Normal); | |||
| } | |||
| //Returns Ghost Object. -duh- | |||
| btPairCachingGhostObject* GetGhostObject() | |||
| { | |||
| return m_ghost_object; | |||
| } | |||
| //"Real" war functions | |||
| bool RecoverFromPenetration(btCollisionWorld* CollisionWorld); | |||
| void UpdateTargetOnHit(const vec3& hit_normal, float TangentMag = .0f, float NormalMag = 1.f); | |||
| void DoMove(btCollisionWorld* CollisionWorld, const vec3& MoveStep, float DeltaTime); | |||
| public: | |||
| ///btActionInterface interface : KEEP IN camelCase | |||
| virtual void updateAction(btCollisionWorld* CollisionWorld, float deltaTime) | |||
| { | |||
| PreStep(CollisionWorld); | |||
| PlayerStep(CollisionWorld, deltaTime); | |||
| } | |||
| //not in the interface, but called above | |||
| void PreStep(btCollisionWorld* CollisionWorld); | |||
| void PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime); | |||
| ///btActionInterface interface : KEEP IN camelCase | |||
| void debugDraw(btIDebugDraw* debugDrawer) { } | |||
| void SetUpAxis(int NewAxis) | |||
| { | |||
| if (NewAxis < 0) | |||
| NewAxis = 0; | |||
| if (NewAxis > 2) | |||
| NewAxis = 2; | |||
| m_i_up_axis = NewAxis; | |||
| } | |||
| //!!!!!! SHOULD DITCH THAT !!!!!! | |||
| //This should probably be called setPositionIncrementPerSimulatorStep. | |||
| //This is neither a Direction nor a velocity, but the amount to | |||
| //increment the position each simulation iteration, regardless | |||
| //of DeltaTime. | |||
| //This call will Reset any velocity set by SetVelocityForTimeInterval(). | |||
| virtual void SetWalkDirection(const vec3& walkDirection) | |||
| { | |||
| m_use_walk_direction = true; | |||
| m_walk_direction = walkDirection; | |||
| m_normalized_direction = normalize(m_walk_direction); | |||
| } | |||
| //Caller provides a velocity with which the character should MoveStep for | |||
| //the given time period. After the time period, velocity is Reset | |||
| //to zero. | |||
| //This call will Reset any walk Direction set by SetWalkDirection(). | |||
| //Negative time intervals will result in no motion. | |||
| virtual void SetVelocityForTimeInterval(const vec3& velocity, float timeInterval) | |||
| { | |||
| m_use_walk_direction = false; | |||
| m_walk_direction = velocity; | |||
| m_normalized_direction = normalize(m_walk_direction); | |||
| m_velocity_time_interval = timeInterval; | |||
| } | |||
| //Usefulness ? | |||
| void Reset() { } | |||
| void Warp(const vec3& NewOrigin) | |||
| { | |||
| btTransform NewTransform; | |||
| NewTransform.setIdentity(); | |||
| NewTransform.setOrigin(LOL2BTU_VEC3(NewOrigin)); | |||
| m_ghost_object->setWorldTransform(NewTransform); | |||
| } | |||
| //External Setup | |||
| //-- | |||
| void SetFallSpeed(float NewFallSpeed) { m_fall_speed = NewFallSpeed; } | |||
| void SetJumpSpeed(float NewJumpSpeed) { m_jump_speed = NewJumpSpeed; } | |||
| void SetMaxJumpHeight(float NewMaxJumpHeight) { m_max_jump_height = NewMaxJumpHeight; } | |||
| //Jump logic will go in EasyCC | |||
| bool CanJump() const { return OnGround(); } | |||
| void Jump(); | |||
| //NewGravity functions | |||
| void SetGravity(float NewGravity) { m_f_gravity = NewGravity; } | |||
| float GetGravity() const { return m_f_gravity; } | |||
| //The max slope determines the maximum angle that the controller can walk up. | |||
| //The slope angle is measured in radians. | |||
| void SetMaxSlope(float NewSlopeRadians) { m_max_slope_radians = NewSlopeRadians; m_max_slope_cosine = lol::cos(NewSlopeRadians); } | |||
| float GetMaxSlope() const { return m_max_slope_radians; } | |||
| void SetUseGhostSweepTest(bool UseGObjectSweepTest) { m_do_gobject_sweep_test = UseGObjectSweepTest; } | |||
| bool OnGround() const { return m_vertical_velocity == .0f && m_vertical_offset == .0f; } | |||
| private: | |||
| btPairCachingGhostObject* m_ghost_object; | |||
| btConvexShape* m_convex_shape; //is also in m_ghost_object, but it needs to be convex, so we store it here to avoid upcast | |||
| //keep track of the contact manifolds | |||
| btManifoldArray m_manifold_array; | |||
| float m_half_height; | |||
| float m_velocity_time_interval; | |||
| float m_vertical_velocity; | |||
| float m_vertical_offset; | |||
| float m_fall_speed; | |||
| float m_jump_speed; | |||
| float m_max_jump_height; | |||
| float m_max_slope_radians; // Slope angle that is set (used for returning the exact value) | |||
| float m_max_slope_cosine; // Cosine equivalent of m_max_slope_radians (calculated once when set, for optimization) | |||
| float m_f_gravity; | |||
| float m_turn_angle; | |||
| float m_step_height; | |||
| float m_added_margin;//@todo: remove this and fix the code | |||
| ///this is the desired walk Direction, set by the user | |||
| vec3 m_walk_direction; | |||
| vec3 m_normalized_direction; | |||
| //some internal variables | |||
| vec3 m_current_position; | |||
| float m_current_step_offset; | |||
| vec3 m_target_position; | |||
| vec3 m_touching_normal; | |||
| bool m_touching_contact; | |||
| bool m_was_on_ground; | |||
| bool m_was_jumping; | |||
| bool m_do_gobject_sweep_test; | |||
| bool m_use_walk_direction; | |||
| int m_i_up_axis; | |||
| //--------------------------------------------------------------------- | |||
| //NEW INTERNAL VARS | |||
| //--------------------------------------------------------------------- | |||
| //Gravity in vec3 | |||
| vec3 m_gravity; | |||
| //Current Velocity | |||
| vec3 m_velocity; | |||
| }; | |||
| #endif // HAVE_PHYS_USE_BULLET | |||
| #endif // USE_LOL_CTRLR_CHARAC | |||
| } /* namespace phys */ | |||
| } /* namespace phys */ | |||
| } /* namespace lol */ | |||
| @@ -34,81 +34,81 @@ namespace phys | |||
| { | |||
| class EasyCharacterController : public EasyPhysic, | |||
| public Entity | |||
| public Entity | |||
| { | |||
| friend class Simulation; | |||
| friend class EasyPhysic; | |||
| friend class Simulation; | |||
| friend class EasyPhysic; | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| public: | |||
| EasyCharacterController(WorldEntity* NewOwnerEntity) : | |||
| EasyPhysic(NewOwnerEntity), | |||
| 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_walk_velocity(vec3(0.f)), | |||
| m_current_velocity(vec3(0.f)) | |||
| { | |||
| m_gamegroup = GAMEGROUP_EZP_CHAR_CTRLR; | |||
| m_up_axis = 1; | |||
| m_gravity = vec3(.0f, -9.81f, .0f); | |||
| m_walk_velocity_damping = 0.2f; | |||
| } | |||
| ~EasyCharacterController() | |||
| { | |||
| delete m_character; | |||
| } | |||
| virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false); | |||
| virtual void InitBodyToGhost(); | |||
| virtual void AddToSimulation(class Simulation* current_simulation); | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation); | |||
| virtual void SetMovementForFrame(vec3 const &MoveQuantity); | |||
| virtual void Jump(); | |||
| virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation); | |||
| EasyCharacterController(WorldEntity* NewOwnerEntity) : | |||
| EasyPhysic(NewOwnerEntity), | |||
| 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_walk_velocity(vec3(0.f)), | |||
| m_current_velocity(vec3(0.f)) | |||
| { | |||
| m_gamegroup = GAMEGROUP_EZP_CHAR_CTRLR; | |||
| m_up_axis = 1; | |||
| m_gravity = vec3(.0f, -9.81f, .0f); | |||
| m_walk_velocity_damping = 0.2f; | |||
| } | |||
| ~EasyCharacterController() | |||
| { | |||
| delete m_character; | |||
| } | |||
| virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false); | |||
| virtual void InitBodyToGhost(); | |||
| virtual void AddToSimulation(class Simulation* current_simulation); | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation); | |||
| virtual void SetMovementForFrame(vec3 const &MoveQuantity); | |||
| virtual void Jump(); | |||
| 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); | |||
| virtual char const *GetName(); | |||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | |||
| virtual char const *GetName(); | |||
| public: | |||
| virtual void TickGame(float seconds); | |||
| virtual void TickGame(float seconds); | |||
| protected: | |||
| virtual btGhostObject* GetGhostObjectInstance(); | |||
| virtual btGhostObject* GetGhostObjectInstance(); | |||
| btPairCachingGhostObject* m_pair_caching_object; | |||
| //btKinematicCharacterController* m_character; | |||
| BulletKinematicCharacterController* m_character; | |||
| btPairCachingGhostObject* m_pair_caching_object; | |||
| //btKinematicCharacterController* m_character; | |||
| BulletKinematicCharacterController* m_character; | |||
| float m_step_height; | |||
| int m_up_axis; | |||
| bool m_base_is_updating; | |||
| vec3 m_base_cached_movement; | |||
| vec3 m_frame_cached_movement; | |||
| float m_step_height; | |||
| int m_up_axis; | |||
| bool m_base_is_updating; | |||
| vec3 m_base_cached_movement; | |||
| vec3 m_frame_cached_movement; | |||
| //---- | |||
| float m_walk_velocity_damping; | |||
| //---- | |||
| float m_walk_velocity_damping; | |||
| //---- | |||
| vec3 m_gravity; | |||
| //---- | |||
| vec3 m_gravity; | |||
| //---- | |||
| vec3 m_walk_velocity; | |||
| vec3 m_current_velocity; | |||
| //---- | |||
| vec3 m_walk_velocity; | |||
| vec3 m_current_velocity; | |||
| #else // NO PHYSIC IMPLEMENTATION | |||
| virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false) { } | |||
| virtual void InitBodyToGhost() { } | |||
| virtual void AddToSimulation(class Simulation* current_simulation) { } | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation) { } | |||
| virtual void SetMovementForFrame(vec3 const &MoveQuantity) { } | |||
| virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false) { } | |||
| virtual void InitBodyToGhost() { } | |||
| virtual void AddToSimulation(class Simulation* current_simulation) { } | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation) { } | |||
| virtual void SetMovementForFrame(vec3 const &MoveQuantity) { } | |||
| #endif // PHYSIC IMPLEMENTATION | |||
| @@ -31,180 +31,180 @@ namespace phys | |||
| class EasyConstraint | |||
| { | |||
| friend class Simulation; | |||
| friend class EasyPhysic; | |||
| friend class Simulation; | |||
| friend class EasyPhysic; | |||
| #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_owner_simulation(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() | |||
| { | |||
| 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; | |||
| } | |||
| void AddToSimulation(class Simulation* current_simulation); | |||
| void RemoveFromSimulation(class Simulation* current_simulation); | |||
| 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_owner_simulation(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() | |||
| { | |||
| 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; | |||
| } | |||
| 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; | |||
| //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) | |||
| { | |||
| } | |||
| 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) { } | |||
| 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() { } | |||
| //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; | |||
| } | |||
| 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: | |||
| Simulation* m_owner_simulation; | |||
| 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; | |||
| Simulation* m_owner_simulation; | |||
| 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; | |||
| }; | |||
| @@ -33,136 +33,136 @@ namespace phys | |||
| class EasyPhysic | |||
| { | |||
| friend class Simulation; | |||
| friend class EasyConstraint; | |||
| friend class Simulation; | |||
| friend class EasyConstraint; | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| public: | |||
| EasyPhysic(WorldEntity* NewOwnerEntity); | |||
| ~EasyPhysic(); | |||
| virtual void SetShapeToBox(lol::vec3& box_size); | |||
| virtual void SetShapeToSphere(float radius); | |||
| virtual void SetShapeToCone(float radius, float height); | |||
| virtual void SetShapeToCylinder(lol::vec3& cyl_size); | |||
| virtual void SetShapeToCapsule(float radius, float height); | |||
| 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))); | |||
| EasyPhysic(WorldEntity* NewOwnerEntity); | |||
| ~EasyPhysic(); | |||
| virtual void SetShapeToBox(lol::vec3& box_size); | |||
| virtual void SetShapeToSphere(float radius); | |||
| virtual void SetShapeToCone(float radius, float height); | |||
| virtual void SetShapeToCylinder(lol::vec3& cyl_size); | |||
| virtual void SetShapeToCapsule(float radius, float height); | |||
| 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))); | |||
| protected: | |||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | |||
| 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(); | |||
| virtual void AddToSimulation(class Simulation* current_simulation); | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation); | |||
| virtual void SetMass(float mass); | |||
| virtual void InitBodyToRigid(bool ZeroMassIsKinematic=false); | |||
| virtual void InitBodyToGhost(); | |||
| virtual void AddToSimulation(class Simulation* current_simulation); | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation); | |||
| protected: | |||
| virtual void SetLocalInertia(float mass); | |||
| virtual void SetShapeTo(btCollisionShape* collision_shape); | |||
| virtual void SetLocalInertia(float mass); | |||
| virtual void SetShapeTo(btCollisionShape* collision_shape); | |||
| virtual btGhostObject* GetGhostObjectInstance(); | |||
| virtual btGhostObject* GetGhostObjectInstance(); | |||
| btCollisionObject* m_collision_object; | |||
| btCollisionObject* m_collision_object; | |||
| btGhostObject* m_ghost_object; | |||
| btGhostObject* m_ghost_object; | |||
| btRigidBody* m_rigid_body; | |||
| btVector3 m_local_inertia; | |||
| btRigidBody* m_rigid_body; | |||
| btVector3 m_local_inertia; | |||
| btCollisionShape* m_collision_shape; | |||
| btConvexShape* m_convex_shape; | |||
| btMotionState* m_motion_state; | |||
| btCollisionShape* m_collision_shape; | |||
| btConvexShape* m_convex_shape; | |||
| btMotionState* m_motion_state; | |||
| #else // NO PHYSIC IMPLEMENTATION | |||
| public: | |||
| EasyPhysic(WorldEntity* NewOwnerEntity) { m_owner_entity = NewOwnerEntity; } | |||
| EasyPhysic(WorldEntity* NewOwnerEntity) { m_owner_entity = NewOwnerEntity; } | |||
| virtual void SetShapeToBox(lol::vec3& BoxSize) { } | |||
| virtual void SetShapeToSphere(float radius) { } | |||
| virtual void SetShapeToCone(float radius, float height) { } | |||
| virtual void SetShapeToCylinder(lol::vec3& cyl_size) { } | |||
| virtual void SetShapeToCapsule(float radius, float height) { } | |||
| virtual void SetShapeToBox(lol::vec3& BoxSize) { } | |||
| virtual void SetShapeToSphere(float radius) { } | |||
| virtual void SetShapeToCone(float radius, float height) { } | |||
| virtual void SetShapeToCylinder(lol::vec3& cyl_size) { } | |||
| virtual void SetShapeToCapsule(float radius, float height) { } | |||
| 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 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))) { } | |||
| private: | |||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | |||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | |||
| public: | |||
| virtual void SetMass(float mass) { } | |||
| virtual void InitBodyToRigid() { } | |||
| virtual void InitBodyToGhost() { } | |||
| virtual void AddToSimulation(class Simulation* current_simulation) { } | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation) { } | |||
| virtual void SetMass(float mass) { } | |||
| virtual void InitBodyToRigid() { } | |||
| virtual void InitBodyToGhost() { } | |||
| virtual void AddToSimulation(class Simulation* current_simulation) { } | |||
| virtual void RemoveFromSimulation(class Simulation* current_simulation) { } | |||
| virtual void InitBodyToGhost() { } | |||
| virtual void InitBodyToGhost() { } | |||
| #endif // PHYSIC IMPLEMENTATION | |||
| public: | |||
| //Sets the collision Group & Mask. | |||
| //Mask can change at runtime, not group ! | |||
| virtual bool SetCollisionChannel(int NewGroup, int NewMask) | |||
| { | |||
| if (CanChangeCollisionChannel()) | |||
| { | |||
| m_collision_group = (1<<NewGroup); | |||
| m_collision_mask = NewMask; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| 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 && 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 if (m_base_physic) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| //Sets the collision Group & Mask. | |||
| //Mask can change at runtime, not group ! | |||
| virtual bool SetCollisionChannel(int NewGroup, int NewMask) | |||
| { | |||
| if (CanChangeCollisionChannel()) | |||
| { | |||
| m_collision_group = (1<<NewGroup); | |||
| m_collision_mask = NewMask; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| 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 && 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 if (m_base_physic) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| protected: | |||
| lol::mat4 m_local_to_world; | |||
| float m_mass; | |||
| int m_collision_group; | |||
| int m_collision_mask; | |||
| WorldEntity* m_owner_entity; | |||
| Simulation* m_owner_simulation; | |||
| //Base/Attachment logic | |||
| Array<EasyPhysic*> m_based_physic_list; //List of objects based on this : this object moves, its based object MoveStep 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 | |||
| lol::mat4 m_local_to_world; | |||
| float m_mass; | |||
| int m_collision_group; | |||
| int m_collision_mask; | |||
| WorldEntity* m_owner_entity; | |||
| Simulation* m_owner_simulation; | |||
| //Base/Attachment logic | |||
| Array<EasyPhysic*> m_based_physic_list; //List of objects based on this : this object moves, its based object MoveStep 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 */ | |||
| @@ -19,32 +19,32 @@ | |||
| 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_INPUT GAMEGROUP_BEFORE | |||
| #define GAMEGROUP_ENT_PLATFORM GAMEGROUP_DEFAULT | |||
| #define GAMEGROUP_ENT_MAIN GAMEGROUP_AFTER | |||
| #define GAMEGROUP_EZP_CHAR_CTRLR GAMEGROUP_AFTER_0 | |||
| #define GAMEGROUP_SIMULATION GAMEGROUP_AFTER_1 | |||
| //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_INPUT GAMEGROUP_BEFORE | |||
| #define GAMEGROUP_ENT_PLATFORM GAMEGROUP_DEFAULT | |||
| #define GAMEGROUP_ENT_MAIN GAMEGROUP_AFTER | |||
| #define GAMEGROUP_EZP_CHAR_CTRLR GAMEGROUP_AFTER_0 | |||
| #define GAMEGROUP_SIMULATION GAMEGROUP_AFTER_1 | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| #define LOL2BT_UNIT 1.0f | |||
| #define BT2LOL_UNIT 1.0f | |||
| #define LOL2BT_UNIT 1.0f | |||
| #define BT2LOL_UNIT 1.0f | |||
| #define LOL2BT_SIZE 0.5f | |||
| #define BT2LOL_SIZE 2.0f | |||
| #define LOL2BT_SIZE 0.5f | |||
| #define BT2LOL_SIZE 2.0f | |||
| #define LOL2BT_VEC3(ELEMENT) btVector3((ELEMENT).x, (ELEMENT).y, (ELEMENT).z) | |||
| #define BT2LOL_VEC3(ELEMENT) (*(lol::vec3*)(&(ELEMENT))) | |||
| #define LOL2BT_VEC3(ELEMENT) btVector3((ELEMENT).x, (ELEMENT).y, (ELEMENT).z) | |||
| #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 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 BT2LOL_QUAT(ELEMENT) lol::quat((ELEMENT).getW(), BT2LOL_VEC3((ELEMENT).getAxis()) | |||
| #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()) | |||
| #endif // HAVE_PHYS_USE_BULLET | |||
| @@ -26,406 +26,406 @@ namespace phys | |||
| enum eRaycastType | |||
| { | |||
| ERT_Closest, | |||
| ERT_AllHit, | |||
| ERT_AnyHit, //Will stop at the first hit. Hit data are supposed to be irrelevant | |||
| ERT_Closest, | |||
| ERT_AllHit, | |||
| ERT_AnyHit, //Will stop at the first hit. Hit data are supposed to be irrelevant | |||
| ERT_MAX | |||
| 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; //??? | |||
| 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 | |||
| { | |||
| public: | |||
| Simulation() : | |||
| m_broadphase(0), | |||
| m_collision_configuration(0), | |||
| m_dispatcher(0), | |||
| m_solver(0), | |||
| m_dynamics_world(0), | |||
| m_timestep(1.f/60.f) | |||
| { | |||
| m_gamegroup = GAMEGROUP_SIMULATION; | |||
| } | |||
| ~Simulation() | |||
| { | |||
| Exit(); | |||
| } | |||
| char const *GetName() { return "<Simulation>"; } | |||
| Simulation() : | |||
| m_broadphase(0), | |||
| m_collision_configuration(0), | |||
| m_dispatcher(0), | |||
| m_solver(0), | |||
| m_dynamics_world(0), | |||
| m_timestep(1.f/60.f) | |||
| { | |||
| m_gamegroup = GAMEGROUP_SIMULATION; | |||
| } | |||
| ~Simulation() | |||
| { | |||
| Exit(); | |||
| } | |||
| char const *GetName() { return "<Simulation>"; } | |||
| #ifdef HAVE_PHYS_USE_BULLET | |||
| public: | |||
| void Init() | |||
| { | |||
| // Build the broadphase | |||
| if (1) | |||
| { | |||
| m_Sweep_broadphase = new btAxisSweep3(LOL2BT_VEC3(m_world_min), LOL2BT_VEC3(m_world_max)); | |||
| m_Sweep_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); | |||
| m_broadphase = m_Sweep_broadphase; | |||
| } | |||
| else | |||
| m_broadphase = new btDbvtBroadphase(); | |||
| // Set up the collision configuration and dispatcher | |||
| m_collision_configuration = new btDefaultCollisionConfiguration(); | |||
| m_dispatcher = new btCollisionDispatcher(m_collision_configuration); | |||
| // The actual physics solver | |||
| m_solver = new btSequentialImpulseConstraintSolver; | |||
| // The world. | |||
| m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collision_configuration); | |||
| } | |||
| virtual void TickGame(float seconds) | |||
| { | |||
| Entity::TickGame(seconds); | |||
| //step the simulation | |||
| if (m_dynamics_world) | |||
| { | |||
| //the "+1" is to have at least one Timestep and to ensure float to int .5f conversion. | |||
| int steps = (int)(seconds / m_timestep) + 1; | |||
| m_dynamics_world->stepSimulation(seconds, steps, m_timestep); | |||
| } | |||
| } | |||
| //Rip-Off of the btKinematicClosestNotMeRayResultCallback | |||
| class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback | |||
| { | |||
| public: | |||
| ClosestNotMeRayResultCallback(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 ClosestNotMeRayResultCallback(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() | |||
| { | |||
| delete m_dynamics_world; | |||
| delete m_solver; | |||
| delete m_dispatcher; | |||
| delete m_collision_configuration; | |||
| delete m_broadphase; | |||
| } | |||
| btDiscreteDynamicsWorld* GetWorld() | |||
| { | |||
| return m_dynamics_world; | |||
| } | |||
| void Init() | |||
| { | |||
| // Build the broadphase | |||
| if (1) | |||
| { | |||
| m_Sweep_broadphase = new btAxisSweep3(LOL2BT_VEC3(m_world_min), LOL2BT_VEC3(m_world_max)); | |||
| m_Sweep_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); | |||
| m_broadphase = m_Sweep_broadphase; | |||
| } | |||
| else | |||
| m_broadphase = new btDbvtBroadphase(); | |||
| // Set up the collision configuration and dispatcher | |||
| m_collision_configuration = new btDefaultCollisionConfiguration(); | |||
| m_dispatcher = new btCollisionDispatcher(m_collision_configuration); | |||
| // The actual physics solver | |||
| m_solver = new btSequentialImpulseConstraintSolver; | |||
| // The world. | |||
| m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collision_configuration); | |||
| } | |||
| virtual void TickGame(float seconds) | |||
| { | |||
| Entity::TickGame(seconds); | |||
| //step the simulation | |||
| if (m_dynamics_world) | |||
| { | |||
| //the "+1" is to have at least one Timestep and to ensure float to int .5f conversion. | |||
| int steps = (int)(seconds / m_timestep) + 1; | |||
| m_dynamics_world->stepSimulation(seconds, steps, m_timestep); | |||
| } | |||
| } | |||
| //Rip-Off of the btKinematicClosestNotMeRayResultCallback | |||
| class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback | |||
| { | |||
| public: | |||
| ClosestNotMeRayResultCallback(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 ClosestNotMeRayResultCallback(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() | |||
| { | |||
| delete m_dynamics_world; | |||
| delete m_solver; | |||
| delete m_dispatcher; | |||
| delete m_collision_configuration; | |||
| delete m_broadphase; | |||
| } | |||
| btDiscreteDynamicsWorld* GetWorld() | |||
| { | |||
| return m_dynamics_world; | |||
| } | |||
| private: | |||
| void CustomSetContinuousDetection(bool ShouldUseCCD) | |||
| { | |||
| if (m_dynamics_world) | |||
| m_dynamics_world->getDispatchInfo().m_useContinuous = ShouldUseCCD; | |||
| } | |||
| void CustomSetGravity(vec3 &NewGravity) | |||
| { | |||
| if (m_dynamics_world) | |||
| m_dynamics_world->setGravity(LOL2BT_VEC3(NewGravity * LOL2BT_UNIT)); | |||
| } | |||
| void CustomSetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax) | |||
| { | |||
| } | |||
| void CustomSetTimestep(float NewTimestep) { } | |||
| //broadphase | |||
| btBroadphaseInterface* m_broadphase; | |||
| btAxisSweep3* m_Sweep_broadphase; | |||
| // Set up the collision configuration and dispatc | |||
| btDefaultCollisionConfiguration* m_collision_configuration; | |||
| btCollisionDispatcher* m_dispatcher; | |||
| // The actual physics solver | |||
| btSequentialImpulseConstraintSolver* m_solver; | |||
| // The world. | |||
| btDiscreteDynamicsWorld* m_dynamics_world; | |||
| void CustomSetContinuousDetection(bool ShouldUseCCD) | |||
| { | |||
| if (m_dynamics_world) | |||
| m_dynamics_world->getDispatchInfo().m_useContinuous = ShouldUseCCD; | |||
| } | |||
| void CustomSetGravity(vec3 &NewGravity) | |||
| { | |||
| if (m_dynamics_world) | |||
| m_dynamics_world->setGravity(LOL2BT_VEC3(NewGravity * LOL2BT_UNIT)); | |||
| } | |||
| void CustomSetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax) | |||
| { | |||
| } | |||
| void CustomSetTimestep(float NewTimestep) { } | |||
| //broadphase | |||
| btBroadphaseInterface* m_broadphase; | |||
| btAxisSweep3* m_Sweep_broadphase; | |||
| // Set up the collision configuration and dispatc | |||
| btDefaultCollisionConfiguration* m_collision_configuration; | |||
| btCollisionDispatcher* m_dispatcher; | |||
| // The actual physics solver | |||
| btSequentialImpulseConstraintSolver* m_solver; | |||
| // The world. | |||
| btDiscreteDynamicsWorld* m_dynamics_world; | |||
| #else // NO PHYSIC IMPLEMENTATION | |||
| public: | |||
| void Init() { } | |||
| void TickGame(float seconds) { } | |||
| bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL) { return false; } | |||
| void Exit() { } | |||
| void Init() { } | |||
| void TickGame(float seconds) { } | |||
| bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL) { return false; } | |||
| void Exit() { } | |||
| private: | |||
| void CustomSetContinuousDetection(bool ShouldUseCCD) { } | |||
| void CustomSetGravity(vec3 &NewGravity) { } | |||
| void CustomSetWorldLimit(vec3 &NewWorldMin, vec3 &NewWorldMax) { } | |||
| void CustomSetTimestep(float NewTimestep) { } | |||
| void CustomSetContinuousDetection(bool ShouldUseCCD) { } | |||
| void CustomSetGravity(vec3 &NewGravity) { } | |||
| void CustomSetWorldLimit(vec3 &NewWorldMin, vec3 &NewWorldMax) { } | |||
| void CustomSetTimestep(float NewTimestep) { } | |||
| #endif // PHYSIC IMPLEMENTATION | |||
| public: | |||
| //Main logic : | |||
| //The Set*() functions do the all-lib-independent data storage. | |||
| //And then it calls the CustomSet*() which are the specialized versions. | |||
| //Sets the continuous collision detection flag. | |||
| void SetContinuousDetection(bool ShouldUseCCD) | |||
| { | |||
| m_using_CCD = ShouldUseCCD; | |||
| CustomSetContinuousDetection(ShouldUseCCD); | |||
| } | |||
| //Sets the simulation gravity. | |||
| void SetGravity(vec3 &NewGravity) | |||
| { | |||
| m_gravity = NewGravity; | |||
| CustomSetGravity(NewGravity); | |||
| } | |||
| //Sets the simulation gravity. | |||
| void SetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax) | |||
| { | |||
| m_world_min = NewWorldMin; | |||
| m_world_max = NewWorldMax; | |||
| CustomSetWorldLimit(NewWorldMin, NewWorldMax); | |||
| } | |||
| //Sets the simulation fixed timestep. | |||
| void SetTimestep(float NewTimestep) | |||
| { | |||
| if (NewTimestep > .0f) | |||
| { | |||
| m_timestep = NewTimestep; | |||
| CustomSetTimestep(NewTimestep); | |||
| } | |||
| } | |||
| //Main logic : | |||
| //The Set*() functions do the all-lib-independent data storage. | |||
| //And then it calls the CustomSet*() which are the specialized versions. | |||
| //Sets the continuous collision detection flag. | |||
| void SetContinuousDetection(bool ShouldUseCCD) | |||
| { | |||
| m_using_CCD = ShouldUseCCD; | |||
| CustomSetContinuousDetection(ShouldUseCCD); | |||
| } | |||
| //Sets the simulation gravity. | |||
| void SetGravity(vec3 &NewGravity) | |||
| { | |||
| m_gravity = NewGravity; | |||
| CustomSetGravity(NewGravity); | |||
| } | |||
| //Sets the simulation gravity. | |||
| void SetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax) | |||
| { | |||
| m_world_min = NewWorldMin; | |||
| m_world_max = NewWorldMax; | |||
| CustomSetWorldLimit(NewWorldMin, NewWorldMax); | |||
| } | |||
| //Sets the simulation fixed timestep. | |||
| void SetTimestep(float NewTimestep) | |||
| { | |||
| if (NewTimestep > .0f) | |||
| { | |||
| m_timestep = NewTimestep; | |||
| CustomSetTimestep(NewTimestep); | |||
| } | |||
| } | |||
| private: | |||
| friend class EasyPhysic; | |||
| friend class EasyCharacterController; | |||
| friend class EasyConstraint; | |||
| enum eEasyPhysicType | |||
| { | |||
| EEPT_Dynamic, | |||
| EEPT_Static, | |||
| EEPT_Ghost, | |||
| EEPT_CollisionObject, | |||
| EEPT_CharacterController, | |||
| EEPT_MAX | |||
| }; | |||
| //m_owner_simulation | |||
| //Adds the given EasyPhysic to the correct list. | |||
| void ObjectRegistration(bool AddObject, EasyPhysic* NewEP, eEasyPhysicType CurType) | |||
| { | |||
| Array<EasyPhysic*>* SearchList = NULL; | |||
| switch(CurType) | |||
| { | |||
| case EEPT_Dynamic: | |||
| { | |||
| SearchList = &m_dynamic_list; | |||
| break; | |||
| } | |||
| case EEPT_Static: | |||
| { | |||
| SearchList = &m_static_list; | |||
| break; | |||
| } | |||
| case EEPT_Ghost: | |||
| { | |||
| SearchList = &m_ghost_list; | |||
| break; | |||
| } | |||
| case EEPT_CollisionObject: | |||
| { | |||
| SearchList = &m_collision_object_list; | |||
| break; | |||
| } | |||
| case EEPT_CharacterController: | |||
| { | |||
| SearchList = &m_character_controller_list; | |||
| break; | |||
| } | |||
| } | |||
| if (AddObject) | |||
| { | |||
| NewEP->m_owner_simulation = this; | |||
| (*SearchList) << NewEP; | |||
| } | |||
| else | |||
| { | |||
| NewEP->m_owner_simulation = NULL; | |||
| for (int i = 0; i < SearchList->Count(); ++i) | |||
| { | |||
| if ((*SearchList)[i] == NewEP) | |||
| { | |||
| SearchList->Remove(i--); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void ObjectRegistration(bool AddObject, EasyConstraint* NewEC) | |||
| { | |||
| Array<EasyConstraint*>* SearchList = NULL; | |||
| SearchList = &m_constraint_list; | |||
| if (AddObject) | |||
| { | |||
| NewEC->m_owner_simulation = this; | |||
| (*SearchList) << NewEC; | |||
| } | |||
| else | |||
| { | |||
| NewEC->m_owner_simulation = NULL; | |||
| for (int i = 0; i < SearchList->Count(); ++i) | |||
| { | |||
| if ((*SearchList)[i] == NewEC) | |||
| { | |||
| SearchList->Remove(i--); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //Easy Physics body List | |||
| Array<EasyPhysic*> m_dynamic_list; | |||
| Array<EasyPhysic*> m_static_list; | |||
| Array<EasyPhysic*> m_ghost_list; | |||
| Array<EasyPhysic*> m_collision_object_list; | |||
| Array<EasyPhysic*> m_character_controller_list; | |||
| Array<EasyConstraint*> m_constraint_list; | |||
| //Easy Physics data storage | |||
| float m_timestep; | |||
| bool m_using_CCD; | |||
| vec3 m_gravity; | |||
| vec3 m_world_min; | |||
| vec3 m_world_max; | |||
| friend class EasyPhysic; | |||
| friend class EasyCharacterController; | |||
| friend class EasyConstraint; | |||
| enum eEasyPhysicType | |||
| { | |||
| EEPT_Dynamic, | |||
| EEPT_Static, | |||
| EEPT_Ghost, | |||
| EEPT_CollisionObject, | |||
| EEPT_CharacterController, | |||
| EEPT_MAX | |||
| }; | |||
| //m_owner_simulation | |||
| //Adds the given EasyPhysic to the correct list. | |||
| void ObjectRegistration(bool AddObject, EasyPhysic* NewEP, eEasyPhysicType CurType) | |||
| { | |||
| Array<EasyPhysic*>* SearchList = NULL; | |||
| switch(CurType) | |||
| { | |||
| case EEPT_Dynamic: | |||
| { | |||
| SearchList = &m_dynamic_list; | |||
| break; | |||
| } | |||
| case EEPT_Static: | |||
| { | |||
| SearchList = &m_static_list; | |||
| break; | |||
| } | |||
| case EEPT_Ghost: | |||
| { | |||
| SearchList = &m_ghost_list; | |||
| break; | |||
| } | |||
| case EEPT_CollisionObject: | |||
| { | |||
| SearchList = &m_collision_object_list; | |||
| break; | |||
| } | |||
| case EEPT_CharacterController: | |||
| { | |||
| SearchList = &m_character_controller_list; | |||
| break; | |||
| } | |||
| } | |||
| if (AddObject) | |||
| { | |||
| NewEP->m_owner_simulation = this; | |||
| (*SearchList) << NewEP; | |||
| } | |||
| else | |||
| { | |||
| NewEP->m_owner_simulation = NULL; | |||
| for (int i = 0; i < SearchList->Count(); ++i) | |||
| { | |||
| if ((*SearchList)[i] == NewEP) | |||
| { | |||
| SearchList->Remove(i--); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void ObjectRegistration(bool AddObject, EasyConstraint* NewEC) | |||
| { | |||
| Array<EasyConstraint*>* SearchList = NULL; | |||
| SearchList = &m_constraint_list; | |||
| if (AddObject) | |||
| { | |||
| NewEC->m_owner_simulation = this; | |||
| (*SearchList) << NewEC; | |||
| } | |||
| else | |||
| { | |||
| NewEC->m_owner_simulation = NULL; | |||
| for (int i = 0; i < SearchList->Count(); ++i) | |||
| { | |||
| if ((*SearchList)[i] == NewEC) | |||
| { | |||
| SearchList->Remove(i--); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //Easy Physics body List | |||
| Array<EasyPhysic*> m_dynamic_list; | |||
| Array<EasyPhysic*> m_static_list; | |||
| Array<EasyPhysic*> m_ghost_list; | |||
| Array<EasyPhysic*> m_collision_object_list; | |||
| Array<EasyPhysic*> m_character_controller_list; | |||
| Array<EasyConstraint*> m_constraint_list; | |||
| //Easy Physics data storage | |||
| float m_timestep; | |||
| bool m_using_CCD; | |||
| vec3 m_gravity; | |||
| vec3 m_world_min; | |||
| vec3 m_world_max; | |||
| }; | |||
| } /* namespace phys */ | |||
| @@ -45,202 +45,202 @@ namespace phys | |||
| //When called, will try to remove Character controller from its collision. | |||
| bool BulletKinematicCharacterController::RecoverFromPenetration(btCollisionWorld* CollisionWorld) | |||
| { | |||
| bool HasPenetration = false; | |||
| //Retrieve all pair with us colliding. | |||
| CollisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghost_object->getOverlappingPairCache(), CollisionWorld->getDispatchInfo(), CollisionWorld->getDispatcher()); | |||
| m_current_position = BT2LOLU_VEC3(m_ghost_object->getWorldTransform().getOrigin()); | |||
| float MaxPen = .0f; | |||
| for (int i = 0; i < m_ghost_object->getOverlappingPairCache()->getNumOverlappingPairs(); i++) | |||
| { | |||
| m_manifold_array.resize(0); | |||
| //this is the equivalent of the "Touch algorithm". Maybe refactor ? | |||
| btBroadphasePair* CollisionPair = &m_ghost_object->getOverlappingPairCache()->getOverlappingPairArray()[i]; | |||
| if (CollisionPair->m_algorithm) | |||
| CollisionPair->m_algorithm->getAllContactManifolds(m_manifold_array); | |||
| for (int j = 0; j < m_manifold_array.size(); ++j) | |||
| { | |||
| btPersistentManifold* CurMfold = m_manifold_array[j]; | |||
| //Normal direction differs if we're Body0 | |||
| float DirSign = CurMfold->getBody0() == m_ghost_object ? -1.f : 1.f; | |||
| for (int k = 0; k < CurMfold->getNumContacts(); k++) | |||
| { | |||
| const btManifoldPoint& MfPoint = CurMfold->getContactPoint(k); | |||
| float Dist = MfPoint.getDistance(); | |||
| if (Dist < .0f) | |||
| { | |||
| if (Dist < MaxPen) | |||
| { | |||
| MaxPen = Dist; | |||
| m_touching_normal = BT2LOL_VEC3(MfPoint.m_normalWorldOnB) * DirSign; | |||
| } | |||
| m_current_position += BT2LOL_VEC3(MfPoint.m_normalWorldOnB) * DirSign * Dist * .2f; | |||
| HasPenetration = true; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| btTransform GObjMx = m_ghost_object->getWorldTransform(); | |||
| GObjMx.setOrigin(LOL2BTU_VEC3(m_current_position)); | |||
| m_ghost_object->setWorldTransform(GObjMx); | |||
| return HasPenetration; | |||
| bool HasPenetration = false; | |||
| //Retrieve all pair with us colliding. | |||
| CollisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghost_object->getOverlappingPairCache(), CollisionWorld->getDispatchInfo(), CollisionWorld->getDispatcher()); | |||
| m_current_position = BT2LOLU_VEC3(m_ghost_object->getWorldTransform().getOrigin()); | |||
| float MaxPen = .0f; | |||
| for (int i = 0; i < m_ghost_object->getOverlappingPairCache()->getNumOverlappingPairs(); i++) | |||
| { | |||
| m_manifold_array.resize(0); | |||
| //this is the equivalent of the "Touch algorithm". Maybe refactor ? | |||
| btBroadphasePair* CollisionPair = &m_ghost_object->getOverlappingPairCache()->getOverlappingPairArray()[i]; | |||
| if (CollisionPair->m_algorithm) | |||
| CollisionPair->m_algorithm->getAllContactManifolds(m_manifold_array); | |||
| for (int j = 0; j < m_manifold_array.size(); ++j) | |||
| { | |||
| btPersistentManifold* CurMfold = m_manifold_array[j]; | |||
| //Normal direction differs if we're Body0 | |||
| float DirSign = CurMfold->getBody0() == m_ghost_object ? -1.f : 1.f; | |||
| for (int k = 0; k < CurMfold->getNumContacts(); k++) | |||
| { | |||
| const btManifoldPoint& MfPoint = CurMfold->getContactPoint(k); | |||
| float Dist = MfPoint.getDistance(); | |||
| if (Dist < .0f) | |||
| { | |||
| if (Dist < MaxPen) | |||
| { | |||
| MaxPen = Dist; | |||
| m_touching_normal = BT2LOL_VEC3(MfPoint.m_normalWorldOnB) * DirSign; | |||
| } | |||
| m_current_position += BT2LOL_VEC3(MfPoint.m_normalWorldOnB) * DirSign * Dist * .2f; | |||
| HasPenetration = true; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| btTransform GObjMx = m_ghost_object->getWorldTransform(); | |||
| GObjMx.setOrigin(LOL2BTU_VEC3(m_current_position)); | |||
| m_ghost_object->setWorldTransform(GObjMx); | |||
| return HasPenetration; | |||
| } | |||
| //When the Controller hits a wall, we modify the target so the controller will MoveStep along the wall. | |||
| void BulletKinematicCharacterController::UpdateTargetOnHit(const vec3& HitNormal, float TangentMag, float NormalMag) | |||
| { | |||
| vec3 Movedir = m_target_position - m_current_position; | |||
| float MoveLength = (float)length(Movedir); | |||
| vec3 Movedir = m_target_position - m_current_position; | |||
| float MoveLength = (float)length(Movedir); | |||
| if (MoveLength > SIMD_EPSILON) | |||
| { | |||
| Movedir = normalize(Movedir); | |||
| if (MoveLength > SIMD_EPSILON) | |||
| { | |||
| Movedir = normalize(Movedir); | |||
| vec3 ReflectDir = normalize(GetReflectedDir(Movedir, HitNormal)); | |||
| vec3 ParallelDir = ProjectDirOnNorm(ReflectDir, HitNormal); | |||
| vec3 PerpindicularDir = ProjectDirOnNormPerpindicular(ReflectDir, HitNormal); | |||
| vec3 ReflectDir = normalize(GetReflectedDir(Movedir, HitNormal)); | |||
| vec3 ParallelDir = ProjectDirOnNorm(ReflectDir, HitNormal); | |||
| vec3 PerpindicularDir = ProjectDirOnNormPerpindicular(ReflectDir, HitNormal); | |||
| m_target_position = m_current_position; | |||
| m_target_position = m_current_position; | |||
| if (NormalMag != .0f) | |||
| m_target_position += PerpindicularDir * NormalMag * MoveLength; | |||
| } | |||
| if (NormalMag != .0f) | |||
| m_target_position += PerpindicularDir * NormalMag * MoveLength; | |||
| } | |||
| } | |||
| //Handles the actual Movement. It actually moves in the 3 dimensions, function name is confusing. | |||
| void BulletKinematicCharacterController::DoMove(btCollisionWorld* CollisionWorld, const vec3& MoveStep, float DeltaTime) | |||
| { | |||
| // phase 2: forward and strafe | |||
| m_target_position = m_current_position + MoveStep; | |||
| btTransform SweepStart, SweepEnd; | |||
| SweepStart.setIdentity(); | |||
| SweepEnd.setIdentity(); | |||
| float Fraction = 1.f; | |||
| float SqDist = .0f; | |||
| if (m_touching_contact && dot(m_normalized_direction, m_touching_normal) > .0f) | |||
| UpdateTargetOnHit(m_touching_normal); | |||
| //Let's loop on movement, until Movement fraction if below 0.01, which means we've reached our destination. | |||
| //Or until we'tried 10 times. | |||
| int MaxMoveLoop = 10; | |||
| while (Fraction > .01f && MaxMoveLoop-- > 0) | |||
| { | |||
| SweepStart.setOrigin(LOL2BTU_VEC3(m_current_position)); | |||
| SweepEnd.setOrigin(LOL2BTU_VEC3(m_target_position)); | |||
| vec3 SweepDirNeg(m_current_position - m_target_position); | |||
| ClosestNotMeConvexResultCallback SweepCallback(m_ghost_object, SweepDirNeg, .0f); | |||
| SweepCallback.m_collisionFilterGroup = GetGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; | |||
| SweepCallback.m_collisionFilterMask = GetGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; | |||
| //The sweep test is done with an added margin, so we use it and then discard it | |||
| float SavedMargin = m_convex_shape->getMargin(); | |||
| m_convex_shape->setMargin(SavedMargin + m_added_margin); //Apply Added Margin | |||
| if (m_do_gobject_sweep_test) | |||
| m_ghost_object->convexSweepTest (m_convex_shape, SweepStart, SweepEnd, SweepCallback, CollisionWorld->getDispatchInfo().m_allowedCcdPenetration); | |||
| else | |||
| CollisionWorld->convexSweepTest (m_convex_shape, SweepStart, SweepEnd, SweepCallback, CollisionWorld->getDispatchInfo().m_allowedCcdPenetration); | |||
| m_convex_shape->setMargin(SavedMargin); //Restore saved margin | |||
| Fraction -= SweepCallback.m_closestHitFraction; | |||
| if (SweepCallback.hasHit()) | |||
| { | |||
| //We moved only a Fraction | |||
| float HitDist = (float)length(BT2LOLU_VEC3(SweepCallback.m_hitPointWorld) - m_current_position); | |||
| UpdateTargetOnHit(BT2LOL_VEC3(SweepCallback.m_hitNormalWorld)); | |||
| vec3 NewDir = m_target_position - m_current_position; | |||
| SqDist = sqlength(NewDir); | |||
| if (SqDist > SIMD_EPSILON) | |||
| { | |||
| NewDir = normalize(NewDir); | |||
| //See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." | |||
| if (dot(NewDir, m_normalized_direction) <= .0f) | |||
| break; | |||
| } | |||
| else | |||
| break; | |||
| } | |||
| else //We moved whole way | |||
| m_current_position = m_target_position; | |||
| } | |||
| // phase 2: forward and strafe | |||
| m_target_position = m_current_position + MoveStep; | |||
| btTransform SweepStart, SweepEnd; | |||
| SweepStart.setIdentity(); | |||
| SweepEnd.setIdentity(); | |||
| float Fraction = 1.f; | |||
| float SqDist = .0f; | |||
| if (m_touching_contact && dot(m_normalized_direction, m_touching_normal) > .0f) | |||
| UpdateTargetOnHit(m_touching_normal); | |||
| //Let's loop on movement, until Movement fraction if below 0.01, which means we've reached our destination. | |||
| //Or until we'tried 10 times. | |||
| int MaxMoveLoop = 10; | |||
| while (Fraction > .01f && MaxMoveLoop-- > 0) | |||
| { | |||
| SweepStart.setOrigin(LOL2BTU_VEC3(m_current_position)); | |||
| SweepEnd.setOrigin(LOL2BTU_VEC3(m_target_position)); | |||
| vec3 SweepDirNeg(m_current_position - m_target_position); | |||
| ClosestNotMeConvexResultCallback SweepCallback(m_ghost_object, SweepDirNeg, .0f); | |||
| SweepCallback.m_collisionFilterGroup = GetGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; | |||
| SweepCallback.m_collisionFilterMask = GetGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; | |||
| //The sweep test is done with an added margin, so we use it and then discard it | |||
| float SavedMargin = m_convex_shape->getMargin(); | |||
| m_convex_shape->setMargin(SavedMargin + m_added_margin); //Apply Added Margin | |||
| if (m_do_gobject_sweep_test) | |||
| m_ghost_object->convexSweepTest (m_convex_shape, SweepStart, SweepEnd, SweepCallback, CollisionWorld->getDispatchInfo().m_allowedCcdPenetration); | |||
| else | |||
| CollisionWorld->convexSweepTest (m_convex_shape, SweepStart, SweepEnd, SweepCallback, CollisionWorld->getDispatchInfo().m_allowedCcdPenetration); | |||
| m_convex_shape->setMargin(SavedMargin); //Restore saved margin | |||
| Fraction -= SweepCallback.m_closestHitFraction; | |||
| if (SweepCallback.hasHit()) | |||
| { | |||
| //We moved only a Fraction | |||
| float HitDist = (float)length(BT2LOLU_VEC3(SweepCallback.m_hitPointWorld) - m_current_position); | |||
| UpdateTargetOnHit(BT2LOL_VEC3(SweepCallback.m_hitNormalWorld)); | |||
| vec3 NewDir = m_target_position - m_current_position; | |||
| SqDist = sqlength(NewDir); | |||
| if (SqDist > SIMD_EPSILON) | |||
| { | |||
| NewDir = normalize(NewDir); | |||
| //See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." | |||
| if (dot(NewDir, m_normalized_direction) <= .0f) | |||
| break; | |||
| } | |||
| else | |||
| break; | |||
| } | |||
| else //We moved whole way | |||
| m_current_position = m_target_position; | |||
| } | |||
| } | |||
| //The PreStepis done in order to recover from any HasPenetration. | |||
| void BulletKinematicCharacterController::PreStep(btCollisionWorld* CollisionWorld) | |||
| { | |||
| int MaxPenetrationLoop = 0; | |||
| m_touching_contact = false; | |||
| while (RecoverFromPenetration(CollisionWorld)) | |||
| { | |||
| MaxPenetrationLoop++; | |||
| m_touching_contact = true; | |||
| if (MaxPenetrationLoop > 4) | |||
| break; | |||
| } | |||
| m_current_position = BT2LOLU_VEC3(m_ghost_object->getWorldTransform().getOrigin()); | |||
| m_target_position = m_current_position; | |||
| int MaxPenetrationLoop = 0; | |||
| m_touching_contact = false; | |||
| while (RecoverFromPenetration(CollisionWorld)) | |||
| { | |||
| MaxPenetrationLoop++; | |||
| m_touching_contact = true; | |||
| if (MaxPenetrationLoop > 4) | |||
| break; | |||
| } | |||
| m_current_position = BT2LOLU_VEC3(m_ghost_object->getWorldTransform().getOrigin()); | |||
| m_target_position = m_current_position; | |||
| } | |||
| //And so we step : | |||
| //StepUpfirst, then movement, then StepDownon the ground. | |||
| void BulletKinematicCharacterController::PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime) | |||
| { | |||
| // quick check... | |||
| if (!m_use_walk_direction && m_velocity_time_interval <= .0f) | |||
| return; // no motion | |||
| // Update fall velocity. | |||
| //m_velocity -= m_gravity * DeltaTime; | |||
| btTransform NewTransform; | |||
| NewTransform = m_ghost_object->getWorldTransform(); | |||
| vec3 MoveStep(.0f); | |||
| if (m_use_walk_direction) | |||
| MoveStep = m_walk_direction; | |||
| else | |||
| { | |||
| //Still have some time left for moving! | |||
| float dtMoving = (DeltaTime < m_velocity_time_interval) ? DeltaTime : m_velocity_time_interval; | |||
| m_velocity_time_interval -= DeltaTime; | |||
| // how far will we MoveStep while we are moving? | |||
| MoveStep = m_walk_direction * dtMoving; | |||
| } | |||
| //Okay, step ! | |||
| DoMove(CollisionWorld, MoveStep, DeltaTime); | |||
| //Movement finished, update World transform | |||
| NewTransform.setOrigin(LOL2BTU_VEC3(m_current_position)); | |||
| m_ghost_object->setWorldTransform(NewTransform); | |||
| // quick check... | |||
| if (!m_use_walk_direction && m_velocity_time_interval <= .0f) | |||
| return; // no motion | |||
| // Update fall velocity. | |||
| //m_velocity -= m_gravity * DeltaTime; | |||
| btTransform NewTransform; | |||
| NewTransform = m_ghost_object->getWorldTransform(); | |||
| vec3 MoveStep(.0f); | |||
| if (m_use_walk_direction) | |||
| MoveStep = m_walk_direction; | |||
| else | |||
| { | |||
| //Still have some time left for moving! | |||
| float dtMoving = (DeltaTime < m_velocity_time_interval) ? DeltaTime : m_velocity_time_interval; | |||
| m_velocity_time_interval -= DeltaTime; | |||
| // how far will we MoveStep while we are moving? | |||
| MoveStep = m_walk_direction * dtMoving; | |||
| } | |||
| //Okay, step ! | |||
| DoMove(CollisionWorld, MoveStep, DeltaTime); | |||
| //Movement finished, update World transform | |||
| NewTransform.setOrigin(LOL2BTU_VEC3(m_current_position)); | |||
| m_ghost_object->setWorldTransform(NewTransform); | |||
| } | |||
| //should MoveStep Jump logic in EasyCC | |||
| void BulletKinematicCharacterController::Jump() | |||
| { | |||
| if (!CanJump()) | |||
| return; | |||
| if (!CanJump()) | |||
| return; | |||
| m_vertical_velocity = m_jump_speed; | |||
| m_was_jumping = true; | |||
| m_vertical_velocity = m_jump_speed; | |||
| m_was_jumping = true; | |||
| } | |||
| #endif // HAVE_PHYS_USE_BULLET | |||
| #endif // USE_LOL_CTRLR_CHARAC | |||
| } /* namespace phys */ | |||
| } /* namespace phys */ | |||
| } /* namespace lol */ | |||
| @@ -38,68 +38,68 @@ void EasyCharacterController::InitBodyToRigid(bool ZeroMassIsKinematic) | |||
| //Return correct Ghost Object | |||
| btGhostObject* EasyCharacterController::GetGhostObjectInstance() | |||
| { | |||
| return new btPairCachingGhostObject(); | |||
| return new btPairCachingGhostObject(); | |||
| } | |||
| //Init to Pair caching ghost object, since Character uses that one. | |||
| void EasyCharacterController::InitBodyToGhost() | |||
| { | |||
| EasyPhysic::InitBodyToGhost(); | |||
| EasyPhysic::InitBodyToGhost(); | |||
| m_pair_caching_object = (btPairCachingGhostObject*)m_ghost_object; | |||
| m_ghost_object->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT | m_ghost_object->getCollisionFlags()); | |||
| m_pair_caching_object = (btPairCachingGhostObject*)m_ghost_object; | |||
| m_ghost_object->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT | m_ghost_object->getCollisionFlags()); | |||
| } | |||
| //Add Physic object to the simulation | |||
| void EasyCharacterController::AddToSimulation(class Simulation* current_simulation) | |||
| { | |||
| EasyPhysic::AddToSimulation(current_simulation); | |||
| EasyPhysic::AddToSimulation(current_simulation); | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_character) | |||
| delete m_character; | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_character) | |||
| delete m_character; | |||
| //m_character = new btKinematicCharacterController(m_pair_caching_object, m_convex_shape, m_step_height, m_up_axis); | |||
| m_character = new BulletKinematicCharacterController(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); | |||
| m_character = new BulletKinematicCharacterController(m_pair_caching_object, m_convex_shape, m_step_height, m_up_axis); | |||
| //Deactivate Character controller basic behaviour. | |||
| //m_character->setGravity(.0f); | |||
| //m_character->setFallSpeed(.0f); | |||
| //Deactivate Character controller basic behaviour. | |||
| //m_character->setGravity(.0f); | |||
| //m_character->setFallSpeed(.0f); | |||
| dynamics_world->addAction(m_character); | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_CharacterController); | |||
| Ticker::Ref(this); | |||
| } | |||
| dynamics_world->addAction(m_character); | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_CharacterController); | |||
| Ticker::Ref(this); | |||
| } | |||
| } | |||
| //Remove Physic object to the simulation | |||
| void EasyCharacterController::RemoveFromSimulation(class Simulation* current_simulation) | |||
| { | |||
| EasyPhysic::RemoveFromSimulation(current_simulation); | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_character) | |||
| { | |||
| dynamics_world->removeAction(m_character); | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_CharacterController); | |||
| Ticker::Unref(this); | |||
| } | |||
| } | |||
| EasyPhysic::RemoveFromSimulation(current_simulation); | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_character) | |||
| { | |||
| dynamics_world->removeAction(m_character); | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_CharacterController); | |||
| Ticker::Unref(this); | |||
| } | |||
| } | |||
| } | |||
| void EasyCharacterController::Jump() | |||
| { | |||
| m_character->Jump(); | |||
| m_character->Jump(); | |||
| } | |||
| //Set movement for this frame | |||
| void EasyCharacterController::SetMovementForFrame(vec3 const &MoveQuantity) | |||
| { | |||
| m_frame_cached_movement = MoveQuantity; | |||
| m_frame_cached_movement = MoveQuantity; | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -107,43 +107,43 @@ void EasyCharacterController::SetMovementForFrame(vec3 const &MoveQuantity) | |||
| //-- | |||
| 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); | |||
| 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; | |||
| m_base_is_updating = true; | |||
| EasyPhysic::BaseTransformChanged(PreviousMatrix, NewMatrix); | |||
| m_base_is_updating = false; | |||
| } | |||
| //--- | |||
| char const *EasyCharacterController::GetName() | |||
| { | |||
| return "<EasyCharacterController>"; | |||
| return "<EasyCharacterController>"; | |||
| } | |||
| //Physic Tick | |||
| void EasyCharacterController::TickGame(float seconds) | |||
| { | |||
| Entity::TickGame(seconds); | |||
| //Send final velocity in Bullet | |||
| { | |||
| int IterationsNb = (int)(seconds / m_owner_simulation->m_timestep); | |||
| float NewSeconds = IterationsNb * m_owner_simulation->m_timestep; | |||
| m_character->SetVelocityForTimeInterval((m_base_cached_movement + m_frame_cached_movement) / NewSeconds, NewSeconds); | |||
| m_base_cached_movement = vec3(.0f); | |||
| } | |||
| Entity::TickGame(seconds); | |||
| //Send final velocity in Bullet | |||
| { | |||
| int IterationsNb = (int)(seconds / m_owner_simulation->m_timestep); | |||
| float NewSeconds = IterationsNb * m_owner_simulation->m_timestep; | |||
| m_character->SetVelocityForTimeInterval((m_base_cached_movement + m_frame_cached_movement) / NewSeconds, NewSeconds); | |||
| m_base_cached_movement = vec3(.0f); | |||
| } | |||
| } | |||
| #endif // HAVE_PHYS_USE_BULLET | |||
| @@ -21,22 +21,22 @@ namespace phys | |||
| 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->ObjectRegistration(true, this); | |||
| } | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world && m_typed_constraint) | |||
| { | |||
| dynamics_world->addConstraint(m_typed_constraint, m_disable_a2b_collision); | |||
| current_simulation->ObjectRegistration(true, 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); | |||
| current_simulation->ObjectRegistration(false, this); | |||
| } | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world && m_typed_constraint) | |||
| { | |||
| dynamics_world->removeConstraint(m_typed_constraint); | |||
| current_simulation->ObjectRegistration(false, this); | |||
| } | |||
| } | |||
| #endif // HAVE_PHYS_USE_BULLET | |||
| @@ -29,29 +29,29 @@ namespace phys | |||
| //EASY_PHYSIC | |||
| //-- | |||
| EasyPhysic::EasyPhysic(WorldEntity* NewOwnerEntity) : | |||
| m_collision_object(NULL), | |||
| m_ghost_object(NULL), | |||
| m_rigid_body(NULL), | |||
| m_local_inertia(btVector3(.0f, .0f, .0f)), | |||
| m_collision_shape(NULL), | |||
| m_convex_shape(NULL), | |||
| m_motion_state(NULL), | |||
| m_mass(.0f), | |||
| m_collision_group(1), | |||
| m_collision_mask(1), | |||
| m_owner_entity(NewOwnerEntity), | |||
| m_owner_simulation(NULL), | |||
| m_base_physic(NULL) | |||
| EasyPhysic::EasyPhysic(WorldEntity* NewOwnerEntity) : | |||
| m_collision_object(NULL), | |||
| m_ghost_object(NULL), | |||
| m_rigid_body(NULL), | |||
| m_local_inertia(btVector3(.0f, .0f, .0f)), | |||
| m_collision_shape(NULL), | |||
| m_convex_shape(NULL), | |||
| m_motion_state(NULL), | |||
| m_mass(.0f), | |||
| m_collision_group(1), | |||
| m_collision_mask(1), | |||
| m_owner_entity(NewOwnerEntity), | |||
| m_owner_simulation(NULL), | |||
| m_base_physic(NULL) | |||
| { | |||
| } | |||
| EasyPhysic::~EasyPhysic() | |||
| { | |||
| m_rigid_body = NULL; | |||
| delete m_collision_object; | |||
| delete m_collision_shape; | |||
| delete m_motion_state; | |||
| m_rigid_body = NULL; | |||
| delete m_collision_object; | |||
| delete m_collision_shape; | |||
| delete m_motion_state; | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -60,55 +60,55 @@ EasyPhysic::~EasyPhysic() | |||
| void EasyPhysic::SetShapeTo(btCollisionShape* collision_shape) | |||
| { | |||
| bool bReinitToRigidBody = false; | |||
| if (m_rigid_body) | |||
| { | |||
| bReinitToRigidBody = true; | |||
| delete m_rigid_body; | |||
| } | |||
| if (m_collision_shape) | |||
| delete m_collision_shape; | |||
| m_collision_shape = collision_shape; | |||
| if (bReinitToRigidBody) | |||
| InitBodyToRigid(); | |||
| bool bReinitToRigidBody = false; | |||
| if (m_rigid_body) | |||
| { | |||
| bReinitToRigidBody = true; | |||
| delete m_rigid_body; | |||
| } | |||
| if (m_collision_shape) | |||
| delete m_collision_shape; | |||
| m_collision_shape = collision_shape; | |||
| if (bReinitToRigidBody) | |||
| InitBodyToRigid(); | |||
| } | |||
| //Box Shape support | |||
| void EasyPhysic::SetShapeToBox(lol::vec3& box_size) | |||
| { | |||
| vec3 new_box_size = box_size * LOL2BT_UNIT * LOL2BT_SIZE; | |||
| m_convex_shape = new btBoxShape(LOL2BT_VEC3(new_box_size)); | |||
| SetShapeTo(m_convex_shape); | |||
| vec3 new_box_size = box_size * LOL2BT_UNIT * LOL2BT_SIZE; | |||
| m_convex_shape = new btBoxShape(LOL2BT_VEC3(new_box_size)); | |||
| SetShapeTo(m_convex_shape); | |||
| } | |||
| void EasyPhysic::SetShapeToSphere(float radius) | |||
| { | |||
| m_convex_shape = new btSphereShape(radius * LOL2BT_UNIT * LOL2BT_SIZE); | |||
| SetShapeTo(m_convex_shape); | |||
| m_convex_shape = new btSphereShape(radius * LOL2BT_UNIT * LOL2BT_SIZE); | |||
| SetShapeTo(m_convex_shape); | |||
| } | |||
| void EasyPhysic::SetShapeToCone(float radius, float height) | |||
| { | |||
| m_convex_shape = new btConeShape( radius * LOL2BT_UNIT, | |||
| height * LOL2BT_UNIT); | |||
| SetShapeTo(m_convex_shape); | |||
| m_convex_shape = new btConeShape( radius * LOL2BT_UNIT, | |||
| height * LOL2BT_UNIT); | |||
| SetShapeTo(m_convex_shape); | |||
| } | |||
| void EasyPhysic::SetShapeToCylinder(lol::vec3& cyl_size) | |||
| { | |||
| vec3 new_cyl_size = cyl_size * LOL2BT_UNIT; | |||
| new_cyl_size.y *= LOL2BT_SIZE; | |||
| m_convex_shape = new btCylinderShape(LOL2BT_VEC3(new_cyl_size)); | |||
| SetShapeTo(m_convex_shape); | |||
| vec3 new_cyl_size = cyl_size * LOL2BT_UNIT; | |||
| new_cyl_size.y *= LOL2BT_SIZE; | |||
| m_convex_shape = new btCylinderShape(LOL2BT_VEC3(new_cyl_size)); | |||
| SetShapeTo(m_convex_shape); | |||
| } | |||
| void EasyPhysic::SetShapeToCapsule(float radius, float height) | |||
| { | |||
| m_convex_shape = new btCapsuleShape(radius * LOL2BT_UNIT * LOL2BT_SIZE, | |||
| height * LOL2BT_UNIT * LOL2BT_SIZE); | |||
| SetShapeTo(m_convex_shape); | |||
| m_convex_shape = new btCapsuleShape(radius * LOL2BT_UNIT * LOL2BT_SIZE, | |||
| height * LOL2BT_UNIT * LOL2BT_SIZE); | |||
| SetShapeTo(m_convex_shape); | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -118,57 +118,57 @@ void EasyPhysic::SetShapeToCapsule(float radius, float height) | |||
| //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; | |||
| 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) | |||
| { | |||
| 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(LOL2BT_UNIT * base_location))); | |||
| else | |||
| { | |||
| if (m_motion_state) | |||
| m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location))); | |||
| else | |||
| 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++) | |||
| { | |||
| if (m_based_physic_list[i]) | |||
| m_based_physic_list[i]->BaseTransformChanged(PreviousMatrix, m_local_to_world); | |||
| else | |||
| m_based_physic_list.Remove(i--); | |||
| } | |||
| 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(LOL2BT_UNIT * base_location))); | |||
| else | |||
| { | |||
| if (m_motion_state) | |||
| m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location))); | |||
| else | |||
| 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++) | |||
| { | |||
| 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))); | |||
| } | |||
| 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))); | |||
| } | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -177,13 +177,13 @@ void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol | |||
| //Set Shape functions | |||
| void EasyPhysic::SetMass(float mass) | |||
| { | |||
| m_mass = mass; | |||
| m_mass = mass; | |||
| if (m_rigid_body) | |||
| { | |||
| SetLocalInertia(m_mass); | |||
| m_rigid_body->setMassProps(mass, m_local_inertia); | |||
| } | |||
| if (m_rigid_body) | |||
| { | |||
| SetLocalInertia(m_mass); | |||
| m_rigid_body->setMassProps(mass, m_local_inertia); | |||
| } | |||
| } | |||
| //------------------------------------------------------------------------- | |||
| @@ -193,49 +193,49 @@ void EasyPhysic::SetMass(float mass) | |||
| //Init to rigid body | |||
| void EasyPhysic::InitBodyToRigid(bool SetToKinematic) | |||
| { | |||
| if (m_collision_object) | |||
| delete m_collision_object; | |||
| if (!m_motion_state) | |||
| SetTransform(vec3(.0f)); | |||
| btRigidBody::btRigidBodyConstructionInfo NewInfos(m_mass, m_motion_state, m_collision_shape, m_local_inertia); | |||
| m_rigid_body = new btRigidBody(NewInfos); | |||
| m_collision_object = m_rigid_body; | |||
| m_collision_object->setUserPointer(this); | |||
| if (m_mass == .0f) | |||
| { | |||
| if (SetToKinematic) | |||
| { | |||
| m_rigid_body->setActivationState(DISABLE_DEACTIVATION); | |||
| m_rigid_body->setCollisionFlags(m_rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); | |||
| } | |||
| } | |||
| else | |||
| SetMass(m_mass); | |||
| if (m_collision_object) | |||
| delete m_collision_object; | |||
| if (!m_motion_state) | |||
| SetTransform(vec3(.0f)); | |||
| btRigidBody::btRigidBodyConstructionInfo NewInfos(m_mass, m_motion_state, m_collision_shape, m_local_inertia); | |||
| m_rigid_body = new btRigidBody(NewInfos); | |||
| m_collision_object = m_rigid_body; | |||
| m_collision_object->setUserPointer(this); | |||
| if (m_mass == .0f) | |||
| { | |||
| if (SetToKinematic) | |||
| { | |||
| m_rigid_body->setActivationState(DISABLE_DEACTIVATION); | |||
| m_rigid_body->setCollisionFlags(m_rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); | |||
| } | |||
| } | |||
| else | |||
| SetMass(m_mass); | |||
| } | |||
| //Return correct Ghost Object | |||
| btGhostObject* EasyPhysic::GetGhostObjectInstance() | |||
| { | |||
| return new btGhostObject(); | |||
| return new btGhostObject(); | |||
| } | |||
| //Init to Ghost object, for Overlap/Sweep Test/Touching logic | |||
| void EasyPhysic::InitBodyToGhost() | |||
| { | |||
| if (m_collision_object) | |||
| delete m_collision_object; | |||
| if (m_collision_object) | |||
| delete m_collision_object; | |||
| m_ghost_object = GetGhostObjectInstance(); | |||
| m_ghost_object->setCollisionShape(m_collision_shape); | |||
| m_collision_object = m_ghost_object; | |||
| m_collision_object->setUserPointer(this); | |||
| m_ghost_object = GetGhostObjectInstance(); | |||
| m_ghost_object->setCollisionShape(m_collision_shape); | |||
| m_collision_object = m_ghost_object; | |||
| m_collision_object->setUserPointer(this); | |||
| SetTransform(m_local_to_world.v3.xyz, lol::quat(m_local_to_world)); | |||
| SetTransform(m_local_to_world.v3.xyz, lol::quat(m_local_to_world)); | |||
| m_ghost_object->setCollisionFlags(m_ghost_object->getCollisionFlags()); | |||
| m_ghost_object->setCollisionFlags(m_ghost_object->getCollisionFlags()); | |||
| } | |||
| //------------- | |||
| @@ -250,7 +250,7 @@ void EasyPhysic::InitBodyToGhost() | |||
| // manifoldArray.clear(); | |||
| // const btBroadphasePair& pair = pairArray[i]; | |||
| // | |||
| // | |||
| // //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache: | |||
| // btBroadphasePair* collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1); | |||
| // if (!collisionPair) | |||
| @@ -265,14 +265,14 @@ void EasyPhysic::InitBodyToGhost() | |||
| // btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0); | |||
| // for (int p=0;p<manifold->getNumContacts();p++) | |||
| // { | |||
| // const btManifoldPoint&pt = manifold->getContactPoint(p); | |||
| // const btManifoldPoint&pt = manifold->getContactPoint(p); | |||
| // if (pt.getDistance()<0.f) | |||
| //{ | |||
| // const btVector3& ptA = pt.getPositionWorldOnA(); | |||
| // const btVector3& ptB = pt.getPositionWorldOnB(); | |||
| // const btVector3& normalOnB = pt.m_normalWorldOnB; | |||
| // /// work here | |||
| //} | |||
| //{ | |||
| // const btVector3& ptA = pt.getPositionWorldOnA(); | |||
| // const btVector3& ptB = pt.getPositionWorldOnB(); | |||
| // const btVector3& normalOnB = pt.m_normalWorldOnB; | |||
| // /// work here | |||
| //} | |||
| // } | |||
| // } | |||
| // } | |||
| @@ -281,61 +281,61 @@ void EasyPhysic::InitBodyToGhost() | |||
| //Add Physic object to the simulation | |||
| void EasyPhysic::AddToSimulation(class Simulation* current_simulation) | |||
| { | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_ghost_object) | |||
| { | |||
| dynamics_world->addCollisionObject(m_ghost_object, m_collision_group, m_collision_mask); | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Ghost); | |||
| } | |||
| else if (m_rigid_body) | |||
| { | |||
| dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask); | |||
| if (m_mass != .0f) | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Dynamic); | |||
| else | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Static); | |||
| } | |||
| else | |||
| { | |||
| dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask); | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_CollisionObject); | |||
| } | |||
| } | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_ghost_object) | |||
| { | |||
| dynamics_world->addCollisionObject(m_ghost_object, m_collision_group, m_collision_mask); | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Ghost); | |||
| } | |||
| else if (m_rigid_body) | |||
| { | |||
| dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask); | |||
| if (m_mass != .0f) | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Dynamic); | |||
| else | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Static); | |||
| } | |||
| else | |||
| { | |||
| dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask); | |||
| current_simulation->ObjectRegistration(true, this, Simulation::EEPT_CollisionObject); | |||
| } | |||
| } | |||
| } | |||
| //Remove Physic object to the simulation | |||
| 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); | |||
| if (m_mass != .0f) | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Dynamic); | |||
| else | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Static); | |||
| } | |||
| else | |||
| { | |||
| dynamics_world->removeCollisionObject(m_collision_object); | |||
| if (m_ghost_object) | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Ghost); | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_CollisionObject); | |||
| } | |||
| } | |||
| btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld(); | |||
| if (dynamics_world) | |||
| { | |||
| if (m_rigid_body) | |||
| { | |||
| dynamics_world->removeRigidBody(m_rigid_body); | |||
| if (m_mass != .0f) | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Dynamic); | |||
| else | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Static); | |||
| } | |||
| else | |||
| { | |||
| dynamics_world->removeCollisionObject(m_collision_object); | |||
| if (m_ghost_object) | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Ghost); | |||
| current_simulation->ObjectRegistration(false, this, Simulation::EEPT_CollisionObject); | |||
| } | |||
| } | |||
| } | |||
| //Set Local Inertia | |||
| void EasyPhysic::SetLocalInertia(float mass) | |||
| { | |||
| if (mass != .0f) | |||
| m_collision_shape->calculateLocalInertia(mass, m_local_inertia); | |||
| else | |||
| m_local_inertia = btVector3(.0f, .0f, .0f); | |||
| if (mass != .0f) | |||
| m_collision_shape->calculateLocalInertia(mass, m_local_inertia); | |||
| else | |||
| m_local_inertia = btVector3(.0f, .0f, .0f); | |||
| } | |||
| #endif // HAVE_PHYS_USE_BULLET | |||