Procházet zdrojové kódy

Merge pull request #70 from blackberry-gaming/next-cculy

Physics debug memory configuration fix, triangle mesh rigid body constraint warnings.
Sean Paul Taylor před 14 roky
rodič
revize
7acfa4a8dc

+ 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

+ 1 - 1
gameplay/src/Node.h

@@ -374,7 +374,7 @@ public:
      * 
      * @param filePath The path to the file that contains the rigid body definition.
      */
-    void setPhysicsRigidBody(const char* url);
+    void setPhysicsRigidBody(const char* filePath);
 
     /**
      * Sets the physics rigid body for this node from the given properties object.

+ 59 - 88
gameplay/src/PhysicsController.cpp

@@ -5,7 +5,7 @@
 #include "PhysicsMotionState.h"
 #include "SceneLoader.h"
 
-// The initial capacity of the bullet debug draw's vertex batch.
+// The initial capacity of the Bullet debug drawer's vertex batch.
 #define INITIAL_CAPACITY 280
 
 namespace gameplay
@@ -20,6 +20,12 @@ PhysicsController::PhysicsController()
     // Default gravity is 9.8 along the negative Y axis.
 }
 
+PhysicsController::~PhysicsController()
+{
+    SAFE_DELETE(_debugDrawer);
+    SAFE_DELETE(_listeners);
+}
+
 void PhysicsController::addStatusListener(Listener* listener)
 {
     if (!_listeners)
@@ -27,15 +33,10 @@ void PhysicsController::addStatusListener(Listener* listener)
 
     _listeners->push_back(listener);
 }
-    
-PhysicsController::~PhysicsController()
-{
-    SAFE_DELETE(_debugDrawer);
-    SAFE_DELETE(_listeners);
-}
 
 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,19 +98,12 @@ 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;
 }
 
-void PhysicsController::drawDebug(const Matrix& viewProjection)
-{
-    _debugDrawer->begin(viewProjection);
-    _world->debugDrawWorld();
-    _debugDrawer->end();
-}
-
 const Vector3& PhysicsController::getGravity(const Vector3& gravity) const
 {
     return _gravity;
@@ -120,6 +117,13 @@ void PhysicsController::setGravity(const Vector3& gravity)
         _world->setGravity(btVector3(_gravity.x, _gravity.y, _gravity.z));
 }
 
+void PhysicsController::drawDebug(const Matrix& viewProjection)
+{
+    _debugDrawer->begin(viewProjection);
+    _world->debugDrawWorld();
+    _debugDrawer->end();
+}
+
 void PhysicsController::initialize()
 {
     _collisionConfiguration = new btDefaultCollisionConfiguration();
@@ -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.
@@ -459,14 +480,15 @@ void PhysicsController::removeConstraint(PhysicsConstraint* constraint)
     
 PhysicsController::DebugDrawer::DebugDrawer()
     : _mode(btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawConstraintLimits | btIDebugDraw::DBG_DrawConstraints | 
-       btIDebugDraw::DBG_DrawContactPoints | btIDebugDraw::DBG_DrawWireframe), _program(0), _positionAttrib(0),
-       _colorAttrib(0), _viewProjectionMatrixUniform(0), _viewProjection(NULL), _vertexData(NULL), _vertexCount(0), _vertexDataSize(0)
+       btIDebugDraw::DBG_DrawContactPoints | btIDebugDraw::DBG_DrawWireframe), _effect(NULL), _positionAttrib(0), _colorAttrib(0),
+       _viewProjectionMatrixUniform(NULL), _viewProjection(NULL), _vertexData(NULL), _vertexCount(0), _vertexDataSize(0)
 {
     // Unused
 }
 
 PhysicsController::DebugDrawer::~DebugDrawer()
 {
+    SAFE_RELEASE(_effect);
     SAFE_DELETE_ARRAY(_vertexData);
 }
 
@@ -478,8 +500,8 @@ void PhysicsController::DebugDrawer::begin(const Matrix& viewProjection)
 
 void PhysicsController::DebugDrawer::end()
 {
-    // Lazy load the shader program for drawing.
-    if (!_program)
+    // Lazy load the effect for drawing.
+    if (!_effect)
     {
         // Vertex shader for drawing colored lines.
         const char* vs_str = 
@@ -506,73 +528,22 @@ void PhysicsController::DebugDrawer::end()
             "}"
         };
         
-        // Load the vertex shader.
-        GLuint vs;
-        GL_ASSERT( vs = glCreateShader(GL_VERTEX_SHADER) );
-        GLint shader_str_len = strlen(vs_str);
-        GL_ASSERT( glShaderSource(vs, 1, &vs_str, &shader_str_len) );
-        GL_ASSERT( glCompileShader(vs) );
-        GLint status;
-        GL_ASSERT( glGetShaderiv(vs, GL_COMPILE_STATUS, &status) );
-        if (status == GL_FALSE)
-        {
-            GLchar errorMessage[512];
-            GL_ASSERT( glGetShaderInfoLog(vs, sizeof(errorMessage), 0, errorMessage) );
-            WARN_VARG("Physics debug drawing will not work; vertex shader failed to compile with error: '%s'", errorMessage);
-            return;
-        }
-        
-        // Load the fragment shader.
-        GLuint fs;
-        GL_ASSERT( fs = glCreateShader(GL_FRAGMENT_SHADER) );
-        shader_str_len = strlen(fs_str);
-        GL_ASSERT( glShaderSource(fs, 1, &fs_str, &shader_str_len) );
-        GL_ASSERT( glCompileShader(fs) );
-        GL_ASSERT( glGetShaderiv(fs, GL_COMPILE_STATUS, &status) );
-        if (status == GL_FALSE)
-        {
-            GLchar errorMessage[512];
-            GL_ASSERT( glGetShaderInfoLog(fs, sizeof(errorMessage), 0, errorMessage) );
-            WARN_VARG("Physics debug drawing will not work; fragment shader failed to compile with error: '%s'", errorMessage);
-            return;
-        }
-        
-        // Create the shader program and link it.
-        GL_ASSERT( _program = glCreateProgram() );
-        GL_ASSERT( glAttachShader(_program, vs) );
-        GL_ASSERT( glAttachShader(_program, fs) );
-        GL_ASSERT( glLinkProgram(_program) );
-        GL_ASSERT( glGetProgramiv(_program, GL_LINK_STATUS, &status) );
-        if (status == GL_FALSE)
-        {
-            GLchar errorMessage[512];
-            GL_ASSERT( glGetProgramInfoLog(_program, sizeof(errorMessage), 0, errorMessage) );
-            WARN_VARG("Physics debug drawing will not work; shader program failed to link with error: '%s'", errorMessage);
-            return;
-        }
-        
-        // Get the attribute and uniform locations.
-        GL_ASSERT( glUseProgram(_program) );
-        GL_ASSERT( _positionAttrib = glGetAttribLocation(_program, "a_position") );
-        GL_ASSERT( _colorAttrib = glGetAttribLocation(_program, "a_color") );
-        GL_ASSERT( _viewProjectionMatrixUniform = glGetUniformLocation(_program, "u_viewProjectionMatrix") );
+        _effect = Effect::createFromSource(vs_str, fs_str);
+        _positionAttrib = _effect->getVertexAttribute("a_position");
+        _colorAttrib = _effect->getVertexAttribute("a_color");
+        _viewProjectionMatrixUniform = _effect->getUniform("u_viewProjectionMatrix");
     }
     
-    // Set the shader program and vertex attributes.
-    GL_ASSERT( glUseProgram(_program) );
+    // Bind the effect and set the vertex attributes.
+    _effect->bind();
     GL_ASSERT( glEnableVertexAttribArray(_positionAttrib) );
     GL_ASSERT( glEnableVertexAttribArray(_colorAttrib) );
     GL_ASSERT( glVertexAttribPointer(_positionAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, _vertexData) );
     GL_ASSERT( glVertexAttribPointer(_colorAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 7, &_vertexData[3]) );
     
     // Set the camera's view projection matrix and draw.
-    GL_ASSERT( glUniformMatrix4fv(_viewProjectionMatrixUniform, 1, GL_FALSE, _viewProjection->m) );
+    _effect->setValue( _viewProjectionMatrixUniform, _viewProjection);
     GL_ASSERT( glDrawArrays(GL_LINES, 0, _vertexCount / 7) );
-    
-    // Reset shader state.
-    GL_ASSERT( glDisableVertexAttribArray(_positionAttrib) );
-    GL_ASSERT( glDisableVertexAttribArray(_colorAttrib) );
-    GL_ASSERT( glUseProgram(0) );
 }
 
 void PhysicsController::DebugDrawer::drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor)

+ 17 - 21
gameplay/src/PhysicsController.h

@@ -47,7 +47,7 @@ public:
         };
 
         /**
-         * Handles when the physics world status event occurs.
+         * Handles when a physics world status event occurs.
          */
         virtual void statusEvent(EventType type) = 0;
     };
@@ -246,44 +246,40 @@ 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);
     
-    // Draws bullet debug information
+    // Draws Bullet debug information.
     class DebugDrawer : public btIDebugDraw
     {
     public:
 
-        DebugDrawer();
-        
+        DebugDrawer();        
         ~DebugDrawer();
         
         void begin(const Matrix& viewProjection);
-        
         void end();
 
-        void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor);
-        
-        void drawLine(const btVector3& from, const btVector3& to, const btVector3& color);
-        
-        void drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color);
-        
-        void reportErrorWarning(const char* warningString);
-        
-        void draw3dText(const btVector3& location, const char* textString);
-        
-        void setDebugMode(int mode);
-        
+        // Overridden Bullet functions from btIDebugDraw.
+        void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor);        
+        void drawLine(const btVector3& from, const btVector3& to, const btVector3& color);        
+        void drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color);        
+        void reportErrorWarning(const char* warningString);        
+        void draw3dText(const btVector3& location, const char* textString);        
+        void setDebugMode(int mode);        
         int	getDebugMode() const;
         
     private:
         
         int _mode;
-        GLuint _program;
-        GLuint _positionAttrib;
-        GLuint _colorAttrib;
-        GLuint _viewProjectionMatrixUniform;
+        Effect* _effect;
+        VertexAttribute _positionAttrib;
+        VertexAttribute _colorAttrib;
+        Uniform* _viewProjectionMatrixUniform;
         const Matrix* _viewProjection;
         float* _vertexData;
         unsigned int _vertexCount;

+ 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