RagdollLoader.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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 <Utils/RagdollLoader.h>
  6. #include <Jolt/Physics/Ragdoll/Ragdoll.h>
  7. #include <Jolt/Physics/Constraints/PointConstraint.h>
  8. #include <Jolt/Physics/Constraints/FixedConstraint.h>
  9. #include <Jolt/Physics/Constraints/HingeConstraint.h>
  10. #include <Jolt/Physics/Constraints/SliderConstraint.h>
  11. #include <Jolt/Physics/Constraints/ConeConstraint.h>
  12. #include <Jolt/Physics/Constraints/SwingTwistConstraint.h>
  13. #include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
  14. #include <Jolt/ObjectStream/ObjectStreamIn.h>
  15. #include <Jolt/ObjectStream/ObjectStreamOut.h>
  16. #include <Layers.h>
  17. #include <Utils/Log.h>
  18. #include <Utils/AssetStream.h>
  19. #ifdef JPH_OBJECT_STREAM
  20. RagdollSettings *RagdollLoader::sLoad(const char *inFileName, EMotionType inMotionType, EConstraintOverride inConstraintOverride)
  21. {
  22. // Read the ragdoll
  23. RagdollSettings *ragdoll = nullptr;
  24. AssetStream stream(inFileName, std::ios::in);
  25. if (!ObjectStreamIn::sReadObject(stream.Get(), ragdoll))
  26. FatalError("Unable to read ragdoll");
  27. for (RagdollSettings::Part &p : ragdoll->mParts)
  28. {
  29. // Update motion type
  30. p.mMotionType = inMotionType;
  31. // Override layer
  32. p.mObjectLayer = Layers::MOVING;
  33. // Create new constraint
  34. Ref<SwingTwistConstraintSettings> original = DynamicCast<SwingTwistConstraintSettings>(p.mToParent);
  35. if (original != nullptr)
  36. switch (inConstraintOverride)
  37. {
  38. case EConstraintOverride::TypeFixed:
  39. {
  40. FixedConstraintSettings *settings = new FixedConstraintSettings();
  41. settings->mPoint1 = settings->mPoint2 = original->mPosition1;
  42. p.mToParent = settings;
  43. break;
  44. }
  45. case EConstraintOverride::TypePoint:
  46. {
  47. PointConstraintSettings *settings = new PointConstraintSettings();
  48. settings->mPoint1 = settings->mPoint2 = original->mPosition1;
  49. p.mToParent = settings;
  50. break;
  51. }
  52. case EConstraintOverride::TypeHinge:
  53. {
  54. HingeConstraintSettings *settings = new HingeConstraintSettings();
  55. settings->mPoint1 = original->mPosition1;
  56. settings->mHingeAxis1 = original->mPlaneAxis1;
  57. settings->mNormalAxis1 = original->mTwistAxis1;
  58. settings->mPoint2 = original->mPosition2;
  59. settings->mHingeAxis2 = original->mPlaneAxis2;
  60. settings->mNormalAxis2 = original->mTwistAxis2;
  61. settings->mLimitsMin = -original->mNormalHalfConeAngle;
  62. settings->mLimitsMax = original->mNormalHalfConeAngle;
  63. settings->mMaxFrictionTorque = original->mMaxFrictionTorque;
  64. settings->mMotorSettings = original->mSwingMotorSettings;
  65. p.mToParent = settings;
  66. break;
  67. }
  68. case EConstraintOverride::TypeSlider:
  69. {
  70. SliderConstraintSettings *settings = new SliderConstraintSettings();
  71. settings->mPoint1 = settings->mPoint2 = original->mPosition1;
  72. settings->mSliderAxis1 = settings->mSliderAxis2 = original->mTwistAxis1;
  73. settings->mNormalAxis1 = settings->mNormalAxis2 = original->mTwistAxis1.GetNormalizedPerpendicular();
  74. settings->mLimitsMin = -1.0f;
  75. settings->mLimitsMax = 1.0f;
  76. settings->mMaxFrictionForce = original->mMaxFrictionTorque;
  77. settings->mMotorSettings = original->mSwingMotorSettings;
  78. p.mToParent = settings;
  79. break;
  80. }
  81. case EConstraintOverride::TypeCone:
  82. {
  83. ConeConstraintSettings *settings = new ConeConstraintSettings();
  84. settings->mPoint1 = original->mPosition1;
  85. settings->mTwistAxis1 = original->mTwistAxis1;
  86. settings->mPoint2 = original->mPosition2;
  87. settings->mTwistAxis2 = original->mTwistAxis2;
  88. settings->mHalfConeAngle = original->mNormalHalfConeAngle;
  89. p.mToParent = settings;
  90. break;
  91. }
  92. case EConstraintOverride::TypeRagdoll:
  93. break;
  94. }
  95. }
  96. // Initialize the skeleton
  97. ragdoll->GetSkeleton()->CalculateParentJointIndices();
  98. // Stabilize the constraints of the ragdoll
  99. ragdoll->Stabilize();
  100. // Optional: Calculate constraint priorities to give more priority to the root
  101. ragdoll->CalculateConstraintPriorities();
  102. // Calculate body <-> constraint map
  103. ragdoll->CalculateBodyIndexToConstraintIndex();
  104. ragdoll->CalculateConstraintIndexToBodyIdxPair();
  105. return ragdoll;
  106. }
  107. #endif // JPH_OBJECT_STREAM
  108. RagdollSettings *RagdollLoader::sCreate()
  109. {
  110. // Create skeleton
  111. Ref<Skeleton> skeleton = new Skeleton;
  112. uint lower_body = skeleton->AddJoint("LowerBody");
  113. uint mid_body = skeleton->AddJoint("MidBody", lower_body);
  114. uint upper_body = skeleton->AddJoint("UpperBody", mid_body);
  115. /*uint head =*/ skeleton->AddJoint("Head", upper_body);
  116. uint upper_arm_l = skeleton->AddJoint("UpperArmL", upper_body);
  117. uint upper_arm_r = skeleton->AddJoint("UpperArmR", upper_body);
  118. /*uint lower_arm_l =*/ skeleton->AddJoint("LowerArmL", upper_arm_l);
  119. /*uint lower_arm_r =*/ skeleton->AddJoint("LowerArmR", upper_arm_r);
  120. uint upper_leg_l = skeleton->AddJoint("UpperLegL", lower_body);
  121. uint upper_leg_r = skeleton->AddJoint("UpperLegR", lower_body);
  122. /*uint lower_leg_l =*/ skeleton->AddJoint("LowerLegL", upper_leg_l);
  123. /*uint lower_leg_r =*/ skeleton->AddJoint("LowerLegR", upper_leg_r);
  124. // Create shapes for limbs
  125. Ref<Shape> shapes[] = {
  126. new CapsuleShape(0.15f, 0.10f), // Lower Body
  127. new CapsuleShape(0.15f, 0.10f), // Mid Body
  128. new CapsuleShape(0.15f, 0.10f), // Upper Body
  129. new CapsuleShape(0.075f, 0.10f), // Head
  130. new CapsuleShape(0.15f, 0.06f), // Upper Arm L
  131. new CapsuleShape(0.15f, 0.06f), // Upper Arm R
  132. new CapsuleShape(0.15f, 0.05f), // Lower Arm L
  133. new CapsuleShape(0.15f, 0.05f), // Lower Arm R
  134. new CapsuleShape(0.2f, 0.075f), // Upper Leg L
  135. new CapsuleShape(0.2f, 0.075f), // Upper Leg R
  136. new CapsuleShape(0.2f, 0.06f), // Lower Leg L
  137. new CapsuleShape(0.2f, 0.06f), // Lower Leg R
  138. };
  139. // Positions of body parts in world space
  140. RVec3 positions[] = {
  141. RVec3(0, 1.15f, 0), // Lower Body
  142. RVec3(0, 1.35f, 0), // Mid Body
  143. RVec3(0, 1.55f, 0), // Upper Body
  144. RVec3(0, 1.825f, 0), // Head
  145. RVec3(-0.425f, 1.55f, 0), // Upper Arm L
  146. RVec3(0.425f, 1.55f, 0), // Upper Arm R
  147. RVec3(-0.8f, 1.55f, 0), // Lower Arm L
  148. RVec3(0.8f, 1.55f, 0), // Lower Arm R
  149. RVec3(-0.15f, 0.8f, 0), // Upper Leg L
  150. RVec3(0.15f, 0.8f, 0), // Upper Leg R
  151. RVec3(-0.15f, 0.3f, 0), // Lower Leg L
  152. RVec3(0.15f, 0.3f, 0), // Lower Leg R
  153. };
  154. // Rotations of body parts in world space
  155. Quat rotations[] = {
  156. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Lower Body
  157. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Mid Body
  158. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Upper Body
  159. Quat::sIdentity(), // Head
  160. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Upper Arm L
  161. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Upper Arm R
  162. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Lower Arm L
  163. Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), // Lower Arm R
  164. Quat::sIdentity(), // Upper Leg L
  165. Quat::sIdentity(), // Upper Leg R
  166. Quat::sIdentity(), // Lower Leg L
  167. Quat::sIdentity() // Lower Leg R
  168. };
  169. // World space constraint positions
  170. RVec3 constraint_positions[] = {
  171. RVec3::sZero(), // Lower Body (unused, there's no parent)
  172. RVec3(0, 1.25f, 0), // Mid Body
  173. RVec3(0, 1.45f, 0), // Upper Body
  174. RVec3(0, 1.65f, 0), // Head
  175. RVec3(-0.225f, 1.55f, 0), // Upper Arm L
  176. RVec3(0.225f, 1.55f, 0), // Upper Arm R
  177. RVec3(-0.65f, 1.55f, 0), // Lower Arm L
  178. RVec3(0.65f, 1.55f, 0), // Lower Arm R
  179. RVec3(-0.15f, 1.05f, 0), // Upper Leg L
  180. RVec3(0.15f, 1.05f, 0), // Upper Leg R
  181. RVec3(-0.15f, 0.55f, 0), // Lower Leg L
  182. RVec3(0.15f, 0.55f, 0), // Lower Leg R
  183. };
  184. // World space twist axis directions
  185. Vec3 twist_axis[] = {
  186. Vec3::sZero(), // Lower Body (unused, there's no parent)
  187. Vec3::sAxisY(), // Mid Body
  188. Vec3::sAxisY(), // Upper Body
  189. Vec3::sAxisY(), // Head
  190. -Vec3::sAxisX(), // Upper Arm L
  191. Vec3::sAxisX(), // Upper Arm R
  192. -Vec3::sAxisX(), // Lower Arm L
  193. Vec3::sAxisX(), // Lower Arm R
  194. -Vec3::sAxisY(), // Upper Leg L
  195. -Vec3::sAxisY(), // Upper Leg R
  196. -Vec3::sAxisY(), // Lower Leg L
  197. -Vec3::sAxisY(), // Lower Leg R
  198. };
  199. // Constraint limits
  200. float twist_angle[] = {
  201. 0.0f, // Lower Body (unused, there's no parent)
  202. 5.0f, // Mid Body
  203. 5.0f, // Upper Body
  204. 90.0f, // Head
  205. 45.0f, // Upper Arm L
  206. 45.0f, // Upper Arm R
  207. 45.0f, // Lower Arm L
  208. 45.0f, // Lower Arm R
  209. 45.0f, // Upper Leg L
  210. 45.0f, // Upper Leg R
  211. 45.0f, // Lower Leg L
  212. 45.0f, // Lower Leg R
  213. };
  214. float normal_angle[] = {
  215. 0.0f, // Lower Body (unused, there's no parent)
  216. 10.0f, // Mid Body
  217. 10.0f, // Upper Body
  218. 45.0f, // Head
  219. 90.0f, // Upper Arm L
  220. 90.0f, // Upper Arm R
  221. 0.0f, // Lower Arm L
  222. 0.0f, // Lower Arm R
  223. 45.0f, // Upper Leg L
  224. 45.0f, // Upper Leg R
  225. 0.0f, // Lower Leg L
  226. 0.0f, // Lower Leg R
  227. };
  228. float plane_angle[] = {
  229. 0.0f, // Lower Body (unused, there's no parent)
  230. 10.0f, // Mid Body
  231. 10.0f, // Upper Body
  232. 45.0f, // Head
  233. 45.0f, // Upper Arm L
  234. 45.0f, // Upper Arm R
  235. 90.0f, // Lower Arm L
  236. 90.0f, // Lower Arm R
  237. 45.0f, // Upper Leg L
  238. 45.0f, // Upper Leg R
  239. 60.0f, // Lower Leg L (cheating here, a knee is not symmetric, we should have rotated the twist axis)
  240. 60.0f, // Lower Leg R
  241. };
  242. // Create ragdoll settings
  243. RagdollSettings *settings = new RagdollSettings;
  244. settings->mSkeleton = skeleton;
  245. settings->mParts.resize(skeleton->GetJointCount());
  246. for (int p = 0; p < skeleton->GetJointCount(); ++p)
  247. {
  248. RagdollSettings::Part &part = settings->mParts[p];
  249. part.SetShape(shapes[p]);
  250. part.mPosition = positions[p];
  251. part.mRotation = rotations[p];
  252. part.mMotionType = EMotionType::Dynamic;
  253. part.mObjectLayer = Layers::MOVING;
  254. // First part is the root, doesn't have a parent and doesn't have a constraint
  255. if (p > 0)
  256. {
  257. SwingTwistConstraintSettings *constraint = new SwingTwistConstraintSettings;
  258. constraint->mDrawConstraintSize = 0.1f;
  259. constraint->mPosition1 = constraint->mPosition2 = constraint_positions[p];
  260. constraint->mTwistAxis1 = constraint->mTwistAxis2 = twist_axis[p];
  261. constraint->mPlaneAxis1 = constraint->mPlaneAxis2 = Vec3::sAxisZ();
  262. constraint->mTwistMinAngle = -DegreesToRadians(twist_angle[p]);
  263. constraint->mTwistMaxAngle = DegreesToRadians(twist_angle[p]);
  264. constraint->mNormalHalfConeAngle = DegreesToRadians(normal_angle[p]);
  265. constraint->mPlaneHalfConeAngle = DegreesToRadians(plane_angle[p]);
  266. part.mToParent = constraint;
  267. }
  268. }
  269. // Optional: Stabilize the inertia of the limbs
  270. settings->Stabilize();
  271. // Optional: Calculate constraint priorities to give more priority to the root
  272. settings->CalculateConstraintPriorities();
  273. // Disable parent child collisions so that we don't get collisions between constrained bodies
  274. settings->DisableParentChildCollisions();
  275. // Calculate the map needed for GetBodyIndexToConstraintIndex()
  276. settings->CalculateBodyIndexToConstraintIndex();
  277. return settings;
  278. }