test.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /** General automatic test for tinyphysicsengine, it should always pass. */
  2. #include "../tinyphysicsengine.h"
  3. #include <stdio.h>
  4. #define ass(cond,text) { printf("[CHECKING] " text ": "); if (!(cond)) { puts("ERROR"); return 1; } else puts("OK"); }
  5. TPE_Unit rampPoits[6] =
  6. {
  7. 0,0,
  8. -2400,1400,
  9. -2400,0
  10. };
  11. TPE_Vec3 envFunc(TPE_Vec3 p, TPE_Unit maxD)
  12. {
  13. TPE_ENV_START( TPE_envAABoxInside(p,TPE_vec3(0,1000,0),TPE_vec3(3000,2500,3000)),p )
  14. TPE_ENV_NEXT( TPE_envAATriPrism(p,TPE_vec3(100,200,-10),rampPoits,3000,2),p)
  15. TPE_ENV_NEXT( TPE_envBox(p,TPE_vec3(30,200,-10),TPE_vec3(500,600,700),TPE_vec3(10,20,30)), p)
  16. TPE_ENV_NEXT( TPE_envAABox(p,TPE_vec3(-100,300,200),TPE_vec3(500,600,700)), p)
  17. TPE_ENV_END
  18. }
  19. TPE_Vec3 envFunc2(TPE_Vec3 p, TPE_Unit maxD)
  20. {
  21. TPE_ENV_START( TPE_envSphereInside(p,TPE_vec3(100,20,-3),5000), p)
  22. TPE_ENV_NEXT( TPE_envGround(p,-500), p)
  23. if (TPE_ENV_BCUBE_TEST(p,maxD,TPE_vec3(300,-40,50),1100) )
  24. {
  25. TPE_ENV_NEXT( TPE_envCylinder(p, TPE_vec3(300,-40,50), TPE_vec3(-400,-200,-50), 751), p)
  26. }
  27. TPE_ENV_END
  28. }
  29. TPE_Vec3 envFuncBad(TPE_Vec3 p, TPE_Unit maxD)
  30. {
  31. p.x += 200;
  32. return p;
  33. }
  34. TPE_Vec3 envFuncBad2(TPE_Vec3 p, TPE_Unit maxD)
  35. {
  36. if (p.y > p.x)
  37. p.x = p.y;
  38. return p;
  39. }
  40. TPE_Vec3 envSimple(TPE_Vec3 p, TPE_Unit maxD)
  41. {
  42. TPE_ENV_START( TPE_envAABoxInside(p,TPE_vec3(0,0,0),TPE_vec3(10000,10000,10000)), p)
  43. TPE_ENV_NEXT( TPE_envHalfPlane(p,TPE_vec3(0,-5000,0),TPE_vec3(500,500,0)), p)
  44. TPE_ENV_END
  45. }
  46. int main(void)
  47. {
  48. puts("== testing tinyphysicsengine ==");
  49. {
  50. ass(TPE_vec2Angle(-100,0) == TPE_FRACTIONS_PER_UNIT / 2,"vec2 angle")
  51. TPE_Unit l;
  52. l = TPE_LENGTH(TPE_vec3Normalized(TPE_vec3(100,0,0)));
  53. ass(TPE_abs(l - TPE_FRACTIONS_PER_UNIT) < 5,"vec3 normalize")
  54. l = TPE_LENGTH(TPE_vec3Normalized(TPE_vec3(0,0,0)));
  55. ass(TPE_abs(l - TPE_FRACTIONS_PER_UNIT) < 5,"zero vec3 normalize")
  56. l = TPE_LENGTH(TPE_vec3Normalized(TPE_vec3(0,-1,0)));
  57. ass(TPE_abs(l - TPE_FRACTIONS_PER_UNIT) < 5,"small vec3 normalize")
  58. l = TPE_LENGTH(TPE_vec3Normalized(TPE_vec3(500000,300000,-700000)));
  59. ass(TPE_abs(l - TPE_FRACTIONS_PER_UNIT) < 5,"big vec3 normalize")
  60. }
  61. {
  62. TPE_Joint joints[16];
  63. TPE_Connection cons[16];
  64. joints[0] = TPE_joint(TPE_vec3(200,100,-400),300);
  65. joints[1] = TPE_joint(TPE_vec3(100,200,-400),300);
  66. joints[2] = TPE_joint(TPE_vec3(200,-400,200),300);
  67. joints[3] = TPE_joint(TPE_vec3(200,100,-400),400);
  68. cons[0].joint1 = 0; cons[0].joint2 = 1; cons[0].length = 1000;
  69. cons[1].joint1 = 1; cons[1].joint2 = 0; cons[1].length = 1000;
  70. cons[2].joint1 = 0; cons[2].joint2 = 1; cons[2].length = 1100;
  71. cons[3].joint1 = 2; cons[3].joint2 = 3; cons[3].length = 100;
  72. uint32_t jHashes[4], cHashes[4];
  73. for (int i = 0; i < 4; ++i)
  74. {
  75. jHashes[i] = TPE_jointHash(&joints[i]);
  76. cHashes[i] = TPE_connectionHash(&cons[i]);
  77. }
  78. for (int i = 0; i < 4; ++i)
  79. for (int j = i + 1; j < 4; ++j)
  80. ass(jHashes[i] != jHashes[j] && cHashes[i] != cHashes[j],"joints/connection hash");
  81. TPE_Body bodies[8];
  82. uint32_t bHashes[4];
  83. TPE_bodyInit(&bodies[0],joints,4,cons,4,300);
  84. TPE_bodyInit(&bodies[1],joints + 1,3,cons,4,300);
  85. TPE_bodyInit(&bodies[2],joints,4,cons,4,300);
  86. bodies[2].flags |= TPE_BODY_FLAG_SOFT | TPE_BODY_FLAG_NONROTATING;
  87. TPE_bodyInit(&bodies[3],joints,4,cons,4,200);
  88. for (int i = 0; i < 4; ++i)
  89. bHashes[i] = TPE_bodyHash(&bodies[i]);
  90. for (int i = 0; i < 4; ++i)
  91. for (int j = i + 1; j < 4; ++j)
  92. ass(bHashes[i] != bHashes[j],"body hash");
  93. TPE_World world;
  94. uint32_t wHashes[4];
  95. TPE_worldInit(&world,bodies,4,0);
  96. wHashes[0] = TPE_worldHash(&world);
  97. bodies[0].jointCount--;
  98. wHashes[1] = TPE_worldHash(&world);
  99. bodies[4] = bodies[0]; bodies[0] = bodies[3]; bodies[3] = bodies[4];
  100. wHashes[2] = TPE_worldHash(&world);
  101. world.bodyCount--;
  102. wHashes[3] = TPE_worldHash(&world);
  103. for (int i = 0; i < 4; ++i)
  104. for (int j = i + 1; j < 4; ++j)
  105. ass(wHashes[i] != wHashes[j],"world hash");
  106. }
  107. {
  108. puts("-- environment functions --");
  109. ass(TPE_testClosestPointFunction(envFunc,TPE_vec3(-3000,-3000,-3000),
  110. TPE_vec3(3000,3000,3000),32,40,0),"env function");
  111. ass(TPE_testClosestPointFunction(envFunc2,TPE_vec3(-2000,-1000,-5000),
  112. TPE_vec3(5000,6000,7000),32,30,0),"env function");
  113. ass(!TPE_testClosestPointFunction(envFuncBad,TPE_vec3(-1000,-1000,-1000),
  114. TPE_vec3(2000,3000,100),32,40,0),"env function bad");
  115. ass(!TPE_testClosestPointFunction(envFuncBad2,TPE_vec3(-1000,-2000,-200),
  116. TPE_vec3(1000,1000,2000),32,40,0),"env function bad");
  117. }
  118. {
  119. puts("-- simulation --");
  120. TPE_World w;
  121. TPE_Joint j[64];
  122. TPE_Connection c[128];
  123. TPE_Body b[4];
  124. j[0] = TPE_joint(TPE_vec3(0,0,0),320);
  125. TPE_bodyInit(&b[0],j,1,0,0,2124);
  126. TPE_bodyMoveBy(&b[0],TPE_vec3(-2000,3000,3000));
  127. TPE_makeBox(j + 1,c,800,900,850,320);
  128. TPE_bodyInit(&b[1],j + 1,8,c,16,1300);
  129. b[1].friction = 400;
  130. b[1].elasticity = 350;
  131. TPE_bodyMoveBy(&b[1],TPE_vec3(-2000,3800,1500));
  132. TPE_make2Line(j + 20,c + 32,1000,300);
  133. TPE_bodyInit(&b[2],j + 20,2,c + 32,1,1300);
  134. b[2].flags |= TPE_BODY_FLAG_NONROTATING;
  135. TPE_bodyMoveBy(&b[2],TPE_vec3(-3000,4100,-1500));
  136. TPE_makeCenterBox(j + 32,c + 64,600,500,510,300);
  137. TPE_bodyInit(&b[3],j + 32,9,c + 64,18,1200);
  138. b[3].flags |= TPE_BODY_FLAG_SOFT;
  139. TPE_bodyMoveBy(&b[3],TPE_vec3(-1500,3500,-3000));
  140. TPE_worldInit(&w,b,4,envSimple);
  141. int16_t bi;
  142. TPE_castBodyRay(TPE_vec3(-1857,3743,-4800),TPE_vec3(0,0,100),-1,&w,&bi,0);
  143. ass(bi >= 0,"body ray hit");
  144. puts("dropping bodies onto a ramp...");
  145. for (int i = 0; i < 300; ++i)
  146. {
  147. for (uint8_t j = 0; j < w.bodyCount; ++j)
  148. TPE_bodyApplyGravity(&w.bodies[j],8);
  149. if (i == 100)
  150. ass(TPE_worldGetNetSpeed(&w) > 100,"world net speed");
  151. TPE_worldStep(&w);
  152. }
  153. puts("simulation finished");
  154. uint32_t hash = TPE_worldHash(&w);
  155. printf("world hash: %lu\n",hash);
  156. // change the hash if functionality changes:
  157. ass(hash == 3862131191,"world hash");
  158. for (int i = 0; i < w.bodyCount; ++i)
  159. {
  160. ass(TPE_bodyGetCenterOfMass(&w.bodies[i]).x > 0,"x position > 0");
  161. ass(w.bodies[i].flags & TPE_BODY_FLAG_DEACTIVATED,"deactivated?");
  162. }
  163. ass(TPE_worldGetNetSpeed(&w) < 100,"world net speed");
  164. TPE_bodyAccelerate(&w.bodies[0],TPE_vec3(200,300,-20));
  165. TPE_bodyAccelerate(&w.bodies[1],TPE_vec3(-700,400,0));
  166. TPE_bodyAccelerate(&w.bodies[2],TPE_vec3(20,-300,-100));
  167. TPE_bodyAccelerate(&w.bodies[3],TPE_vec3(0,30,-900));
  168. puts("exploding bodies...");
  169. for (int i = 0; i < 100; ++i)
  170. {
  171. for (uint8_t j = 0; j < w.bodyCount; ++j)
  172. TPE_bodyApplyGravity(&w.bodies[j],8);
  173. TPE_worldStep(&w);
  174. }
  175. // check if within environment
  176. for (int i = 0; i < w.bodyCount; ++i)
  177. {
  178. TPE_Vec3 p = TPE_bodyGetCenterOfMass(&w.bodies[i]);
  179. ass(p.x < 5000 && p.x > -5000 && p.y < 5000 && p.y > -5000 &&
  180. p.z < 5000 && p.z > -5000,"body within environment");
  181. }
  182. }
  183. return 0;
  184. }