Browse Source

More work on Joints:
- Added onJointBreak callback
- Added a way to enable/disable collisions between joint elements
- Added a restitution parameter to joint limits

BearishSun 10 years ago
parent
commit
b158abffa6

+ 1 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -252,6 +252,7 @@ namespace BansheeEngine
 	class CPlaneCollider;
 	class CCapsuleCollider;
 	class CMeshCollider;
+	class Joint;
 	class FixedJoint;
 	class DistanceJoint;
 	class HingeJoint;

+ 3 - 0
BansheeCore/Include/BsFJoint.h

@@ -30,5 +30,8 @@ namespace BansheeEngine
 
 		virtual float getBreakTorque() const = 0;
 		virtual void setBreakToque(float torque) = 0;
+
+		virtual bool getEnableCollision() const = 0;
+		virtual void setEnableCollision(bool value) = 0;
 	};
 }

+ 8 - 0
BansheeCore/Include/BsJoint.h

@@ -25,6 +25,10 @@ namespace BansheeEngine
 		inline float getBreakTorque() const;
 		inline void setBreakToque(float torque);
 
+		inline bool getEnableCollision() const;
+		inline void setEnableCollision(bool value);
+
+		Event<void()> onJointBreak;
 	protected:
 		FJoint* mInternal = nullptr;
 	};
@@ -56,6 +60,7 @@ namespace BansheeEngine
 		float lower = 0.0f;
 		float upper = 0.0f;
 		float contactDist = -1.0f;
+		float restitution = 0.0f;
 		Spring spring;
 	};
 
@@ -74,6 +79,7 @@ namespace BansheeEngine
 
 		float extent = 0.0f;
 		float contactDist = -1.0f;
+		float restitution = 0.0f;
 		Spring spring;
 	};
 
@@ -93,6 +99,7 @@ namespace BansheeEngine
 		Radian lower = Radian(0.0f);
 		Radian upper = Radian(0.0f);
 		float contactDist = -1.0f;
+		float restitution = 0.0f;
 		Spring spring;
 	};
 
@@ -112,6 +119,7 @@ namespace BansheeEngine
 		Radian yLimitAngle = Radian(Math::PI * 0.5f);
 		Radian zLimitAngle = Radian(Math::PI * 0.5f);
 		float contactDist = -1.0f;
+		float restitution = 0.0f;
 		Spring spring;
 	};
 }

+ 10 - 0
BansheeCore/Source/BsJoint.cpp

@@ -48,4 +48,14 @@ namespace BansheeEngine
 	{
 		mInternal->setBreakToque(torque);
 	}
+
+	bool Joint::getEnableCollision() const
+	{
+		return mInternal->getEnableCollision();
+	}
+
+	void Joint::setEnableCollision(bool value)
+	{
+		mInternal->setEnableCollision(value);
+	}		
 }

+ 3 - 0
BansheePhysX/Include/BsFPhysXJoint.h

@@ -27,6 +27,9 @@ namespace BansheeEngine
 		float getBreakTorque() const override;
 		void setBreakToque(float torque) override;
 
+		bool getEnableCollision() const override;
+		void setEnableCollision(bool value) override;
+
 		physx::PxJoint* _getInternal() const { return mJoint; }
 	protected:
 		physx::PxJoint* mJoint;

+ 7 - 0
BansheePhysX/Include/BsPhysX.h

@@ -35,6 +35,11 @@ namespace BansheeEngine
 			Vector<ContactPoint> points; // Note: Not too happy this is heap allocated, use static allocator?
 		};
 
+		struct JointBreakEvent
+		{
+			Joint* joint;
+		};
+
 	public:
 		PhysX();
 		~PhysX();
@@ -62,6 +67,7 @@ namespace BansheeEngine
 
 		void _reportContactEvent(const ContactEvent& event);
 		void _reportTriggerEvent(const TriggerEvent& event);
+		void _reportJointBreakEvent(const JointBreakEvent& event);
 
 		physx::PxMaterial* getDefaultMaterial() const { return mDefaultMaterial; }
 		physx::PxPhysics* getPhysX() const { return mPhysics; }
@@ -79,6 +85,7 @@ namespace BansheeEngine
 
 		Vector<TriggerEvent> mTriggerEvents;
 		Vector<ContactEvent> mContactEvents;
+		Vector<JointBreakEvent> mJointBreakEvents;
 
 		physx::PxFoundation* mFoundation = nullptr;
 		physx::PxPhysics* mPhysics = nullptr;

+ 10 - 0
BansheePhysX/Source/BsFPhysXJoint.cpp

@@ -116,4 +116,14 @@ namespace BansheeEngine
 		mJoint->getBreakForce(force, dummy);
 		mJoint->setBreakForce(force, torque);
 	}
+
+	bool FPhysXJoint::getEnableCollision() const
+	{
+		return mJoint->getConstraintFlags() & PxConstraintFlag::eCOLLISION_ENABLED;
+	}
+
+	void FPhysXJoint::setEnableCollision(bool value)
+	{
+		mJoint->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED, value);
+	}
 }

+ 27 - 1
BansheePhysX/Source/BsPhysX.cpp

@@ -123,7 +123,6 @@ namespace BansheeEngine
 
 	class PhysXEventCallback : public PxSimulationEventCallback
 	{
-		void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) override { /* Do nothing */ }
 		void onWake(PxActor** actors, PxU32 count) override { /* Do nothing */ }
 		void onSleep(PxActor** actors, PxU32 count) override { /* Do nothing */ }
 
@@ -236,6 +235,22 @@ namespace BansheeEngine
 				gPhysX()._reportContactEvent(event);
 			}
 		}
+
+		void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) override 
+		{ 
+			for (UINT32 i = 0; i < count; i++)
+			{
+				PxConstraintInfo& constraintInfo = constraints[i];
+
+				if (constraintInfo.type != PxConstraintExtIDs::eJOINT)
+					continue;
+
+				PxJoint* pxJoint = (PxJoint*)constraintInfo.externalReference;
+				Joint* joint = (Joint*)pxJoint->userData;
+
+				
+			}
+		}
 	};
 
 	class PhysXCPUDispatcher : public PxCpuDispatcher
@@ -387,6 +402,11 @@ namespace BansheeEngine
 		mTriggerEvents.push_back(event);
 	}
 
+	void PhysX::_reportJointBreakEvent(const JointBreakEvent& event)
+	{
+		mJointBreakEvents.push_back(event);
+	}
+
 	void PhysX::triggerEvents()
 	{
 		CollisionData data;
@@ -460,8 +480,14 @@ namespace BansheeEngine
 			notifyContact(entry.colliderB, entry.colliderA, entry.type, entry.points, false);
 		}
 
+		for(auto& entry : mJointBreakEvents)
+		{
+			entry.joint->onJointBreak();
+		}
+
 		mTriggerEvents.clear();
 		mContactEvents.clear();
+		mJointBreakEvents.clear();
 	}
 
 	SPtr<PhysicsMaterial> PhysX::createMaterial(float staticFriction, float dynamicFriction, float restitution)

+ 7 - 0
BansheePhysX/Source/BsPhysXD6Joint.cpp

@@ -100,6 +100,7 @@ namespace BansheeEngine
 	PhysXD6Joint::PhysXD6Joint(PxPhysics* physx)
 	{
 		PxD6Joint* joint = PxD6JointCreate(*physx, nullptr, PxTransform(), nullptr, PxTransform());
+		joint->userData = this;
 
 		mInternal = bs_new<FPhysXJoint>(joint);
 	}
@@ -141,6 +142,7 @@ namespace BansheeEngine
 		LimitLinear limit;
 		limit.extent = pxLimit.value;
 		limit.contactDist = pxLimit.contactDistance;
+		limit.restitution = pxLimit.restitution;
 		limit.spring.stiffness = pxLimit.stiffness;
 		limit.spring.damping = pxLimit.damping;
 
@@ -152,6 +154,7 @@ namespace BansheeEngine
 		PxJointLinearLimit pxLimit(gPhysX().getScale(), limit.extent, limit.contactDist);
 		pxLimit.stiffness = limit.spring.stiffness;
 		pxLimit.damping = limit.spring.damping;
+		pxLimit.restitution = limit.restitution;
 
 		getInternal()->setLinearLimit(pxLimit);
 	}
@@ -164,6 +167,7 @@ namespace BansheeEngine
 		limit.lower = pxLimit.lower;
 		limit.upper = pxLimit.upper;
 		limit.contactDist = pxLimit.contactDistance;
+		limit.restitution = pxLimit.restitution;
 		limit.spring.stiffness = pxLimit.stiffness;
 		limit.spring.damping = pxLimit.damping;
 
@@ -175,6 +179,7 @@ namespace BansheeEngine
 		PxJointAngularLimitPair pxLimit(limit.lower.valueRadians(), limit.upper.valueRadians(), limit.contactDist);
 		pxLimit.stiffness = limit.spring.stiffness;
 		pxLimit.damping = limit.spring.damping;
+		pxLimit.restitution = limit.restitution;
 
 		getInternal()->setTwistLimit(pxLimit);
 	}
@@ -187,6 +192,7 @@ namespace BansheeEngine
 		limit.yLimitAngle = pxLimit.yAngle;
 		limit.zLimitAngle = pxLimit.zAngle;
 		limit.contactDist = pxLimit.contactDistance;
+		limit.restitution = pxLimit.restitution;
 		limit.spring.stiffness = pxLimit.stiffness;
 		limit.spring.damping = pxLimit.damping;
 
@@ -198,6 +204,7 @@ namespace BansheeEngine
 		PxJointLimitCone pxLimit(limit.yLimitAngle.valueRadians(), limit.zLimitAngle.valueRadians(), limit.contactDist);
 		pxLimit.stiffness = limit.spring.stiffness;
 		pxLimit.damping = limit.spring.damping;
+		pxLimit.restitution = limit.restitution;
 
 		getInternal()->setSwingLimit(pxLimit);
 	}

+ 1 - 0
BansheePhysX/Source/BsPhysXDistanceJoint.cpp

@@ -24,6 +24,7 @@ namespace BansheeEngine
 	PhysXDistanceJoint::PhysXDistanceJoint(PxPhysics* physx)
 	{
 		PxDistanceJoint* joint = PxDistanceJointCreate(*physx, nullptr, PxTransform(), nullptr, PxTransform());
+		joint->userData = this;
 
 		mInternal = bs_new<FPhysXJoint>(joint);
 	}

+ 1 - 0
BansheePhysX/Source/BsPhysXFixedJoint.cpp

@@ -11,6 +11,7 @@ namespace BansheeEngine
 	PhysXFixedJoint::PhysXFixedJoint(PxPhysics* physx)
 	{
 		PxFixedJoint* joint = PxFixedJointCreate(*physx, nullptr, PxTransform(), nullptr, PxTransform());
+		joint->userData = this;
 
 		mInternal = bs_new<FPhysXJoint>(joint);
 	}

+ 3 - 0
BansheePhysX/Source/BsPhysXHingeJoint.cpp

@@ -22,6 +22,7 @@ namespace BansheeEngine
 	PhysXHingeJoint::PhysXHingeJoint(PxPhysics* physx)
 	{
 		PxRevoluteJoint* joint = PxRevoluteJointCreate(*physx, nullptr, PxTransform(), nullptr, PxTransform());
+		joint->userData = this;
 
 		mInternal = bs_new<FPhysXJoint>(joint);
 	}
@@ -49,6 +50,7 @@ namespace BansheeEngine
 		limit.lower = pxLimit.lower;
 		limit.upper = pxLimit.upper;
 		limit.contactDist = pxLimit.contactDistance;
+		limit.restitution = pxLimit.restitution;
 		limit.spring.stiffness = pxLimit.stiffness;
 		limit.spring.damping = pxLimit.damping;
 
@@ -60,6 +62,7 @@ namespace BansheeEngine
 		PxJointAngularLimitPair pxLimit(limit.lower.valueRadians(), limit.upper.valueRadians(), limit.contactDist);
 		pxLimit.stiffness = limit.spring.stiffness;
 		pxLimit.damping = limit.spring.damping;
+		pxLimit.restitution = limit.restitution;
 
 		getInternal()->setLimit(pxLimit);
 	}

+ 3 - 0
BansheePhysX/Source/BsPhysXSliderJoint.cpp

@@ -21,6 +21,7 @@ namespace BansheeEngine
 	PhysXSliderJoint::PhysXSliderJoint(PxPhysics* physx)
 	{
 		PxPrismaticJoint* joint = PxPrismaticJointCreate(*physx, nullptr, PxTransform(), nullptr, PxTransform());
+		joint->userData = this;
 
 		mInternal = bs_new<FPhysXJoint>(joint);
 	}
@@ -48,6 +49,7 @@ namespace BansheeEngine
 		limit.lower = pxLimit.lower;
 		limit.upper = pxLimit.upper;
 		limit.contactDist = pxLimit.contactDistance;
+		limit.restitution = pxLimit.restitution;
 		limit.spring.stiffness = pxLimit.stiffness;
 		limit.spring.damping = pxLimit.damping;
 
@@ -59,6 +61,7 @@ namespace BansheeEngine
 		PxJointLinearLimitPair pxLimit(gPhysX().getScale(), limit.lower, limit.upper, limit.contactDist);
 		pxLimit.stiffness = limit.spring.stiffness;
 		pxLimit.damping = limit.spring.damping;
+		pxLimit.restitution = limit.restitution;
 
 		getInternal()->setLimit(pxLimit);
 	}

+ 3 - 0
BansheePhysX/Source/BsPhysXSphericalJoint.cpp

@@ -20,6 +20,7 @@ namespace BansheeEngine
 	PhysXSphericalJoint::PhysXSphericalJoint(PxPhysics* physx)
 	{
 		PxSphericalJoint* joint = PxSphericalJointCreate(*physx, nullptr, PxTransform(), nullptr, PxTransform());
+		joint->userData = this;
 
 		mInternal = bs_new<FPhysXJoint>(joint);
 	}
@@ -37,6 +38,7 @@ namespace BansheeEngine
 		limit.yLimitAngle = pxLimit.yAngle;
 		limit.zLimitAngle = pxLimit.zAngle;
 		limit.contactDist = pxLimit.contactDistance;
+		limit.restitution = pxLimit.restitution;
 		limit.spring.stiffness = pxLimit.stiffness;
 		limit.spring.damping = pxLimit.damping;
 
@@ -48,6 +50,7 @@ namespace BansheeEngine
 		PxJointLimitCone pxLimit(limit.yLimitAngle.valueRadians(), limit.zLimitAngle.valueRadians(), limit.contactDist);
 		pxLimit.stiffness = limit.spring.stiffness;
 		pxLimit.damping = limit.spring.damping;
+		pxLimit.restitution = limit.restitution;
 
 		getInternal()->setLimitCone(pxLimit);
 	}