Просмотр исходного кода

Fixes debug memory configuration when using physics subsystem.
Fixes memory leak in physics debug drawing.
Adds warnings for triangle mesh rigid bodies when used in constraints (since it is not currently supported).

Chris Culy 14 лет назад
Родитель
Сommit
94838d5fe1

+ 0 - 33
gameplay/src/Base.h

@@ -71,41 +71,8 @@ extern void printError(const char* format, ...);
 // Bullet Physics
 #include <btBulletDynamicsCommon.h>
 
-// Since Bullet overrides new, we have to allocate objects manually using its
-// aligned allocation function when we turn on memory leak detection in GamePlay.
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
-#define BULLET_NEW(type, name) \
-    type* name = (type*)btAlignedAlloc(sizeof(type), 16); \
-    type __##name##_tmp; \
-    memcpy(name, &__##name##_tmp, sizeof(type))
-
-#define BULLET_NEW_VARG(type, name, ...) \
-    type* name = (type*)btAlignedAlloc(sizeof(type), 16); \
-    type __##name##_tmp (__VA_ARGS__); \
-    memcpy(name, &__##name##_tmp, sizeof(type))
-
-#define BULLET_DELETE(name) \
-    if (name) \
-    { \
-        btAlignedFree(name); \
-        name = NULL; \
-    }
-
-#else
-#define BULLET_NEW(type, name) \
-    type* name = new type()
-
-#define BULLET_NEW_VARG(type, name, ...) \
-    type* name = new type(__VA_ARGS__)
-
-#define BULLET_DELETE(name) SAFE_DELETE(name)
-#endif
-
-
 // Debug new for memory leak detection
-#ifdef GAMEPLAY_MEM_LEAK_DETECTION
 #include "DebugNew.h"
-#endif
 
 // Object deletion macro
 #define SAFE_DELETE(x) \

+ 40 - 1
gameplay/src/DebugNew.h

@@ -4,7 +4,7 @@
 /**
  * Global overrides of the new and delete operators for memory tracking.
  * This file is only included when memory leak detection is explicitly
- * request via the pre-processor defintion GAMEPLAY_MEM_LEAK_DETECTION.
+ * request via the pre-processor definition GAMEPLAY_MEM_LEAK_DETECTION.
  */
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
 
@@ -37,4 +37,43 @@ void operator delete[] (void* p, const char* file, int line) throw();
 #define new DEBUG_NEW
 
 #endif
+
+// Since Bullet overrides new, we define custom functions to allocate Bullet objects that undef
+// 'new' before allocation and redefine it to our custom version afterwards (we support 0-2 parameter constructors).
+template<typename T> T* bullet_new()
+{
+#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#undef new
+    T* t = new T();
+#define new DEBUG_NEW
+    return t;
+#else
+    return new T();
+#endif
+}
+
+template<typename T, typename T1> T* bullet_new(T1 t1)
+{
+#ifdef GAMEPLAY_MEM_LEAK_DETECTION 
+#undef new 
+    T* t = new T(t1);
+#define new DEBUG_NEW
+    return t;
+#else
+    return new T(t1);
+#endif
+}
+
+template<typename T, typename T1, typename T2> T* bullet_new(T1 t1, T2 t2)
+{
+#ifdef GAMEPLAY_MEM_LEAK_DETECTION
+#undef new
+    T* t = new T(t1, t2);
+#define new DEBUG_NEW
+    return t;
+#else
+    return new T(t1, t2);
+#endif
+}
+
 #endif

+ 34 - 12
gameplay/src/PhysicsController.cpp

@@ -36,6 +36,7 @@ void PhysicsController::addStatusListener(Listener* listener)
 
 PhysicsFixedConstraint* PhysicsController::createFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
 {
+    checkConstraintRigidBodies(a, b);
     PhysicsFixedConstraint* constraint = new PhysicsFixedConstraint(a, b);
     addConstraint(a, b, constraint);
     return constraint;
@@ -43,6 +44,7 @@ PhysicsFixedConstraint* PhysicsController::createFixedConstraint(PhysicsRigidBod
 
 PhysicsGenericConstraint* PhysicsController::createGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
 {
+    checkConstraintRigidBodies(a, b);
     PhysicsGenericConstraint* constraint = new PhysicsGenericConstraint(a, b);
     addConstraint(a, b, constraint);
     return constraint;
@@ -52,8 +54,8 @@ PhysicsGenericConstraint* PhysicsController::createGenericConstraint(PhysicsRigi
     const Quaternion& rotationOffsetA, const Vector3& translationOffsetA, PhysicsRigidBody* b,
     const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
 {
-    PhysicsGenericConstraint* constraint = new PhysicsGenericConstraint(a, rotationOffsetA, translationOffsetA, 
-                                                                        b, rotationOffsetB, translationOffsetB);
+    checkConstraintRigidBodies(a, b);
+    PhysicsGenericConstraint* constraint = new PhysicsGenericConstraint(a, rotationOffsetA, translationOffsetA, b, rotationOffsetB, translationOffsetB);
     addConstraint(a, b, constraint);
     return constraint;
 }
@@ -62,14 +64,15 @@ PhysicsHingeConstraint* PhysicsController::createHingeConstraint(PhysicsRigidBod
     const Quaternion& rotationOffsetA, const Vector3& translationOffsetA, PhysicsRigidBody* b, 
     const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
 {
-    PhysicsHingeConstraint* constraint = new PhysicsHingeConstraint(a, rotationOffsetA, translationOffsetA, 
-                                                                    b, rotationOffsetB, translationOffsetB);
+    checkConstraintRigidBodies(a, b);
+    PhysicsHingeConstraint* constraint = new PhysicsHingeConstraint(a, rotationOffsetA, translationOffsetA, b, rotationOffsetB, translationOffsetB);
     addConstraint(a, b, constraint);
     return constraint;
 }
 
 PhysicsSocketConstraint* PhysicsController::createSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
 {
+    checkConstraintRigidBodies(a, b);
     PhysicsSocketConstraint* constraint = new PhysicsSocketConstraint(a, b);
     addConstraint(a, b, constraint);
     return constraint;
@@ -78,14 +81,15 @@ PhysicsSocketConstraint* PhysicsController::createSocketConstraint(PhysicsRigidB
 PhysicsSocketConstraint* PhysicsController::createSocketConstraint(PhysicsRigidBody* a,
     const Vector3& translationOffsetA, PhysicsRigidBody* b, const Vector3& translationOffsetB)
 {
-    PhysicsSocketConstraint* constraint = new PhysicsSocketConstraint(a,translationOffsetA, 
-                                                                      b, translationOffsetB);
+    checkConstraintRigidBodies(a, b);
+    PhysicsSocketConstraint* constraint = new PhysicsSocketConstraint(a,translationOffsetA, b, translationOffsetB);
     addConstraint(a, b, constraint);
     return constraint;
 }
 
 PhysicsSpringConstraint* PhysicsController::createSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
 {
+    checkConstraintRigidBodies(a, b);
     PhysicsSpringConstraint* constraint = new PhysicsSpringConstraint(a, b);
     addConstraint(a, b, constraint);
     return constraint;
@@ -94,8 +98,8 @@ PhysicsSpringConstraint* PhysicsController::createSpringConstraint(PhysicsRigidB
 PhysicsSpringConstraint* PhysicsController::createSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,           
                                                                    PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
 {
-    PhysicsSpringConstraint* constraint = new PhysicsSpringConstraint(a, rotationOffsetA, translationOffsetA, 
-                                                                      b, rotationOffsetB, translationOffsetB);
+    checkConstraintRigidBodies(a, b);
+    PhysicsSpringConstraint* constraint = new PhysicsSpringConstraint(a, rotationOffsetA, translationOffsetA, b, rotationOffsetB, translationOffsetB);
     addConstraint(a, b, constraint);
     return constraint;
 }
@@ -310,7 +314,7 @@ PhysicsRigidBody* PhysicsController::getRigidBody(const btCollisionObject* colli
 btCollisionShape* PhysicsController::createBox(const Vector3& min, const Vector3& max, const btVector3& scale)
 {
     btVector3 halfExtents(scale.x() * 0.5 * abs(max.x - min.x), scale.y() * 0.5 * abs(max.y - min.y), scale.z() * 0.5 * abs(max.z - min.z));
-    BULLET_NEW_VARG(btBoxShape, box, halfExtents);
+    btBoxShape* box = bullet_new<btBoxShape>(halfExtents);
     _shapes.push_back(box);
 
     return box;
@@ -326,7 +330,7 @@ btCollisionShape* PhysicsController::createSphere(float radius, const btVector3&
     if (uniformScale < scale.z())
         uniformScale = scale.z();
     
-    BULLET_NEW_VARG(btSphereShape, sphere, uniformScale * radius);
+    btSphereShape* sphere = bullet_new<btSphereShape>(uniformScale * radius);
     _shapes.push_back(sphere);
     
     return sphere;
@@ -353,7 +357,7 @@ btCollisionShape* PhysicsController::createMesh(PhysicsRigidBody* body)
         memcpy(&(body->_vertexData[i * 3]), &v, sizeof(float) * 3);
     }
     
-    BULLET_NEW(btTriangleIndexVertexArray, meshInterface);
+    btTriangleIndexVertexArray* meshInterface = bullet_new<btTriangleIndexVertexArray>();
 
     if (data->mesh->getPartCount() > 0)
     {
@@ -426,7 +430,7 @@ btCollisionShape* PhysicsController::createMesh(PhysicsRigidBody* body)
         meshInterface->addIndexedMesh(indexedMesh, indexedMesh.m_indexType);
     }
 
-    BULLET_NEW_VARG(btBvhTriangleMeshShape, shape, meshInterface, true);
+    btBvhTriangleMeshShape* shape = bullet_new<btBvhTriangleMeshShape>(meshInterface, true);
     _shapes.push_back(shape);
 
     return shape;
@@ -442,7 +446,24 @@ void PhysicsController::addConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b,
     
     _world->addConstraint(constraint->_constraint);
 }
+
+bool PhysicsController::checkConstraintRigidBodies(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    if (!a->supportsConstraints())
+    {
+        WARN_VARG("Rigid body '%s' does not support constraints; unexpected behavior may occur.", a->_node->getId());
+        return false;
+    }
     
+    if (b && !b->supportsConstraints())
+    {
+        WARN_VARG("Rigid body '%s' does not support constraints; unexpected behavior may occur.", b->_node->getId());
+        return false;
+    }
+
+    return true;
+}
+
 void PhysicsController::removeConstraint(PhysicsConstraint* constraint)
 {
     // Find the constraint and remove it from the physics world.
@@ -467,6 +488,7 @@ PhysicsController::DebugDrawer::DebugDrawer()
 
 PhysicsController::DebugDrawer::~DebugDrawer()
 {
+    SAFE_RELEASE(_effect);
     SAFE_DELETE_ARRAY(_vertexData);
 }
 

+ 3 - 0
gameplay/src/PhysicsController.h

@@ -246,6 +246,9 @@ private:
 
     // Sets up the given constraint for the given two rigid bodies.
     void addConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b, PhysicsConstraint* constraint);
+
+    // Checks whether constraints are supported for the given rigid bodies and emits a warning if they are not.
+    bool checkConstraintRigidBodies(PhysicsRigidBody* a, PhysicsRigidBody* b);
     
     // Removes the given constraint from the simulated physics world.
     void removeConstraint(PhysicsConstraint* constraint);

+ 8 - 4
gameplay/src/PhysicsRigidBody.cpp

@@ -72,11 +72,10 @@ PhysicsRigidBody::~PhysicsRigidBody()
         if (_body->getMotionState())
             delete _body->getMotionState();
 
-        if (_shape)
-            BULLET_DELETE(_shape);
+        SAFE_DELETE(_shape);
 
         Game::getInstance()->getPhysicsController()->removeRigidBody(this);
-        BULLET_DELETE(_body);
+        SAFE_DELETE(_body);
     }
 
     SAFE_DELETE(_listeners);
@@ -317,7 +316,7 @@ btRigidBody* PhysicsRigidBody::createRigidBodyInternal(btCollisionShape* shape,
     rbInfo.m_restitution = restitution;
     rbInfo.m_linearDamping = linearDamping;
     rbInfo.m_angularDamping = angularDamping;
-    BULLET_NEW_VARG(btRigidBody, body, rbInfo);
+    btRigidBody* body = bullet_new<btRigidBody>(rbInfo);
 
     return body;
 }
@@ -339,6 +338,11 @@ void PhysicsRigidBody::removeConstraint(PhysicsConstraint* constraint)
     }
 }
 
+bool PhysicsRigidBody::supportsConstraints()
+{
+    return _shape->getShapeType() != TRIANGLE_MESH_SHAPE_PROXYTYPE;
+}
+
 PhysicsRigidBody::CollisionPair::CollisionPair(PhysicsRigidBody* rbA, PhysicsRigidBody* rbB)
     : _rbA(rbA), _rbB(rbB)
 {

+ 3 - 0
gameplay/src/PhysicsRigidBody.h

@@ -341,6 +341,9 @@ private:
 
     // Removes a constraint from this rigid body (used by the constraint destructor).
     void removeConstraint(PhysicsConstraint* constraint);
+    
+    // Whether or not the rigid body supports constraints fully.
+    bool supportsConstraints();
 
     // Internal class used to implement the collidesWith(PhysicsRigidBody*) function.
     struct CollidesWithCallback : public btCollisionWorld::ContactResultCallback