ConvexHullShape.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Physics/Collision/Shape/ConvexShape.h>
  6. #include <Jolt/Physics/PhysicsSettings.h>
  7. #include <Jolt/Geometry/Plane.h>
  8. #ifdef JPH_DEBUG_RENDERER
  9. #include <Jolt/Renderer/DebugRenderer.h>
  10. #endif // JPH_DEBUG_RENDERER
  11. JPH_NAMESPACE_BEGIN
  12. /// Class that constructs a ConvexHullShape
  13. class ConvexHullShapeSettings final : public ConvexShapeSettings
  14. {
  15. public:
  16. JPH_DECLARE_SERIALIZABLE_VIRTUAL(ConvexHullShapeSettings)
  17. /// Default constructor for deserialization
  18. ConvexHullShapeSettings() = default;
  19. /// Create a convex hull from inPoints and maximum convex radius inMaxConvexRadius, the radius is automatically lowered if the hull requires it.
  20. /// (internally this will be subtracted so the total size will not grow with the convex radius).
  21. ConvexHullShapeSettings(const Vec3 *inPoints, int inNumPoints, float inMaxConvexRadius = cDefaultConvexRadius, const PhysicsMaterial *inMaterial = nullptr) : ConvexShapeSettings(inMaterial), mPoints(inPoints, inPoints + inNumPoints), mMaxConvexRadius(inMaxConvexRadius) { }
  22. ConvexHullShapeSettings(const Array<Vec3> &inPoints, float inConvexRadius = cDefaultConvexRadius, const PhysicsMaterial *inMaterial = nullptr) : ConvexShapeSettings(inMaterial), mPoints(inPoints), mMaxConvexRadius(inConvexRadius) { }
  23. // See: ShapeSettings
  24. virtual ShapeResult Create() const override;
  25. Array<Vec3> mPoints; ///< Points to create the hull from
  26. float mMaxConvexRadius = 0.0f; ///< Convex radius as supplied by the constructor. Note that during hull creation the convex radius can be made smaller if the value is too big for the hull.
  27. float mMaxErrorConvexRadius = 0.05f; ///< Maximum distance between the shrunk hull + convex radius and the actual hull.
  28. float mHullTolerance = 1.0e-3f; ///< Points are allowed this far outside of the hull (increasing this yields a hull with less vertices). Note that the actual used value can be larger if the points of the hull are far apart.
  29. };
  30. /// A convex hull
  31. class ConvexHullShape final : public ConvexShape
  32. {
  33. public:
  34. JPH_OVERRIDE_NEW_DELETE
  35. /// Maximum amount of points supported in a convex hull. Note that while constructing a hull, interior points are discarded so you can provide more points.
  36. /// The ConvexHullShapeSettings::Create function will return an error when too many points are provided.
  37. static constexpr int cMaxPointsInHull = 256;
  38. /// Constructor
  39. ConvexHullShape() : ConvexShape(EShapeSubType::ConvexHull) { }
  40. ConvexHullShape(const ConvexHullShapeSettings &inSettings, ShapeResult &outResult);
  41. // See Shape::GetCenterOfMass
  42. virtual Vec3 GetCenterOfMass() const override { return mCenterOfMass; }
  43. // See Shape::GetLocalBounds
  44. virtual AABox GetLocalBounds() const override { return mLocalBounds; }
  45. // See Shape::GetInnerRadius
  46. virtual float GetInnerRadius() const override { return mInnerRadius; }
  47. // See Shape::GetMassProperties
  48. virtual MassProperties GetMassProperties() const override;
  49. // See Shape::GetSurfaceNormal
  50. virtual Vec3 GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
  51. // See Shape::GetSupportingFace
  52. virtual void GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
  53. // See ConvexShape::GetSupportFunction
  54. virtual const Support * GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
  55. // See Shape::GetSubmergedVolume
  56. virtual void GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const override;
  57. #ifdef JPH_DEBUG_RENDERER
  58. // See Shape::Draw
  59. virtual void Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
  60. /// Debugging helper draw function that draws how all points are moved when a shape is shrunk by the convex radius
  61. void DrawShrunkShape(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale) const;
  62. #endif // JPH_DEBUG_RENDERER
  63. // See Shape::CastRay
  64. virtual bool CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
  65. virtual void CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
  66. // See: Shape::CollidePoint
  67. virtual void CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
  68. // See Shape::GetTrianglesStart
  69. virtual void GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const override;
  70. // See Shape::GetTrianglesNext
  71. virtual int GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;
  72. // See Shape
  73. virtual void SaveBinaryState(StreamOut &inStream) const override;
  74. // See Shape::GetStats
  75. virtual Stats GetStats() const override;
  76. // See Shape::GetVolume
  77. virtual float GetVolume() const override { return mVolume; }
  78. /// Get the convex radius of this convex hull
  79. float GetConvexRadius() const { return mConvexRadius; }
  80. /// Get the planes of this convex hull
  81. const Array<Plane> & GetPlanes() const { return mPlanes; }
  82. /// Get the number of vertices in this convex hull
  83. inline uint GetNumPoints() const { return (uint)mPoints.size(); }
  84. /// Get a vertex of this convex hull relative to the center of mass
  85. inline Vec3 GetPoint(uint inIndex) const { return mPoints[inIndex].mPosition; }
  86. /// Get the number of faces in this convex hull
  87. inline uint GetNumFaces() const { return (uint)mFaces.size(); }
  88. /// Get the number of vertices in a face
  89. inline uint GetNumVerticesInFace(uint inFaceIndex) const { return mFaces[inFaceIndex].mNumVertices; }
  90. /// Get the vertices indices of a face
  91. /// @param inFaceIndex Index of the face.
  92. /// @param inMaxVertices Maximum number of vertices to return.
  93. /// @param outVertices Array of vertices indices, must be at least inMaxVertices in size, the vertices are returned in counter clockwise order and the positions can be obtained using GetPoint(index).
  94. /// @return Number of vertices in face, if this is bigger than inMaxVertices, not all vertices were retrieved.
  95. inline uint GetFaceVertices(uint inFaceIndex, uint inMaxVertices, uint *outVertices) const
  96. {
  97. const Face &face = mFaces[inFaceIndex];
  98. const uint8 *first_vertex = mVertexIdx.data() + face.mFirstVertex;
  99. uint num_vertices = min<uint>(face.mNumVertices, inMaxVertices);
  100. for (uint i = 0; i < num_vertices; ++i)
  101. outVertices[i] = first_vertex[i];
  102. return face.mNumVertices;
  103. }
  104. // Register shape functions with the registry
  105. static void sRegister();
  106. #ifdef JPH_DEBUG_RENDERER
  107. /// Draw the outlines of the faces of the convex hull when drawing the shape
  108. inline static bool sDrawFaceOutlines = false;
  109. #endif // JPH_DEBUG_RENDERER
  110. protected:
  111. // See: Shape::RestoreBinaryState
  112. virtual void RestoreBinaryState(StreamIn &inStream) override;
  113. private:
  114. /// Helper function that returns the min and max fraction along the ray that hits the convex hull. Returns false if there is no hit.
  115. bool CastRayHelper(const RayCast &inRay, float &outMinFraction, float &outMaxFraction) const;
  116. /// Class for GetTrianglesStart/Next
  117. class CHSGetTrianglesContext;
  118. /// Classes for GetSupportFunction
  119. class HullNoConvex;
  120. class HullWithConvex;
  121. class HullWithConvexScaled;
  122. struct Face
  123. {
  124. uint16 mFirstVertex; ///< First index in mVertexIdx to use
  125. uint16 mNumVertices = 0; ///< Number of vertices in the mVertexIdx to use
  126. };
  127. static_assert(sizeof(Face) == 4, "Unexpected size");
  128. static_assert(alignof(Face) == 2, "Unexpected alignment");
  129. struct Point
  130. {
  131. Vec3 mPosition; ///< Position of vertex
  132. int mNumFaces = 0; ///< Number of faces in the face array below
  133. int mFaces[3] = { -1, -1, -1 }; ///< Indices of 3 neighboring faces with the biggest difference in normal (used to shift vertices for convex radius)
  134. };
  135. static_assert(sizeof(Point) == 32, "Unexpected size");
  136. static_assert(alignof(Point) == JPH_VECTOR_ALIGNMENT, "Unexpected alignment");
  137. Vec3 mCenterOfMass; ///< Center of mass of this convex hull
  138. Mat44 mInertia; ///< Inertia matrix assuming density is 1 (needs to be multiplied by density)
  139. AABox mLocalBounds; ///< Local bounding box for the convex hull
  140. Array<Point> mPoints; ///< Points on the convex hull surface
  141. Array<Face> mFaces; ///< Faces of the convex hull surface
  142. Array<Plane> mPlanes; ///< Planes for the faces (1-on-1 with mFaces array, separate because they need to be 16 byte aligned)
  143. Array<uint8> mVertexIdx; ///< A list of vertex indices (indexing in mPoints) for each of the faces
  144. float mConvexRadius = 0.0f; ///< Convex radius
  145. float mVolume; ///< Total volume of the convex hull
  146. float mInnerRadius = FLT_MAX; ///< Radius of the biggest sphere that fits entirely in the convex hull
  147. #ifdef JPH_DEBUG_RENDERER
  148. mutable DebugRenderer::GeometryRef mGeometry;
  149. #endif // JPH_DEBUG_RENDERER
  150. };
  151. JPH_NAMESPACE_END