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 // Libraries
27 #include <reactphysics3d/engine/PhysicsCommon.h>
28
29 using namespace reactphysics3d;
30
31 // Static variables
32 Logger* PhysicsCommon::mLogger = nullptr;
33
34 /// Constructor
35 /**
36 * @param baseMemoryAllocator Pointer to a user custom memory allocator
37 */
PhysicsCommon(MemoryAllocator * baseMemoryAllocator)38 PhysicsCommon::PhysicsCommon(MemoryAllocator* baseMemoryAllocator)
39 : mMemoryManager(baseMemoryAllocator),
40 mPhysicsWorlds(mMemoryManager.getHeapAllocator()), mSphereShapes(mMemoryManager.getHeapAllocator()),
41 mBoxShapes(mMemoryManager.getHeapAllocator()), mCapsuleShapes(mMemoryManager.getHeapAllocator()),
42 mConvexMeshShapes(mMemoryManager.getHeapAllocator()), mConcaveMeshShapes(mMemoryManager.getHeapAllocator()),
43 mHeightFieldShapes(mMemoryManager.getHeapAllocator()), mPolyhedronMeshes(mMemoryManager.getHeapAllocator()),
44 mTriangleMeshes(mMemoryManager.getHeapAllocator()),
45 mProfilers(mMemoryManager.getHeapAllocator()), mDefaultLoggers(mMemoryManager.getHeapAllocator()) {
46
47 }
48
49 // Destructor
~PhysicsCommon()50 PhysicsCommon::~PhysicsCommon() {
51
52 // Release the allocated memory
53 release();
54 }
55
56 // Destroy and release everything that has been allocated
release()57 void PhysicsCommon::release() {
58
59 // Destroy the physics worlds
60 for (auto it = mPhysicsWorlds.begin(); it != mPhysicsWorlds.end(); ++it) {
61 destroyPhysicsWorld(*it);
62 }
63
64 // Destroy the sphere shapes
65 for (auto it = mSphereShapes.begin(); it != mSphereShapes.end(); ++it) {
66 destroySphereShape(*it);
67 }
68
69 // Destroy the box shapes
70 for (auto it = mBoxShapes.begin(); it != mBoxShapes.end(); ++it) {
71 destroyBoxShape(*it);
72 }
73
74 // Destroy the capsule shapes
75 for (auto it = mCapsuleShapes.begin(); it != mCapsuleShapes.end(); ++it) {
76 destroyCapsuleShape(*it);
77 }
78
79 // Destroy the convex mesh shapes
80 for (auto it = mConvexMeshShapes.begin(); it != mConvexMeshShapes.end(); ++it) {
81 destroyConvexMeshShape(*it);
82 }
83
84 // Destroy the heigh-field shapes
85 for (auto it = mHeightFieldShapes.begin(); it != mHeightFieldShapes.end(); ++it) {
86 destroyHeightFieldShape(*it);
87 }
88
89 // Destroy the concave mesh shapes
90 for (auto it = mConcaveMeshShapes.begin(); it != mConcaveMeshShapes.end(); ++it) {
91 destroyConcaveMeshShape(*it);
92 }
93
94 // Destroy the polyhedron mesh
95 for (auto it = mPolyhedronMeshes.begin(); it != mPolyhedronMeshes.end(); ++it) {
96 destroyPolyhedronMesh(*it);
97 }
98
99 // Destroy the triangle mesh
100 for (auto it = mTriangleMeshes.begin(); it != mTriangleMeshes.end(); ++it) {
101 destroyTriangleMesh(*it);
102 }
103
104 // Destroy the default loggers
105 for (auto it = mDefaultLoggers.begin(); it != mDefaultLoggers.end(); ++it) {
106 destroyDefaultLogger(*it);
107 }
108
109 // If profiling is enabled
110 #ifdef IS_RP3D_PROFILING_ENABLED
111
112
113 // Destroy the profilers
114 for (auto it = mProfilers.begin(); it != mProfilers.end(); ++it) {
115 destroyProfiler(*it);
116 }
117
118 #endif
119
120 }
121
122 // Create and return an instance of PhysicsWorld
123 /**
124 * @param worldSettings The settings of the physics world
125 * @return A pointer to the created physics world
126 */
createPhysicsWorld(const PhysicsWorld::WorldSettings & worldSettings)127 PhysicsWorld* PhysicsCommon::createPhysicsWorld(const PhysicsWorld::WorldSettings& worldSettings) {
128
129 Profiler* profiler = nullptr;
130
131 #ifdef IS_RP3D_PROFILING_ENABLED
132
133
134 profiler = createProfiler();
135
136 // Add a destination file for the profiling data
137 profiler->addFileDestination("rp3d_profiling_" + worldSettings.worldName + ".txt", Profiler::Format::Text);
138
139 #endif
140
141 PhysicsWorld* world = new(mMemoryManager.allocate(MemoryManager::AllocationType::Heap, sizeof(PhysicsWorld))) PhysicsWorld(mMemoryManager, worldSettings, profiler);
142
143 mPhysicsWorlds.add(world);
144
145 return world;
146 }
147
148 // Destroy an instance of PhysicsWorld
149 /**
150 * @param world A pointer to the physics world to destroy
151 */
destroyPhysicsWorld(PhysicsWorld * world)152 void PhysicsCommon::destroyPhysicsWorld(PhysicsWorld* world) {
153
154 // Call the destructor of the world
155 world->~PhysicsWorld();
156
157 // Release allocated memory
158 mMemoryManager.release(MemoryManager::AllocationType::Heap, world, sizeof(PhysicsWorld));
159
160 mPhysicsWorlds.remove(world);
161 }
162
163 // Create and return a sphere collision shape
164 /**
165 * @param radius The radius of the sphere collision shape
166 * @return A pointer to the created sphere shape
167 */
createSphereShape(const decimal radius)168 SphereShape* PhysicsCommon::createSphereShape(const decimal radius) {
169
170 if (radius <= decimal(0.0)) {
171
172 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
173 "Error when creating a SphereShape: radius must be a positive value", __FILE__, __LINE__);
174 }
175
176 SphereShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(SphereShape))) SphereShape(radius, mMemoryManager.getHeapAllocator());
177 mSphereShapes.add(shape);
178
179 return shape;
180 }
181
182 // Destroy a sphere collision shape
183 /**
184 * @param sphereShape A pointer to the sphere collision shape to destroy
185 */
destroySphereShape(SphereShape * sphereShape)186 void PhysicsCommon::destroySphereShape(SphereShape* sphereShape) {
187
188 // If the shape is still part of some colliders
189 if (sphereShape->mColliders.size() > 0) {
190
191 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
192 "Error when destroying the SphereShape because it is still used by some colliders", __FILE__, __LINE__);
193 }
194
195 // Call the destructor of the shape
196 sphereShape->~SphereShape();
197
198 // Release allocated memory
199 mMemoryManager.release(MemoryManager::AllocationType::Pool, sphereShape, sizeof(SphereShape));
200
201 mSphereShapes.remove(sphereShape);
202 }
203
204 // Create and return a box collision shape
205 /**
206 * @param halfExtents A vector with the three half-extents of the box shape
207 * @return A pointer to the created box shape
208 */
createBoxShape(const Vector3 & halfExtents)209 BoxShape* PhysicsCommon::createBoxShape(const Vector3& halfExtents) {
210
211 if (halfExtents.x <= decimal(0.0) || halfExtents.y <= decimal(0.0) || halfExtents.z <= decimal(0.0)) {
212
213 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
214 "Error when creating a BoxShape: the half extents must be positive values", __FILE__, __LINE__);
215 }
216 BoxShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(BoxShape))) BoxShape(halfExtents, mMemoryManager.getHeapAllocator());
217
218 mBoxShapes.add(shape);
219
220 return shape;
221 }
222
223 // Destroy a box collision shape
224 /**
225 * @param boxShape A pointer to the box shape to destroy
226 */
destroyBoxShape(BoxShape * boxShape)227 void PhysicsCommon::destroyBoxShape(BoxShape* boxShape) {
228
229 // If the shape is still part of some colliders
230 if (boxShape->mColliders.size() > 0) {
231
232 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
233 "Error when destroying the BoxShape because it is still used by some colliders", __FILE__, __LINE__);
234 }
235
236 // Call the destructor of the shape
237 boxShape->~BoxShape();
238
239 // Release allocated memory
240 mMemoryManager.release(MemoryManager::AllocationType::Pool, boxShape, sizeof(BoxShape));
241
242 mBoxShapes.remove(boxShape);
243 }
244
245 // Create and return a capsule shape
246 /**
247 * @param radius The radius of the sphere of the capsule shape
248 * @param height The height of the capsule shape (distance betwen the two spheres centers)
249 * @return boxShape A pointer to the created capsule shape
250 */
createCapsuleShape(decimal radius,decimal height)251 CapsuleShape* PhysicsCommon::createCapsuleShape(decimal radius, decimal height) {
252
253 if (radius <= decimal(0.0)) {
254
255 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
256 "Error when creating a CapsuleShape: radius must be a positive value", __FILE__, __LINE__);
257 }
258
259 if (height <= decimal(0.0)) {
260
261 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
262 "Error when creating a CapsuleShape: height must be a positive value", __FILE__, __LINE__);
263 }
264
265 CapsuleShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(CapsuleShape))) CapsuleShape(radius, height, mMemoryManager.getHeapAllocator());
266
267 mCapsuleShapes.add(shape);
268
269 return shape;
270 }
271
272 // Destroy a capsule collision shape
273 /**
274 * @param capsuleShape A pointer to the capsule shape to destroy
275 */
destroyCapsuleShape(CapsuleShape * capsuleShape)276 void PhysicsCommon::destroyCapsuleShape(CapsuleShape* capsuleShape) {
277
278 // If the shape is still part of some colliders
279 if (capsuleShape->mColliders.size() > 0) {
280
281 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
282 "Error when destroying the CapsuleShape because it is still used by some colliders", __FILE__, __LINE__);
283 }
284
285 // Call the destructor of the shape
286 capsuleShape->~CapsuleShape();
287
288 // Release allocated memory
289 mMemoryManager.release(MemoryManager::AllocationType::Pool, capsuleShape, sizeof(CapsuleShape));
290
291 mCapsuleShapes.remove(capsuleShape);
292 }
293
294 // Create and return a convex mesh shape
295 /**
296 * @param polyhedronMesh A pointer to the polyhedron mesh used to create the convex shape
297 * @param scaling Scaling factor to scale the polyhedron mesh if necessary
298 * @return A pointer to the created convex mesh shape
299 */
createConvexMeshShape(PolyhedronMesh * polyhedronMesh,const Vector3 & scaling)300 ConvexMeshShape* PhysicsCommon::createConvexMeshShape(PolyhedronMesh* polyhedronMesh, const Vector3& scaling) {
301
302 ConvexMeshShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(ConvexMeshShape))) ConvexMeshShape(polyhedronMesh, mMemoryManager.getHeapAllocator(), scaling);
303
304 mConvexMeshShapes.add(shape);
305
306 return shape;
307 }
308
309 // Destroy a convex mesh shape
310 /**
311 * @param convexMeshShape A pointer to the convex mesh shape to destroy
312 */
destroyConvexMeshShape(ConvexMeshShape * convexMeshShape)313 void PhysicsCommon::destroyConvexMeshShape(ConvexMeshShape* convexMeshShape) {
314
315 // If the shape is still part of some colliders
316 if (convexMeshShape->mColliders.size() > 0) {
317
318 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
319 "Error when destroying the ConvexMeshShape because it is still used by some colliders", __FILE__, __LINE__);
320 }
321
322 // Call the destructor of the shape
323 convexMeshShape->~ConvexMeshShape();
324
325 // Release allocated memory
326 mMemoryManager.release(MemoryManager::AllocationType::Pool, convexMeshShape, sizeof(ConvexMeshShape));
327
328 mConvexMeshShapes.remove(convexMeshShape);
329 }
330
331 // Create and return a height-field shape
332 /**
333 * @param nbGridColumns Number of columns in the grid of the height field
334 * @param nbGridRows Number of rows in the grid of the height field
335 * @param minHeight Minimum height value of the height field
336 * @param maxHeight Maximum height value of the height field
337 * @param heightFieldData Pointer to the first height value data (note that values are shared and not copied)
338 * @param dataType Data type for the height values (int, float, double)
339 * @param upAxis Integer representing the up axis direction (0 for x, 1 for y and 2 for z)
340 * @param integerHeightScale Scaling factor used to scale the height values (only when height values type is integer)
341 * @return A pointer to the created height field shape
342 */
createHeightFieldShape(int nbGridColumns,int nbGridRows,decimal minHeight,decimal maxHeight,const void * heightFieldData,HeightFieldShape::HeightDataType dataType,int upAxis,decimal integerHeightScale,const Vector3 & scaling)343 HeightFieldShape* PhysicsCommon::createHeightFieldShape(int nbGridColumns, int nbGridRows, decimal minHeight, decimal maxHeight,
344 const void* heightFieldData, HeightFieldShape::HeightDataType dataType,
345 int upAxis, decimal integerHeightScale, const Vector3& scaling) {
346
347 HeightFieldShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(HeightFieldShape))) HeightFieldShape(nbGridColumns, nbGridRows, minHeight, maxHeight,
348 heightFieldData, dataType, mMemoryManager.getHeapAllocator(), upAxis, integerHeightScale, scaling);
349
350 mHeightFieldShapes.add(shape);
351
352 return shape;
353 }
354
355 // Destroy a height-field shape
356 /**
357 * @param heightFieldShape A pointer to the height field shape to destroy
358 */
destroyHeightFieldShape(HeightFieldShape * heightFieldShape)359 void PhysicsCommon::destroyHeightFieldShape(HeightFieldShape* heightFieldShape) {
360
361 // If the shape is still part of some colliders
362 if (heightFieldShape->mColliders.size() > 0) {
363
364 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
365 "Error when destroying the HeightFieldShape because it is still used by some colliders", __FILE__, __LINE__);
366 }
367
368 // Call the destructor of the shape
369 heightFieldShape->~HeightFieldShape();
370
371 // Release allocated memory
372 mMemoryManager.release(MemoryManager::AllocationType::Pool, heightFieldShape, sizeof(HeightFieldShape));
373
374 mHeightFieldShapes.remove(heightFieldShape);
375 }
376
377 // Create and return a concave mesh shape
378 /**
379 * @param triangleMesh A pointer to the triangle mesh to use to create the concave mesh shape
380 * @param scaling An optional scaling factor to scale the triangle mesh
381 * @return A pointer to the created concave mesh shape
382 */
createConcaveMeshShape(TriangleMesh * triangleMesh,const Vector3 & scaling)383 ConcaveMeshShape* PhysicsCommon::createConcaveMeshShape(TriangleMesh* triangleMesh, const Vector3& scaling) {
384
385 ConcaveMeshShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(ConcaveMeshShape))) ConcaveMeshShape(triangleMesh, mMemoryManager.getHeapAllocator(), scaling);
386
387 mConcaveMeshShapes.add(shape);
388
389 return shape;
390 }
391
392 // Destroy a concave mesh shape
393 /**
394 * @param concaveMeshShape A pointer to the concave mesh shape to destroy
395 */
destroyConcaveMeshShape(ConcaveMeshShape * concaveMeshShape)396 void PhysicsCommon::destroyConcaveMeshShape(ConcaveMeshShape* concaveMeshShape) {
397
398 // If the shape is still part of some colliders
399 if (concaveMeshShape->mColliders.size() > 0) {
400
401 RP3D_LOG("PhysicsCommon", Logger::Level::Error, Logger::Category::PhysicCommon,
402 "Error when destroying the ConcaveMeshShape because it is still used by some colliders", __FILE__, __LINE__);
403 }
404
405 // Call the destructor of the shape
406 concaveMeshShape->~ConcaveMeshShape();
407
408 // Release allocated memory
409 mMemoryManager.release(MemoryManager::AllocationType::Pool, concaveMeshShape, sizeof(ConcaveMeshShape));
410
411 mConcaveMeshShapes.remove(concaveMeshShape);
412 }
413
414 // Create a polyhedron mesh
415 /**
416 * @param polygonVertexArray A pointer to the polygon vertex array to use to create the polyhedron mesh
417 * @return A pointer to the created polyhedron mesh
418 */
createPolyhedronMesh(PolygonVertexArray * polygonVertexArray)419 PolyhedronMesh* PhysicsCommon::createPolyhedronMesh(PolygonVertexArray* polygonVertexArray) {
420
421 PolyhedronMesh* mesh = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(PolyhedronMesh))) PolyhedronMesh(polygonVertexArray, mMemoryManager.getHeapAllocator());
422
423 mPolyhedronMeshes.add(mesh);
424
425 return mesh;
426 }
427
428 // Destroy a polyhedron mesh
429 /**
430 * @param polyhedronMesh A pointer to the polyhedron mesh to destroy
431 */
destroyPolyhedronMesh(PolyhedronMesh * polyhedronMesh)432 void PhysicsCommon::destroyPolyhedronMesh(PolyhedronMesh* polyhedronMesh) {
433
434 // Call the destructor of the shape
435 polyhedronMesh->~PolyhedronMesh();
436
437 // Release allocated memory
438 mMemoryManager.release(MemoryManager::AllocationType::Pool, polyhedronMesh, sizeof(PolyhedronMesh));
439
440 mPolyhedronMeshes.remove(polyhedronMesh);
441 }
442
443 // Create a triangle mesh
444 /**
445 * @return A pointer to the created triangle mesh
446 */
createTriangleMesh()447 TriangleMesh* PhysicsCommon::createTriangleMesh() {
448
449 TriangleMesh* mesh = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(TriangleMesh))) TriangleMesh(mMemoryManager.getHeapAllocator());
450
451 mTriangleMeshes.add(mesh);
452
453 return mesh;
454 }
455
456 // Destroy a triangle mesh
457 /**
458 * @param A pointer to the triangle mesh to destroy
459 */
destroyTriangleMesh(TriangleMesh * triangleMesh)460 void PhysicsCommon::destroyTriangleMesh(TriangleMesh* triangleMesh) {
461
462 // Call the destructor of the shape
463 triangleMesh->~TriangleMesh();
464
465 // Release allocated memory
466 mMemoryManager.release(MemoryManager::AllocationType::Pool, triangleMesh, sizeof(TriangleMesh));
467
468 mTriangleMeshes.remove(triangleMesh);
469 }
470
471 // Create and return a new logger
472 /**
473 * @return A pointer to the created default logger
474 */
createDefaultLogger()475 DefaultLogger* PhysicsCommon::createDefaultLogger() {
476
477 DefaultLogger* logger = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(DefaultLogger))) DefaultLogger(mMemoryManager.getHeapAllocator());
478
479 mDefaultLoggers.add(logger);
480
481 return logger;
482 }
483
484 // Destroy a logger
485 /**
486 * @param A pointer to the default logger to destroy
487 */
destroyDefaultLogger(DefaultLogger * logger)488 void PhysicsCommon::destroyDefaultLogger(DefaultLogger* logger) {
489
490 // Call the destructor of the logger
491 logger->~DefaultLogger();
492
493 // Release allocated memory
494 mMemoryManager.release(MemoryManager::AllocationType::Pool, logger, sizeof(DefaultLogger));
495
496 mDefaultLoggers.remove(logger);
497 }
498
499 // If profiling is enabled
500 #ifdef IS_RP3D_PROFILING_ENABLED
501
502
503 // Create and return a new profiler
504 /// Note that you need to use a different profiler for each PhysicsWorld.
createProfiler()505 Profiler* PhysicsCommon::createProfiler() {
506
507 Profiler* profiler = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(Profiler))) Profiler();
508
509 mProfilers.add(profiler);
510
511 return profiler;
512 }
513
514 // Destroy a profiler
destroyProfiler(Profiler * profiler)515 void PhysicsCommon::destroyProfiler(Profiler* profiler) {
516
517 // Call the destructor of the profiler
518 profiler->~Profiler();
519
520 // Release allocated memory
521 mMemoryManager.release(MemoryManager::AllocationType::Pool, profiler, sizeof(Profiler));
522
523 mProfilers.remove(profiler);
524 }
525
526 #endif
527