MeshShape.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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/Shape.h>
  6. #include <Jolt/Physics/Collision/PhysicsMaterial.h>
  7. #include <Jolt/Core/ByteBuffer.h>
  8. #include <Jolt/Geometry/Triangle.h>
  9. #include <Jolt/Geometry/IndexedTriangle.h>
  10. #ifdef JPH_DEBUG_RENDERER
  11. #include <Jolt/Renderer/DebugRenderer.h>
  12. #endif // JPH_DEBUG_RENDERER
  13. JPH_NAMESPACE_BEGIN
  14. class ConvexShape;
  15. class CollideShapeSettings;
  16. /// Class that constructs a MeshShape
  17. class JPH_EXPORT MeshShapeSettings final : public ShapeSettings
  18. {
  19. public:
  20. JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, MeshShapeSettings)
  21. /// Default constructor for deserialization
  22. MeshShapeSettings() = default;
  23. /// Create a mesh shape.
  24. MeshShapeSettings(const TriangleList &inTriangles, PhysicsMaterialList inMaterials = PhysicsMaterialList());
  25. MeshShapeSettings(VertexList inVertices, IndexedTriangleList inTriangles, PhysicsMaterialList inMaterials = PhysicsMaterialList());
  26. /// Sanitize the mesh data. Remove duplicate and degenerate triangles. This is called automatically when constructing the MeshShapeSettings with a list of (indexed-) triangles.
  27. void Sanitize();
  28. // See: ShapeSettings
  29. virtual ShapeResult Create() const override;
  30. /// Vertices belonging to mIndexedTriangles
  31. VertexList mTriangleVertices;
  32. /// Original list of indexed triangles (triangles will be reordered internally in the mesh shape).
  33. /// Triangles must be provided in counter clockwise order.
  34. /// For simulation, the triangles are considered to be single sided.
  35. /// For ray casts you can choose to make triangles double sided by setting RayCastSettings::mBackFaceMode to EBackFaceMode::CollideWithBackFaces.
  36. /// For collide shape tests you can use CollideShapeSettings::mBackFaceMode and for shape casts you can use ShapeCastSettings::mBackFaceModeTriangles.
  37. IndexedTriangleList mIndexedTriangles;
  38. /// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex
  39. PhysicsMaterialList mMaterials;
  40. /// Maximum number of triangles in each leaf of the axis aligned box tree. This is a balance between memory and performance. Can be in the range [1, MeshShape::MaxTrianglesPerLeaf].
  41. /// Sensible values are between 4 (for better performance) and 8 (for less memory usage).
  42. uint mMaxTrianglesPerLeaf = 8;
  43. /// Cosine of the threshold angle (if the angle between the two triangles is bigger than this, the edge is active, note that a concave edge is always inactive).
  44. /// Setting this value too small can cause ghost collisions with edges, setting it too big can cause depenetration artifacts (objects not depenetrating quickly).
  45. /// Valid ranges are between cos(0 degrees) and cos(90 degrees). The default value is cos(5 degrees).
  46. float mActiveEdgeCosThresholdAngle = 0.996195f; // cos(5 degrees)
  47. };
  48. /// A mesh shape, consisting of triangles. Mesh shapes are mostly used for static geometry.
  49. /// They can be used by dynamic or kinematic objects but only if they don't collide with other mesh or heightfield shapes as those collisions are currently not supported.
  50. /// Note that if you make a mesh shape a dynamic or kinematic object, you need to provide a mass yourself as mesh shapes don't need to form a closed hull so don't have a well defined volume from which the mass can be calculated.
  51. class JPH_EXPORT MeshShape final : public Shape
  52. {
  53. public:
  54. JPH_OVERRIDE_NEW_DELETE
  55. /// Constructor
  56. MeshShape() : Shape(EShapeType::Mesh, EShapeSubType::Mesh) { }
  57. MeshShape(const MeshShapeSettings &inSettings, ShapeResult &outResult);
  58. // See Shape::MustBeStatic
  59. virtual bool MustBeStatic() const override { return true; }
  60. // See Shape::GetLocalBounds
  61. virtual AABox GetLocalBounds() const override;
  62. // See Shape::GetSubShapeIDBitsRecursive
  63. virtual uint GetSubShapeIDBitsRecursive() const override;
  64. // See Shape::GetInnerRadius
  65. virtual float GetInnerRadius() const override { return 0.0f; }
  66. // See Shape::GetMassProperties
  67. virtual MassProperties GetMassProperties() const override;
  68. // See Shape::GetMaterial
  69. virtual const PhysicsMaterial * GetMaterial(const SubShapeID &inSubShapeID) const override;
  70. /// Get the list of all materials
  71. const PhysicsMaterialList & GetMaterialList() const { return mMaterials; }
  72. /// Determine which material index a particular sub shape uses (note that if there are no materials this function will return 0 so check the array size)
  73. /// Note: This could for example be used to create a decorator shape around a mesh shape that overrides the GetMaterial call to replace a material with another material.
  74. uint GetMaterialIndex(const SubShapeID &inSubShapeID) const;
  75. // See Shape::GetSurfaceNormal
  76. virtual Vec3 GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
  77. // See Shape::GetSupportingFace
  78. virtual void GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
  79. #ifdef JPH_DEBUG_RENDERER
  80. // See Shape::Draw
  81. virtual void Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
  82. #endif // JPH_DEBUG_RENDERER
  83. // See Shape::CastRay
  84. virtual bool CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
  85. virtual void CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
  86. /// See: Shape::CollidePoint
  87. /// Note that for CollidePoint to work for a mesh shape, the mesh needs to be closed (a manifold) or multiple non-intersecting manifolds. Triangles may be facing the interior of the manifold.
  88. /// Insideness is tested by counting the amount of triangles encountered when casting an infinite ray from inPoint. If the number of hits is odd we're inside, if it's even we're outside.
  89. virtual void CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
  90. // See: Shape::CollideSoftBodyVertices
  91. virtual void CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, SoftBodyVertex *ioVertices, uint inNumVertices, float inDeltaTime, Vec3Arg inDisplacementDueToGravity, int inCollidingShapeIndex) const override;
  92. // See Shape::GetTrianglesStart
  93. virtual void GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const override;
  94. // See Shape::GetTrianglesNext
  95. virtual int GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;
  96. // See Shape::GetSubmergedVolume
  97. virtual void GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const override { JPH_ASSERT(false, "Not supported"); }
  98. // See Shape
  99. virtual void SaveBinaryState(StreamOut &inStream) const override;
  100. virtual void SaveMaterialState(PhysicsMaterialList &outMaterials) const override;
  101. virtual void RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, uint inNumMaterials) override;
  102. // See Shape::GetStats
  103. virtual Stats GetStats() const override;
  104. // See Shape::GetVolume
  105. virtual float GetVolume() const override { return 0; }
  106. #ifdef JPH_DEBUG_RENDERER
  107. // Settings
  108. static bool sDrawTriangleGroups;
  109. static bool sDrawTriangleOutlines;
  110. #endif // JPH_DEBUG_RENDERER
  111. // Register shape functions with the registry
  112. static void sRegister();
  113. protected:
  114. // See: Shape::RestoreBinaryState
  115. virtual void RestoreBinaryState(StreamIn &inStream) override;
  116. private:
  117. struct MSGetTrianglesContext; ///< Context class for GetTrianglesStart/Next
  118. static constexpr int NumTriangleBits = 3; ///< How many bits to reserve to encode the triangle index
  119. static constexpr int MaxTrianglesPerLeaf = 1 << NumTriangleBits; ///< Number of triangles that are stored max per leaf aabb node
  120. /// Find and flag active edges
  121. static void sFindActiveEdges(const MeshShapeSettings &inSettings, IndexedTriangleList &ioIndices);
  122. /// Visit the entire tree using a visitor pattern
  123. template <class Visitor>
  124. void WalkTree(Visitor &ioVisitor) const;
  125. /// Same as above but with a callback per triangle instead of per block of triangles
  126. template <class Visitor>
  127. void WalkTreePerTriangle(const SubShapeIDCreator &inSubShapeIDCreator2, Visitor &ioVisitor) const;
  128. /// Decode a sub shape ID
  129. inline void DecodeSubShapeID(const SubShapeID &inSubShapeID, const void *&outTriangleBlock, uint32 &outTriangleIndex) const;
  130. // Helper functions called by CollisionDispatch
  131. static void sCollideConvexVsMesh(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);
  132. static void sCollideSphereVsMesh(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);
  133. static void sCastConvexVsMesh(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
  134. static void sCastSphereVsMesh(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
  135. /// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex
  136. PhysicsMaterialList mMaterials;
  137. ByteBuffer mTree; ///< Resulting packed data structure
  138. /// 8 bit flags stored per triangle
  139. enum ETriangleFlags
  140. {
  141. /// Material index
  142. FLAGS_MATERIAL_BITS = 5,
  143. FLAGS_MATERIAL_MASK = (1 << FLAGS_MATERIAL_BITS) - 1,
  144. /// Active edge bits
  145. FLAGS_ACTIVE_EGDE_SHIFT = FLAGS_MATERIAL_BITS,
  146. FLAGS_ACTIVE_EDGE_BITS = 3,
  147. FLAGS_ACTIVE_EDGE_MASK = (1 << FLAGS_ACTIVE_EDGE_BITS) - 1
  148. };
  149. #ifdef JPH_DEBUG_RENDERER
  150. mutable DebugRenderer::GeometryRef mGeometry; ///< Debug rendering data
  151. mutable bool mCachedTrianglesColoredPerGroup = false; ///< This is used to regenerate the triangle batch if the drawing settings change
  152. mutable bool mCachedUseMaterialColors = false; ///< This is used to regenerate the triangle batch if the drawing settings change
  153. #endif // JPH_DEBUG_RENDERER
  154. };
  155. JPH_NAMESPACE_END