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