You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

449 lines
12 KiB

  1. //
  2. // BtPhysTest
  3. //
  4. // Copyright: (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
  5. // (c) 2012 Sam Hocevar <sam@hocevar.net>
  6. //
  7. #if defined HAVE_CONFIG_H
  8. # include "config.h"
  9. #endif
  10. #if defined _WIN32
  11. # include <direct.h>
  12. #endif
  13. #if defined _XBOX
  14. # define _USE_MATH_DEFINES /* for M_PI */
  15. # include <xtl.h>
  16. # undef near /* Fuck Microsoft */
  17. # undef far /* Fuck Microsoft again */
  18. #elif defined _WIN32
  19. # define _USE_MATH_DEFINES /* for M_PI */
  20. # define WIN32_LEAN_AND_MEAN
  21. # include <windows.h>
  22. # undef near /* Fuck Microsoft */
  23. # undef far /* Fuck Microsoft again */
  24. #else
  25. # include <cmath>
  26. #endif
  27. #include "core.h"
  28. #include "loldebug.h"
  29. using namespace lol;
  30. #ifndef HAVE_PHYS_USE_BULLET
  31. #define HAVE_PHYS_USE_BULLET
  32. #endif /* HAVE_PHYS_USE_BULLET */
  33. #include "Physics/Include/LolPhysics.h"
  34. #include "Physics/Include/EasyPhysics.h"
  35. #include "PhysicObject.h"
  36. #include "BtPhysTest.h"
  37. using namespace lol::phys;
  38. #define CUBE_HALF_EXTENTS .5f
  39. #define EXTRA_HEIGHT 1.f
  40. int gNumObjects = 64;
  41. #define USE_WALL 1
  42. #define USE_PLATFORM 1
  43. #define USE_ROPE 0
  44. #define USE_BODIES 0
  45. #define USE_ROTATION 0
  46. #define USE_CHARACTER 1
  47. #define IPT_MOVE_FORWARD "Move_Forward"
  48. #define IPT_MOVE_BACKWARD "Move_Backward"
  49. #define IPT_MOVE_STRAFE_LEFT "Strafe_Left"
  50. #define IPT_MOVE_STRAFE_RIGHT "Strafe_right"
  51. #define IPT_MOVE_JUMP "Move_Jump"
  52. BtPhysTest::BtPhysTest(bool editor)
  53. {
  54. m_loop_value = .0f;
  55. /* Create a camera that matches the settings of XNA BtPhysTest */
  56. m_camera = new Camera(vec3(0.f, 600.f, 0.f),
  57. vec3(0.f, 0.f, 0.f),
  58. vec3(0, 1, 0));
  59. m_camera->SetRotation(quat::fromeuler_xyz(0.f, 0.f, 0.f));
  60. m_camera->SetPerspective(45.f, 1280.f, 960.f, .1f, 1000.f);
  61. //m_camera->SetOrtho(1280.f / 6, 960.f / 6, -1000.f, 1000.f);
  62. Ticker::Ref(m_camera);
  63. m_ready = false;
  64. m_simulation = new Simulation();
  65. m_simulation->SetWorldLimit(vec3(-1000.0f, -1000.0f, -1000.0f), vec3(1000.0f, 1000.0f, 1000.0f));
  66. m_simulation->Init();
  67. vec3 NewGravity = vec3(.0f, -10.0f, .0f);
  68. m_simulation->SetGravity(NewGravity);
  69. m_simulation->SetContinuousDetection(true);
  70. m_simulation->SetTimestep(1.f / 120.f);
  71. Ticker::Ref(m_simulation);
  72. float offset = 29.5f;
  73. vec3 pos_offset = vec3(.0f, 30.f, .0f);
  74. if (USE_WALL)
  75. {
  76. for (int i=0; i < 6; i++)
  77. {
  78. vec3 NewPosition = vec3(.0f);
  79. quat NewRotation = quat(1.f);
  80. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation);
  81. int idx = i/2;
  82. NewPosition = pos_offset;
  83. NewPosition[idx] += offset;
  84. offset *= -1.f;
  85. if (idx != 1)
  86. {
  87. vec3 axis = vec3(.0f);
  88. axis[2 - idx] = 1;
  89. NewRotation = quat::rotate(90.f, axis);
  90. }
  91. NewPhyobj->SetTransform(NewPosition, NewRotation);
  92. Ticker::Ref(NewPhyobj);
  93. m_ground_list << NewPhyobj;
  94. }
  95. }
  96. PhysicsObject* BasePhyobj = NULL;
  97. if (USE_PLATFORM)
  98. {
  99. quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
  100. vec3 NewPosition = pos_offset + vec3(5.0f, -25.0f, -15.0f);
  101. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  102. m_platform_list << NewPhyobj;
  103. Ticker::Ref(NewPhyobj);
  104. NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f);
  105. NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  106. BasePhyobj = NewPhyobj;
  107. m_platform_list << NewPhyobj;
  108. Ticker::Ref(NewPhyobj);
  109. NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f);
  110. NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f);
  111. NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  112. NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, true);
  113. m_platform_list << NewPhyobj;
  114. Ticker::Ref(NewPhyobj);
  115. //NewPosition += vec3(-0.0f, .0f, .0f);
  116. //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  117. //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, false);
  118. //m_platform_list << NewPhyobj;
  119. //Ticker::Ref(NewPhyobj);
  120. //NewPosition += vec3(-2.0f, .0f, .0f);
  121. //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  122. //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false);
  123. //m_platform_list << NewPhyobj;
  124. //Ticker::Ref(NewPhyobj);
  125. }
  126. if (USE_CHARACTER)
  127. {
  128. quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
  129. vec3 NewPosition = pos_offset + vec3(-15.0f, -10.0f, .0f);
  130. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2);
  131. m_character_list << NewPhyobj;
  132. Ticker::Ref(NewPhyobj);
  133. Input::LinkActionToKey(IPT_MOVE_FORWARD, Key::K_UP);
  134. Input::LinkActionToKey(IPT_MOVE_BACKWARD, Key::K_DOWN);
  135. Input::LinkActionToKey(IPT_MOVE_STRAFE_LEFT, Key::K_LEFT);
  136. Input::LinkActionToKey(IPT_MOVE_STRAFE_RIGHT, Key::K_RIGHT);
  137. Input::LinkActionToKey(IPT_MOVE_JUMP, Key::K_SPACE);
  138. //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true);
  139. }
  140. if (USE_BODIES)
  141. {
  142. for (int x=0; x < 6; x++)
  143. {
  144. for (int y=0; y < 6; y++)
  145. {
  146. for (int z=0; z < 5; z++)
  147. {
  148. PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
  149. vec3(-20.f, 15.f, -20.f) +
  150. vec3(8.f * (float)x, 8.f * (float)y, 8.f * (float)z));
  151. m_physobj_list << new_physobj;
  152. Ticker::Ref(new_physobj);
  153. }
  154. }
  155. }
  156. }
  157. if (USE_ROPE)
  158. {
  159. Array<PhysicsObject*> RopeElements;
  160. for (int i = 0; i < 14; i++)
  161. {
  162. PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
  163. vec3(0.f, 15.f, -20.f) +
  164. vec3(0.f, 0.f, 2.f * (float)i), 1);
  165. RopeElements << new_physobj;
  166. m_physobj_list << new_physobj;
  167. Ticker::Ref(new_physobj);
  168. if (RopeElements.Count() > 1)
  169. {
  170. EasyConstraint* new_constraint = new EasyConstraint();
  171. vec3 A2B = .5f * (RopeElements[i]->GetPhysic()->GetTransform().v3.xyz -
  172. RopeElements[i - 1]->GetPhysic()->GetTransform().v3.xyz);
  173. new_constraint->SetPhysObjA(RopeElements[i - 1]->GetPhysic(), lol::mat4::translate(A2B));
  174. new_constraint->SetPhysObjB(RopeElements[i]->GetPhysic(), lol::mat4::translate(-A2B));
  175. new_constraint->InitConstraintToPoint2Point();
  176. new_constraint->DisableCollisionBetweenObjs(true);
  177. new_constraint->AddToSimulation(m_simulation);
  178. m_constraint_list << new_constraint;
  179. }
  180. }
  181. }
  182. }
  183. void BtPhysTest::TickGame(float seconds)
  184. {
  185. WorldEntity::TickGame(seconds);
  186. if (Input::GetButtonState(27 /*SDLK_ESCAPE*/))
  187. Ticker::Shutdown();
  188. m_loop_value += seconds;
  189. if (m_loop_value > M_PI * 2.0f)
  190. m_loop_value -= M_PI * 2.0f;
  191. vec3 GroundBarycenter = vec3(.0f);
  192. vec3 PhysObjBarycenter = vec3(.0f);
  193. float factor = .0f;
  194. if (USE_WALL)
  195. {
  196. for (int i = 0; i < m_ground_list.Count(); i++)
  197. {
  198. PhysicsObject* PhysObj = m_ground_list[i];
  199. mat4 GroundMat = PhysObj->GetTransform();
  200. GroundBarycenter += GroundMat.v3.xyz;
  201. factor += 1.f;
  202. }
  203. GroundBarycenter /= factor;
  204. for (int i = 0; i < m_ground_list.Count(); i++)
  205. {
  206. PhysicsObject* PhysObj = m_ground_list[i];
  207. mat4 GroundMat = PhysObj->GetTransform();
  208. vec3 CenterToGround = GroundMat.v3.xyz - GroundBarycenter;
  209. vec3 CenterToCam = m_camera->m_position - GroundBarycenter;
  210. if (dot(normalize(CenterToCam - CenterToGround),
  211. normalize(CenterToGround)) > 0.f)
  212. PhysObj->SetRender(false);
  213. else
  214. PhysObj->SetRender(true);
  215. }
  216. }
  217. if (USE_ROTATION)
  218. {
  219. for (int i = 0; i < m_ground_list.Count(); i++)
  220. {
  221. PhysicsObject* PhysObj = m_ground_list[i];
  222. mat4 GroundMat = PhysObj->GetTransform();
  223. mat4 CenterMx = mat4::translate(GroundBarycenter);
  224. GroundMat = inverse(CenterMx) * GroundMat;
  225. GroundMat = CenterMx *
  226. mat4(quat::fromeuler_xyz(vec3(.0f, 20.f, 20.0f) * seconds))
  227. * GroundMat;
  228. PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
  229. }
  230. }
  231. if (USE_PLATFORM)
  232. {
  233. for (int i = 0; i < m_platform_list.Count(); i++)
  234. {
  235. PhysicsObject* PhysObj = m_platform_list[i];
  236. mat4 GroundMat = PhysObj->GetTransform();
  237. if (i == 0)
  238. {
  239. GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds));
  240. PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
  241. }
  242. else if (i == 1)
  243. {
  244. GroundMat =
  245. mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) *
  246. mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * 20.f, .0f)));
  247. PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
  248. }
  249. }
  250. }
  251. if (USE_CHARACTER)
  252. {
  253. for (int i = 0; i < m_character_list.Count(); i++)
  254. {
  255. PhysicsObject* PhysObj = m_character_list[i];
  256. EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter();
  257. mat4 CtlrMx = Character->GetTransform();
  258. int HMovement = Input::GetStatus(IPT_MOVE_STRAFE_RIGHT) - Input::GetStatus(IPT_MOVE_STRAFE_LEFT);
  259. int VMovement = Input::GetStatus(IPT_MOVE_FORWARD) - Input::GetStatus(IPT_MOVE_BACKWARD);
  260. int RMovement = 0;//Input::GetButtonState(280 /*SDLK_PAGEUP*/) - Input::GetButtonState(281 /*SDLK_PAGEDOWN*/);
  261. vec3 CharMove = vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f);
  262. if (Input::WasReleased(IPT_MOVE_JUMP))
  263. Character->Jump();
  264. Character->SetMovementForFrame(CharMove);
  265. RayCastResult HitResult;
  266. if (m_simulation->RayHits(HitResult, ERT_Closest, Character->GetTransform().v3.xyz, (Character->GetTransform().v3.xyz + vec3(.0f, -1.f, .0f)), Character))
  267. Character->AttachTo(HitResult.m_collider_list[0], true, true);
  268. else
  269. Character->AttachTo(NULL);
  270. }
  271. }
  272. if (USE_CHARACTER)
  273. {
  274. PhysObjBarycenter = vec3(.0f);
  275. factor = .0f;
  276. for (int i = 0; i < m_character_list.Count(); i++)
  277. {
  278. PhysicsObject* PhysObj = m_character_list[i];
  279. mat4 GroundMat = PhysObj->GetTransform();
  280. PhysObjBarycenter += GroundMat.v3.xyz;
  281. factor += 1.f;
  282. }
  283. PhysObjBarycenter /= factor;
  284. m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget()));
  285. vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f);
  286. m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f);
  287. }
  288. else
  289. {
  290. PhysObjBarycenter = vec3(.0f);
  291. for (int i = 0; i < m_physobj_list.Count(); i++)
  292. {
  293. PhysicsObject* PhysObj = m_physobj_list[i];
  294. mat4 GroundMat = PhysObj->GetTransform();
  295. PhysObjBarycenter += GroundMat.v3.xyz;
  296. factor += 1.f;
  297. }
  298. PhysObjBarycenter /= factor;
  299. m_camera->SetTarget(PhysObjBarycenter);
  300. m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f);
  301. }
  302. }
  303. void BtPhysTest::TickDraw(float seconds)
  304. {
  305. WorldEntity::TickDraw(seconds);
  306. if (!m_ready)
  307. {
  308. /* FIXME: this object never cleans up */
  309. m_ready = true;
  310. }
  311. //Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f));
  312. }
  313. BtPhysTest::~BtPhysTest()
  314. {
  315. Ticker::Unref(m_camera);
  316. while (m_constraint_list.Count())
  317. {
  318. EasyConstraint* CurPop = m_constraint_list.Last();
  319. m_constraint_list.Pop();
  320. CurPop->RemoveFromSimulation(m_simulation);
  321. delete CurPop;
  322. }
  323. while (m_ground_list.Count())
  324. {
  325. PhysicsObject* CurPop = m_ground_list.Last();
  326. m_ground_list.Pop();
  327. CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  328. Ticker::Unref(CurPop);
  329. }
  330. while (m_character_list.Count())
  331. {
  332. PhysicsObject* CurPop = m_character_list.Last();
  333. m_character_list.Pop();
  334. CurPop->GetCharacter()->RemoveFromSimulation(m_simulation);
  335. Ticker::Unref(CurPop);
  336. }
  337. while (m_platform_list.Count())
  338. {
  339. PhysicsObject* CurPop = m_platform_list.Last();
  340. m_platform_list.Pop();
  341. CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  342. Ticker::Unref(CurPop);
  343. }
  344. while (m_physobj_list.Count())
  345. {
  346. PhysicsObject* CurPop = m_physobj_list.Last();
  347. m_physobj_list.Pop();
  348. CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  349. Ticker::Unref(CurPop);
  350. }
  351. Ticker::Unref(m_simulation);
  352. }
  353. int main(int argc, char **argv)
  354. {
  355. Application app("BtPhysTest", ivec2(1280, 720), 60.0f);
  356. #if defined _MSC_VER && !defined _XBOX
  357. _chdir("..");
  358. #elif defined _WIN32 && !defined _XBOX
  359. _chdir("../..");
  360. #endif
  361. new BtPhysTest(argc > 1);
  362. app.ShowPointer(false);
  363. app.Run();
  364. return EXIT_SUCCESS;
  365. }