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.
 
 
 

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