2
0
Эх сурвалжийг харах

Adds findContact to regular physics bodies so that they can find contacting objects and surfaces in a way similar to players.

Areloch 9 жил өмнө
parent
commit
b64123a452

+ 64 - 0
Engine/source/T3D/physics/bullet/btBody.cpp

@@ -378,3 +378,67 @@ void BtBody::setSimulationEnabled( bool enabled )
 
 
    mIsEnabled = enabled;
    mIsEnabled = enabled;
 }
 }
+
+void BtBody::findContact(SceneObject **contactObject,
+   VectorF *contactNormal,
+   Vector<SceneObject*> *outOverlapObjects) const
+{
+   AssertFatal(mActor, "BtPlayer::findContact - The controller is null!");
+
+   VectorF normal;
+   F32 maxDot = -1.0f;
+
+   // Go thru the contact points... get the first contact.
+   //mWorld->getDynamicsWorld()->computeOverlappingPairs();
+   btOverlappingPairCache *pairCache = mWorld->getDynamicsWorld()->getBroadphase()->getOverlappingPairCache();
+
+   btBroadphasePairArray& pairArray = pairCache->getOverlappingPairArray();
+   U32 numPairs = pairArray.size();
+   btManifoldArray manifoldArray;
+
+   for (U32 i = 0; i < numPairs; i++)
+   {
+      const btBroadphasePair &pair = pairArray[i];
+
+      btBroadphasePair *collisionPair = pairCache->findPair(pair.m_pProxy0, pair.m_pProxy1);
+      if (!collisionPair || !collisionPair->m_algorithm)
+         continue;
+
+      btCollisionObject *other = (btCollisionObject*)pair.m_pProxy0->m_clientObject;
+      if (other == mActor)
+         other = (btCollisionObject*)pair.m_pProxy1->m_clientObject;
+
+     // AssertFatal(!outOverlapObjects->contains(PhysicsUserData::getObject(other->getUserPointer())),
+      //   "Got multiple pairs of the same object!");
+      outOverlapObjects->push_back(PhysicsUserData::getObject(other->getUserPointer()));
+
+      if (other->getCollisionFlags() & btCollisionObject::CF_NO_CONTACT_RESPONSE)
+         continue;
+
+      manifoldArray.clear();
+      collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
+
+      for (U32 j = 0; j < manifoldArray.size(); j++)
+      {
+         btPersistentManifold *manifold = manifoldArray[j];
+         btScalar directionSign = manifold->getBody0() == mActor ? 1.0f : -1.0f;
+
+         for (U32 p = 0; p < manifold->getNumContacts(); p++)
+         {
+            const btManifoldPoint &pt = manifold->getContactPoint(p);
+
+            // Test the normal... is it the most vertical one we got?
+            normal = btCast<Point3F>(pt.m_normalWorldOnB * directionSign);
+            F32 dot = mDot(normal, VectorF(0, 0, 1));
+            if (dot > maxDot)
+            {
+               maxDot = dot;
+
+               btCollisionObject *colObject = (btCollisionObject*)collisionPair->m_pProxy0->m_clientObject;
+               *contactObject = PhysicsUserData::getObject(colObject->getUserPointer());
+               *contactNormal = normal;
+            }
+         }
+      }
+   }
+}

+ 2 - 0
Engine/source/T3D/physics/bullet/btBody.h

@@ -111,6 +111,8 @@ public:
                               F32 staticFriction );
                               F32 staticFriction );
    virtual void applyCorrection( const MatrixF &xfm );
    virtual void applyCorrection( const MatrixF &xfm );
    virtual void applyImpulse( const Point3F &origin, const Point3F &force );
    virtual void applyImpulse( const Point3F &origin, const Point3F &force );
+
+   virtual void findContact(SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects) const;
 };
 };
 
 
 #endif // _T3D_PHYSICS_BTBODY_H_
 #endif // _T3D_PHYSICS_BTBODY_H_

+ 4 - 0
Engine/source/T3D/physics/physicsBody.h

@@ -113,6 +113,10 @@ public:
 
 
    ///
    ///
    virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0;
    virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0;
+
+   virtual void findContact(SceneObject **contactObject,
+      VectorF *contactNormal,
+      Vector<SceneObject*> *outOverlapObjects) const = 0;
 };
 };
 
 
 
 

+ 52 - 0
Engine/source/T3D/physics/physx3/px3Body.cpp

@@ -417,3 +417,55 @@ void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force )
 
 
 }
 }
 
 
+void Px3Body::findContact(SceneObject **contactObject,
+   VectorF *contactNormal,
+   Vector<SceneObject*> *outOverlapObjects) const
+{
+   // Calculate the sweep motion...
+   F32 halfCapSize = mOriginOffset;
+   F32 halfSmallCapSize = halfCapSize * 0.8f;
+   F32 diff = halfCapSize - halfSmallCapSize;
+
+   F32 distance = diff + mSkinWidth + 0.01f;
+   physx::PxVec3 dir(0, 0, -1);
+
+   physx::PxScene *scene = mWorld->getScene();
+   physx::PxHitFlags hitFlags(physx::PxHitFlag::eDEFAULT);
+   physx::PxQueryFilterData filterData(physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::eSTATIC);
+   filterData.data.word0 = PX3_DEFAULT;
+   physx::PxSweepHit sweepHit;
+   physx::PxRigidDynamic *actor = mController->getActor();
+   physx::PxU32 shapeIndex;
+
+   bool hit = physx::PxRigidBodyExt::linearSweepSingle(*actor, *scene, dir, distance, hitFlags, sweepHit, shapeIndex, filterData);
+   if (hit)
+   {
+      PhysicsUserData *data = PhysicsUserData::cast(sweepHit.actor->userData);
+      if (data)
+      {
+         *contactObject = data->getObject();
+         *contactNormal = px3Cast<Point3F>(sweepHit.normal);
+      }
+   }
+
+   // Check for overlapped objects ( triggers )
+
+   if (!outOverlapObjects)
+      return;
+
+   filterData.data.word0 = PX3_TRIGGER;
+
+   const physx::PxU32 bufferSize = 10;
+   physx::PxOverlapBufferN<bufferSize> hitBuffer;
+   hit = scene->overlap(mGeometry, actor->getGlobalPose(), hitBuffer, filterData);
+   if (hit)
+   {
+      for (U32 i = 0; i < hitBuffer.nbTouches; i++)
+      {
+         PhysicsUserData *data = PhysicsUserData::cast(hitBuffer.touches[i].actor->userData);
+         if (data)
+            outOverlapObjects->push_back(data->getObject());
+      }
+   }
+
+}

+ 3 - 0
Engine/source/T3D/physics/physx3/px3Body.h

@@ -117,6 +117,9 @@ public:
                               F32 staticFriction );
                               F32 staticFriction );
    virtual void applyCorrection( const MatrixF &xfm );
    virtual void applyCorrection( const MatrixF &xfm );
    virtual void applyImpulse( const Point3F &origin, const Point3F &force );
    virtual void applyImpulse( const Point3F &origin, const Point3F &force );
+
+   virtual void findContact(SceneObject **contactObject, VectorF *contactNormal,
+      Vector<SceneObject*> *outOverlapObjects) const;
 };
 };
 
 
 #endif // _PX3BODY_H_
 #endif // _PX3BODY_H_