ActiveEdgesTest.cpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Tests/General/ActiveEdgesTest.h>
  6. #include <Jolt/Physics/Collision/Shape/BoxShape.h>
  7. #include <Jolt/Physics/Collision/Shape/MeshShape.h>
  8. #include <Jolt/Physics/Body/BodyCreationSettings.h>
  9. #include <Jolt/Geometry/Triangle.h>
  10. #include <Layers.h>
  11. JPH_IMPLEMENT_RTTI_VIRTUAL(ActiveEdgesTest)
  12. {
  13. JPH_ADD_BASE_CLASS(ActiveEdgesTest, Test)
  14. }
  15. void ActiveEdgesTest::Initialize()
  16. {
  17. const float cWidth = 5.0f;
  18. const float cLength = 10.0f;
  19. // Setings for a frictionless box
  20. Ref<BoxShape> box_shape = new BoxShape(Vec3(1.0f, 1.0f, 1.0f), cDefaultConvexRadius);
  21. BodyCreationSettings box_settings(box_shape, RVec3::sZero(), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
  22. box_settings.mFriction = 0.0f;
  23. box_settings.mLinearDamping = 0.0f;
  24. box_settings.mAllowSleeping = false;
  25. // Create various triangle strips
  26. TriangleList triangles;
  27. for (int angle = -90; angle <= 90; angle++)
  28. {
  29. // Under which normal we want to place the block
  30. Vec3 desired_normal = angle < 0? Vec3(0, 1, -1).Normalized() : Vec3(0, 1, 0);
  31. float best_dot = -FLT_MAX;
  32. // Place segments
  33. float x = cWidth * angle;
  34. Vec3 v1(x, 0.0f, -0.5f * cLength);
  35. Vec3 v2(x + cWidth, 0.0f, -0.5f * cLength);
  36. for (int total_angle = 0, cur_segment = 0; abs(total_angle) <= 90 && cur_segment < 90; total_angle += angle, ++cur_segment)
  37. {
  38. // Determine positions of end of this segment
  39. float total_angle_rad = DegreesToRadians(float(total_angle));
  40. Quat rotation = Quat::sRotation(Vec3::sAxisX(), total_angle_rad);
  41. Vec3 delta = cLength * rotation.RotateAxisZ();
  42. Vec3 v3 = v1 + delta;
  43. Vec3 v4 = v2 + delta;
  44. // Check if this segment is the best segment to place the dynamic block on
  45. Vec3 normal = (v3 - v1).Cross(v2 - v1).Normalized();
  46. float dot = normal.Dot(desired_normal);
  47. if (dot > best_dot)
  48. {
  49. best_dot = dot;
  50. box_settings.mPosition = RVec3((v1 + v2 + v3 + v4) / 4 + normal);
  51. box_settings.mRotation = rotation;
  52. }
  53. // Add segment
  54. triangles.push_back(Triangle(v1, v3, v4));
  55. triangles.push_back(Triangle(v1, v4, v2));
  56. // Add segment mirrored in Z axis
  57. if (cur_segment != 0)
  58. {
  59. Vec3 flip(1, 1, -1);
  60. triangles.push_back(Triangle(flip * v1, flip * v4, flip * v3));
  61. triangles.push_back(Triangle(flip * v1, flip * v2, flip * v4));
  62. }
  63. // The end of the segment will be the start for the next iteration
  64. v1 = v3;
  65. v2 = v4;
  66. }
  67. // Place box on best segment
  68. Body &body = *mBodyInterface->CreateBody(box_settings);
  69. mBodyInterface->AddBody(body.GetID(), EActivation::Activate);
  70. // For convex segments give the block a push
  71. if (angle >= 0)
  72. body.SetLinearVelocity(Vec3(0, 0, 2.0f));
  73. }
  74. // Mesh shape
  75. MeshShapeSettings mesh_shape(triangles);
  76. mesh_shape.SetEmbedded();
  77. mesh_shape.mActiveEdgeCosThresholdAngle = Cos(DegreesToRadians(50.0f));
  78. // Mesh
  79. BodyCreationSettings mesh_settings(&mesh_shape, RVec3::sZero(), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING);
  80. mesh_settings.mFriction = 0.0f;
  81. Body &mesh = *mBodyInterface->CreateBody(mesh_settings);
  82. mBodyInterface->AddBody(mesh.GetID(), EActivation::DontActivate);
  83. }