Преглед изворни кода

Updates collision listener interface to notify when a collision starts and stops and also to pass both contact points of a collision.
Minor fix for mesh rigid bodies (scale stuff).

Chris Culy пре 14 година
родитељ
комит
61eee71297

+ 24 - 11
gameplay/src/PhysicsController.cpp

@@ -234,14 +234,22 @@ void PhysicsController::update(long elapsedTime)
     }
 
     // Go through the physics rigid bodies and update the collision listeners.
-    for (unsigned int i = 0; i < _bodies.size(); i++)
+    unsigned int size = _bodies.size();
+    unsigned int listenerCount = 0;
+    PhysicsRigidBody* body = NULL;
+    PhysicsRigidBody::Listener* listener = NULL;
+    PhysicsController* physicsController = Game::getInstance()->getPhysicsController();
+    for (unsigned int i = 0; i < size; i++)
     {
-        if (_bodies[i]->_listeners)
+        body = _bodies[i];
+        if (body->_listeners)
         {
-            for (unsigned int k = 0; k < _bodies[i]->_listeners->size(); k++)
+            listenerCount = body->_listeners->size();
+            for (unsigned int k = 0; k < listenerCount; k++)
             {
-                std::map<PhysicsRigidBody::CollisionPair, int>::iterator iter = (*_bodies[i]->_listeners)[k]->_collisionStatus.begin();
-                for (; iter != (*_bodies[i]->_listeners)[k]->_collisionStatus.end(); iter++)
+                listener = (*body->_listeners)[k];
+                std::map<PhysicsRigidBody::CollisionPair, int>::iterator iter = listener->_collisionStatus.begin();
+                for (; iter != listener->_collisionStatus.end(); iter++)
                 {
                     // If this collision pair was one that was registered for listening, then perform the collision test.
                     // (In the case where we register for all collisions with a rigid body, there will be a lot
@@ -249,9 +257,9 @@ void PhysicsController::update(long elapsedTime)
                     if ((iter->second & PhysicsRigidBody::Listener::REGISTERED) != 0)
                     {
                         if (iter->first._rbB)
-                            Game::getInstance()->getPhysicsController()->_world->contactPairTest(iter->first._rbA->_body, iter->first._rbB->_body, *(*_bodies[i]->_listeners)[k]);
+                            physicsController->_world->contactPairTest(iter->first._rbA->_body, iter->first._rbB->_body, *listener);
                         else
-                            Game::getInstance()->getPhysicsController()->_world->contactTest(iter->first._rbA->_body, *(*_bodies[i]->_listeners)[k]);
+                            physicsController->_world->contactTest(iter->first._rbA->_body, *listener);
                     }
                 }   
             }
@@ -270,6 +278,11 @@ void PhysicsController::update(long elapsedTime)
                 {
                     if ((iter->second & PhysicsRigidBody::Listener::DIRTY) != 0)
                     {
+                        if ((iter->second & PhysicsRigidBody::Listener::COLLISION) != 0 && iter->first._rbB)
+                        {
+                            (*_bodies[i]->_listeners)[k]->collisionEvent(PhysicsRigidBody::Listener::NOT_COLLIDING, iter->first, Vector3::zero());
+                        }
+
                         iter->second &= ~PhysicsRigidBody::Listener::COLLISION;
                     }
                 }
@@ -407,14 +420,14 @@ btCollisionShape* PhysicsController::createSphere(float radius, const btVector3&
     return sphere;
 }
 
-btCollisionShape* PhysicsController::createMesh(PhysicsRigidBody* body)
+btCollisionShape* PhysicsController::createMesh(PhysicsRigidBody* body, const Vector3& scale)
 {
     // Retrieve the mesh rigid body data from the loaded scene.
     const SceneLoader::MeshRigidBodyData* data = SceneLoader::getMeshRigidBodyData(body->_node->getId());
 
     // Copy the scaled vertex position data to the rigid body's local buffer.
     Matrix m;
-    Matrix::createScale(body->_node->getScaleX(), body->_node->getScaleY(), body->_node->getScaleZ(), &m);
+    Matrix::createScale(scale, &m);
     unsigned int vertexCount = data->mesh->getVertexCount();
     body->_vertexData = new float[vertexCount * 3];
     Vector3 v;
@@ -467,7 +480,7 @@ btCollisionShape* PhysicsController::createMesh(PhysicsRigidBody* body)
             indexedMesh.m_numTriangles = meshPart->getIndexCount() / 3;
             indexedMesh.m_numVertices = meshPart->getIndexCount();
             indexedMesh.m_triangleIndexBase = (const unsigned char*)body->_indexData[i];
-            indexedMesh.m_triangleIndexStride = indexStride;
+            indexedMesh.m_triangleIndexStride = indexStride*3;
             indexedMesh.m_vertexBase = (const unsigned char*)body->_vertexData;
             indexedMesh.m_vertexStride = sizeof(float)*3;
             indexedMesh.m_vertexType = PHY_FLOAT;
@@ -664,4 +677,4 @@ int	PhysicsController::DebugDrawer::getDebugMode() const
     return _mode;
 }
 
-}
+}

+ 2 - 2
gameplay/src/PhysicsController.h

@@ -253,7 +253,7 @@ private:
     btCollisionShape* createSphere(float radius, const btVector3& scale);
 
     // Creates a triangle mesh collision shape to be used in the creation of a rigid body.
-    btCollisionShape* createMesh(PhysicsRigidBody* body);
+    btCollisionShape* createMesh(PhysicsRigidBody* body, const Vector3& scale);
 
     // Sets up the given constraint for the given two rigid bodies.
     void addConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b, PhysicsConstraint* constraint);
@@ -312,4 +312,4 @@ private:
 
 }
 
-#endif
+#endif

+ 5 - 3
gameplay/src/PhysicsRigidBody.cpp

@@ -44,7 +44,7 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, floa
         }
         case SHAPE_MESH:
         {
-            _shape = Game::getInstance()->getPhysicsController()->createMesh(this);
+            _shape = Game::getInstance()->getPhysicsController()->createMesh(this, node->getScale());
             break;
         }
     }
@@ -583,11 +583,13 @@ btScalar PhysicsRigidBody::Listener::addSingleResult(btManifoldPoint& cp,
     if (_collisionStatus.count(pair) > 0)
     {
         if ((_collisionStatus[pair] & COLLISION) == 0)
-            collisionEvent(pair, Vector3(cp.getPositionWorldOnA().x(), cp.getPositionWorldOnA().y(), cp.getPositionWorldOnA().z()));
+            collisionEvent(COLLIDING, pair, Vector3(cp.getPositionWorldOnA().x(), cp.getPositionWorldOnA().y(), cp.getPositionWorldOnA().z()),
+                Vector3(cp.getPositionWorldOnB().x(), cp.getPositionWorldOnB().y(), cp.getPositionWorldOnB().z()));
     }
     else
     {
-        collisionEvent(pair, Vector3(cp.getPositionWorldOnA().x(), cp.getPositionWorldOnA().y(), cp.getPositionWorldOnA().z()));
+        collisionEvent(COLLIDING, pair, Vector3(cp.getPositionWorldOnA().x(), cp.getPositionWorldOnA().y(), cp.getPositionWorldOnA().z()),
+            Vector3(cp.getPositionWorldOnB().x(), cp.getPositionWorldOnB().y(), cp.getPositionWorldOnB().z()));
     }
 
     // Update the collision status cache (we remove the dirty bit

+ 22 - 6
gameplay/src/PhysicsRigidBody.h

@@ -75,21 +75,37 @@ public:
         friend class PhysicsController;
 
     public:
+        /**
+         * The type of collision event.
+         */
+        enum EventType
+        {
+            /**
+             * Event fired when the two rigid bodies start colliding.
+             */
+            COLLIDING,
+
+            /**
+             * Event fired when the two rigid bodies no longer collide.
+             */
+            NOT_COLLIDING
+        };
+
         /**
          * Destructor.
          */
         virtual ~Listener();
 
         /**
-         * Handles when a collision occurs for the rigid body where this listener is registered.
+         * Handles when a collision starts or stops occurring for the rigid body where this listener is registered.
          * 
+         * @param type The type of collision event.
          * @param collisionPair The two rigid bodies involved in the collision.
-         * @param contactPoint The point (in world space) where the collision occurred.
+         * @param contactPointA The contact point with the first rigid body (in world space).
+         * @param contactPointB The contact point with the second rigid body (in world space).
          */
-        virtual void collisionEvent(const CollisionPair& collisionPair, const Vector3& contactPoint) = 0;
-        
-    protected:
-        
+        virtual void collisionEvent(EventType type, const CollisionPair& collisionPair, const Vector3& contactPointA = Vector3(), const Vector3& contactPointB = Vector3()) = 0;
+
         /**
          * Internal function used for Bullet integration (do not use or override).
          */