///<summary> /// Constructs a new space for things to live in. ///</summary> ///<param name="parallelLooper">Used by the space to perform multithreaded updates. Pass null if multithreading is not required.</param> public Space(IParallelLooper parallelLooper) { timeStepSettings = new TimeStepSettings(); this.parallelLooper = parallelLooper; SpaceObjectBuffer = new SpaceObjectBuffer(this); EntityStateWriteBuffer = new EntityStateWriteBuffer(); DeactivationManager = new DeactivationManager(TimeStepSettings, ParallelLooper); ForceUpdater = new ForceUpdater(TimeStepSettings, ParallelLooper); BoundingBoxUpdater = new BoundingBoxUpdater(TimeStepSettings, ParallelLooper); BroadPhase = new DynamicHierarchy(ParallelLooper); NarrowPhase = new NarrowPhase(TimeStepSettings, BroadPhase.Overlaps, ParallelLooper); Solver = new Solver(TimeStepSettings, DeactivationManager, ParallelLooper); NarrowPhase.Solver = Solver; PositionUpdater = new ContinuousPositionUpdater(TimeStepSettings, ParallelLooper); BufferedStates = new BufferedStatesManager(ParallelLooper); DeferredEventDispatcher = new DeferredEventDispatcher(); DuringForcesUpdateables = new DuringForcesUpdateableManager(timeStepSettings, ParallelLooper); BeforeNarrowPhaseUpdateables = new BeforeNarrowPhaseUpdateableManager(timeStepSettings, ParallelLooper); BeforeSolverUpdateables = new BeforeSolverUpdateableManager(timeStepSettings, ParallelLooper); BeforePositionUpdateUpdateables = new BeforePositionUpdateUpdateableManager(timeStepSettings, ParallelLooper); EndOfTimeStepUpdateables = new EndOfTimeStepUpdateableManager(timeStepSettings, ParallelLooper); EndOfFrameUpdateables = new EndOfFrameUpdateableManager(timeStepSettings, ParallelLooper); }
void DoTimeStep() { #if PROFILE start = Stopwatch.GetTimestamp(); #endif SpaceObjectBuffer.Update(); EntityStateWriteBuffer.Update(); DeactivationManager.Update(); ForceUpdater.Update(); DuringForcesUpdateables.Update(); BoundingBoxUpdater.Update(); BroadPhase.Update(); BeforeNarrowPhaseUpdateables.Update(); NarrowPhase.Update(); BeforeSolverUpdateables.Update(); Solver.Update(); BeforePositionUpdateUpdateables.Update(); PositionUpdater.Update(); BufferedStates.ReadBuffers.Update(); DeferredEventDispatcher.Update(); EndOfTimeStepUpdateables.Update(); #if PROFILE end = Stopwatch.GetTimestamp(); #endif }
public void LineLineNotOverlapping() { var lineA = new Line(new Position2D(0, 1), new Position2D(1, 0)); var lineB = new Line(new Position2D(-1, -1), new Position2D(-2, -2)); NarrowPhase.TestCollision(lineA, Transform2D.DefaultTransform, lineB, Transform2D.DefaultTransform).Should().BeFalse(); }
public OctTree(BoundingBox r, List <HRigidBody> o, NarrowPhase n, float min) { region = r; objects = o; narrowPhase = n; minSize = min; }
/// <summary> /// Clears the contacts associated with this pair handler. /// </summary> public override void ClearContacts() { if (previousContactCount > 0) { //Just exited collision. //Remove the solver item. if (Parent != null) { Parent.RemoveSolverUpdateable(ContactConstraint); } else if (NarrowPhase != null) { NarrowPhase.NotifyUpdateableRemoved(ContactConstraint); } if (!suppressEvents) { var a = CollidableA; var b = CollidableB; a.EventTriggerer.OnCollisionEnded(b, this); b.EventTriggerer.OnCollisionEnded(a, this); } } ContactManifold.ClearContacts(); base.ClearContacts(); }
///<summary> /// Constructs a new space for things to live in. ///</summary> public Space() { NarrowPhaseHelper.CollisionManagers = NarrowPhaseHelper.CollisionManagers; //Forces the NarrowPhaseHelper to run the static constructor. Better to do it now instead of mid-simulation. timeStepSettings = new TimeStepSettings(); #if !WINDOWS threadManager = new SpecializedThreadManager(); #else threadManager = new SpecializedThreadManager(); #endif SpaceObjectBuffer = new SpaceObjectBuffer(this); EntityStateWriteBuffer = new EntityStateWriteBuffer(); DeactivationManager = new DeactivationManager(TimeStepSettings, ThreadManager); ForceUpdater = new ForceUpdater(TimeStepSettings, ThreadManager); BoundingBoxUpdater = new BoundingBoxUpdater(TimeStepSettings, ThreadManager); BroadPhase = new DynamicHierarchy(ThreadManager); NarrowPhase = new NarrowPhase(TimeStepSettings, BroadPhase.Overlaps, ThreadManager); Solver = new Solver(TimeStepSettings, DeactivationManager, ThreadManager); NarrowPhase.Solver = Solver; PositionUpdater = new ContinuousPositionUpdater(TimeStepSettings, ThreadManager); BufferedStates = new BufferedStatesManager(ThreadManager); DeferredEventDispatcher = new DeferredEventDispatcher(); DuringForcesUpdateables = new DuringForcesUpdateableManager(timeStepSettings, ThreadManager); BeforeNarrowPhaseUpdateables = new BeforeNarrowPhaseUpdateableManager(timeStepSettings, ThreadManager); BeforeSolverUpdateables = new BeforeSolverUpdateableManager(timeStepSettings, ThreadManager); BeforePositionUpdateUpdateables = new BeforePositionUpdateUpdateableManager(timeStepSettings, ThreadManager); EndOfTimeStepUpdateables = new EndOfTimeStepUpdateableManager(timeStepSettings, ThreadManager); EndOfFrameUpdateables = new EndOfFrameUpdateableManager(timeStepSettings, ThreadManager); }
public void PointRectangleOverlapping() { var point = new Point(); var rectangle = new Rectangle(-2, -2, 2, 2); NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeTrue(); }
/// <summary> /// Constructs a simulation supporting dynamic movement and constraints with the specified narrow phase callbacks. /// </summary> /// <param name="bufferPool">Buffer pool used to fill persistent structures and main thread ephemeral resources across the engine.</param> /// <param name="narrowPhaseCallbacks">Callbacks to use in the narrow phase.</param> /// <param name="initialAllocationSizes">Allocation sizes to initialize the simulation with. If left null, default values are chosen.</param> /// <returns>New simulation.</returns> public static Simulation Create <TNarrowPhaseCallbacks>(BufferPool bufferPool, TNarrowPhaseCallbacks narrowPhaseCallbacks, SimulationAllocationSizes?initialAllocationSizes = null) where TNarrowPhaseCallbacks : struct, INarrowPhaseCallbacks { if (initialAllocationSizes == null) { initialAllocationSizes = new SimulationAllocationSizes { Bodies = 4096, Statics = 4096, ShapesPerType = 128, ConstraintCountPerBodyEstimate = 8, Constraints = 16384, ConstraintsPerTypeBatch = 256 }; } var simulation = new Simulation(bufferPool, initialAllocationSizes.Value); var narrowPhase = new NarrowPhase <TNarrowPhaseCallbacks>(simulation, DefaultTypes.CreateDefaultCollisionTaskRegistry(), narrowPhaseCallbacks, initialAllocationSizes.Value.Islands + 1); DefaultTypes.RegisterDefaults(simulation.Solver, narrowPhase); simulation.NarrowPhase = narrowPhase; simulation.Sleeper.pairCache = narrowPhase.PairCache; simulation.Awakener.pairCache = narrowPhase.PairCache; simulation.Solver.pairCache = narrowPhase.PairCache; simulation.BroadPhaseOverlapFinder = new CollidableOverlapFinder <TNarrowPhaseCallbacks>(narrowPhase, simulation.BroadPhase); return(simulation); }
// Use this for initialization public void StartSweepAndPrune() { narrowPhase = GetComponent <NarrowPhase> (); BpOnly = narrowPhase.BpOnly; BpNp = narrowPhase.BpNp; objects = narrowPhase.physicsEngines; pm = new pairManager(objects); int i = 0; foreach (HRigidBody h in objects) { h.index = i; i++; } xEndPoints = new List <EndPoint> (); yEndPoints = new List <EndPoint> (); zEndPoints = new List <EndPoint> (); foreach (HRigidBody h in objects) { h.mins = new EndPoint[3]; h.maxs = new EndPoint[3]; } setEndPoints(); //collectInitialOverlaps (); }
/// <summary> /// Constructs a simulation supporting dynamic movement and constraints with the specified narrow phase callbacks. /// </summary> /// <param name="bufferPool">Buffer pool used to fill persistent structures and main thread ephemeral resources across the engine.</param> /// <param name="narrowPhaseCallbacks">Callbacks to use in the narrow phase.</param> /// <param name="poseIntegratorCallbacks">Callbacks to use in the pose integrator.</param> /// <param name="timestepper">Timestepper that defines how the simulation state should be updated. If null, defaults to PositionFirstTimestepper.</param> /// <param name="solverIterationCount">Number of iterations the solver should use.</param> /// <param name="solverFallbackBatchThreshold">Number of synchronized batches the solver should maintain before falling back to a lower quality jacobi hybrid solver.</param> /// <param name="initialAllocationSizes">Allocation sizes to initialize the simulation with. If left null, default values are chosen.</param> /// <returns>New simulation.</returns> public static Simulation Create <TNarrowPhaseCallbacks, TPoseIntegratorCallbacks>( BufferPool bufferPool, TNarrowPhaseCallbacks narrowPhaseCallbacks, TPoseIntegratorCallbacks poseIntegratorCallbacks, ITimestepper timestepper = null, int solverIterationCount = 8, int solverFallbackBatchThreshold = 32, SimulationAllocationSizes?initialAllocationSizes = null) where TNarrowPhaseCallbacks : struct, INarrowPhaseCallbacks where TPoseIntegratorCallbacks : struct, IPoseIntegratorCallbacks { if (initialAllocationSizes == null) { initialAllocationSizes = new SimulationAllocationSizes { Bodies = 4096, Statics = 4096, ShapesPerType = 128, ConstraintCountPerBodyEstimate = 8, Constraints = 16384, ConstraintsPerTypeBatch = 256 }; } var simulation = new Simulation(bufferPool, initialAllocationSizes.Value, solverIterationCount, solverFallbackBatchThreshold, timestepper == null ? new PositionFirstTimestepper() : timestepper); simulation.PoseIntegrator = new PoseIntegrator <TPoseIntegratorCallbacks>(simulation.Bodies, simulation.Shapes, simulation.BroadPhase, poseIntegratorCallbacks); var narrowPhase = new NarrowPhase <TNarrowPhaseCallbacks>(simulation, DefaultTypes.CreateDefaultCollisionTaskRegistry(), DefaultTypes.CreateDefaultSweepTaskRegistry(), narrowPhaseCallbacks, initialAllocationSizes.Value.Islands + 1); DefaultTypes.RegisterDefaults(simulation.Solver, narrowPhase); simulation.NarrowPhase = narrowPhase; simulation.Sleeper.pairCache = narrowPhase.PairCache; simulation.Awakener.pairCache = narrowPhase.PairCache; simulation.Solver.pairCache = narrowPhase.PairCache; simulation.BroadPhaseOverlapFinder = new CollidableOverlapFinder <TNarrowPhaseCallbacks>(narrowPhase, simulation.BroadPhase); return(simulation); }
public void PointRectangleNotOverlapping() { var point = new Point(); var pointTransform = new Transform2D(new Position2D(5, 5)); var rectangle = new Rectangle(-2, -2, 2, 2); NarrowPhase.TestCollision(point, pointTransform, rectangle, Transform2D.DefaultTransform).Should().BeFalse(); }
public void PointLineNotOverlapping() { var point = new Point(); var pointTransform = new Transform2D(new Position2D(1, 1)); var line = new Line(new Position2D(-3, -2), new Position2D(-9, -5)); NarrowPhase.TestCollision(point, pointTransform, line, Transform2D.DefaultTransform).Should().BeFalse(); }
public void PointCircleNotOverlapping() { var point = new Point(); var pointTransform = new Transform2D(new Position2D(3, 0)); var circle = new Circle(1); NarrowPhase.TestCollision(point, pointTransform, circle, Transform2D.DefaultTransform).Should().BeFalse(); }
public void CircleCircleOverlapping() { var circleA = new Circle(2); var transformA = new Transform2D(new Vector2(-1, -1)); var circleB = new Circle(2); var transformB = new Transform2D(new Vector2(1, 1)); NarrowPhase.TestCollision(circleA, transformA, circleB, transformB).Should().BeTrue(); }
public void LineCircleOverlapping() { var line = new Line(new Position2D(-1, -1), new Position2D(1, 1)); var transformA = Transform2D.DefaultTransform; var circle = new Circle(1); var transformB = Transform2D.DefaultTransform; NarrowPhase.TestCollision(line, transformA, circle, transformB).Should().BeTrue(); }
public void ScaledCirclesNotOverlapping() { var circleA = new Circle(2); var transformA = new Transform2D(new Vector2(-5, -5), 0, new Vector2(0.2f, 0.2f)); var circleB = new Circle(2); var transformB = new Transform2D(new Vector2(5, 5), 0, new Vector2(0.2f, 0.2f)); NarrowPhase.TestCollision(circleA, transformA, circleB, transformB).Should().BeFalse(); }
public void ScaledCirclesOverlapping() { var circleA = new Circle(2); var transformA = new Transform2D(new Vector2(-3, 0), 0f, new Vector2(2, 2)); var circleB = new Circle(2); var transformB = new Transform2D(new Vector2(3, 0), 0f, new Vector2(2, 2)); NarrowPhase.TestCollision(circleA, transformA, circleB, transformB).Should().BeTrue(); }
public void LineCircleNotOverlapping() { var line = new Line(new Position2D(-5, -5), new Position2D(-4, -4)); var transformA = Transform2D.DefaultTransform; var circle = new Circle(1); var transformB = Transform2D.DefaultTransform; NarrowPhase.TestCollision(line, transformA, circle, transformB).Should().BeFalse(); }
public void ScaledLinesNotOverlapping() { var lineA = new Line(new Position2D(0, 1), new Position2D(1, 0)); var lineB = new Line(new Position2D(-1, -1), new Position2D(-2, -2)); var transform = new Transform2D(new Position2D(0, 0), 0f, new Vector2(2, 2)); NarrowPhase.TestCollision(lineA, transform, lineB, transform).Should().BeFalse(); }
public void PointCircleOverlapping() { var point = new Point(); var circle = new Circle(3); var pointTransform = new Transform2D(new Position2D(1, 1)); var circleTransform = new Transform2D(new Position2D(-1, 0)); NarrowPhase.TestCollision(point, pointTransform, circle, circleTransform).Should().BeTrue(); }
public void RectanglesTouchingGJK2D() { var rectangleA = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); var transformA = new Transform2D(new Position2D(-1, 0)); var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); var transformB = new Transform2D(new Vector2(1, 0)); NarrowPhase.TestCollision(rectangleA, transformA, rectangleB, transformB).Should().BeTrue(); }
public void RotatedRectanglesOverlapping() { var rectangleA = new MoonTools.Core.Bonk.Rectangle(-1, -1, 2, 2); var transformA = new Transform2D(new Vector2(-1, 0), -90f); var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); var transformB = new Transform2D(new Vector2(1, 0)); NarrowPhase.TestCollision(rectangleA, transformA, rectangleB, transformB).Should().BeTrue(); }
public void RectanglesOverlappingOverlap() { var rectangleA = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); var transformA = new Transform2D(new Position2D(0, 0)); var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); var transformB = new Transform2D(new Vector2(1, 0)); NarrowPhase.TestRectangleOverlap(rectangleA, transformA, rectangleB, transformB).Should().BeTrue(); }
public void RectanglesNotOverlapping() { var rectangleA = new MoonTools.Core.Bonk.Rectangle(-6, -6, 6, 6); var transformA = new Transform2D(new Position2D(39, 249)); var rectangleB = new MoonTools.Core.Bonk.Rectangle(0, 0, 16, 16); var transformB = new Transform2D(new Position2D(16, 240)); NarrowPhase.TestCollision(rectangleA, transformA, rectangleB, transformB).Should().BeFalse(); }
// Use this for initialization public void StartBounds() { narrowPhase = GetComponent <NarrowPhase> (); physicsEngines = narrowPhase.physicsEngines; //directions = new Vector3[physicsEngines.Length]; foreach (HRigidBody s in physicsEngines) { s.directions = new Vector3(Random.Range(-4, 5), Random.Range(-4, 5), Random.Range(-4, 5)); } }
/// <summary> /// Registers the set of constraints that are packaged in the engine. /// </summary> public static void RegisterDefaults(Solver solver, NarrowPhase narrowPhase) { solver.Register <BallSocket>(); solver.Register <AngularHinge>(); solver.Register <AngularSwivelHinge>(); solver.Register <SwingLimit>(); solver.Register <GrabMotor>(); solver.Register <Contact1OneBody>(); solver.Register <Contact2OneBody>(); solver.Register <Contact3OneBody>(); solver.Register <Contact4OneBody>(); solver.Register <Contact1>(); solver.Register <Contact2>(); solver.Register <Contact3>(); solver.Register <Contact4>(); solver.Register <Contact2NonconvexOneBody>(); solver.Register <Contact3NonconvexOneBody>(); solver.Register <Contact4NonconvexOneBody>(); solver.Register <Contact5NonconvexOneBody>(); solver.Register <Contact6NonconvexOneBody>(); solver.Register <Contact7NonconvexOneBody>(); solver.Register <Contact8NonconvexOneBody>(); solver.Register <Contact2Nonconvex>(); solver.Register <Contact3Nonconvex>(); solver.Register <Contact4Nonconvex>(); solver.Register <Contact5Nonconvex>(); solver.Register <Contact6Nonconvex>(); solver.Register <Contact7Nonconvex>(); solver.Register <Contact8Nonconvex>(); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact8Nonconvex, Contact8NonconvexAccumulatedImpulses, ContactImpulses8, ConstraintCache8>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact7Nonconvex, Contact7NonconvexAccumulatedImpulses, ContactImpulses7, ConstraintCache7>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact6Nonconvex, Contact6NonconvexAccumulatedImpulses, ContactImpulses6, ConstraintCache6>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact5Nonconvex, Contact5NonconvexAccumulatedImpulses, ContactImpulses5, ConstraintCache5>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact4Nonconvex, Contact4NonconvexAccumulatedImpulses, ContactImpulses4, ConstraintCache4>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact3Nonconvex, Contact3NonconvexAccumulatedImpulses, ContactImpulses3, ConstraintCache3>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexTwoBodyAccessor <Contact2Nonconvex, Contact2NonconvexAccumulatedImpulses, ContactImpulses2, ConstraintCache2>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact8NonconvexOneBody, Contact8NonconvexAccumulatedImpulses, ContactImpulses8, ConstraintCache8>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact7NonconvexOneBody, Contact7NonconvexAccumulatedImpulses, ContactImpulses7, ConstraintCache7>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact6NonconvexOneBody, Contact6NonconvexAccumulatedImpulses, ContactImpulses6, ConstraintCache6>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact5NonconvexOneBody, Contact5NonconvexAccumulatedImpulses, ContactImpulses5, ConstraintCache5>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact4NonconvexOneBody, Contact4NonconvexAccumulatedImpulses, ContactImpulses4, ConstraintCache4>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact3NonconvexOneBody, Contact3NonconvexAccumulatedImpulses, ContactImpulses3, ConstraintCache3>()); narrowPhase.RegisterContactConstraintAccessor(new NonconvexOneBodyAccessor <Contact2NonconvexOneBody, Contact2NonconvexAccumulatedImpulses, ContactImpulses2, ConstraintCache2>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexTwoBodyAccessor <Contact4, Contact4AccumulatedImpulses, ContactImpulses4, ConstraintCache4>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexTwoBodyAccessor <Contact3, Contact3AccumulatedImpulses, ContactImpulses3, ConstraintCache3>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexTwoBodyAccessor <Contact2, Contact2AccumulatedImpulses, ContactImpulses2, ConstraintCache2>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexTwoBodyAccessor <Contact1, Contact1AccumulatedImpulses, ContactImpulses1, ConstraintCache1>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexOneBodyAccessor <Contact4OneBody, Contact4AccumulatedImpulses, ContactImpulses4, ConstraintCache4>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexOneBodyAccessor <Contact3OneBody, Contact3AccumulatedImpulses, ContactImpulses3, ConstraintCache3>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexOneBodyAccessor <Contact2OneBody, Contact2AccumulatedImpulses, ContactImpulses2, ConstraintCache2>()); narrowPhase.RegisterContactConstraintAccessor(new ConvexOneBodyAccessor <Contact1OneBody, Contact1AccumulatedImpulses, ContactImpulses1, ConstraintCache1>()); }
/// <summary> /// Clears the simulation of every object and returns all pooled memory to the buffer pool. Leaves the simulation in an unusable state. /// </summary> public void Dispose() { Clear(); Activator.Dispose(); Deactivator.Dispose(); Solver.Dispose(); BroadPhase.Dispose(); NarrowPhase.Dispose(); Bodies.Dispose(); Statics.Dispose(); BodyLayoutOptimizer.Dispose(BufferPool); Shapes.Dispose(); }
public void CirclePolygonNotOverlapping() { var circle = new Circle(1); var circleTransform = new Transform2D(new Vector2(5, 0)); var square = new Polygon(ImmutableArray.Create( new Position2D(-1, -1), new Position2D(1, -1), new Position2D(1, 1), new Position2D(-1, 1) )); var squareTransform = Transform2D.DefaultTransform; NarrowPhase.TestCollision(circle, circleTransform, square, squareTransform).Should().BeFalse(); }
public void PointPolygonNotOverlapping() { var point = new Point(); var pointTransform = new Transform2D(new Position2D(5, 5)); var polygon = new Polygon(ImmutableArray.Create( new Position2D(-2, -2), new Position2D(-3, 2), new Position2D(3, 2), new Position2D(3, -2) )); NarrowPhase.TestCollision(point, pointTransform, polygon, Transform2D.DefaultTransform).Should().BeFalse(); }
public void CirclePolygonOverlapping() { var circle = new Circle(1); var transformA = new Transform2D(new Vector2(0.25f, 0)); var square = new Polygon(ImmutableArray.Create( new Position2D(-1, -1), new Position2D(1, -1), new Position2D(1, 1), new Position2D(-1, 1) )); var transformB = Transform2D.DefaultTransform; NarrowPhase.TestCollision(circle, transformA, square, transformB).Should().BeTrue(); }