conservation.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /** Example that fakes the momentum/energy conservation. We simply keep the
  2. record of total speed in the system (as an approximation of
  3. momentum/energy/whatever) and if it changes too much, we multiply them
  4. accordingly to get them back :) */
  5. #include "helper.h"
  6. #define SPHERE_R (7 * TPE_F)
  7. TPE_Vec3 environmentDistance(TPE_Vec3 p, TPE_Unit maxD)
  8. {
  9. TPE_ENV_START( TPE_envSphereInside(p,TPE_vec3(0,0,0),SPHERE_R),p )
  10. TPE_ENV_END
  11. }
  12. int main(void)
  13. {
  14. helper_init();
  15. tpe_world.environmentFunction = environmentDistance;
  16. s3l_scene.camera.transform.translation.z = -1 * SPHERE_R - 2 * TPE_F;
  17. for (int i = 0; i < 4; ++i) // add bodies
  18. {
  19. switch (i)
  20. {
  21. case 0: helper_addBox(5 * TPE_F / 4,5 * TPE_F / 4,5 * TPE_F / 4,TPE_F,2 * TPE_F); break;
  22. case 1: helper_addBall(TPE_F,TPE_F / 4); break;
  23. case 2: helper_addRect(5 * TPE_F / 4,5 * TPE_F / 4,TPE_F,2 * TPE_F); break;
  24. case 3: helper_add2Line(2 * TPE_F,TPE_F / 2,TPE_F); break;
  25. default: break;
  26. }
  27. TPE_bodyMoveBy(&helper_lastBody,TPE_vec3((i - 2) * TPE_F * 2,-1 * TPE_F * i,TPE_F / 2));
  28. /* We don't want any energy losses due to friction and non-elastic collision,
  29. so we'll turn them off. This alone won't be enough though as numeric errors
  30. will still change the total energy. */
  31. helper_lastBody.friction = 0;
  32. helper_lastBody.elasticity = TPE_FRACTIONS_PER_UNIT;
  33. helper_lastBody.flags |= TPE_BODY_FLAG_ALWAYS_ACTIVE;
  34. TPE_bodyAccelerate(&helper_lastBody, // give some initial velocity
  35. TPE_vec3Plus(TPE_vec3Times(TPE_bodyGetCenterOfMass(&helper_lastBody),TPE_F / 10),TPE_vec3(0,TPE_F / 100,0)));
  36. }
  37. TPE_Unit sTotal = TPE_worldGetNetSpeed(&tpe_world);
  38. // ^ keep the record of total speed
  39. while (helper_running)
  40. {
  41. helper_frameStart();
  42. helper_cameraFreeMovement();
  43. TPE_worldStep(&tpe_world);
  44. TPE_Unit s = TPE_worldGetNetSpeed(&tpe_world);
  45. TPE_Unit ratio = (sTotal * TPE_FRACTIONS_PER_UNIT) / TPE_nonZero(s);
  46. if (ratio < (4 * TPE_FRACTIONS_PER_UNIT) / 5 ||
  47. ratio > (6 * TPE_FRACTIONS_PER_UNIT) / 5)
  48. {
  49. // if total speed changed by more than 1/5, we adjust it
  50. printf("net speed is now %d but needs to be %d, correcting!\n",s,sTotal);
  51. for (int i = 0; i < tpe_world.bodyCount; ++i)
  52. TPE_bodyMultiplyNetSpeed(&tpe_world.bodies[i],ratio);
  53. }
  54. helper_set3DColor(200,10,10);
  55. for (int i = 0; i < tpe_world.bodyCount; ++i) // draw the bodies
  56. {
  57. TPE_Joint *joints = tpe_world.bodies[i].joints;
  58. TPE_Vec3 pos = TPE_bodyGetCenterOfMass(&tpe_world.bodies[i]);
  59. TPE_Vec3 right = TPE_vec3(TPE_F,0,0);
  60. TPE_Vec3 forw = TPE_vec3(0,0,TPE_F);
  61. if (i != 1) // ugly code to get the correct orientation :)
  62. {
  63. if (i != 3)
  64. {
  65. forw = TPE_vec3Minus(joints[2].position,joints[0].position);
  66. right = TPE_vec3Minus(joints[1].position,joints[0].position);
  67. }
  68. else
  69. forw = TPE_vec3Minus(joints[1].position,joints[0].position);
  70. }
  71. TPE_Vec3 orient = TPE_rotationFromVecs(forw,right);
  72. switch (i % 5) // and draw the correct shape
  73. {
  74. case 0: helper_draw3DBox(pos,TPE_vec3(1200,1200,1200),orient); break;
  75. case 1: helper_draw3DSphere(pos,TPE_vec3(500,500,500),orient); break;
  76. case 2: helper_draw3DBox(pos,TPE_vec3(1200,400,1200),orient); break;
  77. case 3: helper_draw3DBox(pos,TPE_vec3(200,200,1200),orient); break;
  78. default: break;
  79. }
  80. }
  81. helper_set3DColor(200,200,200);
  82. helper_draw3DSphereInside(TPE_vec3(0,0,0),
  83. TPE_vec3(SPHERE_R,SPHERE_R,SPHERE_R),TPE_vec3(0,0,0));
  84. if (helper_debugDrawOn)
  85. helper_debugDraw(1);
  86. helper_frameEnd();
  87. }
  88. helper_end();
  89. return 0;
  90. }