ConveyorBeltTest.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2023 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Tests/General/ConveyorBeltTest.h>
  6. #include <Jolt/Physics/Collision/Shape/BoxShape.h>
  7. #include <Jolt/Physics/Collision/Shape/CylinderShape.h>
  8. #include <Jolt/Physics/Body/BodyCreationSettings.h>
  9. #include <Layers.h>
  10. JPH_IMPLEMENT_RTTI_VIRTUAL(ConveyorBeltTest)
  11. {
  12. JPH_ADD_BASE_CLASS(ConveyorBeltTest, Test)
  13. }
  14. void ConveyorBeltTest::Initialize()
  15. {
  16. // Floor
  17. CreateFloor();
  18. // Create conveyor belts
  19. const float cBeltWidth = 10.0f;
  20. const float cBeltLength = 50.0f;
  21. BodyCreationSettings belt_settings(new BoxShape(Vec3(cBeltWidth, 0.1f, cBeltLength)), RVec3::sZero(), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING);
  22. for (int i = 0; i < 4; ++i)
  23. {
  24. belt_settings.mFriction = 0.25f * (i + 1);
  25. belt_settings.mRotation = Quat::sRotation(Vec3::sAxisY(), 0.5f * JPH_PI * i) * Quat::sRotation(Vec3::sAxisX(), DegreesToRadians(1.0f));
  26. belt_settings.mPosition = RVec3(belt_settings.mRotation * Vec3(cBeltLength, 6.0f, cBeltWidth));
  27. mLinearBelts.push_back(mBodyInterface->CreateAndAddBody(belt_settings, EActivation::DontActivate));
  28. }
  29. // Bodies with decreasing friction
  30. BodyCreationSettings cargo_settings(new BoxShape(Vec3::sReplicate(2.0f)), RVec3::sZero(), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
  31. for (int i = 0; i <= 10; ++i)
  32. {
  33. cargo_settings.mPosition = RVec3(-cBeltLength + i * 10.0f, 10.0f, -cBeltLength);
  34. cargo_settings.mFriction = max(0.0f, 1.0f - 0.1f * i);
  35. mBodyInterface->CreateAndAddBody(cargo_settings, EActivation::Activate);
  36. }
  37. // Create 2 cylinders
  38. BodyCreationSettings cylinder_settings(new CylinderShape(6.0f, 1.0f), RVec3(-25.0f, 1.0f, -20.0f), Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), EMotionType::Dynamic, Layers::MOVING);
  39. mBodyInterface->CreateAndAddBody(cylinder_settings, EActivation::Activate);
  40. cylinder_settings.mPosition.SetZ(20.0f);
  41. mBodyInterface->CreateAndAddBody(cylinder_settings, EActivation::Activate);
  42. // Let a dynamic belt rest on it
  43. BodyCreationSettings dynamic_belt(new BoxShape(Vec3(5.0f, 0.1f, 25.0f), 0.0f), RVec3(-25.0f, 3.0f, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
  44. mLinearBelts.push_back(mBodyInterface->CreateAndAddBody(dynamic_belt, EActivation::Activate));
  45. // Create cargo on the dynamic belt
  46. cargo_settings.mPosition = RVec3(-25.0f, 6.0f, 15.0f);
  47. cargo_settings.mFriction = 1.0f;
  48. mBodyInterface->CreateAndAddBody(cargo_settings, EActivation::Activate);
  49. // Create an angular belt
  50. BodyCreationSettings angular_belt(new BoxShape(Vec3(20.0f, 0.1f, 20.0f), 0.0f), RVec3(10.0f, 3.0f, 0), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING);
  51. mAngularBelt = mBodyInterface->CreateAndAddBody(angular_belt, EActivation::Activate);
  52. // Bodies with decreasing friction dropping on the angular belt
  53. for (int i = 0; i <= 6; ++i)
  54. {
  55. cargo_settings.mPosition = RVec3(10.0f, 10.0f, -15.0f + 5.0f * i);
  56. cargo_settings.mFriction = max(0.0f, 1.0f - 0.1f * i);
  57. mBodyInterface->CreateAndAddBody(cargo_settings, EActivation::Activate);
  58. }
  59. }
  60. void ConveyorBeltTest::OnContactAdded(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings)
  61. {
  62. // Linear belts
  63. bool body1_linear_belt = std::find(mLinearBelts.begin(), mLinearBelts.end(), inBody1.GetID()) != mLinearBelts.end();
  64. bool body2_linear_belt = std::find(mLinearBelts.begin(), mLinearBelts.end(), inBody2.GetID()) != mLinearBelts.end();
  65. if (body1_linear_belt || body2_linear_belt)
  66. {
  67. // Determine the world space surface velocity of both bodies
  68. const Vec3 cLocalSpaceVelocity(0, 0, -10.0f);
  69. Vec3 body1_linear_surface_velocity = body1_linear_belt? inBody1.GetRotation() * cLocalSpaceVelocity : Vec3::sZero();
  70. Vec3 body2_linear_surface_velocity = body2_linear_belt? inBody2.GetRotation() * cLocalSpaceVelocity : Vec3::sZero();
  71. // Calculate the relative surface velocity
  72. ioSettings.mRelativeLinearSurfaceVelocity = body2_linear_surface_velocity - body1_linear_surface_velocity;
  73. }
  74. // Angular belt
  75. bool body1_angular = inBody1.GetID() == mAngularBelt;
  76. bool body2_angular = inBody2.GetID() == mAngularBelt;
  77. if (body1_angular || body2_angular)
  78. {
  79. // Determine the world space angular surface velocity of both bodies
  80. const Vec3 cLocalSpaceAngularVelocity(0, DegreesToRadians(10.0f), 0);
  81. Vec3 body1_angular_surface_velocity = body1_angular? inBody1.GetRotation() * cLocalSpaceAngularVelocity : Vec3::sZero();
  82. Vec3 body2_angular_surface_velocity = body2_angular? inBody2.GetRotation() * cLocalSpaceAngularVelocity : Vec3::sZero();
  83. // Note that the angular velocity is the angular velocity around body 1's center of mass, so we need to add the linear velocity of body 2's center of mass
  84. Vec3 body2_linear_surface_velocity = body2_angular? body2_angular_surface_velocity.Cross(Vec3(inBody1.GetCenterOfMassPosition() - inBody2.GetCenterOfMassPosition())) : Vec3::sZero();
  85. // Calculate the relative angular surface velocity
  86. ioSettings.mRelativeLinearSurfaceVelocity = body2_linear_surface_velocity;
  87. ioSettings.mRelativeAngularSurfaceVelocity = body2_angular_surface_velocity - body1_angular_surface_velocity;
  88. }
  89. }
  90. void ConveyorBeltTest::OnContactPersisted(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings)
  91. {
  92. // Same behavior as contact added
  93. OnContactAdded(inBody1, inBody2, inManifold, ioSettings);
  94. }