LoadSnapshotTest.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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/Tools/LoadSnapshotTest.h>
  6. #include <Jolt/Physics/PhysicsScene.h>
  7. #include <Jolt/Core/StreamWrapper.h>
  8. #include <Application/DebugUI.h>
  9. #include <Utils/Log.h>
  10. #include <Layers.h>
  11. JPH_SUPPRESS_WARNINGS_STD_BEGIN
  12. #ifdef JPH_PLATFORM_WINDOWS
  13. #include <commdlg.h>
  14. #endif
  15. #include <fstream>
  16. JPH_SUPPRESS_WARNINGS_STD_END
  17. JPH_IMPLEMENT_RTTI_VIRTUAL(LoadSnapshotTest)
  18. {
  19. JPH_ADD_BASE_CLASS(LoadSnapshotTest, Test)
  20. }
  21. void LoadSnapshotTest::Initialize()
  22. {
  23. #ifdef JPH_PLATFORM_WINDOWS
  24. // Let user browse for a file
  25. char file_name[MAX_PATH] = "";
  26. OPENFILENAMEA ofn;
  27. memset(&ofn, 0, sizeof(ofn));
  28. ofn.lStructSize = sizeof(ofn);
  29. ofn.lpstrFilter = "Snapshots\0*.bin\0";
  30. ofn.lpstrFile = file_name;
  31. ofn.nMaxFile = MAX_PATH;
  32. ofn.lpstrTitle = "Select a Jolt Binary Snapshot";
  33. ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
  34. if (!GetOpenFileNameA(&ofn))
  35. return;
  36. #else
  37. // Can't browse for a file, use the default name
  38. char file_name[] = "snapshot.bin";
  39. #endif
  40. ifstream stream(file_name, ifstream::in | ifstream::binary);
  41. if (!stream.is_open())
  42. FatalError("Unable to open file");
  43. StreamInWrapper wrapper(stream);
  44. PhysicsScene::PhysicsSceneResult result = PhysicsScene::sRestoreFromBinaryState(wrapper);
  45. if (result.HasError())
  46. FatalError(result.GetError().c_str());
  47. Ref<PhysicsScene> scene = result.Get();
  48. // Determine quaternion that rotates the world so that up is Y
  49. Quat up_rotation;
  50. switch (sUpAxis)
  51. {
  52. case 0: up_rotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI); break;
  53. case 2: up_rotation = Quat::sRotation(Vec3::sAxisX(), -0.5f * JPH_PI); break;
  54. default: up_rotation = Quat::sIdentity(); break;
  55. }
  56. // Determine if we are forced to override the object layers because one of the bodies has a layer number that is invalid in the context of this application
  57. bool override_layers = sOverrideLayers;
  58. if (!override_layers)
  59. {
  60. for (const BodyCreationSettings &settings : scene->GetBodies())
  61. if (settings.mObjectLayer >= Layers::NUM_LAYERS)
  62. {
  63. override_layers = true;
  64. break;
  65. }
  66. for (const SoftBodyCreationSettings &settings : scene->GetSoftBodies())
  67. if (settings.mObjectLayer >= Layers::NUM_LAYERS)
  68. {
  69. override_layers = true;
  70. break;
  71. }
  72. }
  73. for (BodyCreationSettings &settings : scene->GetBodies())
  74. {
  75. if (override_layers)
  76. {
  77. // Override the layer so that all static objects are in the non-moving layer and everything else is in the moving layer
  78. if (settings.mMotionType == EMotionType::Static)
  79. settings.mObjectLayer = Layers::NON_MOVING;
  80. else
  81. settings.mObjectLayer = Layers::MOVING;
  82. }
  83. // Rotate the body so that it matches Y is up
  84. settings.mPosition = RMat44::sRotation(up_rotation) * settings.mPosition;
  85. settings.mRotation = up_rotation * settings.mRotation;
  86. }
  87. for (SoftBodyCreationSettings &settings : scene->GetSoftBodies())
  88. {
  89. if (override_layers)
  90. settings.mObjectLayer = Layers::MOVING;
  91. // Rotate the body so that it matches Y is up
  92. settings.mPosition = RMat44::sRotation(up_rotation) * settings.mPosition;
  93. settings.mRotation = up_rotation * settings.mRotation;
  94. }
  95. scene->CreateBodies(mPhysicsSystem);
  96. }
  97. void LoadSnapshotTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
  98. {
  99. inUI->CreateComboBox(inSubMenu, "Up Axis", { "X", "Y", "Z" }, sUpAxis, [](int inItem) { sUpAxis = inItem; });
  100. inUI->CreateCheckBox(inSubMenu, "Override Object Layers", sOverrideLayers, [](UICheckBox::EState inState) { sOverrideLayers = inState == UICheckBox::STATE_CHECKED; });
  101. inUI->CreateTextButton(inSubMenu, "Accept Changes", [this]() { RestartTest(); });
  102. }