SoftBodyMotionProperties.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2023 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Geometry/AABox.h>
  6. #include <Jolt/Physics/Body/BodyID.h>
  7. #include <Jolt/Physics/Body/MotionProperties.h>
  8. #include <Jolt/Physics/SoftBody/SoftBodySharedSettings.h>
  9. #include <Jolt/Physics/SoftBody/SoftBodyVertex.h>
  10. #include <Jolt/Physics/SoftBody/SoftBodyUpdateContext.h>
  11. JPH_NAMESPACE_BEGIN
  12. class PhysicsSystem;
  13. struct PhysicsSettings;
  14. class Body;
  15. class Shape;
  16. class SoftBodyCreationSettings;
  17. #ifdef JPH_DEBUG_RENDERER
  18. class DebugRenderer;
  19. #endif // JPH_DEBUG_RENDERER
  20. /// This class contains the runtime information of a soft body.
  21. //
  22. // Based on: XPBD, Extended Position Based Dynamics, Matthias Muller, Ten Minute Physics
  23. // See: https://matthias-research.github.io/pages/tenMinutePhysics/09-xpbd.pdf
  24. class JPH_EXPORT SoftBodyMotionProperties : public MotionProperties
  25. {
  26. public:
  27. using Vertex = SoftBodyVertex;
  28. using Edge = SoftBodySharedSettings::Edge;
  29. using Face = SoftBodySharedSettings::Face;
  30. using Volume = SoftBodySharedSettings::Volume;
  31. /// Initialize the soft body motion properties
  32. void Initialize(const SoftBodyCreationSettings &inSettings);
  33. /// Get the shared settings of the soft body
  34. const SoftBodySharedSettings * GetSettings() const { return mSettings; }
  35. /// Get the vertices of the soft body
  36. const Array<Vertex> & GetVertices() const { return mVertices; }
  37. Array<Vertex> & GetVertices() { return mVertices; }
  38. /// Access an individual vertex
  39. const Vertex & GetVertex(uint inIndex) const { return mVertices[inIndex]; }
  40. Vertex & GetVertex(uint inIndex) { return mVertices[inIndex]; }
  41. /// Get the materials of the soft body
  42. const PhysicsMaterialList & GetMaterials() const { return mSettings->mMaterials; }
  43. /// Get the faces of the soft body
  44. const Array<Face> & GetFaces() const { return mSettings->mFaces; }
  45. /// Access to an individual face
  46. const Face & GetFace(uint inIndex) const { return mSettings->mFaces[inIndex]; }
  47. /// Get the number of solver iterations
  48. uint32 GetNumIterations() const { return mNumIterations; }
  49. void SetNumIterations(uint32 inNumIterations) { mNumIterations = inNumIterations; }
  50. /// Get the pressure of the soft body
  51. float GetPressure() const { return mPressure; }
  52. void SetPressure(float inPressure) { mPressure = inPressure; }
  53. /// Update the position of the body while simulating (set to false for something that is attached to the static world)
  54. bool GetUpdatePosition() const { return mUpdatePosition; }
  55. void SetUpdatePosition(bool inUpdatePosition) { mUpdatePosition = inUpdatePosition; }
  56. /// Get local bounding box
  57. const AABox & GetLocalBounds() const { return mLocalBounds; }
  58. /// Get the volume of the soft body. Note can become negative if the shape is inside out!
  59. float GetVolume() const { return GetVolumeTimesSix() / 6.0f; }
  60. /// Calculate the total mass and inertia of this body based on the current state of the vertices
  61. void CalculateMassAndInertia();
  62. #ifdef JPH_DEBUG_RENDERER
  63. /// Draw the state of a soft body
  64. void DrawVertices(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
  65. void DrawEdgeConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
  66. void DrawVolumeConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
  67. void DrawPredictedBounds(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
  68. #endif // JPH_DEBUG_RENDERER
  69. /// Saving state for replay
  70. void SaveState(StateRecorder &inStream) const;
  71. /// Restoring state for replay
  72. void RestoreState(StateRecorder &inStream);
  73. /// Initialize the update context (used internally by the PhysicsSystem)
  74. void InitializeUpdateContext(float inDeltaTime, Body &inSoftBody, const PhysicsSystem &inSystem, SoftBodyUpdateContext &ioContext);
  75. /// Do a broad phase check and collect all bodies that can possibly collide with this soft body
  76. void DetermineCollidingShapes(const SoftBodyUpdateContext &inContext, const PhysicsSystem &inSystem);
  77. /// Return code for ParallelUpdate
  78. enum class EStatus
  79. {
  80. NoWork = 1 << 0, ///< No work was done because other threads were still working on a batch that cannot run concurrently
  81. DidWork = 1 << 1, ///< Work was done to progress the update
  82. Done = 1 << 2, ///< All work is done
  83. };
  84. /// Update the soft body, will process a batch of work. Used internally.
  85. EStatus ParallelUpdate(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings);
  86. /// Update the velocities of all rigid bodies that we collided with. Used internally.
  87. void UpdateRigidBodyVelocities(const SoftBodyUpdateContext &inContext, PhysicsSystem &inSystem);
  88. private:
  89. // Collect information about the colliding bodies
  90. struct CollidingShape
  91. {
  92. /// Get the velocity of a point on this body
  93. Vec3 GetPointVelocity(Vec3Arg inPointRelativeToCOM) const
  94. {
  95. return mLinearVelocity + mAngularVelocity.Cross(inPointRelativeToCOM);
  96. }
  97. Mat44 mCenterOfMassTransform; ///< Transform of the body relative to the soft body
  98. RefConst<Shape> mShape; ///< Shape of the body we hit
  99. BodyID mBodyID; ///< Body ID of the body we hit
  100. EMotionType mMotionType; ///< Motion type of the body we hit
  101. float mInvMass; ///< Inverse mass of the body we hit
  102. float mFriction; ///< Combined friction of the two bodies
  103. float mRestitution; ///< Combined restitution of the two bodies
  104. bool mUpdateVelocities; ///< If the linear/angular velocity changed and the body needs to be updated
  105. Mat44 mInvInertia; ///< Inverse inertia in local space to the soft body
  106. Vec3 mLinearVelocity; ///< Linear velocity of the body in local space to the soft body
  107. Vec3 mAngularVelocity; ///< Angular velocity of the body in local space to the soft body
  108. Vec3 mOriginalLinearVelocity; ///< Linear velocity of the body in local space to the soft body at start
  109. Vec3 mOriginalAngularVelocity; ///< Angular velocity of the body in local space to the soft body at start
  110. };
  111. /// Do a narrow phase check and determine the closest feature that we can collide with
  112. void DetermineCollisionPlanes(const SoftBodyUpdateContext &inContext, uint inVertexStart, uint inNumVertices);
  113. /// Apply pressure force and update the vertex velocities
  114. void ApplyPressure(const SoftBodyUpdateContext &inContext);
  115. /// Integrate the positions of all vertices by 1 sub step
  116. void IntegratePositions(const SoftBodyUpdateContext &inContext);
  117. /// Enforce all volume constraints
  118. void ApplyVolumeConstraints(const SoftBodyUpdateContext &inContext);
  119. /// Enforce all edge constraints
  120. void ApplyEdgeConstraints(const SoftBodyUpdateContext &inContext, uint inStartIndex, uint inEndIndex);
  121. /// Enforce all collision constraints & update all velocities according the the XPBD algorithm
  122. void ApplyCollisionConstraintsAndUpdateVelocities(const SoftBodyUpdateContext &inContext);
  123. /// Update the state of the soft body (position, velocity, bounds)
  124. void UpdateSoftBodyState(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings);
  125. /// Executes tasks that need to run on the start of an iteration (i.e. the stuff that can't run in parallel)
  126. void StartNextIteration(const SoftBodyUpdateContext &ioContext);
  127. /// Helper function for ParallelUpdate that works on batches of collision planes
  128. EStatus ParallelDetermineCollisionPlanes(SoftBodyUpdateContext &ioContext);
  129. /// Helper function for ParallelUpdate that works on batches of edges
  130. EStatus ParallelApplyEdgeConstraints(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings);
  131. /// Returns 6 times the volume of the soft body
  132. float GetVolumeTimesSix() const;
  133. RefConst<SoftBodySharedSettings> mSettings; ///< Configuration of the particles and constraints
  134. Array<Vertex> mVertices; ///< Current state of all vertices in the simulation
  135. Array<CollidingShape> mCollidingShapes; ///< List of colliding shapes retrieved during the last update
  136. AABox mLocalBounds; ///< Bounding box of all vertices
  137. AABox mLocalPredictedBounds; ///< Predicted bounding box for all vertices using extrapolation of velocity by last step delta time
  138. uint32 mNumIterations; ///< Number of solver iterations
  139. float mPressure; ///< n * R * T, amount of substance * ideal gass constant * absolute temperature, see https://en.wikipedia.org/wiki/Pressure
  140. bool mUpdatePosition; ///< Update the position of the body while simulating (set to false for something that is attached to the static world)
  141. };
  142. JPH_NAMESPACE_END