- 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) | void EasyMesh::RadialJitter(float r) | ||||
| { | { | ||||
| Array<int> Welded; | Array<int> Welded; | ||||
| Welded.Push(-1); | |||||
| Welded.Push(-1); | |||||
| for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++) | 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++) | 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) | 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; | vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n; | ||||
| /* Construct normal */ | /* 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; | n.y = r1 * (r1 - r2) / h; | ||||
| if (!smooth) | if (!smooth) | ||||
| n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n; | 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++) | for (int i = 0; i < ilen / 3; i++) | ||||
| { | { | ||||
| } | } | ||||
| /* Fun shit: reduce all triangles */ | /* Fun shit: reduce all triangles */ | ||||
| @@ -45,11 +45,11 @@ protected: | |||||
| { | { | ||||
| GAMEGROUP_BEFORE = 0, | GAMEGROUP_BEFORE = 0, | ||||
| GAMEGROUP_DEFAULT, | 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 | GAMEGROUP_END | ||||
| } | } | ||||
| m_gamegroup; | m_gamegroup; | ||||
| @@ -31,7 +31,7 @@ namespace lol | |||||
| * Input implementation class | * Input implementation class | ||||
| */ | */ | ||||
| InputTracker* Input::m_input_tracker = NULL; | |||||
| InputTracker* Input::m_input_tracker = NULL; | |||||
| static class InputData | static class InputData | ||||
| { | { | ||||
| @@ -66,10 +66,10 @@ static InputData * const data = &inputdata; | |||||
| int ButtonSetting::GetActionSettingIdx(ACTION_TYPE SearchAction) | 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() | 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 | //Internal | ||||
| int InputTracker::GetButtonSettingIdx(Key Button) | 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) | 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) | 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 | //Internal : Updates the action status & timers | ||||
| @@ -116,146 +116,146 @@ void InputTracker::UpdateActionStatus(float seconds) | |||||
| { | { | ||||
| #if defined USE_SDL | #if defined USE_SDL | ||||
| #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION >= 3 | #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION >= 3 | ||||
| Uint8 *keystate = SDL_GetKeyboardState(NULL); | |||||
| Uint8 *keystate = SDL_GetKeyboardState(NULL); | |||||
| #else | #else | ||||
| Uint8 *keystate = SDL_GetKeyState(NULL); | |||||
| Uint8 *keystate = SDL_GetKeyState(NULL); | |||||
| #endif | #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 | #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. | //Helps link a software input Action-Id to an hardware input Button-Id. | ||||
| void InputTracker::LinkActionToKey(ACTION_TYPE Action, Key Button) | 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. | //Helps unlink a software input Action-Id to an hardware input Button-Id. | ||||
| void InputTracker::UnlinkAction(ACTION_TYPE Action) | 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 | //Returns the current status of a given action | ||||
| int InputTracker::GetStatus(ACTION_TYPE 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 | //Returns TRUE if action status went from Active to Inactive this frame | ||||
| bool InputTracker::WasReleased(ACTION_TYPE Action) | 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 | //Returns TRUE if action status went from Inactive to Active this frame | ||||
| bool InputTracker::WasPressed(ACTION_TYPE Action) | 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 | //Returns the current status of a given action | ||||
| int InputTracker::GetStatus(Key Button) | int InputTracker::GetStatus(Key Button) | ||||
| { | { | ||||
| return GetCurrentButtonStatus(Button); | |||||
| return GetCurrentButtonStatus(Button); | |||||
| } | } | ||||
| //Returns TRUE if action status went from Active to Inactive this frame | //Returns TRUE if action status went from Active to Inactive this frame | ||||
| bool InputTracker::WasReleased(Key Button) | 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 | //Returns TRUE if action status went from Inactive to Active this frame | ||||
| bool InputTracker::WasPressed(Key Button) | 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. | //Helps link a software input Action-Id to an hardware input Button-Id. | ||||
| void Input::LinkActionToKey(ACTION_TYPE Action, struct Key Button) | 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. | //Helps unlink a software input Action-Id to an hardware input Button-Id. | ||||
| void Input::UnlinkAction(ACTION_TYPE Action) | 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 | //Returns the current status of a given action | ||||
| int Input::GetStatus(ACTION_TYPE 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 | //Returns TRUE if action status when from Active to Inactive this frame | ||||
| bool Input::WasPressed(ACTION_TYPE Action) | 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 | //Returns TRUE if action status when from Active to Inactive this frame | ||||
| bool Input::WasReleased(ACTION_TYPE Action) | 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 | //Returns the current status of a given action | ||||
| int Input::GetStatus(Key Button) | 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 | //Returns TRUE if action status when from Active to Inactive this frame | ||||
| bool Input::WasPressed(Key Button) | 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 | //Returns TRUE if action status when from Active to Inactive this frame | ||||
| bool Input::WasReleased(Key Button) | 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 ivec2 GetMousePos(); | ||||
| static ivec3 GetMouseButtons(); | static ivec3 GetMouseButtons(); | ||||
| //BH : Shouldn't use this | |||||
| //BH : Shouldn't use this | |||||
| static int GetButtonState(int button); | static int GetButtonState(int button); | ||||
| /* Action management */ | /* 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) | 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) | 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 | //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) | 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)); | return lol::lerp(a, b, dt / (dt + x)); | ||||
| } | } | ||||
| @@ -28,7 +28,7 @@ WorldEntity::WorldEntity() | |||||
| m_position = vec3(0); | m_position = vec3(0); | ||||
| m_rotation = quat(1); | m_rotation = quat(1); | ||||
| m_velocity = vec3(0); | m_velocity = vec3(0); | ||||
| m_rotation_velocity = vec3(0); | |||||
| m_rotation_velocity = vec3(0); | |||||
| m_bbox[0] = m_bbox[1] = vec3(0); | m_bbox[0] = m_bbox[1] = vec3(0); | ||||
| m_mousepos = ivec2(0); | m_mousepos = ivec2(0); | ||||
| @@ -49,25 +49,25 @@ using namespace lol::phys; | |||||
| int gNumObjects = 64; | 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) | BtPhysTest::BtPhysTest(bool editor) | ||||
| { | { | ||||
| m_loop_value = .0f; | |||||
| m_loop_value = .0f; | |||||
| /* Create a camera that matches the settings of XNA BtPhysTest */ | /* Create a camera that matches the settings of XNA BtPhysTest */ | ||||
| m_camera = new Camera(vec3(0.f, 600.f, 0.f), | m_camera = new Camera(vec3(0.f, 600.f, 0.f), | ||||
| @@ -75,191 +75,191 @@ BtPhysTest::BtPhysTest(bool editor) | |||||
| vec3(0, 1, 0)); | vec3(0, 1, 0)); | ||||
| m_camera->SetRotation(quat::fromeuler_xyz(0.f, 0.f, 0.f)); | 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->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); | Ticker::Ref(m_camera); | ||||
| m_ready = false; | 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); | 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) | void BtPhysTest::TickGame(float seconds) | ||||
| @@ -269,143 +269,143 @@ void BtPhysTest::TickGame(float seconds) | |||||
| if (Input::WasReleased(Key::Escape)) | if (Input::WasReleased(Key::Escape)) | ||||
| Ticker::Shutdown(); | 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() | 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); | Ticker::Unref(m_simulation); | ||||
| } | } | ||||
| @@ -21,18 +21,18 @@ protected: | |||||
| virtual void TickDraw(float seconds); | virtual void TickDraw(float seconds); | ||||
| private: | 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__ | #endif // __BTPHYSTEST_H__ | ||||
| @@ -23,279 +23,279 @@ using namespace lol::phys; | |||||
| class PhysicsObject : public WorldEntity | class PhysicsObject : public WorldEntity | ||||
| { | { | ||||
| public: | 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: | 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: | 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__ */ | #endif /* __PHYSICOBJECT_H__ */ | ||||
| @@ -29,259 +29,259 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| namespace phys | |||||
| { | |||||
| namespace phys | |||||
| { | |||||
| #ifdef USE_LOL_CTRLR_CHARAC | #ifdef USE_LOL_CTRLR_CHARAC | ||||
| #ifdef HAVE_PHYS_USE_BULLET | #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 // HAVE_PHYS_USE_BULLET | ||||
| #endif // USE_LOL_CTRLR_CHARAC | #endif // USE_LOL_CTRLR_CHARAC | ||||
| } /* namespace phys */ | |||||
| } /* namespace phys */ | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -34,81 +34,81 @@ namespace phys | |||||
| { | { | ||||
| class EasyCharacterController : public EasyPhysic, | 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 | #ifdef HAVE_PHYS_USE_BULLET | ||||
| public: | 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: | 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: | public: | ||||
| virtual void TickGame(float seconds); | |||||
| virtual void TickGame(float seconds); | |||||
| protected: | 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 | #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 | #endif // PHYSIC IMPLEMENTATION | ||||
| @@ -31,180 +31,180 @@ namespace phys | |||||
| class EasyConstraint | class EasyConstraint | ||||
| { | { | ||||
| friend class Simulation; | |||||
| friend class EasyPhysic; | |||||
| friend class Simulation; | |||||
| friend class EasyPhysic; | |||||
| #ifdef HAVE_PHYS_USE_BULLET | #ifdef HAVE_PHYS_USE_BULLET | ||||
| public: | 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: | 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 | #else // NO PHYSIC IMPLEMENTATION | ||||
| public: | 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: | 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 | #endif // PHYSIC IMPLEMENTATION | ||||
| public: | 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: | 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 | class EasyPhysic | ||||
| { | { | ||||
| friend class Simulation; | |||||
| friend class EasyConstraint; | |||||
| friend class Simulation; | |||||
| friend class EasyConstraint; | |||||
| #ifdef HAVE_PHYS_USE_BULLET | #ifdef HAVE_PHYS_USE_BULLET | ||||
| public: | 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: | protected: | ||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | |||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix); | |||||
| public: | public: | ||||
| virtual void SetMass(float mass); | |||||
| virtual void 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: | 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 | #else // NO PHYSIC IMPLEMENTATION | ||||
| public: | 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: | private: | ||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | |||||
| virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) { } | |||||
| public: | public: | ||||
| virtual void SetMass(float mass) { } | |||||
| virtual void 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 | #endif // PHYSIC IMPLEMENTATION | ||||
| public: | 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: | 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 */ | } /* namespace phys */ | ||||
| @@ -19,32 +19,32 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| //Override Gamegroups names for Physic-useage | |||||
| //"_ENT_" means that this is a group for Entities that use EasyPhysic primitives. | |||||
| //"_EZP_" means that this is a group for EasyPhysic primitives. | |||||
| #define GAMEGROUP_ENT_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 | #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 | //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 | #endif // HAVE_PHYS_USE_BULLET | ||||
| @@ -26,406 +26,406 @@ namespace phys | |||||
| enum eRaycastType | 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 | 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 | class Simulation : public Entity | ||||
| { | { | ||||
| public: | 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 | #ifdef HAVE_PHYS_USE_BULLET | ||||
| public: | 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: | 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 | #else // NO PHYSIC IMPLEMENTATION | ||||
| public: | 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: | 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 | #endif // PHYSIC IMPLEMENTATION | ||||
| public: | 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: | 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 */ | } /* namespace phys */ | ||||
| @@ -45,202 +45,202 @@ namespace phys | |||||
| //When called, will try to remove Character controller from its collision. | //When called, will try to remove Character controller from its collision. | ||||
| bool BulletKinematicCharacterController::RecoverFromPenetration(btCollisionWorld* CollisionWorld) | 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. | //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) | 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. | //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) | 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. | //The PreStepis done in order to recover from any HasPenetration. | ||||
| void BulletKinematicCharacterController::PreStep(btCollisionWorld* CollisionWorld) | 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 : | //And so we step : | ||||
| //StepUpfirst, then movement, then StepDownon the ground. | //StepUpfirst, then movement, then StepDownon the ground. | ||||
| void BulletKinematicCharacterController::PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime) | 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 | //should MoveStep Jump logic in EasyCC | ||||
| void BulletKinematicCharacterController::Jump() | 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 // HAVE_PHYS_USE_BULLET | ||||
| #endif // USE_LOL_CTRLR_CHARAC | #endif // USE_LOL_CTRLR_CHARAC | ||||
| } /* namespace phys */ | |||||
| } /* namespace phys */ | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -38,68 +38,68 @@ void EasyCharacterController::InitBodyToRigid(bool ZeroMassIsKinematic) | |||||
| //Return correct Ghost Object | //Return correct Ghost Object | ||||
| btGhostObject* EasyCharacterController::GetGhostObjectInstance() | btGhostObject* EasyCharacterController::GetGhostObjectInstance() | ||||
| { | { | ||||
| return new btPairCachingGhostObject(); | |||||
| return new btPairCachingGhostObject(); | |||||
| } | } | ||||
| //Init to Pair caching ghost object, since Character uses that one. | //Init to Pair caching ghost object, since Character uses that one. | ||||
| void EasyCharacterController::InitBodyToGhost() | 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 | //Add Physic object to the simulation | ||||
| void EasyCharacterController::AddToSimulation(class Simulation* current_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 | //Remove Physic object to the simulation | ||||
| void EasyCharacterController::RemoveFromSimulation(class Simulation* current_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() | void EasyCharacterController::Jump() | ||||
| { | { | ||||
| m_character->Jump(); | |||||
| m_character->Jump(); | |||||
| } | } | ||||
| //Set movement for this frame | //Set movement for this frame | ||||
| void EasyCharacterController::SetMovementForFrame(vec3 const &MoveQuantity) | 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) | 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. | //Internal callback when Base transform has changed. | ||||
| void EasyCharacterController::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) | 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() | char const *EasyCharacterController::GetName() | ||||
| { | { | ||||
| return "<EasyCharacterController>"; | |||||
| return "<EasyCharacterController>"; | |||||
| } | } | ||||
| //Physic Tick | //Physic Tick | ||||
| void EasyCharacterController::TickGame(float seconds) | 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 | #endif // HAVE_PHYS_USE_BULLET | ||||
| @@ -21,22 +21,22 @@ namespace phys | |||||
| void EasyConstraint::AddToSimulation(class Simulation* current_simulation) | 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) | 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 | #endif // HAVE_PHYS_USE_BULLET | ||||
| @@ -29,29 +29,29 @@ namespace phys | |||||
| //EASY_PHYSIC | //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() | 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) | 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 | //Box Shape support | ||||
| void EasyPhysic::SetShapeToBox(lol::vec3& box_size) | 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) | 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) | 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) | 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) | 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 | //Getter | ||||
| mat4 EasyPhysic::GetTransform() | 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 | //Setter | ||||
| void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation) | ||||
| { | { | ||||
| lol::mat4 PreviousMatrix = m_local_to_world; | |||||
| 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. | //Internal callback when Base transform has changed. | ||||
| void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix) | 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 | //Set Shape functions | ||||
| void EasyPhysic::SetMass(float mass) | 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 | //Init to rigid body | ||||
| void EasyPhysic::InitBodyToRigid(bool SetToKinematic) | 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 | //Return correct Ghost Object | ||||
| btGhostObject* EasyPhysic::GetGhostObjectInstance() | btGhostObject* EasyPhysic::GetGhostObjectInstance() | ||||
| { | { | ||||
| return new btGhostObject(); | |||||
| return new btGhostObject(); | |||||
| } | } | ||||
| //Init to Ghost object, for Overlap/Sweep Test/Touching logic | //Init to Ghost object, for Overlap/Sweep Test/Touching logic | ||||
| void EasyPhysic::InitBodyToGhost() | 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(); | // manifoldArray.clear(); | ||||
| // const btBroadphasePair& pair = pairArray[i]; | // const btBroadphasePair& pair = pairArray[i]; | ||||
| // | |||||
| // | |||||
| // //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache: | // //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); | // btBroadphasePair* collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1); | ||||
| // if (!collisionPair) | // if (!collisionPair) | ||||
| @@ -265,14 +265,14 @@ void EasyPhysic::InitBodyToGhost() | |||||
| // btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0); | // btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0); | ||||
| // for (int p=0;p<manifold->getNumContacts();p++) | // 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) | // 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 | //Add Physic object to the simulation | ||||
| void EasyPhysic::AddToSimulation(class Simulation* current_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 | //Remove Physic object to the simulation | ||||
| void EasyPhysic::RemoveFromSimulation(class Simulation* current_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 | //Set Local Inertia | ||||
| void EasyPhysic::SetLocalInertia(float mass) | 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 | #endif // HAVE_PHYS_USE_BULLET | ||||