Forráskód Böngészése

Merge pull request #1966 from eugeneko/master

Re-factored PhysicsWorld2D::ContactInfo. Removed NodeEndContact2D::P_…
Eugene Kozlov 8 éve
szülő
commit
d2ac2067c6

+ 1 - 0
Docs/Urho3D.dox

@@ -1090,6 +1090,7 @@ From 1.6 to master:
 - AnimatedModel allows unclamped morph weights, also negative.
 - AnimatedModel allows unclamped morph weights, also negative.
 - StaticModel::SetModel() will no longer warn and redirect to AnimatedModel::SetModel() if the wrong function is called from C++ code. The AngelScript API will instead redirect properly without producing a warning.
 - StaticModel::SetModel() will no longer warn and redirect to AnimatedModel::SetModel() if the wrong function is called from C++ code. The AngelScript API will instead redirect properly without producing a warning.
 - Graphics::SetMode(), Graphics::GetDesktopResolution() and Graphics::GetResolutions() have gained an extra parameter to specify the monitor to use. Use Graphics::GetMonitorCount() to get the number of attached monitors. Monitor number 0 means the default primary monitor.
 - Graphics::SetMode(), Graphics::GetDesktopResolution() and Graphics::GetResolutions() have gained an extra parameter to specify the monitor to use. Use Graphics::GetMonitorCount() to get the number of attached monitors. Monitor number 0 means the default primary monitor.
+- P_CONTACT parameter was removed from 2D physics collision events. Use P_CONTACTS buffer instead.
 - Build system - the "Urho3D-CMake-common.cmake" file is now renamed to "UrhoCommon.cmake".
 - Build system - the "Urho3D-CMake-common.cmake" file is now renamed to "UrhoCommon.cmake".
 - Build system - downstream project is now responsible to add the HTML shell-file by calling the add_html_shell() macro or by passing "HTML_SHELL" option when calling the define_resource_dirs() in order to generate the HTML output when targeting Web platform, i.e. the build system defaults to JS output now, except when URHO3D_TESTING build option is set. When URHO3D_TESTING is set then it is assumed the output should be test runnable by using emrun, therefore the build system will automatically add the default HTML shell-file if none has been added yet.
 - Build system - downstream project is now responsible to add the HTML shell-file by calling the add_html_shell() macro or by passing "HTML_SHELL" option when calling the define_resource_dirs() in order to generate the HTML output when targeting Web platform, i.e. the build system defaults to JS output now, except when URHO3D_TESTING build option is set. When URHO3D_TESTING is set then it is assumed the output should be test runnable by using emrun, therefore the build system will automatically add the default HTML shell-file if none has been added yet.
 - Build system - when targeting macOS platform, the build tree will be configured to only target x86_64 arch by default as we are phasing out 32-bit mode. Use the URHO3D_UNIVERSAL build option, if you still want the universal binary build.
 - Build system - when targeting macOS platform, the build tree will be configured to only target x86_64 arch by default as we are phasing out 32-bit mode. Use the URHO3D_UNIVERSAL build option, if you still want the universal binary build.

+ 4 - 3
Source/Urho3D/Physics/PhysicsWorld.cpp

@@ -151,6 +151,7 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     world_->setDebugDrawer(this);
     world_->setDebugDrawer(this);
     world_->setInternalTickCallback(InternalPreTickCallback, static_cast<void*>(this), true);
     world_->setInternalTickCallback(InternalPreTickCallback, static_cast<void*>(this), true);
     world_->setInternalTickCallback(InternalTickCallback, static_cast<void*>(this), false);
     world_->setInternalTickCallback(InternalTickCallback, static_cast<void*>(this), false);
+    world_->setSynchronizeAllMotionStates(true);
 }
 }
 
 
 
 
@@ -646,15 +647,15 @@ void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const BoundingB
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const RigidBody* body)
 void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const RigidBody* body)
 {
 {
     URHO3D_PROFILE(PhysicsBodyQuery);
     URHO3D_PROFILE(PhysicsBodyQuery);
-    
+
     result.Clear();
     result.Clear();
-    
+
     if (!body || !body->GetBody())
     if (!body || !body->GetBody())
         return;
         return;
 
 
     PhysicsQueryCallback callback(result, body->GetCollisionMask());
     PhysicsQueryCallback callback(result, body->GetCollisionMask());
     world_->contactTest(body->GetBody(), callback);
     world_->contactTest(body->GetBody(), callback);
-    
+
     // Remove the body itself from the returned list
     // Remove the body itself from the returned list
     for (unsigned i = 0; i < result.Size(); i++)
     for (unsigned i = 0; i < result.Size(); i++)
     {
     {

+ 6 - 12
Source/Urho3D/Urho2D/PhysicsEvents2D.h

@@ -39,8 +39,7 @@ URHO3D_EVENT(E_PHYSICSUPDATECONTACT2D, PhysicsUpdateContact2D)
     URHO3D_PARAM(P_BODYB, BodyB);                  // RigidBody2D pointer
     URHO3D_PARAM(P_BODYB, BodyB);                  // RigidBody2D pointer
     URHO3D_PARAM(P_NODEA, NodeA);                  // Node pointer
     URHO3D_PARAM(P_NODEA, NodeA);                  // Node pointer
     URHO3D_PARAM(P_NODEB, NodeB);                  // Node pointer
     URHO3D_PARAM(P_NODEB, NodeB);                  // Node pointer
-    URHO3D_PARAM(P_CONTACT, Contact);              // b2Contact pointer
-    URHO3D_PARAM(P_CONTACTPOINTS, ContactPoints);  // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
+    URHO3D_PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
     URHO3D_PARAM(P_SHAPEA, ShapeA);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEA, ShapeA);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEB, ShapeB);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEB, ShapeB);                // CollisionShape2D pointer
     URHO3D_PARAM(P_ENABLED, Enabled);              // bool [in/out]
     URHO3D_PARAM(P_ENABLED, Enabled);              // bool [in/out]
@@ -54,8 +53,7 @@ URHO3D_EVENT(E_PHYSICSBEGINCONTACT2D, PhysicsBeginContact2D)
     URHO3D_PARAM(P_BODYB, BodyB);                  // RigidBody2D pointer
     URHO3D_PARAM(P_BODYB, BodyB);                  // RigidBody2D pointer
     URHO3D_PARAM(P_NODEA, NodeA);                  // Node pointer
     URHO3D_PARAM(P_NODEA, NodeA);                  // Node pointer
     URHO3D_PARAM(P_NODEB, NodeB);                  // Node pointer
     URHO3D_PARAM(P_NODEB, NodeB);                  // Node pointer
-    URHO3D_PARAM(P_CONTACT, Contact);              // b2Contact pointer
-    URHO3D_PARAM(P_CONTACTPOINTS, ContactPoints);  // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
+    URHO3D_PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
     URHO3D_PARAM(P_SHAPEA, ShapeA);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEA, ShapeA);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEB, ShapeB);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEB, ShapeB);                // CollisionShape2D pointer
 }
 }
@@ -68,8 +66,7 @@ URHO3D_EVENT(E_PHYSICSENDCONTACT2D, PhysicsEndContact2D)
     URHO3D_PARAM(P_BODYB, BodyB);                  // RigidBody2D pointer
     URHO3D_PARAM(P_BODYB, BodyB);                  // RigidBody2D pointer
     URHO3D_PARAM(P_NODEA, NodeA);                  // Node pointer
     URHO3D_PARAM(P_NODEA, NodeA);                  // Node pointer
     URHO3D_PARAM(P_NODEB, NodeB);                  // Node pointer
     URHO3D_PARAM(P_NODEB, NodeB);                  // Node pointer
-    URHO3D_PARAM(P_CONTACT, Contact);              // b2Contact pointer
-    URHO3D_PARAM(P_CONTACTPOINTS, ContactPoints);  // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
+    URHO3D_PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
     URHO3D_PARAM(P_SHAPEA, ShapeA);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEA, ShapeA);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEB, ShapeB);                // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPEB, ShapeB);                // CollisionShape2D pointer
 }
 }
@@ -80,8 +77,7 @@ URHO3D_EVENT(E_NODEUPDATECONTACT2D, NodeUpdateContact2D)
     URHO3D_PARAM(P_BODY, Body);                    // RigidBody2D pointer
     URHO3D_PARAM(P_BODY, Body);                    // RigidBody2D pointer
     URHO3D_PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     URHO3D_PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     URHO3D_PARAM(P_OTHERBODY, OtherBody);          // RigidBody2D pointer
     URHO3D_PARAM(P_OTHERBODY, OtherBody);          // RigidBody2D pointer
-    URHO3D_PARAM(P_CONTACT, Contact);              // b2Contact pointer
-    URHO3D_PARAM(P_CONTACTPOINTS, ContactPoints);  // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
+    URHO3D_PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
     URHO3D_PARAM(P_SHAPE, Shape);                  // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPE, Shape);                  // CollisionShape2D pointer
     URHO3D_PARAM(P_OTHERSHAPE, OtherShape);        // CollisionShape2D pointer
     URHO3D_PARAM(P_OTHERSHAPE, OtherShape);        // CollisionShape2D pointer
     URHO3D_PARAM(P_ENABLED, Enabled);              // bool [in/out]
     URHO3D_PARAM(P_ENABLED, Enabled);              // bool [in/out]
@@ -93,8 +89,7 @@ URHO3D_EVENT(E_NODEBEGINCONTACT2D, NodeBeginContact2D)
     URHO3D_PARAM(P_BODY, Body);                    // RigidBody2D pointer
     URHO3D_PARAM(P_BODY, Body);                    // RigidBody2D pointer
     URHO3D_PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     URHO3D_PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     URHO3D_PARAM(P_OTHERBODY, OtherBody);          // RigidBody2D pointer
     URHO3D_PARAM(P_OTHERBODY, OtherBody);          // RigidBody2D pointer
-    URHO3D_PARAM(P_CONTACT, Contact);              // b2Contact pointer
-    URHO3D_PARAM(P_CONTACTPOINTS, ContactPoints);  // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
+    URHO3D_PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
     URHO3D_PARAM(P_SHAPE, Shape);                  // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPE, Shape);                  // CollisionShape2D pointer
     URHO3D_PARAM(P_OTHERSHAPE, OtherShape);        // CollisionShape2D pointer
     URHO3D_PARAM(P_OTHERSHAPE, OtherShape);        // CollisionShape2D pointer
 }
 }
@@ -105,8 +100,7 @@ URHO3D_EVENT(E_NODEENDCONTACT2D, NodeEndContact2D)
     URHO3D_PARAM(P_BODY, Body);                    // RigidBody2D pointer
     URHO3D_PARAM(P_BODY, Body);                    // RigidBody2D pointer
     URHO3D_PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     URHO3D_PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     URHO3D_PARAM(P_OTHERBODY, OtherBody);          // RigidBody2D pointer
     URHO3D_PARAM(P_OTHERBODY, OtherBody);          // RigidBody2D pointer
-    URHO3D_PARAM(P_CONTACT, Contact);              // b2Contact pointer
-    URHO3D_PARAM(P_CONTACTPOINTS, ContactPoints);  // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
+    URHO3D_PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector2), normal (Vector2), negative overlap distance (float). Normal is the same for all points.
     URHO3D_PARAM(P_SHAPE, Shape);                  // CollisionShape2D pointer
     URHO3D_PARAM(P_SHAPE, Shape);                  // CollisionShape2D pointer
     URHO3D_PARAM(P_OTHERSHAPE, OtherShape);        // CollisionShape2D pointer
     URHO3D_PARAM(P_OTHERSHAPE, OtherShape);        // CollisionShape2D pointer
 }
 }

+ 25 - 36
Source/Urho3D/Urho2D/PhysicsWorld2D.cpp

@@ -46,21 +46,6 @@ static const Vector2 DEFAULT_GRAVITY(0.0f, -9.81f);
 static const int DEFAULT_VELOCITY_ITERATIONS = 8;
 static const int DEFAULT_VELOCITY_ITERATIONS = 8;
 static const int DEFAULT_POSITION_ITERATIONS = 3;
 static const int DEFAULT_POSITION_ITERATIONS = 3;
 
 
-// Helper function to write contact info into buffer.
-const PODVector<unsigned char>& WriteContactInfo(VectorBuffer& buffer, b2Contact* contact)
-{
-    buffer.Clear();
-    b2WorldManifold worldManifold;
-    contact->GetWorldManifold(&worldManifold);
-    for (int i = 0; i < contact->GetManifold()->pointCount; ++i)
-    {
-        buffer.WriteVector2(Vector2(worldManifold.points[i].x, worldManifold.points[i].y));
-        buffer.WriteVector2(Vector2(worldManifold.normal.x, worldManifold.normal.y));
-        buffer.WriteFloat(worldManifold.separations[i]);
-    }
-    return buffer.GetBuffer();
-}
-
 PhysicsWorld2D::PhysicsWorld2D(Context* context) :
 PhysicsWorld2D::PhysicsWorld2D(Context* context) :
     Component(context),
     Component(context),
     gravity_(DEFAULT_GRAVITY),
     gravity_(DEFAULT_GRAVITY),
@@ -168,8 +153,7 @@ void PhysicsWorld2D::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
     eventData[PhysicsUpdateContact2D::P_BODYB] = contactInfo.bodyB_.Get();
     eventData[PhysicsUpdateContact2D::P_BODYB] = contactInfo.bodyB_.Get();
     eventData[PhysicsUpdateContact2D::P_NODEA] = contactInfo.nodeA_.Get();
     eventData[PhysicsUpdateContact2D::P_NODEA] = contactInfo.nodeA_.Get();
     eventData[PhysicsUpdateContact2D::P_NODEB] = contactInfo.nodeB_.Get();
     eventData[PhysicsUpdateContact2D::P_NODEB] = contactInfo.nodeB_.Get();
-    eventData[PhysicsUpdateContact2D::P_CONTACT] = (void*)contactInfo.contact_;
-    eventData[PhysicsUpdateContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_);
+    eventData[PhysicsUpdateContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_);
     eventData[PhysicsUpdateContact2D::P_SHAPEA] = contactInfo.shapeA_.Get();
     eventData[PhysicsUpdateContact2D::P_SHAPEA] = contactInfo.shapeA_.Get();
     eventData[PhysicsUpdateContact2D::P_SHAPEB] = contactInfo.shapeB_.Get();
     eventData[PhysicsUpdateContact2D::P_SHAPEB] = contactInfo.shapeB_.Get();
 
 
@@ -179,8 +163,7 @@ void PhysicsWorld2D::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
 
 
     // Send node event
     // Send node event
     eventData[NodeUpdateContact2D::P_ENABLED] = contact->IsEnabled();
     eventData[NodeUpdateContact2D::P_ENABLED] = contact->IsEnabled();
-    eventData[NodeUpdateContact2D::P_CONTACT] = (void*)contactInfo.contact_;
-    eventData[NodeUpdateContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_);
+    eventData[NodeUpdateContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_);
 
 
     if (contactInfo.nodeA_)
     if (contactInfo.nodeA_)
     {
     {
@@ -758,15 +741,13 @@ void PhysicsWorld2D::SendBeginContactEvents()
         eventData[P_BODYB] = contactInfo.bodyB_.Get();
         eventData[P_BODYB] = contactInfo.bodyB_.Get();
         eventData[P_NODEA] = contactInfo.nodeA_.Get();
         eventData[P_NODEA] = contactInfo.nodeA_.Get();
         eventData[P_NODEB] = contactInfo.nodeB_.Get();
         eventData[P_NODEB] = contactInfo.nodeB_.Get();
-        eventData[P_CONTACT] = (void*)contactInfo.contact_;
-        eventData[P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_);
+        eventData[P_CONTACTS] = contactInfo.Serialize(contacts_);
         eventData[P_SHAPEA] = contactInfo.shapeA_.Get();
         eventData[P_SHAPEA] = contactInfo.shapeA_.Get();
         eventData[P_SHAPEB] = contactInfo.shapeB_.Get();
         eventData[P_SHAPEB] = contactInfo.shapeB_.Get();
 
 
         SendEvent(E_PHYSICSBEGINCONTACT2D, eventData);
         SendEvent(E_PHYSICSBEGINCONTACT2D, eventData);
 
 
-        nodeEventData[NodeBeginContact2D::P_CONTACT] = (void*)contactInfo.contact_;
-        nodeEventData[NodeBeginContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_);
+        nodeEventData[NodeBeginContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_);
 
 
         if (contactInfo.nodeA_)
         if (contactInfo.nodeA_)
         {
         {
@@ -811,15 +792,13 @@ void PhysicsWorld2D::SendEndContactEvents()
         eventData[P_BODYB] = contactInfo.bodyB_.Get();
         eventData[P_BODYB] = contactInfo.bodyB_.Get();
         eventData[P_NODEA] = contactInfo.nodeA_.Get();
         eventData[P_NODEA] = contactInfo.nodeA_.Get();
         eventData[P_NODEB] = contactInfo.nodeB_.Get();
         eventData[P_NODEB] = contactInfo.nodeB_.Get();
-        eventData[P_CONTACT] = (void*)contactInfo.contact_;
-        eventData[P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_);
+        eventData[P_CONTACTS] = contactInfo.Serialize(contacts_);
         eventData[P_SHAPEA] = contactInfo.shapeA_.Get();
         eventData[P_SHAPEA] = contactInfo.shapeA_.Get();
         eventData[P_SHAPEB] = contactInfo.shapeB_.Get();
         eventData[P_SHAPEB] = contactInfo.shapeB_.Get();
 
 
         SendEvent(E_PHYSICSENDCONTACT2D, eventData);
         SendEvent(E_PHYSICSENDCONTACT2D, eventData);
 
 
-        nodeEventData[NodeEndContact2D::P_CONTACT] = (void*)contactInfo.contact_;
-        nodeEventData[NodeEndContact2D::P_CONTACTPOINTS] = WriteContactInfo(contacts_, contactInfo.contact_);
+        nodeEventData[NodeEndContact2D::P_CONTACTS] = contactInfo.Serialize(contacts_);
 
 
         if (contactInfo.nodeA_)
         if (contactInfo.nodeA_)
         {
         {
@@ -859,20 +838,30 @@ PhysicsWorld2D::ContactInfo::ContactInfo(b2Contact* contact)
     bodyB_ = (RigidBody2D*)(fixtureB->GetBody()->GetUserData());
     bodyB_ = (RigidBody2D*)(fixtureB->GetBody()->GetUserData());
     nodeA_ = bodyA_->GetNode();
     nodeA_ = bodyA_->GetNode();
     nodeB_ = bodyB_->GetNode();
     nodeB_ = bodyB_->GetNode();
-    contact_ = contact;
     shapeA_ = (CollisionShape2D*)fixtureA->GetUserData();
     shapeA_ = (CollisionShape2D*)fixtureA->GetUserData();
     shapeB_ = (CollisionShape2D*)fixtureB->GetUserData();
     shapeB_ = (CollisionShape2D*)fixtureB->GetUserData();
+
+    b2WorldManifold worldManifold;
+    contact->GetWorldManifold(&worldManifold);
+    numPoints_ = contact->GetManifold()->pointCount;
+    worldNormal_ = Vector2(worldManifold.normal.x, worldManifold.normal.y);
+    for (int i = 0; i < numPoints_; ++i)
+    {
+        worldPositions_[i] = Vector2(worldManifold.points[i].x, worldManifold.points[i].y);
+        separations_[i] = worldManifold.separations[i];
+    }
 }
 }
 
 
-PhysicsWorld2D::ContactInfo::ContactInfo(const ContactInfo& other) :
-    bodyA_(other.bodyA_),
-    bodyB_(other.bodyB_),
-    nodeA_(other.nodeA_),
-    nodeB_(other.nodeB_),
-    contact_(other.contact_),
-    shapeA_(other.shapeA_),
-    shapeB_(other.shapeB_)
+const Urho3D::PODVector<unsigned char>& PhysicsWorld2D::ContactInfo::Serialize(VectorBuffer& buffer) const
 {
 {
+    buffer.Clear();
+    for (int i = 0; i < numPoints_; ++i)
+    {
+        buffer.WriteVector2(worldPositions_[i]);
+        buffer.WriteVector2(worldNormal_);
+        buffer.WriteFloat(separations_[i]);
+    }
+    return buffer.GetBuffer();
 }
 }
 
 
 }
 }

+ 10 - 4
Source/Urho3D/Urho2D/PhysicsWorld2D.h

@@ -256,8 +256,8 @@ protected:
         ContactInfo();
         ContactInfo();
         /// Construct.
         /// Construct.
         ContactInfo(b2Contact* contract);
         ContactInfo(b2Contact* contract);
-        /// Copy construct.
-        ContactInfo(const ContactInfo& other);
+        /// Write contact info to buffer.
+        const PODVector<unsigned char>& Serialize(VectorBuffer& buffer) const;
 
 
         /// Rigid body A.
         /// Rigid body A.
         SharedPtr<RigidBody2D> bodyA_;
         SharedPtr<RigidBody2D> bodyA_;
@@ -267,12 +267,18 @@ protected:
         SharedPtr<Node> nodeA_;
         SharedPtr<Node> nodeA_;
         /// Node B.
         /// Node B.
         SharedPtr<Node> nodeB_;
         SharedPtr<Node> nodeB_;
-        /// Box2D contact.
-        b2Contact* contact_;
         /// Shape A.
         /// Shape A.
         SharedPtr<CollisionShape2D> shapeA_;
         SharedPtr<CollisionShape2D> shapeA_;
         /// Shape B.
         /// Shape B.
         SharedPtr<CollisionShape2D> shapeB_;
         SharedPtr<CollisionShape2D> shapeB_;
+        /// Number of contact points.
+        int numPoints_;
+        /// Contact normal in world space.
+        Vector2 worldNormal_;
+        /// Contact positions in world space.
+        Vector2 worldPositions_[b2_maxManifoldPoints];
+        /// Contact overlap values.
+        float separations_[b2_maxManifoldPoints];
     };
     };
     /// Begin contact infos.
     /// Begin contact infos.
     Vector<ContactInfo> beginContactInfos_;
     Vector<ContactInfo> beginContactInfos_;