Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/MeshShape.h
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Physics/Collision/Shape/Shape.h>
8
#include <Jolt/Physics/Collision/PhysicsMaterial.h>
9
#include <Jolt/Core/ByteBuffer.h>
10
#include <Jolt/Geometry/Triangle.h>
11
#include <Jolt/Geometry/IndexedTriangle.h>
12
#ifdef JPH_DEBUG_RENDERER
13
#include <Jolt/Renderer/DebugRenderer.h>
14
#endif // JPH_DEBUG_RENDERER
15
16
JPH_NAMESPACE_BEGIN
17
18
class ConvexShape;
19
class CollideShapeSettings;
20
21
/// Class that constructs a MeshShape
22
class JPH_EXPORT MeshShapeSettings final : public ShapeSettings
23
{
24
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, MeshShapeSettings)
25
26
public:
27
/// Default constructor for deserialization
28
MeshShapeSettings() = default;
29
30
/// Create a mesh shape.
31
MeshShapeSettings(const TriangleList &inTriangles, PhysicsMaterialList inMaterials = PhysicsMaterialList());
32
MeshShapeSettings(VertexList inVertices, IndexedTriangleList inTriangles, PhysicsMaterialList inMaterials = PhysicsMaterialList());
33
34
/// Sanitize the mesh data. Remove duplicate and degenerate triangles. This is called automatically when constructing the MeshShapeSettings with a list of (indexed-) triangles.
35
void Sanitize();
36
37
// See: ShapeSettings
38
virtual ShapeResult Create() const override;
39
40
/// Vertices belonging to mIndexedTriangles
41
VertexList mTriangleVertices;
42
43
/// Original list of indexed triangles (triangles will be reordered internally in the mesh shape).
44
/// Triangles must be provided in counter clockwise order.
45
/// Degenerate triangles will automatically be removed during mesh creation but no other mesh simplifications are performed, use an external library if this is desired.
46
/// For simulation, the triangles are considered to be single sided.
47
/// For ray casts you can choose to make triangles double sided by setting RayCastSettings::mBackFaceMode to EBackFaceMode::CollideWithBackFaces.
48
/// For collide shape tests you can use CollideShapeSettings::mBackFaceMode and for shape casts you can use ShapeCastSettings::mBackFaceModeTriangles.
49
IndexedTriangleList mIndexedTriangles;
50
51
/// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex
52
PhysicsMaterialList mMaterials;
53
54
/// 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].
55
/// Sensible values are between 4 (for better performance) and 8 (for less memory usage).
56
uint mMaxTrianglesPerLeaf = 8;
57
58
/// 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).
59
/// Setting this value too small can cause ghost collisions with edges, setting it too big can cause depenetration artifacts (objects not depenetrating quickly).
60
/// Valid ranges are between cos(0 degrees) and cos(90 degrees). The default value is cos(5 degrees).
61
/// Negative values will make all edges active and causes EActiveEdgeMode::CollideOnlyWithActive to behave as EActiveEdgeMode::CollideWithAll.
62
/// This speeds up the build process but will require all bodies that can interact with the mesh to use BodyCreationSettings::mEnhancedInternalEdgeRemoval = true.
63
float mActiveEdgeCosThresholdAngle = 0.996195f; // cos(5 degrees)
64
65
/// When true, we store the user data coming from Triangle::mUserData or IndexedTriangle::mUserData in the mesh shape.
66
/// This can be used to store additional data like the original index of the triangle in the mesh.
67
/// Can be retrieved using MeshShape::GetTriangleUserData.
68
/// Turning this on increases the memory used by the MeshShape by roughly 25%.
69
bool mPerTriangleUserData = false;
70
71
enum class EBuildQuality
72
{
73
FavorRuntimePerformance, ///< Favor runtime performance, takes more time to build the MeshShape but performs better
74
FavorBuildSpeed, ///< Favor build speed, build the tree faster but the MeshShape will be slower
75
};
76
77
/// Determines the quality of the tree building process.
78
EBuildQuality mBuildQuality = EBuildQuality::FavorRuntimePerformance;
79
};
80
81
/// A mesh shape, consisting of triangles. Mesh shapes are mostly used for static geometry.
82
/// 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.
83
/// 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.
84
class JPH_EXPORT MeshShape final : public Shape
85
{
86
public:
87
JPH_OVERRIDE_NEW_DELETE
88
89
/// Constructor
90
MeshShape() : Shape(EShapeType::Mesh, EShapeSubType::Mesh) { }
91
MeshShape(const MeshShapeSettings &inSettings, ShapeResult &outResult);
92
93
// See Shape::MustBeStatic
94
virtual bool MustBeStatic() const override { return true; }
95
96
// See Shape::GetLocalBounds
97
virtual AABox GetLocalBounds() const override;
98
99
// See Shape::GetSubShapeIDBitsRecursive
100
virtual uint GetSubShapeIDBitsRecursive() const override;
101
102
// See Shape::GetInnerRadius
103
virtual float GetInnerRadius() const override { return 0.0f; }
104
105
// See Shape::GetMassProperties
106
virtual MassProperties GetMassProperties() const override;
107
108
// See Shape::GetMaterial
109
virtual const PhysicsMaterial * GetMaterial(const SubShapeID &inSubShapeID) const override;
110
111
/// Get the list of all materials
112
const PhysicsMaterialList & GetMaterialList() const { return mMaterials; }
113
114
/// 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)
115
/// 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.
116
uint GetMaterialIndex(const SubShapeID &inSubShapeID) const;
117
118
// See Shape::GetSurfaceNormal
119
virtual Vec3 GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
120
121
// See Shape::GetSupportingFace
122
virtual void GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
123
124
#ifdef JPH_DEBUG_RENDERER
125
// See Shape::Draw
126
virtual void Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
127
#endif // JPH_DEBUG_RENDERER
128
129
// See Shape::CastRay
130
virtual bool CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
131
virtual void CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
132
133
/// See: Shape::CollidePoint
134
/// 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.
135
/// 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.
136
virtual void CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
137
138
// See: Shape::CollideSoftBodyVertices
139
virtual void CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const override;
140
141
// See Shape::GetTrianglesStart
142
virtual void GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const override;
143
144
// See Shape::GetTrianglesNext
145
virtual int GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;
146
147
// See Shape::GetSubmergedVolume
148
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"); }
149
150
// See Shape
151
virtual void SaveBinaryState(StreamOut &inStream) const override;
152
virtual void SaveMaterialState(PhysicsMaterialList &outMaterials) const override;
153
virtual void RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, uint inNumMaterials) override;
154
155
// See Shape::GetStats
156
virtual Stats GetStats() const override;
157
158
// See Shape::GetVolume
159
virtual float GetVolume() const override { return 0; }
160
161
// When MeshShape::mPerTriangleUserData is true, this function can be used to retrieve the user data that was stored in the mesh shape.
162
uint32 GetTriangleUserData(const SubShapeID &inSubShapeID) const;
163
164
#ifdef JPH_DEBUG_RENDERER
165
// Settings
166
static bool sDrawTriangleGroups;
167
static bool sDrawTriangleOutlines;
168
#endif // JPH_DEBUG_RENDERER
169
170
// Register shape functions with the registry
171
static void sRegister();
172
173
protected:
174
// See: Shape::RestoreBinaryState
175
virtual void RestoreBinaryState(StreamIn &inStream) override;
176
177
private:
178
struct MSGetTrianglesContext; ///< Context class for GetTrianglesStart/Next
179
180
static constexpr int NumTriangleBits = 3; ///< How many bits to reserve to encode the triangle index
181
static constexpr int MaxTrianglesPerLeaf = 1 << NumTriangleBits; ///< Number of triangles that are stored max per leaf aabb node
182
183
/// Find and flag active edges
184
static void sFindActiveEdges(const MeshShapeSettings &inSettings, IndexedTriangleList &ioIndices);
185
186
/// Visit the entire tree using a visitor pattern
187
template <class Visitor>
188
void WalkTree(Visitor &ioVisitor) const;
189
190
/// Same as above but with a callback per triangle instead of per block of triangles
191
template <class Visitor>
192
void WalkTreePerTriangle(const SubShapeIDCreator &inSubShapeIDCreator2, Visitor &ioVisitor) const;
193
194
/// Decode a sub shape ID
195
inline void DecodeSubShapeID(const SubShapeID &inSubShapeID, const void *&outTriangleBlock, uint32 &outTriangleIndex) const;
196
197
// Helper functions called by CollisionDispatch
198
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);
199
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);
200
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);
201
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);
202
203
/// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex
204
PhysicsMaterialList mMaterials;
205
206
ByteBuffer mTree; ///< Resulting packed data structure
207
208
/// 8 bit flags stored per triangle
209
enum ETriangleFlags
210
{
211
/// Material index
212
FLAGS_MATERIAL_BITS = 5,
213
FLAGS_MATERIAL_MASK = (1 << FLAGS_MATERIAL_BITS) - 1,
214
215
/// Active edge bits
216
FLAGS_ACTIVE_EGDE_SHIFT = FLAGS_MATERIAL_BITS,
217
FLAGS_ACTIVE_EDGE_BITS = 3,
218
FLAGS_ACTIVE_EDGE_MASK = (1 << FLAGS_ACTIVE_EDGE_BITS) - 1
219
};
220
221
#ifdef JPH_DEBUG_RENDERER
222
mutable DebugRenderer::GeometryRef mGeometry; ///< Debug rendering data
223
mutable bool mCachedTrianglesColoredPerGroup = false; ///< This is used to regenerate the triangle batch if the drawing settings change
224
mutable bool mCachedUseMaterialColors = false; ///< This is used to regenerate the triangle batch if the drawing settings change
225
#endif // JPH_DEBUG_RENDERER
226
};
227
228
JPH_NAMESPACE_END
229
230