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.
 
 
 

771 line
25 KiB

  1. //
  2. // Lol Engine — BtPhys tutorial
  3. //
  4. // Copyright © 2012—2020 Sam Hocevar <sam@hocevar.net>
  5. // © 2009—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  6. //
  7. // Lol Engine is free software. It comes without any warranty, to
  8. // the extent permitted by applicable law. You can redistribute it
  9. // and/or modify it under the terms of the Do What the Fuck You Want
  10. // to Public License, Version 2, as published by the WTFPL Task Force.
  11. // See http://www.wtfpl.net/ for more details.
  12. //
  13. #if HAVE_CONFIG_H
  14. # include "config.h"
  15. #endif
  16. #include <lol/engine.h>
  17. #include <lol/color>
  18. #include "loldebug.h"
  19. using namespace lol;
  20. #include "physics/lolphysics.h"
  21. #include "physics/easyphysics.h"
  22. #define CAT_MODE 0
  23. #define OBJ_SIZE 2.f
  24. #define NB_SPRITE 4
  25. #define PARTICLE_SIZE 4
  26. #include "physicobject.h"
  27. #include "btphystest.h"
  28. using namespace lol::phys;
  29. #define CUBE_HALF_EXTENTS .5f
  30. #define EXTRA_HEIGHT 1.f
  31. #define BASE_TIME 2.f
  32. #define ZERO_TIME (BASE_TIME + rand(-BASE_TIME * .4f, BASE_TIME * .4f))
  33. #define ZERO_SPEED 3.5f
  34. #define JUMP_HEIGHT 30.f
  35. #define JUMP_STRAFE .5f
  36. #define TARGET_TIMER 10.f + (rand(4.f) - 2.f)
  37. int gNumObjects = 16;
  38. #if CAT_MODE
  39. #define USE_WALL 1
  40. #define USE_BODIES 1
  41. #else
  42. #define USE_WALL 1
  43. #define USE_PLATFORM 0
  44. #define USE_ROPE 0
  45. #define USE_BODIES 1
  46. #define USE_ROTATION 1
  47. #define USE_CHARACTER 0
  48. #define USE_STAIRS 0
  49. #endif
  50. LOLFX_RESOURCE_DECLARE(front_camera_sprite);
  51. //Damp for float
  52. template <typename T1, typename T2, typename Tf>
  53. static inline T1 damp(const T1 &a, const T2 &b, const Tf &x, const Tf &dt)
  54. {
  55. if (dt <= .0f)
  56. return a;
  57. return lol::lerp(a, b, dt / (dt + x));
  58. }
  59. BtPhysTest::BtPhysTest(bool editor)
  60. {
  61. m_init_status = 0;
  62. }
  63. void BtPhysTest::InitApp()
  64. {
  65. m_init_status = 1;
  66. m_loop_value = .0f;
  67. #if CAT_MODE
  68. /* cat datas setup */
  69. m_cat_texture = Tiler::Register("data/CatsSheet.png", ivec2::zero, ivec2(0,1));
  70. m_fov_dp = .0f;
  71. m_loc_dp = .0f;
  72. #endif //CAT_MODE
  73. /* Create a camera that matches the settings of XNA BtPhysTest */
  74. m_camera = new Camera();
  75. #if CAT_MODE
  76. m_camera->SetView(vec3(70.f, 50.f, 0.f),
  77. vec3(0.f, 0.f, 0.f),
  78. vec3(0, 1, 0));
  79. m_camera->SetProjection(radians(60.f), .1f, 1000.f, (float)Video::GetSize().x, (float)Video::GetSize().y / (float)Video::GetSize().x);
  80. m_target_timer = TARGET_TIMER;
  81. m_cam_target = -1;
  82. #else
  83. m_camera->SetView(vec3(50.f, 50.f, 0.f),
  84. vec3(0.f, 0.f, 0.f),
  85. vec3(0, 1, 0));
  86. m_camera->SetProjection(radians(45.f), .1f, 1000.f, (float)Video::GetSize().x, (float)Video::GetSize().y / (float)Video::GetSize().x);
  87. #endif
  88. Scene& scene = Scene::GetScene();
  89. scene.PushCamera(m_camera);
  90. m_ready = false;
  91. m_simulation = new Simulation();
  92. m_simulation->SetWorldLimit(vec3(-1000.0f, -1000.0f, -1000.0f), vec3(1000.0f, 1000.0f, 1000.0f));
  93. m_simulation->Init();
  94. vec3 NewGravity = vec3(.0f, -10.0f, .0f);
  95. m_simulation->SetGravity(NewGravity);
  96. m_simulation->SetContinuousDetection(true);
  97. m_simulation->SetTimestep(1.f / 120.f);
  98. Ticker::Ref(m_simulation);
  99. /* Add a white directional light */
  100. m_light1 = new Light();
  101. m_light1->SetPosition(vec3(0.2f, 0.2f, 0.f));
  102. m_light1->SetColor(vec4(0.5f, 0.5f, 0.5f, 1.f));
  103. m_light1->SetType(LightType::Directional);
  104. Ticker::Ref(m_light1);
  105. /* Add an orangeish point light */
  106. m_light2 = new Light();
  107. m_light2->SetPosition(vec3(-15.f, 15.f, 15.f));
  108. m_light2->SetColor(vec4(0.4f, 0.3f, 0.2f, 1.f));
  109. m_light2->SetType(LightType::Point);
  110. Ticker::Ref(m_light2);
  111. float offset = 29.5f;
  112. vec3 pos_offset = vec3(.0f, 30.f, .0f);
  113. #if USE_STAIRS
  114. {
  115. vec3 new_offset = vec3(1.0f, .125f, .0f);
  116. quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
  117. vec3 NewPosition = pos_offset + vec3(5.0f, -29.f, 15.0f);
  118. {
  119. NewRotation = quat::fromeuler_xyz(0.f, 0.f, radians(30.f));
  120. NewPosition += vec3(4.0f, .0f, -4.0f);
  121. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
  122. Ticker::Ref(NewPhyobj);
  123. m_stairs_list.push_back(NewPhyobj);
  124. }
  125. {
  126. NewRotation = quat::fromeuler_xyz(0.f, 0.f, radians(40.f));
  127. NewPosition += vec3(4.0f, .0f, -4.0f);
  128. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
  129. Ticker::Ref(NewPhyobj);
  130. m_stairs_list.push_back(NewPhyobj);
  131. }
  132. NewPosition = pos_offset + vec3(5.0f, -29.5f, 15.0f);
  133. NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
  134. for (int i=0; i < 15; i++)
  135. {
  136. NewPosition += new_offset;
  137. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
  138. Ticker::Ref(NewPhyobj);
  139. m_stairs_list.push_back(NewPhyobj);
  140. }
  141. }
  142. #endif //USE_STAIRS
  143. #if USE_WALL
  144. {
  145. for (int i=0; i < 6; i++)
  146. {
  147. vec3 NewPosition = vec3(.0f);
  148. quat NewRotation = quat(1.f);
  149. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation);
  150. int idx = i/2;
  151. NewPosition = pos_offset;
  152. NewPosition[idx] += offset;
  153. offset *= -1.f;
  154. if (idx != 1)
  155. {
  156. vec3 NewAxis = vec3(.0f);
  157. NewAxis[2 - idx] = 1;
  158. NewRotation = quat::rotate(radians(90.f), NewAxis);
  159. }
  160. NewPhyobj->SetTransform(NewPosition, NewRotation);
  161. Ticker::Ref(NewPhyobj);
  162. m_ground_list.push_back(NewPhyobj);
  163. }
  164. }
  165. #endif //USE_WALL
  166. PhysicsObject* BasePhyobj = nullptr;
  167. #if USE_PLATFORM
  168. {
  169. quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
  170. vec3 NewPosition = pos_offset + vec3(5.0f, -25.0f, -15.0f);
  171. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  172. m_platform_list.push_back(NewPhyobj);
  173. Ticker::Ref(NewPhyobj);
  174. NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f);
  175. NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  176. BasePhyobj = NewPhyobj;
  177. m_platform_list.push_back(NewPhyobj);
  178. Ticker::Ref(NewPhyobj);
  179. NewRotation = quat::fromeuler_xyz(0.f, 0.f, radians(90.f));
  180. NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f);
  181. NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  182. NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, true);
  183. m_platform_list.push_back(NewPhyobj);
  184. Ticker::Ref(NewPhyobj);
  185. //NewPosition += vec3(-0.0f, .0f, .0f);
  186. //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  187. //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, false);
  188. //m_platform_list.push_back(NewPhyobj);
  189. //Ticker::Ref(NewPhyobj);
  190. //NewPosition += vec3(-2.0f, .0f, .0f);
  191. //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
  192. //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false);
  193. //m_platform_list.push_back(NewPhyobj);
  194. //Ticker::Ref(NewPhyobj);
  195. }
  196. #endif //USE_PLATFORM
  197. #if USE_CHARACTER
  198. {
  199. quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
  200. vec3 NewPosition = pos_offset + vec3(-5.0f, -10.0f, 15.0f);
  201. PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2);
  202. m_character_list.push_back(NewPhyobj);
  203. Ticker::Ref(NewPhyobj);
  204. //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true);
  205. }
  206. #endif //USE_CHARACTER
  207. #if USE_BODIES
  208. {
  209. for (int x=0; x < 6; x++)
  210. {
  211. for (int y=0; y < 2; y++)
  212. {
  213. for (int z=0; z < 5; z++)
  214. {
  215. PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
  216. vec3(-20.f, 15.f, -20.f) +
  217. #if CAT_MODE
  218. vec3(rand(4.f), rand(2.f), rand(4.f)) -
  219. vec3(2.f , 1.f , 2.f) +
  220. #endif //CAT_MODE
  221. vec3(8.f * (float)x, 8.f * (float)y, 8.f * (float)z));
  222. m_physobj_list.push_back(animated_object { new_physobj, ZERO_TIME });
  223. Ticker::Ref(new_physobj);
  224. }
  225. }
  226. }
  227. }
  228. #endif //USE_BODIES
  229. #if USE_ROPE
  230. {
  231. std::vector<PhysicsObject*> RopeElements;
  232. for (int i = 0; i < 14; i++)
  233. {
  234. PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
  235. vec3(0.f, 15.f, -20.f) +
  236. vec3(0.f, 0.f, 2.f * (float)i), 1);
  237. RopeElements.push_back(new_physobj);
  238. m_physobj_list.push_back(animated_object { new_physobj, ZERO_TIME });
  239. Ticker::Ref(new_physobj);
  240. if (RopeElements.size() > 1)
  241. {
  242. EasyConstraint* new_constraint = new EasyConstraint();
  243. vec3 A2B = .5f * (RopeElements[i]->GetPhysic()->GetTransform()[3].xyz -
  244. RopeElements[i - 1]->GetPhysic()->GetTransform()[3].xyz);
  245. new_constraint->SetPhysObjA(RopeElements[i - 1]->GetPhysic(), lol::mat4::translate(A2B));
  246. new_constraint->SetPhysObjB(RopeElements[i]->GetPhysic(), lol::mat4::translate(-A2B));
  247. new_constraint->InitConstraintToPoint2Point();
  248. new_constraint->DisableCollisionBetweenObjs(true);
  249. new_constraint->AddToSimulation(m_simulation);
  250. m_constraint_list.push_back(new_constraint);
  251. }
  252. }
  253. }
  254. #endif //USE_ROPE
  255. }
  256. BtPhysTest::~BtPhysTest()
  257. {
  258. Scene& scene = Scene::GetScene();
  259. scene.PopCamera(m_camera);
  260. Ticker::Unref(m_light1);
  261. Ticker::Unref(m_light2);
  262. #if CAT_MODE
  263. /* cat datas setup */
  264. Shader::Destroy(m_cat_shader);
  265. Tiler::Deregister(m_cat_texture);
  266. #endif //CAT_MODE
  267. while (m_constraint_list.size())
  268. {
  269. EasyConstraint* CurPop = m_constraint_list.back();
  270. m_constraint_list.pop_back();
  271. CurPop->RemoveFromSimulation(m_simulation);
  272. delete CurPop;
  273. }
  274. std::vector<PhysicsObject*> objects;
  275. for (auto *obj : m_ground_list)
  276. objects.push_back(obj);
  277. for (auto *obj : m_stairs_list)
  278. objects.push_back(obj);
  279. for (auto *obj : m_character_list)
  280. objects.push_back(obj);
  281. for (auto *obj : m_platform_list)
  282. objects.push_back(obj);
  283. // Back insertion; is this really necessary?
  284. while (m_physobj_list.size())
  285. {
  286. objects.push_back(m_physobj_list.back().obj);
  287. m_physobj_list.pop_back();
  288. }
  289. m_ground_list.clear();
  290. m_stairs_list.clear();
  291. m_character_list.clear();
  292. m_platform_list.clear();
  293. while (objects.size())
  294. {
  295. PhysicsObject* CurPop = objects.back();
  296. objects.pop_back();
  297. CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  298. Ticker::Unref(CurPop);
  299. }
  300. //while (m_ground_list.size())
  301. //{
  302. // PhysicsObject* CurPop = m_ground_list.back();
  303. // m_ground_list.pop_back();
  304. // CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  305. // Ticker::Unref(CurPop);
  306. //}
  307. //while (m_stairs_list.size())
  308. //{
  309. // PhysicsObject* CurPop = m_stairs_list.back();
  310. // m_stairs_list.pop_back();
  311. // CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  312. // Ticker::Unref(CurPop);
  313. //}
  314. //while (m_character_list.size())
  315. //{
  316. // PhysicsObject* CurPop = m_character_list.back();
  317. // m_character_list.pop_back();
  318. // CurPop->GetCharacter()->RemoveFromSimulation(m_simulation);
  319. // Ticker::Unref(CurPop);
  320. //}
  321. //while (m_platform_list.size())
  322. //{
  323. // PhysicsObject* CurPop = m_platform_list.back();
  324. // m_platform_list.pop_back();
  325. // CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  326. // Ticker::Unref(CurPop);
  327. //}
  328. //while (m_physobj_list.size())
  329. //{
  330. // PhysicsObject* CurPop = m_physobj_list.back().obj;
  331. // m_physobj_list.pop_back();
  332. // CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
  333. // Ticker::Unref(CurPop);
  334. //}
  335. Ticker::Unref(m_simulation);
  336. }
  337. void BtPhysTest::tick_game(float seconds)
  338. {
  339. WorldEntity::tick_game(seconds);
  340. if (!m_init_status)
  341. {
  342. if (Scene::GetCount())
  343. InitApp();
  344. return;
  345. }
  346. else if (m_init_status == 1)
  347. {
  348. m_init_status++;
  349. return;
  350. }
  351. auto context = Debug::DrawContext::New(color::white, 1.f);
  352. Debug::DrawGrid(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f);
  353. if (input::keyboard()->key_released(input::key::SC_Escape))
  354. Ticker::Shutdown();
  355. m_loop_value += seconds;
  356. if (m_loop_value > F_PI * 2.0f)
  357. m_loop_value -= F_PI * 2.0f;
  358. vec3 GroundBarycenter = vec3(.0f);
  359. vec3 PhysObjBarycenter = vec3(.0f);
  360. float factor = .0f;
  361. #if CAT_MODE
  362. #if USE_BODIES
  363. vec3 cam_center(0.f);
  364. float cam_factor = .0f;
  365. vec2 screen_min_max[2] = { vec2(FLT_MAX), vec2(-FLT_MAX) };
  366. Scene& scene = Scene::GetScene();
  367. mat4 world_cam = scene.GetCamera()->GetView();
  368. mat4 cam_screen = scene.GetCamera()->GetProjection();
  369. m_target_timer -= seconds;
  370. if (m_target_timer < .0f)
  371. {
  372. m_target_timer = TARGET_TIMER;
  373. if (m_cam_target == -1)
  374. m_cam_target = rand(m_physobj_list.size());
  375. else
  376. m_cam_target = -1;
  377. }
  378. for (size_t i = 0; i < m_physobj_list.size(); i++)
  379. {
  380. PhysicsObject* PhysObj = m_physobj_list[i].obj;
  381. float &obj_timer = m_physobj_list[i].anim;
  382. vec3 obj_loc = PhysObj->GetPhysic()->GetTransform()[3].xyz;
  383. if (m_cam_target == -1 || m_cam_target == i)
  384. {
  385. cam_center += obj_loc;
  386. cam_factor += 1.f;
  387. mat4 LocalPos = mat4::translate(obj_loc);
  388. vec3 vpos;
  389. LocalPos = world_cam * LocalPos;
  390. mat4 LocalPos0 = LocalPos;
  391. int j = 2;
  392. while (j-- > 0)
  393. {
  394. if (j == 1)
  395. LocalPos = mat4::translate(vec3(-4.f)) * LocalPos0;
  396. else
  397. LocalPos = mat4::translate(vec3(4.f)) * LocalPos0;
  398. LocalPos = cam_screen * LocalPos;
  399. vpos = (LocalPos[3] / LocalPos[3].w).xyz;
  400. screen_min_max[0] = min(vpos.xy, screen_min_max[0]);
  401. screen_min_max[1] = max(vpos.xy, screen_min_max[1]);
  402. }
  403. }
  404. //Jump handling
  405. //if (length(PhysObj->GetPhysic()->GetLinearVelocity()) < ZERO_SPEED)
  406. if (lol::fabs(PhysObj->GetPhysic()->GetLinearVelocity().y) < ZERO_SPEED)
  407. obj_timer -= seconds;
  408. if (obj_timer < .0f)
  409. {
  410. PhysObj->GetPhysic()->AddImpulse(JUMP_HEIGHT *
  411. vec3(JUMP_STRAFE, 1.f, JUMP_STRAFE) *
  412. vec3(rand(-1.f, 1.f), 1.0f, rand(-1.f, 1.f)) *
  413. PhysObj->GetPhysic()->GetMass());
  414. obj_timer = ZERO_TIME;
  415. }
  416. }
  417. float fov_ratio = max(max(lol::fabs(screen_min_max[0].x), lol::fabs(screen_min_max[0].y)),
  418. max(lol::fabs(screen_min_max[1].x), lol::fabs(screen_min_max[1].y)));
  419. vec3 new_target = cam_center / cam_factor;
  420. float fov_dp = .0f;
  421. float loc_dp = .0f;
  422. //ideally fov is on the target
  423. if (lol::fabs(fov_ratio - 1.f) < .2f)
  424. fov_dp = ((m_cam_target == -1)?(.7f):(.2f));
  425. else
  426. fov_dp = ((m_cam_target == -1)?(1.7f):(.9f));
  427. //ideally loc is on the target
  428. if (length(new_target - m_camera->GetTarget()) < 6.f)
  429. loc_dp = ((m_cam_target == -1)?(.5f):(.03f));
  430. else
  431. loc_dp = ((m_cam_target == -1)?(.9f):(.5f));
  432. m_fov_dp = damp(m_fov_dp, fov_dp, 0.08f, seconds);
  433. m_loc_dp = damp(m_loc_dp, loc_dp, 0.08f, seconds);
  434. m_camera->SetFov(damp(m_camera->GetFov(), m_camera->GetFov() * fov_ratio * 1.1f, m_fov_dp, seconds));
  435. vec3 tmp = damp(m_camera->GetTarget(), new_target, m_loc_dp, seconds);
  436. m_camera->SetView((mat4::rotate(radians(10.f) * seconds, vec3(.0f, 1.f, .0f)) * vec4(m_camera->GetPosition(), 1.0f)).xyz,
  437. tmp, vec3(0, 1, 0));
  438. #endif //USE_BODIES
  439. #endif //CAT_MODE
  440. #if USE_WALL
  441. {
  442. for (size_t i = 0; i < m_ground_list.size(); i++)
  443. {
  444. PhysicsObject* PhysObj = m_ground_list[i];
  445. mat4 GroundMat = PhysObj->GetTransform();
  446. GroundBarycenter += GroundMat[3].xyz;
  447. factor += 1.f;
  448. }
  449. GroundBarycenter /= factor;
  450. for (size_t i = 0; i < m_ground_list.size(); i++)
  451. {
  452. PhysicsObject* PhysObj = m_ground_list[i];
  453. mat4 GroundMat = PhysObj->GetTransform();
  454. vec3 CenterToGround = GroundMat[3].xyz - GroundBarycenter;
  455. vec3 CenterToCam = m_camera->GetPosition() - GroundBarycenter;
  456. if (dot(normalize(CenterToCam - CenterToGround),
  457. normalize(CenterToGround)) > 0.f)
  458. PhysObj->SetRender(false);
  459. else
  460. PhysObj->SetRender(true);
  461. }
  462. }
  463. #endif //USE_WALL
  464. #if USE_ROTATION
  465. {
  466. for (size_t i = 0; i < m_ground_list.size(); i++)
  467. {
  468. PhysicsObject* PhysObj = m_ground_list[i];
  469. mat4 GroundMat = PhysObj->GetTransform();
  470. mat4 CenterMx = mat4::translate(GroundBarycenter);
  471. GroundMat = inverse(CenterMx) * GroundMat;
  472. GroundMat = CenterMx *
  473. mat4(quat::fromeuler_xyz(vec3(.0f, radians(20.f), radians(20.0f)) * seconds))
  474. * GroundMat;
  475. PhysObj->SetTransform(GroundMat[3].xyz, quat(mat3(GroundMat)));
  476. }
  477. }
  478. #endif //USE_ROTATION
  479. #if USE_PLATFORM
  480. {
  481. for (size_t i = 0; i < m_platform_list.size(); i++)
  482. {
  483. PhysicsObject* PhysObj = m_platform_list[i];
  484. mat4 GroundMat = PhysObj->GetTransform();
  485. if (i == 0)
  486. {
  487. GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(radians(20.f), .0f, .0f) * seconds));
  488. PhysObj->SetTransform(GroundMat[3].xyz, quat(mat3(GroundMat)));
  489. }
  490. else if (i == 1)
  491. {
  492. GroundMat =
  493. mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) *
  494. mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * radians(20.f), .0f)));
  495. PhysObj->SetTransform(GroundMat[3].xyz, quat(mat3(GroundMat)));
  496. }
  497. }
  498. }
  499. #endif //USE_PLATFORM
  500. #if USE_CHARACTER
  501. {
  502. auto keyboard = input::keyboard();
  503. for (size_t i = 0; i < m_character_list.size(); i++)
  504. {
  505. PhysicsObject* PhysObj = m_character_list[i];
  506. EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter();
  507. mat4 CtlrMx = Character->GetTransform();
  508. vec3 movement(0.f);
  509. movement.z = (keyboard->key(input::key::SC_Right) ? 1.f : 0.f)
  510. - (keyboard->key(input::key::SC_Left) ? 1.f : 0.f);
  511. movement.x = (keyboard->key(input::key::SC_Up) ? 1.f : 0.f)
  512. - (keyboard->key(input::key::SC_Down) ? 1.f : 0.f);
  513. movement.y = (keyboard->key(input::key::SC_PageUp) ? 1.f : 0.f)
  514. - (keyboard->key(input::key::SC_PageDown) ? 1.f : 0.f);
  515. vec3 CharMove = movement * seconds * vec3(4.f, 10.f, 4.f);
  516. if (input::keyboard()->key_released(input::key::SC_Space))
  517. Character->Jump();
  518. Character->SetMovementForFrame(CharMove);
  519. RayCastResult HitResult;
  520. if (m_simulation->RayHits(HitResult, ERT_Closest, Character->GetTransform()[3].xyz, (Character->GetTransform()[3].xyz + vec3(.0f, -1.f, .0f)), Character))
  521. Character->AttachTo(HitResult.m_collider_list[0], true, true);
  522. else
  523. Character->AttachTo(nullptr);
  524. }
  525. }
  526. #endif //USE_CHARACTER
  527. #if USE_CHARACTER
  528. {
  529. PhysObjBarycenter = vec3(.0f);
  530. factor = .0f;
  531. for (size_t i = 0; i < m_character_list.size(); i++)
  532. {
  533. PhysicsObject* PhysObj = m_character_list[i];
  534. mat4 GroundMat = PhysObj->GetTransform();
  535. PhysObjBarycenter += GroundMat[3].xyz;
  536. factor += 1.f;
  537. }
  538. PhysObjBarycenter /= factor;
  539. #if 0
  540. m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget()));
  541. vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f);
  542. m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f);
  543. #endif
  544. }
  545. #else
  546. {
  547. PhysObjBarycenter = vec3(.0f);
  548. for (size_t i = 0; i < m_physobj_list.size(); i++)
  549. {
  550. PhysicsObject* PhysObj = m_physobj_list[i].obj;
  551. mat4 GroundMat = PhysObj->GetTransform();
  552. PhysObjBarycenter += GroundMat[3].xyz;
  553. factor += 1.f;
  554. }
  555. PhysObjBarycenter /= factor;
  556. #if 0
  557. m_camera->SetTarget(PhysObjBarycenter);
  558. m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f);
  559. #endif
  560. }
  561. #endif //USE_CHARACTER
  562. }
  563. void BtPhysTest::tick_draw(float seconds, Scene &scene)
  564. {
  565. WorldEntity::tick_draw(seconds, scene);
  566. if (m_init_status != 2)
  567. return;
  568. if (!m_ready)
  569. {
  570. #if CAT_MODE
  571. /* cat datas setup */
  572. m_cat_shader = Shader::Create(LOLFX_RESOURCE_NAME(front_camera_sprite));
  573. #if USE_BODIES
  574. for (size_t i = 0; i < m_physobj_list.size(); i++)
  575. {
  576. PhysicsObject* PhysObj = m_physobj_list[i].obj;
  577. m_cat_sdata = new CatShaderData(((1 << VertexUsage::Position) |
  578. (1 << VertexUsage::Color) |
  579. (1 << VertexUsage::TexCoord) |
  580. (1 << VertexUsage::TexCoordExt)),
  581. m_cat_shader);
  582. m_cat_sdata->m_tex_uniform = m_cat_texture->GetTexture()->GetTextureUniform();
  583. m_cat_sdata->m_sprite_flip = ((rand(2) == 1)?(1.f):(0.f)) / (float)(NB_SPRITE * PARTICLE_SIZE);
  584. PhysObj->SetCustomShaderData(m_cat_sdata);
  585. m_cat_sdata = nullptr;
  586. }
  587. #endif //USE_BODIES
  588. #endif //CAT_MODE
  589. /* FIXME: this object never cleans up */
  590. m_ready = true;
  591. }
  592. else
  593. {
  594. #if CAT_MODE
  595. for (size_t i = 0; i < m_physobj_list.size(); i++)
  596. {
  597. PhysicsObject* PhysObj = m_physobj_list[i].obj;
  598. CatShaderData* ShaderData = (CatShaderData*)PhysObj->GetCustomShaderData();
  599. ShaderData->m_sprite_orientation = damp(ShaderData->m_sprite_orientation,
  600. F_PI_4 * ((ShaderData->m_sprite_flip * 2.f * (float)(NB_SPRITE * PARTICLE_SIZE)) - 1.f) *
  601. clamp(PhysObj->GetPhysic()->GetLinearVelocity().y / 20.0f, -1.f, 1.f),
  602. 0.1f, seconds);
  603. }
  604. #endif //CAT_MODE
  605. }
  606. //Video::set_clear_color(vec4(0.0f, 0.0f, 0.12f, 1.0f));
  607. }
  608. //-----------------------------------------------------------------------------
  609. // CShaderData
  610. //-----------------------------------------------------------------------------
  611. CatShaderData::CatShaderData(uint32_t vert_decl_flags, std::shared_ptr<Shader> shader)
  612. : GpuShaderData(vert_decl_flags, shader, DebugRenderMode::Default)
  613. {
  614. m_sprite_orientation = .0f;
  615. m_sprite_flip = .0f;
  616. SetupDefaultData();
  617. }
  618. //-----------------------------------------------------------------------------
  619. void CatShaderData::SetupDefaultData()
  620. {
  621. AddUniform("u_model_view");
  622. AddUniform("u_normal_mat");
  623. AddUniform("u_proj");
  624. AddUniform("u_texture");
  625. AddUniform("u_sprite_orientation");
  626. AddUniform("u_sprite_flip");
  627. }
  628. //-----------------------------------------------------------------------------
  629. void CatShaderData::SetupShaderDatas(mat4 const &model)
  630. {
  631. Scene& scene = Scene::GetScene();
  632. mat4 proj = scene.GetCamera()->GetProjection();
  633. mat4 view = scene.GetCamera()->GetView();
  634. mat4 modelview = view * model;
  635. mat3 normalmat = transpose(inverse(mat3(view)));
  636. m_shader->SetUniform(*GetUniform("u_model_view"), modelview);
  637. m_shader->SetUniform(*GetUniform("u_normal_mat"), normalmat);
  638. m_shader->SetUniform(*GetUniform("u_proj"), proj);
  639. m_shader->SetUniform(*GetUniform("u_texture"), m_tex_uniform, 0);
  640. m_shader->SetUniform(*GetUniform("u_sprite_orientation"), m_sprite_orientation);
  641. m_shader->SetUniform(*GetUniform("u_sprite_flip"), m_sprite_flip);
  642. }
  643. int main(int argc, char **argv)
  644. {
  645. sys::init(argc, argv);
  646. Application app("BtPhysTest", ivec2(1280, 960), 60.0f);
  647. new BtPhysTest(argc > 1);
  648. app.ShowPointer(false);
  649. app.Run();
  650. return EXIT_SUCCESS;
  651. }