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

Fixed UBSAN false positive that detected a dirty trick in SimShapeFilter (#1671)

Fixes #1667
Jorrit Rouwe 1 сар өмнө
parent
commit
56131e0342

+ 11 - 34
Jolt/Physics/Collision/SimShapeFilterWrapper.h

@@ -11,7 +11,7 @@ JPH_NAMESPACE_BEGIN
 
 
 /// Helper class to forward ShapeFilter calls to a SimShapeFilter
 /// Helper class to forward ShapeFilter calls to a SimShapeFilter
 /// INTERNAL CLASS DO NOT USE!
 /// INTERNAL CLASS DO NOT USE!
-class SimShapeFilterWrapper : public ShapeFilter
+class SimShapeFilterWrapper : private ShapeFilter
 {
 {
 public:
 public:
 	/// Constructor
 	/// Constructor
@@ -19,6 +19,8 @@ public:
 		mFilter(inFilter),
 		mFilter(inFilter),
 		mBody1(inBody1)
 		mBody1(inBody1)
 	{
 	{
+		// Fall back to an empty filter if no simulation shape filter is set, this reduces the virtual call to 'return true'
+		mFinalFilter = inFilter != nullptr? this : &mDefault;
 	}
 	}
 
 
 	/// Forward to the simulation shape filter
 	/// Forward to the simulation shape filter
@@ -39,43 +41,18 @@ public:
 		mBody2 = inBody2;
 		mBody2 = inBody2;
 	}
 	}
 
 
-private:
-	const SimShapeFilter *	mFilter;
-	const Body *			mBody1;
-	const Body *			mBody2;
-};
-
-/// In case we don't have a simulation shape filter, we fall back to using a default shape filter that always returns true
-/// INTERNAL CLASS DO NOT USE!
-union SimShapeFilterWrapperUnion
-{
-public:
-	/// Constructor
-							SimShapeFilterWrapperUnion(const SimShapeFilter *inFilter, const Body *inBody1)
+	/// Returns the actual filter to use for collision detection
+	const ShapeFilter &		GetFilter() const
 	{
 	{
-		// Dirty trick: if we don't have a filter, placement new a standard ShapeFilter so that we
-		// don't have to check for nullptr in the ShouldCollide function
-		if (inFilter != nullptr)
-			new (&mSimShapeFilterWrapper) SimShapeFilterWrapper(inFilter, inBody1);
-		else
-			new (&mSimShapeFilterWrapper) ShapeFilter();
-	}
-
-	/// Destructor
-							~SimShapeFilterWrapperUnion()
-	{
-		// Doesn't need to be destructed
-	}
-
-	/// Accessor
-	SimShapeFilterWrapper &	GetSimShapeFilterWrapper()
-	{
-		return mSimShapeFilterWrapper;
+		return *mFinalFilter;
 	}
 	}
 
 
 private:
 private:
-	SimShapeFilterWrapper	mSimShapeFilterWrapper;
-	ShapeFilter				mShapeFilter;
+	const ShapeFilter *		mFinalFilter;
+	const SimShapeFilter *	mFilter;
+	const Body *			mBody1;
+	const Body *			mBody2 = nullptr;
+	const ShapeFilter		mDefault;
 };
 };
 
 
 JPH_NAMESPACE_END
 JPH_NAMESPACE_END

+ 5 - 7
Jolt/Physics/PhysicsSystem.cpp

@@ -1033,8 +1033,7 @@ void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const
 		settings.mActiveEdgeMovementDirection = body1->GetLinearVelocity() - body2->GetLinearVelocity();
 		settings.mActiveEdgeMovementDirection = body1->GetLinearVelocity() - body2->GetLinearVelocity();
 
 
 		// Create shape filter
 		// Create shape filter
-		SimShapeFilterWrapperUnion shape_filter_union(mSimShapeFilter, body1);
-		SimShapeFilterWrapper &shape_filter = shape_filter_union.GetSimShapeFilterWrapper();
+		SimShapeFilterWrapper shape_filter(mSimShapeFilter, body1);
 		shape_filter.SetBody2(body2);
 		shape_filter.SetBody2(body2);
 
 
 		// Get transforms relative to body1
 		// Get transforms relative to body1
@@ -1156,7 +1155,7 @@ void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const
 			ReductionCollideShapeCollector collector(this, body1, body2);
 			ReductionCollideShapeCollector collector(this, body1, body2);
 
 
 			// Perform collision detection between the two shapes
 			// Perform collision detection between the two shapes
-			mSimCollideBodyVsBody(*body1, *body2, transform1, transform2, settings, collector, shape_filter);
+			mSimCollideBodyVsBody(*body1, *body2, transform1, transform2, settings, collector, shape_filter.GetFilter());
 
 
 			// Add the contacts
 			// Add the contacts
 			for (ContactManifold &manifold : collector.mManifolds)
 			for (ContactManifold &manifold : collector.mManifolds)
@@ -1255,7 +1254,7 @@ void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const
 			NonReductionCollideShapeCollector collector(this, ioContactAllocator, body1, body2, body_pair_handle);
 			NonReductionCollideShapeCollector collector(this, ioContactAllocator, body1, body2, body_pair_handle);
 
 
 			// Perform collision detection between the two shapes
 			// Perform collision detection between the two shapes
-			mSimCollideBodyVsBody(*body1, *body2, transform1, transform2, settings, collector, shape_filter);
+			mSimCollideBodyVsBody(*body1, *body2, transform1, transform2, settings, collector, shape_filter.GetFilter());
 
 
 			constraint_created = collector.mConstraintCreated;
 			constraint_created = collector.mConstraintCreated;
 		}
 		}
@@ -1908,7 +1907,7 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
 
 
 				// Do narrow phase collision check
 				// Do narrow phase collision check
 				RShapeCast relative_cast(mShapeCast.mShape, mShapeCast.mScale, mShapeCast.mCenterOfMassStart, direction, mShapeCast.mShapeWorldBounds);
 				RShapeCast relative_cast(mShapeCast.mShape, mShapeCast.mScale, mShapeCast.mCenterOfMassStart, direction, mShapeCast.mShapeWorldBounds);
-				body2.GetTransformedShape().CastShape(relative_cast, mShapeCastSettings, mShapeCast.mCenterOfMassStart.GetTranslation(), mCollector, mShapeFilter);
+				body2.GetTransformedShape().CastShape(relative_cast, mShapeCastSettings, mShapeCast.mCenterOfMassStart.GetTranslation(), mCollector, mShapeFilter.GetFilter());
 
 
 				// Update early out fraction based on narrow phase collector
 				// Update early out fraction based on narrow phase collector
 				if (!mCollector.mRejectAll)
 				if (!mCollector.mRejectAll)
@@ -1928,8 +1927,7 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
 		};
 		};
 
 
 		// Create shape filter
 		// Create shape filter
-		SimShapeFilterWrapperUnion shape_filter_union(mSimShapeFilter, &body);
-		SimShapeFilterWrapper &shape_filter = shape_filter_union.GetSimShapeFilterWrapper();
+		SimShapeFilterWrapper shape_filter(mSimShapeFilter, &body);
 
 
 		// Check if we collide with any other body. Note that we use the non-locking interface as we know the broadphase cannot be modified at this point.
 		// Check if we collide with any other body. Note that we use the non-locking interface as we know the broadphase cannot be modified at this point.
 		RShapeCast shape_cast(body.GetShape(), Vec3::sOne(), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);
 		RShapeCast shape_cast(body.GetShape(), Vec3::sOne(), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);

+ 2 - 3
Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp

@@ -186,7 +186,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
 						Array<LeafShape>	mHits;
 						Array<LeafShape>	mHits;
 					};
 					};
 					LeafShapeCollector collector;
 					LeafShapeCollector collector;
-					body.GetShape()->CollectTransformedShapes(mLocalBounds, com.GetTranslation(), com.GetQuaternion(), Vec3::sOne(), SubShapeIDCreator(), collector, mShapeFilter);
+					body.GetShape()->CollectTransformedShapes(mLocalBounds, com.GetTranslation(), com.GetQuaternion(), Vec3::sOne(), SubShapeIDCreator(), collector, mShapeFilter.GetFilter());
 					if (collector.mHits.empty())
 					if (collector.mHits.empty())
 						return;
 						return;
 
 
@@ -244,8 +244,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
 	AABox world_bounds = local_bounds.Transformed(inContext.mCenterOfMassTransform);
 	AABox world_bounds = local_bounds.Transformed(inContext.mCenterOfMassTransform);
 
 
 	// Create shape filter
 	// Create shape filter
-	SimShapeFilterWrapperUnion shape_filter_union(inContext.mSimShapeFilter, inContext.mBody);
-	SimShapeFilterWrapper &shape_filter = shape_filter_union.GetSimShapeFilterWrapper();
+	SimShapeFilterWrapper shape_filter(inContext.mSimShapeFilter, inContext.mBody);
 
 
 	Collector collector(inContext, inSystem, inBodyLockInterface, local_bounds, shape_filter, mCollidingShapes, mCollidingSensors);
 	Collector collector(inContext, inSystem, inBodyLockInterface, local_bounds, shape_filter, mCollidingShapes, mCollidingSensors);
 	ObjectLayer layer = inContext.mBody->GetObjectLayer();
 	ObjectLayer layer = inContext.mBody->GetObjectLayer();