Browse Source

fixed 23 files out of 277:

- fixed 1270 CR characters
 - fixed 56 trailing spaces
 - fixed 5085 tabs
legacy
Lolbot lolbot 12 years ago
parent
commit
23807ea88e
20 changed files with 2190 additions and 2190 deletions
  1. +41
    -41
      src/easymesh/easymesh.cpp
  2. +4
    -4
      src/entity.h
  3. +131
    -131
      src/input/input.cpp
  4. +1
    -1
      src/input/input.h
  5. +2
    -2
      src/lol/math/math.h
  6. +2
    -2
      src/numeric.h
  7. +1
    -1
      src/worldentity.cpp
  8. +376
    -376
      test/BtPhysTest.cpp
  9. +12
    -12
      test/BtPhysTest.h
  10. +269
    -269
      test/PhysicObject.h
  11. +245
    -245
      test/Physics/Include/BulletCharacterController.h
  12. +56
    -56
      test/Physics/Include/EasyCharacterController.h
  13. +153
    -153
      test/Physics/Include/EasyConstraint.h
  14. +102
    -102
      test/Physics/Include/EasyPhysics.h
  15. +18
    -18
      test/Physics/Include/LolBtPhysicsIntegration.h
  16. +373
    -373
      test/Physics/Include/LolPhysics.h
  17. +161
    -161
      test/Physics/Src/BulletCharacterController.cpp
  18. +55
    -55
      test/Physics/Src/EasyCharacterController.cpp
  19. +12
    -12
      test/Physics/Src/EasyConstraint.cpp
  20. +176
    -176
      test/Physics/Src/EasyPhysics.cpp

+ 41
- 41
src/easymesh/easymesh.cpp View File

@@ -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 */


+ 4
- 4
src/entity.h View File

@@ -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;


+ 131
- 131
src/input/input.cpp View File

@@ -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;
}

//--


+ 1
- 1
src/input/input.h View File

@@ -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 */


+ 2
- 2
src/lol/math/math.h View File

@@ -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;
}




+ 2
- 2
src/numeric.h View File

@@ -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));
}



+ 1
- 1
src/worldentity.cpp View File

@@ -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);


+ 376
- 376
test/BtPhysTest.cpp View File

@@ -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);

}


+ 12
- 12
test/BtPhysTest.h View File

@@ -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__


+ 269
- 269
test/PhysicObject.h View File

@@ -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__ */


+ 245
- 245
test/Physics/Include/BulletCharacterController.h View File

@@ -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 */



+ 56
- 56
test/Physics/Include/EasyCharacterController.h View File

@@ -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



+ 153
- 153
test/Physics/Include/EasyConstraint.h View File

@@ -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;

};



+ 102
- 102
test/Physics/Include/EasyPhysics.h View File

@@ -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 */


+ 18
- 18
test/Physics/Include/LolBtPhysicsIntegration.h View File

@@ -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



+ 373
- 373
test/Physics/Include/LolPhysics.h View File

@@ -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 */


+ 161
- 161
test/Physics/Src/BulletCharacterController.cpp View File

@@ -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 */

+ 55
- 55
test/Physics/Src/EasyCharacterController.cpp View File

@@ -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


+ 12
- 12
test/Physics/Src/EasyConstraint.cpp View File

@@ -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


+ 176
- 176
test/Physics/Src/EasyPhysics.cpp View File

@@ -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


Loading…
Cancel
Save