2
0

PoweredHingeConstraintTest.cpp 4.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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/Constraints/PoweredHingeConstraintTest.h>
  6. #include <Jolt/Physics/Collision/Shape/BoxShape.h>
  7. #include <Jolt/Physics/Collision/GroupFilterTable.h>
  8. #include <Jolt/Physics/Body/BodyCreationSettings.h>
  9. #include <Application/DebugUI.h>
  10. #include <Layers.h>
  11. JPH_IMPLEMENT_RTTI_VIRTUAL(PoweredHingeConstraintTest)
  12. {
  13. JPH_ADD_BASE_CLASS(PoweredHingeConstraintTest, Test)
  14. }
  15. void PoweredHingeConstraintTest::Initialize()
  16. {
  17. // Floor
  18. CreateFloor();
  19. // Create group filter
  20. Ref<GroupFilterTable> group_filter = new GroupFilterTable;
  21. // Create box
  22. float box_size = 4.0f;
  23. RefConst<Shape> box = new BoxShape(Vec3::sReplicate(0.5f * box_size));
  24. RVec3 body1_position(0, 10, 0);
  25. Body &body1 = *mBodyInterface->CreateBody(BodyCreationSettings(box, body1_position, Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING));
  26. body1.SetCollisionGroup(CollisionGroup(group_filter, 0, 0));
  27. mBodyInterface->AddBody(body1.GetID(), EActivation::DontActivate);
  28. RVec3 body2_position = body1_position + Vec3(box_size, 0, 0);
  29. Body &body2 = *mBodyInterface->CreateBody(BodyCreationSettings(box, body2_position, Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING));
  30. body2.SetCollisionGroup(CollisionGroup(group_filter, 0, 0));
  31. body2.GetMotionProperties()->SetLinearDamping(0.0f);
  32. body2.GetMotionProperties()->SetAngularDamping(0.0f);
  33. body2.SetAllowSleeping(false);
  34. mBodyInterface->AddBody(body2.GetID(), EActivation::Activate);
  35. RVec3 constraint_position = body1_position + Vec3(0.5f * box_size, 0, 0.5f * box_size);
  36. HingeConstraintSettings settings;
  37. settings.mPoint1 = settings.mPoint2 = constraint_position;
  38. settings.mHingeAxis1 = settings.mHingeAxis2 = Vec3::sAxisY();
  39. settings.mNormalAxis1 = settings.mNormalAxis2 = Vec3::sAxisX();
  40. mConstraint = static_cast<HingeConstraint *>(settings.Create(body1, body2));
  41. mConstraint->SetMotorState(EMotorState::Velocity);
  42. mConstraint->SetTargetAngularVelocity(DegreesToRadians(25));
  43. mPhysicsSystem->AddConstraint(mConstraint);
  44. // Calculate inertia of body 2 as seen from the constraint
  45. MassProperties body2_inertia_from_constraint;
  46. body2_inertia_from_constraint.mMass = 1.0f / body2.GetMotionProperties()->GetInverseMass();
  47. body2_inertia_from_constraint.mInertia = body2.GetMotionProperties()->GetLocalSpaceInverseInertia().Inversed3x3();
  48. body2_inertia_from_constraint.Translate(Vec3(body2_position - constraint_position));
  49. mInertiaBody2AsSeenFromConstraint = (body2_inertia_from_constraint.mInertia * Vec3::sAxisY()).Length();
  50. }
  51. void PoweredHingeConstraintTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
  52. {
  53. // Torque = Inertia * Angular Acceleration (alpha)
  54. MotorSettings &motor_settings = mConstraint->GetMotorSettings();
  55. motor_settings.SetTorqueLimit(mInertiaBody2AsSeenFromConstraint * sMaxAngularAcceleration);
  56. motor_settings.mSpringSettings.mFrequency = sFrequency;
  57. motor_settings.mSpringSettings.mDamping = sDamping;
  58. mConstraint->SetMaxFrictionTorque(mInertiaBody2AsSeenFromConstraint * sMaxFrictionAngularAcceleration);
  59. }
  60. void PoweredHingeConstraintTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
  61. {
  62. inUI->CreateComboBox(inSubMenu, "Motor", { "Off", "Velocity", "Position" }, (int)mConstraint->GetMotorState(), [this](int inItem) { mConstraint->SetMotorState((EMotorState)inItem); });
  63. inUI->CreateSlider(inSubMenu, "Target Angular Velocity (deg/s)", RadiansToDegrees(mConstraint->GetTargetAngularVelocity()), -90.0f, 90.0f, 1.0f, [this](float inValue) { mConstraint->SetTargetAngularVelocity(DegreesToRadians(inValue)); });
  64. inUI->CreateSlider(inSubMenu, "Target Angle (deg)", RadiansToDegrees(mConstraint->GetTargetAngle()), -180.0f, 180.0f, 1.0f, [this](float inValue) { mConstraint->SetTargetAngle(DegreesToRadians(inValue)); });
  65. inUI->CreateSlider(inSubMenu, "Max Angular Acceleration (deg/s^2)", RadiansToDegrees(sMaxAngularAcceleration), 0.0f, 3600.0f, 10.0f, [](float inValue) { sMaxAngularAcceleration = DegreesToRadians(inValue); });
  66. inUI->CreateSlider(inSubMenu, "Frequency (Hz)", sFrequency, 0.0f, 20.0f, 0.1f, [](float inValue) { sFrequency = inValue; });
  67. inUI->CreateSlider(inSubMenu, "Damping", sDamping, 0.0f, 2.0f, 0.01f, [](float inValue) { sDamping = inValue; });
  68. inUI->CreateSlider(inSubMenu, "Max Friction Angular Acceleration (deg/s^2)", RadiansToDegrees(sMaxFrictionAngularAcceleration), 0.0f, 90.0f, 1.0f, [](float inValue) { sMaxFrictionAngularAcceleration = DegreesToRadians(inValue); });
  69. }