BodyCreationSettings.cpp 7.7 KB

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