BodyCreationSettings.cpp 7.3 KB

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