BodyCreationSettings.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #include <Jolt/Physics/Body/BodyCreationSettings.h>
  6. #include <Jolt/ObjectStream/TypeDeclarations.h>
  7. #include <Jolt/Core/StreamIn.h>
  8. #include <Jolt/Core/StreamOut.h>
  9. JPH_NAMESPACE_BEGIN
  10. JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(BodyCreationSettings)
  11. {
  12. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mPosition)
  13. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mRotation)
  14. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mLinearVelocity)
  15. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAngularVelocity)
  16. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mUserData)
  17. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mShape)
  18. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mCollisionGroup)
  19. JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mObjectLayer)
  20. JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mMotionType)
  21. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAllowDynamicOrKinematic)
  22. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mIsSensor)
  23. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mUseManifoldReduction)
  24. JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mMotionQuality)
  25. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAllowSleeping)
  26. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mFriction)
  27. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mRestitution)
  28. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mLinearDamping)
  29. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAngularDamping)
  30. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mMaxLinearVelocity)
  31. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mMaxAngularVelocity)
  32. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mGravityFactor)
  33. JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mOverrideMassProperties)
  34. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mInertiaMultiplier)
  35. JPH_ADD_ATTRIBUTE(BodyCreationSettings, mMassPropertiesOverride)
  36. }
  37. void BodyCreationSettings::SaveBinaryState(StreamOut &inStream) const
  38. {
  39. inStream.Write(mPosition);
  40. inStream.Write(mRotation);
  41. inStream.Write(mLinearVelocity);
  42. inStream.Write(mAngularVelocity);
  43. mCollisionGroup.SaveBinaryState(inStream);
  44. inStream.Write(mObjectLayer);
  45. inStream.Write(mMotionType);
  46. inStream.Write(mAllowDynamicOrKinematic);
  47. inStream.Write(mIsSensor);
  48. inStream.Write(mUseManifoldReduction);
  49. inStream.Write(mMotionQuality);
  50. inStream.Write(mAllowSleeping);
  51. inStream.Write(mFriction);
  52. inStream.Write(mRestitution);
  53. inStream.Write(mLinearDamping);
  54. inStream.Write(mAngularDamping);
  55. inStream.Write(mMaxLinearVelocity);
  56. inStream.Write(mMaxAngularVelocity);
  57. inStream.Write(mGravityFactor);
  58. inStream.Write(mOverrideMassProperties);
  59. inStream.Write(mInertiaMultiplier);
  60. mMassPropertiesOverride.SaveBinaryState(inStream);
  61. }
  62. void BodyCreationSettings::RestoreBinaryState(StreamIn &inStream)
  63. {
  64. inStream.Read(mPosition);
  65. inStream.Read(mRotation);
  66. inStream.Read(mLinearVelocity);
  67. inStream.Read(mAngularVelocity);
  68. mCollisionGroup.RestoreBinaryState(inStream);
  69. inStream.Read(mObjectLayer);
  70. inStream.Read(mMotionType);
  71. inStream.Read(mAllowDynamicOrKinematic);
  72. inStream.Read(mIsSensor);
  73. inStream.Read(mUseManifoldReduction);
  74. inStream.Read(mMotionQuality);
  75. inStream.Read(mAllowSleeping);
  76. inStream.Read(mFriction);
  77. inStream.Read(mRestitution);
  78. inStream.Read(mLinearDamping);
  79. inStream.Read(mAngularDamping);
  80. inStream.Read(mMaxLinearVelocity);
  81. inStream.Read(mMaxAngularVelocity);
  82. inStream.Read(mGravityFactor);
  83. inStream.Read(mOverrideMassProperties);
  84. inStream.Read(mInertiaMultiplier);
  85. mMassPropertiesOverride.RestoreBinaryState(inStream);
  86. }
  87. Shape::ShapeResult BodyCreationSettings::ConvertShapeSettings()
  88. {
  89. // If we already have a shape, return it
  90. if (mShapePtr != nullptr)
  91. {
  92. mShape = nullptr;
  93. Shape::ShapeResult result;
  94. result.Set(const_cast<Shape *>(mShapePtr.GetPtr()));
  95. return result;
  96. }
  97. // Check if we have shape settings
  98. if (mShape == nullptr)
  99. {
  100. Shape::ShapeResult result;
  101. result.SetError("No shape present!");
  102. return result;
  103. }
  104. // Create the shape
  105. Shape::ShapeResult result = mShape->Create();
  106. if (result.IsValid())
  107. mShapePtr = result.Get();
  108. mShape = nullptr;
  109. return result;
  110. }
  111. const Shape *BodyCreationSettings::GetShape() const
  112. {
  113. // If we already have a shape, return it
  114. if (mShapePtr != nullptr)
  115. return mShapePtr;
  116. // Check if we have shape settings
  117. if (mShape == nullptr)
  118. return nullptr;
  119. // Create the shape
  120. Shape::ShapeResult result = mShape->Create();
  121. if (result.IsValid())
  122. return result.Get();
  123. Trace("Error: %s", result.GetError().c_str());
  124. JPH_ASSERT(false, "An error occurred during shape creation. Use ConvertShapeSettings() to convert the shape and get the error!");
  125. return nullptr;
  126. }
  127. MassProperties BodyCreationSettings::GetMassProperties() const
  128. {
  129. // Calculate mass properties
  130. MassProperties mass_properties;
  131. switch (mOverrideMassProperties)
  132. {
  133. case EOverrideMassProperties::CalculateMassAndInertia:
  134. mass_properties = GetShape()->GetMassProperties();
  135. mass_properties.mInertia *= mInertiaMultiplier;
  136. mass_properties.mInertia(3, 3) = 1.0f;
  137. break;
  138. case EOverrideMassProperties::CalculateInertia:
  139. mass_properties = GetShape()->GetMassProperties();
  140. mass_properties.ScaleToMass(mMassPropertiesOverride.mMass);
  141. mass_properties.mInertia *= mInertiaMultiplier;
  142. mass_properties.mInertia(3, 3) = 1.0f;
  143. break;
  144. case EOverrideMassProperties::MassAndInertiaProvided:
  145. mass_properties = mMassPropertiesOverride;
  146. break;
  147. }
  148. return mass_properties;
  149. }
  150. void BodyCreationSettings::SaveWithChildren(StreamOut &inStream, ShapeToIDMap *ioShapeMap, MaterialToIDMap *ioMaterialMap, GroupFilterToIDMap *ioGroupFilterMap) const
  151. {
  152. // Save creation settings
  153. SaveBinaryState(inStream);
  154. // Save shape
  155. if (ioShapeMap != nullptr && ioMaterialMap != nullptr)
  156. GetShape()->SaveWithChildren(inStream, *ioShapeMap, *ioMaterialMap);
  157. else
  158. inStream.Write(~uint32(0));
  159. // Save group filter
  160. const GroupFilter *group_filter = mCollisionGroup.GetGroupFilter();
  161. if (ioGroupFilterMap == nullptr || group_filter == nullptr)
  162. {
  163. // Write null ID
  164. inStream.Write(~uint32(0));
  165. }
  166. else
  167. {
  168. GroupFilterToIDMap::const_iterator group_filter_id = ioGroupFilterMap->find(group_filter);
  169. if (group_filter_id != ioGroupFilterMap->end())
  170. {
  171. // Existing group filter, write ID
  172. inStream.Write(group_filter_id->second);
  173. }
  174. else
  175. {
  176. // New group filter, write the ID
  177. uint32 new_group_filter_id = (uint32)ioGroupFilterMap->size();
  178. (*ioGroupFilterMap)[group_filter] = new_group_filter_id;
  179. inStream.Write(new_group_filter_id);
  180. // Write the group filter
  181. group_filter->SaveBinaryState(inStream);
  182. }
  183. }
  184. }
  185. BodyCreationSettings::BCSResult BodyCreationSettings::sRestoreWithChildren(StreamIn &inStream, IDToShapeMap &ioShapeMap, IDToMaterialMap &ioMaterialMap, IDToGroupFilterMap &ioGroupFilterMap)
  186. {
  187. BCSResult result;
  188. // Read creation settings
  189. BodyCreationSettings settings;
  190. settings.RestoreBinaryState(inStream);
  191. if (inStream.IsEOF() || inStream.IsFailed())
  192. {
  193. result.SetError("Error reading body creation settings");
  194. return result;
  195. }
  196. // Read shape
  197. Shape::ShapeResult shape_result = Shape::sRestoreWithChildren(inStream, ioShapeMap, ioMaterialMap);
  198. if (shape_result.HasError())
  199. {
  200. result.SetError(shape_result.GetError());
  201. return result;
  202. }
  203. settings.SetShape(shape_result.Get());
  204. // Read group filter
  205. const GroupFilter *group_filter = nullptr;
  206. uint32 group_filter_id = ~uint32(0);
  207. inStream.Read(group_filter_id);
  208. if (group_filter_id != ~uint32(0))
  209. {
  210. // Check if it already exists
  211. if (group_filter_id >= ioGroupFilterMap.size())
  212. {
  213. // New group filter, restore it
  214. GroupFilter::GroupFilterResult group_filter_result = GroupFilter::sRestoreFromBinaryState(inStream);
  215. if (group_filter_result.HasError())
  216. {
  217. result.SetError(group_filter_result.GetError());
  218. return result;
  219. }
  220. group_filter = group_filter_result.Get();
  221. JPH_ASSERT(group_filter_id == ioGroupFilterMap.size());
  222. ioGroupFilterMap.push_back(group_filter);
  223. }
  224. else
  225. {
  226. // Existing group filter
  227. group_filter = ioGroupFilterMap[group_filter_id];
  228. }
  229. }
  230. // Set the group filter on the part
  231. settings.mCollisionGroup.SetGroupFilter(group_filter);
  232. result.Set(settings);
  233. return result;
  234. }
  235. JPH_NAMESPACE_END