소스 검색

Triggering collider callbacks

BearishSun 10 년 전
부모
커밋
9b97a26cd4

+ 1 - 1
BansheeCore/Include/BsCollider.h

@@ -39,7 +39,7 @@ namespace BansheeEngine
 		inline void setLayer(UINT64 layer);
 		inline void setLayer(UINT64 layer);
 		inline UINT64 getLayer() const;
 		inline UINT64 getLayer() const;
 
 
-		Event<void(const CollisionData&)> onCollisionStart;
+		Event<void(const CollisionData&)> onCollisionBegin;
 		Event<void(const CollisionData&)> onCollisionStay;
 		Event<void(const CollisionData&)> onCollisionStay;
 		Event<void(const CollisionData&)> onCollisionEnd;
 		Event<void(const CollisionData&)> onCollisionEnd;
 
 

+ 2 - 2
BansheeCore/Include/BsCollision.h

@@ -18,7 +18,7 @@ namespace BansheeEngine
 
 
 	struct CollisionData
 	struct CollisionData
 	{
 	{
-		SPtr<Collider> collider;
-		Vector<ContactPoint> contactPoints;
+		Collider* collider;
+		Vector<ContactPoint> contactPoints; // Note: Not too happy this is heap allocated, use static allocator?
 	};
 	};
 }
 }

+ 1 - 1
BansheeCore/Include/BsRigidbody.h

@@ -19,7 +19,7 @@ namespace BansheeEngine
 
 
 		static SPtr<Rigidbody> create(const Vector3& position, const Quaternion& rotation);
 		static SPtr<Rigidbody> create(const Vector3& position, const Quaternion& rotation);
 
 
-		Event<void(const CollisionData&)> onCollisionStart;
+		Event<void(const CollisionData&)> onCollisionBegin;
 		Event<void(const CollisionData&)> onCollisionStay;
 		Event<void(const CollisionData&)> onCollisionStay;
 		Event<void(const CollisionData&)> onCollisionEnd;
 		Event<void(const CollisionData&)> onCollisionEnd;
 	protected:
 	protected:

+ 5 - 3
BansheePhysX/Include/BsPhysX.h

@@ -15,9 +15,9 @@ namespace BansheeEngine
 	{
 	{
 		enum class ContactEventType
 		enum class ContactEventType
 		{
 		{
-			ContactStart,
+			ContactBegin,
 			ContactStay,
 			ContactStay,
-			ContactStop
+			ContactEnd
 		};
 		};
 
 
 		struct TriggerEvent
 		struct TriggerEvent
@@ -32,7 +32,7 @@ namespace BansheeEngine
 			Collider* colliderA;
 			Collider* colliderA;
 			Collider* colliderB;
 			Collider* colliderB;
 			ContactEventType type;
 			ContactEventType type;
-			Vector<ContactPoint> points;
+			Vector<ContactPoint> points; // Note: Not too happy this is heap allocated, use static allocator?
 		};
 		};
 
 
 	public:
 	public:
@@ -62,6 +62,8 @@ namespace BansheeEngine
 	private:
 	private:
 		friend class PhysXEventCallback;
 		friend class PhysXEventCallback;
 
 
+		void triggerEvents();
+
 		float mSimulationStep = 1.0f/60.0f;
 		float mSimulationStep = 1.0f/60.0f;
 		float mLastSimulationTime = 0.0f;
 		float mLastSimulationTime = 0.0f;
 
 

+ 1 - 1
BansheePhysX/Source/BsFPhysXCollider.cpp

@@ -9,7 +9,7 @@ using namespace physx;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	FPhysXCollider::FPhysXCollider(physx::PxShape* shape)
+	FPhysXCollider::FPhysXCollider(PxShape* shape)
 		:mShape(shape), mStaticBody(nullptr), mIsTrigger(false)
 		:mShape(shape), mStaticBody(nullptr), mIsTrigger(false)
 	{
 	{
 		mStaticBody = gPhysX().getPhysX()->createRigidStatic(PxTransform());
 		mStaticBody = gPhysX().getPhysX()->createRigidStatic(PxTransform());

+ 83 - 13
BansheePhysX/Source/BsPhysX.cpp

@@ -130,13 +130,13 @@ namespace BansheeEngine
 				switch ((UINT32)pair.status)
 				switch ((UINT32)pair.status)
 				{
 				{
 				case PxPairFlag::eNOTIFY_TOUCH_FOUND:
 				case PxPairFlag::eNOTIFY_TOUCH_FOUND:
-					type = PhysX::ContactEventType::ContactStart;
+					type = PhysX::ContactEventType::ContactBegin;
 					break;
 					break;
 				case PxPairFlag::eNOTIFY_TOUCH_PERSISTS:
 				case PxPairFlag::eNOTIFY_TOUCH_PERSISTS:
 					type = PhysX::ContactEventType::ContactStay;
 					type = PhysX::ContactEventType::ContactStay;
 					break;
 					break;
 				case PxPairFlag::eNOTIFY_TOUCH_LOST:
 				case PxPairFlag::eNOTIFY_TOUCH_LOST:
-					type = PhysX::ContactEventType::ContactStop;
+					type = PhysX::ContactEventType::ContactEnd;
 					break;
 					break;
 				default:
 				default:
 					ignoreContact = true;
 					ignoreContact = true;
@@ -166,13 +166,13 @@ namespace BansheeEngine
 				switch((UINT32)pair.events)
 				switch((UINT32)pair.events)
 				{
 				{
 				case PxPairFlag::eNOTIFY_TOUCH_FOUND:
 				case PxPairFlag::eNOTIFY_TOUCH_FOUND:
-					type = PhysX::ContactEventType::ContactStart;
+					type = PhysX::ContactEventType::ContactBegin;
 					break;
 					break;
 				case PxPairFlag::eNOTIFY_TOUCH_PERSISTS:
 				case PxPairFlag::eNOTIFY_TOUCH_PERSISTS:
 					type = PhysX::ContactEventType::ContactStay;
 					type = PhysX::ContactEventType::ContactStay;
 					break;
 					break;
 				case PxPairFlag::eNOTIFY_TOUCH_LOST:
 				case PxPairFlag::eNOTIFY_TOUCH_LOST:
-					type = PhysX::ContactEventType::ContactStop;
+					type = PhysX::ContactEventType::ContactEnd;
 					break;
 					break;
 				default:
 				default:
 					ignoreContact = true;
 					ignoreContact = true;
@@ -281,7 +281,7 @@ namespace BansheeEngine
 	{
 	{
 		PHYSICS_INIT_DESC input; // TODO - Make this an input parameter.
 		PHYSICS_INIT_DESC input; // TODO - Make this an input parameter.
 
 
-		PxTolerancesScale scale; // TODO - Use these same values for cooking, physx init and scene desc
+		PxTolerancesScale scale;
 		scale.length = input.typicalLength;
 		scale.length = input.typicalLength;
 		scale.speed = input.typicalSpeed;
 		scale.speed = input.typicalSpeed;
 
 
@@ -302,10 +302,6 @@ namespace BansheeEngine
 		sceneDesc.filterShader = PhysXFilterShader;
 		sceneDesc.filterShader = PhysXFilterShader;
 		sceneDesc.simulationEventCallback = &gPhysXEventCallback;
 		sceneDesc.simulationEventCallback = &gPhysXEventCallback;
 
 
-		// TODO - Allow for continuous collision detection, and regions of interest stuff
-		// TODO - Set up various performance limits, call flushCache when needed
-		// TODO - Probably many more startup settings I'm missing
-
 		mScene = mPhysics->createScene(sceneDesc);
 		mScene = mPhysics->createScene(sceneDesc);
 		mSimulationStep = input.timeStep;
 		mSimulationStep = input.timeStep;
 		mDefaultMaterial = mPhysics->createMaterial(0.0f, 0.0f, 0.0f);
 		mDefaultMaterial = mPhysics->createMaterial(0.0f, 0.0f, 0.0f);
@@ -351,10 +347,7 @@ namespace BansheeEngine
 
 
 		mLastSimulationTime = curFrameTime; 
 		mLastSimulationTime = curFrameTime; 
 
 
-		// TODO - Send out contact and trigger events
-
-		mTriggerEvents.clear();
-		mContactEvents.clear();
+		triggerEvents();
 	}
 	}
 
 
 	void PhysX::_reportContactEvent(const ContactEvent& event)
 	void PhysX::_reportContactEvent(const ContactEvent& event)
@@ -367,6 +360,83 @@ namespace BansheeEngine
 		mTriggerEvents.push_back(event);
 		mTriggerEvents.push_back(event);
 	}
 	}
 
 
+	void PhysX::triggerEvents()
+	{
+		CollisionData data;
+
+		for(auto& entry : mTriggerEvents)
+		{
+			data.collider = entry.other;
+
+			switch (entry.type)
+			{
+			case ContactEventType::ContactBegin:
+				entry.trigger->onCollisionBegin(data);
+				break;
+			case ContactEventType::ContactStay:
+				entry.trigger->onCollisionStay(data);
+				break;
+			case ContactEventType::ContactEnd:
+				entry.trigger->onCollisionEnd(data);
+				break;
+			}
+		}
+
+		auto notifyContact = [&](Collider* obj, Collider* other, ContactEventType type, 
+			const Vector<ContactPoint>& points, bool flipNormals = false)
+		{
+			data.collider = other;
+			data.contactPoints = points;
+
+			if(flipNormals)
+			{
+				for (auto& point : data.contactPoints)
+					point.normal = -point.normal;
+			}
+
+			SPtr<Rigidbody> rigidbody = obj->getRigidbody();
+			if(rigidbody != nullptr)
+			{
+				switch (type)
+				{
+				case ContactEventType::ContactBegin:
+					rigidbody->onCollisionBegin(data);
+					break;
+				case ContactEventType::ContactStay:
+					rigidbody->onCollisionStay(data);
+					break;
+				case ContactEventType::ContactEnd:
+					rigidbody->onCollisionEnd(data);
+					break;
+				}
+			}
+			else
+			{
+				switch (type)
+				{
+				case ContactEventType::ContactBegin:
+					obj->onCollisionBegin(data);
+					break;
+				case ContactEventType::ContactStay:
+					obj->onCollisionStay(data);
+					break;
+				case ContactEventType::ContactEnd:
+					obj->onCollisionEnd(data);
+					break;
+				}
+			}
+		};
+
+		for (auto& entry : mContactEvents)
+		{
+			notifyContact(entry.colliderA, entry.colliderB, entry.type, entry.points, true);
+			notifyContact(entry.colliderB, entry.colliderA, entry.type, entry.points, false);
+		}
+
+		mTriggerEvents.clear();
+		mContactEvents.clear();
+	}
+
 	SPtr<PhysicsMaterial> PhysX::createMaterial(float staticFriction, float dynamicFriction, float restitution)
 	SPtr<PhysicsMaterial> PhysX::createMaterial(float staticFriction, float dynamicFriction, float restitution)
 	{
 	{
 		return bs_shared_ptr_new<PhysXMaterial>(mPhysics, staticFriction, dynamicFriction, restitution);
 		return bs_shared_ptr_new<PhysXMaterial>(mPhysics, staticFriction, dynamicFriction, restitution);

+ 1 - 0
BansheePhysX/Source/BsPhysXBoxCollider.cpp

@@ -14,6 +14,7 @@ namespace BansheeEngine
 
 
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		shape->setLocalPose(toPxTransform(position, rotation));
 		shape->setLocalPose(toPxTransform(position, rotation));
+		shape->userData = this;
 
 
 		mInternal = bs_new<FPhysXCollider>(shape);
 		mInternal = bs_new<FPhysXCollider>(shape);
 	}
 	}

+ 1 - 0
BansheePhysX/Source/BsPhysXCapsuleCollider.cpp

@@ -14,6 +14,7 @@ namespace BansheeEngine
 
 
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		shape->setLocalPose(toPxTransform(position, rotation));
 		shape->setLocalPose(toPxTransform(position, rotation));
+		shape->userData = this;
 
 
 		mInternal = bs_new<FPhysXCollider>(shape);
 		mInternal = bs_new<FPhysXCollider>(shape);
 	}
 	}

+ 1 - 0
BansheePhysX/Source/BsPhysXPlaneCollider.cpp

@@ -13,6 +13,7 @@ namespace BansheeEngine
 
 
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		shape->setLocalPose(toPxTransform(position, rotation));
 		shape->setLocalPose(toPxTransform(position, rotation));
+		shape->userData = this;
 
 
 		mInternal = bs_new<FPhysXCollider>(shape);
 		mInternal = bs_new<FPhysXCollider>(shape);
 	}
 	}

+ 1 - 0
BansheePhysX/Source/BsPhysXSphereCollider.cpp

@@ -14,6 +14,7 @@ namespace BansheeEngine
 
 
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
 		shape->setLocalPose(toPxTransform(position, rotation));
 		shape->setLocalPose(toPxTransform(position, rotation));
+		shape->userData = this;
 
 
 		mInternal = bs_new<FPhysXCollider>(shape);
 		mInternal = bs_new<FPhysXCollider>(shape);
 	}
 	}