1 /********************************************************************************
2 * ReactPhysics3D physics library, http://www.reactphysics3d.com *
3 * Copyright (c) 2010-2020 Daniel Chappuis *
4 *********************************************************************************
5 * *
6 * This software is provided 'as-is', without any express or implied warranty. *
7 * In no event will the authors be held liable for any damages arising from the *
8 * use of this software. *
9 * *
10 * Permission is granted to anyone to use this software for any purpose, *
11 * including commercial applications, and to alter it and redistribute it *
12 * freely, subject to the following restrictions: *
13 * *
14 * 1. The origin of this software must not be misrepresented; you must not claim *
15 * that you wrote the original software. If you use this software in a *
16 * product, an acknowledgment in the product documentation would be *
17 * appreciated but is not required. *
18 * *
19 * 2. Altered source versions must be plainly marked as such, and must not be *
20 * misrepresented as being the original software. *
21 * *
22 * 3. This notice may not be removed or altered from any source distribution. *
23 * *
24 ********************************************************************************/
25
26 #ifndef REACTPHYSICS3D_TRIANGLE_SHAPE_H
27 #define REACTPHYSICS3D_TRIANGLE_SHAPE_H
28
29 // Libraries
30 #include <reactphysics3d/mathematics/mathematics.h>
31 #include <reactphysics3d/collision/shapes/ConvexPolyhedronShape.h>
32
33 /// ReactPhysics3D namespace
34 namespace reactphysics3d {
35
36 /// Raycast test side for the triangle
37 enum class TriangleRaycastSide {
38
39 /// Raycast against front triangle
40 FRONT,
41
42 /// Raycast against back triangle
43 BACK,
44
45 /// Raycast against front and back triangle
46 FRONT_AND_BACK
47 };
48
49 // Class TriangleShape
50 /**
51 * This class represents a triangle collision shape that is centered
52 * at the origin and defined three points. A user cannot instanciate
53 * an object of this class. This class is for internal use only. Instances
54 * of this class are created when the user creates an HeightFieldShape and
55 * a ConcaveMeshShape
56 */
57 class TriangleShape : public ConvexPolyhedronShape {
58
59 protected:
60
61 // -------------------- Attribute -------------------- //
62
63
64 /// Three points of the triangle
65 Vector3 mPoints[3];
66
67 /// Normal of the triangle
68 Vector3 mNormal;
69
70 /// Three vertices normals for smooth collision with triangle mesh
71 Vector3 mVerticesNormals[3];
72
73 /// Raycast test type for the triangle (front, back, front-back)
74 TriangleRaycastSide mRaycastTestType;
75
76 /// Faces information for the two faces of the triangle
77 HalfEdgeStructure::Face mFaces[2];
78
79 /// Edges information for the six edges of the triangle
80 HalfEdgeStructure::Edge mEdges[6];
81
82 // -------------------- Methods -------------------- //
83
84 /// Return a local support point in a given direction without the object margin
85 virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction) const override;
86
87 /// Get a smooth contact normal for collision for a triangle of the mesh
88 Vector3 computeSmoothLocalContactNormalForTriangle(const Vector3& localContactPoint) const;
89
90 /// Return true if a point is inside the collider
91 virtual bool testPointInside(const Vector3& localPoint, Collider* collider) const override;
92
93 /// Raycast method with feedback information
94 virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider,
95 MemoryAllocator& allocator) const override;
96
97 /// Return the number of bytes used by the collision shape
98 virtual size_t getSizeInBytes() const override;
99
100 /// Generate the id of the shape (used for temporal coherence)
101 void generateId();
102
103 // -------------------- Methods -------------------- //
104
105 /// This method implements the technique described in Game Physics Pearl book
106 void computeSmoothMeshContact(Vector3 localContactPointTriangle, const Transform& triangleShapeToWorldTransform,
107 const Transform& worldToOtherShapeTransform, decimal penetrationDepth, bool isTriangleShape1,
108 Vector3& outNewLocalContactPointOtherShape, Vector3& outSmoothWorldContactTriangleNormal) const;
109
110 /// Constructor
111 TriangleShape(const Vector3* vertices, const Vector3* verticesNormals,
112 uint shapeId, MemoryAllocator& allocator);
113
114 /// Destructor
115 virtual ~TriangleShape() override = default;
116
117 public:
118
119 // -------------------- Methods -------------------- //
120
121 /// Deleted copy-constructor
122 TriangleShape(const TriangleShape& shape) = delete;
123
124 /// Deleted assignment operator
125 TriangleShape& operator=(const TriangleShape& shape) = delete;
126
127 /// Return the local bounds of the shape in x, y and z directions.
128 virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
129
130 /// Return the local inertia tensor of the collision shape
131 virtual Vector3 getLocalInertiaTensor(decimal mass) const override;
132
133 /// Update the AABB of a body using its collision shape
134 virtual void computeAABB(AABB& aabb, const Transform& transform) const override;
135
136 /// Return the raycast test type (front, back, front-back)
137 TriangleRaycastSide getRaycastTestType() const;
138
139 // Set the raycast test type (front, back, front-back)
140 void setRaycastTestType(TriangleRaycastSide testType);
141
142 /// Return the number of faces of the polyhedron
143 virtual uint getNbFaces() const override;
144
145 /// Return a given face of the polyhedron
146 virtual const HalfEdgeStructure::Face& getFace(uint faceIndex) const override;
147
148 /// Return the number of vertices of the polyhedron
149 virtual uint getNbVertices() const override;
150
151 /// Return a given vertex of the polyhedron
152 virtual HalfEdgeStructure::Vertex getVertex(uint vertexIndex) const override;
153
154 /// Return the position of a given vertex
155 virtual Vector3 getVertexPosition(uint vertexIndex) const override;
156
157 /// Return the normal vector of a given face of the polyhedron
158 virtual Vector3 getFaceNormal(uint faceIndex) const override;
159
160 /// Return the number of half-edges of the polyhedron
161 virtual uint getNbHalfEdges() const override;
162
163 /// Return a given half-edge of the polyhedron
164 virtual const HalfEdgeStructure::Edge& getHalfEdge(uint edgeIndex) const override;
165
166 /// Return the centroid of the polyhedron
167 virtual Vector3 getCentroid() const override;
168
169 /// Compute and return the volume of the collision shape
170 virtual decimal getVolume() const override;
171
172 /// This method compute the smooth mesh contact with a triangle in case one of the two collision shapes is a triangle. The idea in this case is to use a smooth vertex normal of the triangle mesh
173 static void computeSmoothTriangleMeshContact(const CollisionShape* shape1, const CollisionShape* shape2,
174 Vector3& localContactPointShape1, Vector3& localContactPointShape2,
175 const Transform& shape1ToWorld, const Transform& shape2ToWorld,
176 decimal penetrationDepth, Vector3& outSmoothVertexNormal);
177
178 /// Return the string representation of the shape
179 virtual std::string to_string() const override;
180
181 // ---------- Friendship ---------- //
182
183 friend class ConcaveMeshRaycastCallback;
184 friend class TriangleOverlapCallback;
185 friend class MiddlePhaseTriangleCallback;
186 friend class HeightFieldShape;
187 friend class CollisionDetectionSystem;
188 };
189
190 // Return the number of bytes used by the collision shape
getSizeInBytes()191 inline size_t TriangleShape::getSizeInBytes() const {
192 return sizeof(TriangleShape);
193 }
194
195 // Return a local support point in a given direction without the object margin
getLocalSupportPointWithoutMargin(const Vector3 & direction)196 inline Vector3 TriangleShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
197 Vector3 dotProducts(direction.dot(mPoints[0]), direction.dot(mPoints[1]), direction.dot(mPoints[2]));
198 return mPoints[dotProducts.getMaxAxis()];
199 }
200
201 // Return the local bounds of the shape in x, y and z directions.
202 // This method is used to compute the AABB of the box
203 /**
204 * @param min The minimum bounds of the shape in local-space coordinates
205 * @param max The maximum bounds of the shape in local-space coordinates
206 */
getLocalBounds(Vector3 & min,Vector3 & max)207 inline void TriangleShape::getLocalBounds(Vector3& min, Vector3& max) const {
208
209 const Vector3 xAxis(mPoints[0].x, mPoints[1].x, mPoints[2].x);
210 const Vector3 yAxis(mPoints[0].y, mPoints[1].y, mPoints[2].y);
211 const Vector3 zAxis(mPoints[0].z, mPoints[1].z, mPoints[2].z);
212 min.setAllValues(xAxis.getMinValue(), yAxis.getMinValue(), zAxis.getMinValue());
213 max.setAllValues(xAxis.getMaxValue(), yAxis.getMaxValue(), zAxis.getMaxValue());
214
215 min -= Vector3(mMargin, mMargin, mMargin);
216 max += Vector3(mMargin, mMargin, mMargin);
217 }
218
219 // Return the local inertia tensor of the triangle shape
220 /**
221 * @param[out] tensor The 3x3 inertia tensor matrix of the shape in local-space
222 * coordinates
223 * @param mass Mass to use to compute the inertia tensor of the collision shape
224 */
getLocalInertiaTensor(decimal mass)225 inline Vector3 TriangleShape::getLocalInertiaTensor(decimal mass) const {
226 return Vector3(0, 0, 0);
227 }
228
229 // Return true if a point is inside the collision shape
testPointInside(const Vector3 & localPoint,Collider * collider)230 inline bool TriangleShape::testPointInside(const Vector3& localPoint, Collider* collider) const {
231 return false;
232 }
233
234 // Return the number of faces of the polyhedron
getNbFaces()235 inline uint TriangleShape::getNbFaces() const {
236 return 2;
237 }
238
239 // Return a given face of the polyhedron
getFace(uint faceIndex)240 inline const HalfEdgeStructure::Face& TriangleShape::getFace(uint faceIndex) const {
241 assert(faceIndex < 2);
242 return mFaces[faceIndex];
243 }
244
245 // Return the number of vertices of the polyhedron
getNbVertices()246 inline uint TriangleShape::getNbVertices() const {
247 return 3;
248 }
249
250 // Return a given vertex of the polyhedron
getVertex(uint vertexIndex)251 inline HalfEdgeStructure::Vertex TriangleShape::getVertex(uint vertexIndex) const {
252 assert(vertexIndex < 3);
253
254 HalfEdgeStructure::Vertex vertex(vertexIndex);
255 switch (vertexIndex) {
256 case 0: vertex.edgeIndex = 0; break;
257 case 1: vertex.edgeIndex = 2; break;
258 case 2: vertex.edgeIndex = 4; break;
259 }
260 return vertex;
261 }
262
263 // Return a given half-edge of the polyhedron
getHalfEdge(uint edgeIndex)264 inline const HalfEdgeStructure::Edge& TriangleShape::getHalfEdge(uint edgeIndex) const {
265 assert(edgeIndex < getNbHalfEdges());
266 return mEdges[edgeIndex];
267 }
268
269 // Return the position of a given vertex
getVertexPosition(uint vertexIndex)270 inline Vector3 TriangleShape::getVertexPosition(uint vertexIndex) const {
271 assert(vertexIndex < 3);
272 return mPoints[vertexIndex];
273 }
274
275 // Return the normal vector of a given face of the polyhedron
getFaceNormal(uint faceIndex)276 inline Vector3 TriangleShape::getFaceNormal(uint faceIndex) const {
277 assert(faceIndex < 2);
278 return faceIndex == 0 ? mNormal : -mNormal;
279 }
280
281 // Return the centroid of the box
getCentroid()282 inline Vector3 TriangleShape::getCentroid() const {
283 return (mPoints[0] + mPoints[1] + mPoints[2]) / decimal(3.0);
284 }
285
286 // Return the number of half-edges of the polyhedron
getNbHalfEdges()287 inline uint TriangleShape::getNbHalfEdges() const {
288 return 6;
289 }
290
291 // Return the raycast test type (front, back, front-back)
getRaycastTestType()292 inline TriangleRaycastSide TriangleShape::getRaycastTestType() const {
293 return mRaycastTestType;
294 }
295
296 // Set the raycast test type (front, back, front-back)
297 /**
298 * @param testType Raycast test type for the triangle (front, back, front-back)
299 */
setRaycastTestType(TriangleRaycastSide testType)300 inline void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
301 mRaycastTestType = testType;
302 }
303
304 // Return the string representation of the shape
to_string()305 inline std::string TriangleShape::to_string() const {
306 return "TriangleShape{v1=" + mPoints[0].to_string() + ", v2=" + mPoints[1].to_string() + "," +
307 "v3=" + mPoints[2].to_string() + "}";
308 }
309
310 // Compute and return the volume of the collision shape
getVolume()311 inline decimal TriangleShape::getVolume() const {
312 return decimal(0.0);
313 }
314
315 }
316
317 #endif
318
319