collision.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include <UnitTest++.h>
  2. #include <ode/ode.h>
  3. TEST(test_collision_trimesh_sphere_exact)
  4. {
  5. /*
  6. * This tests some extreme cases, where a sphere barely touches some triangles
  7. * with zero depth.
  8. */
  9. #ifdef dTRIMESH_GIMPACT
  10. /*
  11. * Although GIMPACT is algorithmically able to handle this extreme case,
  12. * the numerical approximation used for the square root produces inexact results.
  13. */
  14. return;
  15. #endif
  16. dInitODE();
  17. {
  18. const int VertexCount = 4;
  19. const int IndexCount = 2*3;
  20. // this is a square on the XY plane
  21. float vertices[VertexCount * 3] = {
  22. -1,-1,0,
  23. 1,-1,0,
  24. 1,1,0,
  25. -1,1,0
  26. };
  27. dTriIndex indices[IndexCount] = {
  28. 0,1,2,
  29. 0,2,3
  30. };
  31. dTriMeshDataID data = dGeomTriMeshDataCreate();
  32. dGeomTriMeshDataBuildSingle(data,
  33. vertices,
  34. 3 * sizeof(float),
  35. VertexCount,
  36. indices,
  37. IndexCount,
  38. 3 * sizeof(dTriIndex));
  39. dGeomID trimesh = dCreateTriMesh(0, data, 0, 0, 0);
  40. const dReal radius = 4;
  41. dGeomID sphere = dCreateSphere(0, radius);
  42. dGeomSetPosition(sphere, 0,0,radius);
  43. dContactGeom cg[4];
  44. int nc;
  45. // check extreme case
  46. nc = dCollide(trimesh, sphere, 4, &cg[0], sizeof cg[0]);
  47. CHECK_EQUAL(1, nc);
  48. CHECK_EQUAL(0, cg[0].depth);
  49. // now translate both geoms
  50. dGeomSetPosition(trimesh, 10,30,40);
  51. dGeomSetPosition(sphere, 10,30,40+radius);
  52. // check extreme case, again
  53. nc = dCollide(trimesh, sphere, 4, &cg[0], sizeof cg[0]);
  54. CHECK_EQUAL(1, nc);
  55. CHECK_EQUAL(0, cg[0].depth);
  56. // and now, let's rotate the trimesh, 90 degrees on X
  57. dMatrix3 rot = { 1, 0, 0, 0,
  58. 0, 0, -1, 0,
  59. 0, 1, 0, 0 };
  60. dGeomSetPosition(trimesh, 10,30,40);
  61. dGeomSetRotation(trimesh, rot);
  62. dGeomSetPosition(sphere, 10,30-radius,40);
  63. // check extreme case, again
  64. nc = dCollide(trimesh, sphere, 4, &cg[0], sizeof cg[0]);
  65. CHECK_EQUAL(1, nc);
  66. CHECK_EQUAL(0, cg[0].depth);
  67. }
  68. dCloseODE();
  69. }
  70. TEST(test_collision_heightfield_ray_fail)
  71. {
  72. /*
  73. * This test demonstrated a bug in the AABB handling of the
  74. * heightfield.
  75. */
  76. dInitODE();
  77. {
  78. // Create quick heightfield with dummy data
  79. dHeightfieldDataID heightfieldData = dGeomHeightfieldDataCreate();
  80. unsigned char dataBuffer[16+1] = "1234567890123456";
  81. dGeomHeightfieldDataBuildByte(heightfieldData, dataBuffer, 0, 4, 4, 4, 4, 1, 0, 0, 0);
  82. dGeomHeightfieldDataSetBounds(heightfieldData, '0', '9');
  83. dGeomID height = dCreateHeightfield(0, heightfieldData, 1);
  84. // Create ray outside bounds
  85. dGeomID ray = dCreateRay(0, 20);
  86. dGeomRaySet(ray, 5, 10, 1, 0, -1, 0);
  87. dContact contactBuf[10];
  88. // Crash!
  89. dCollide(ray, height, 10, &(contactBuf[0].geom), sizeof(dContact));
  90. dGeomDestroy(height);
  91. dGeomDestroy(ray);
  92. dGeomHeightfieldDataDestroy(heightfieldData);
  93. }
  94. dCloseODE();
  95. }