public static IShape OffsetSingleShape(IConvexShape shape, Vector3?offset = null, Quaternion?rotation = null, bool kinematic = false) { if (offset.HasValue == false && rotation.HasValue == false) { return(shape); } if (shape is ICompoundShape) { throw new InvalidOperationException("Cannot offset a compound shape. Can't support nested compounds."); } using (var compoundBuilder = new CompoundBuilder(BepuSimulation.safeBufferPool, BepuSimulation.instance.internalSimulation.Shapes, 1)) { using (BepuSimulation.instance.simulationLocker.WriteLock()) { if (kinematic) { compoundBuilder.AddForKinematicEasy(shape, new BepuPhysics.RigidPose(ToBepu(offset ?? Vector3.Zero), ToBepu(rotation ?? Quaternion.Identity)), 1f); } else { compoundBuilder.AddEasy(shape, new BepuPhysics.RigidPose(ToBepu(offset ?? Vector3.Zero), ToBepu(rotation ?? Quaternion.Identity)), 1f); } return(compoundBuilder.BuildCompleteCompoundShape(BepuSimulation.instance.internalSimulation.Shapes, BepuSimulation.safeBufferPool, kinematic)); } } }
/// <summary> /// Returns whether this shape overlaps with another. /// </summary> public bool IntersectsWith(IConvexShape shape) { float touchingAtSpeedFraction; Point intersectionAxis; return(IntersectsWith(shape, Point.Zero, out touchingAtSpeedFraction, out intersectionAxis)); }
protected virtual BodyInertia GetBodyInertia(IConvexShape shape, float mass) { shape.ComputeInertia(mass, out var bodyInertia); // this locks rotation along the X and Z axes, aiding 2d physics bodyInertia.InverseInertiaTensor.XX = 0; bodyInertia.InverseInertiaTensor.ZZ = 0; return(bodyInertia); }
public bool IntersectsWith(IConvexShape shape) { //so it won't enter a call-loop of infinite proportions if (shape.GetType() == typeof(Point)) { return(this == (Point)shape); } else //call Shape's better suited sat check { return(shape.IntersectsWith(this)); } }
public void SetCollider(PhysicsType type) { if (PhysicsBodyInitialized) { RemoveCollider(); if (type == PhysicsType.None) { PhysicsType = type; if (Physics.PhysicsObjects.Contains(this)) { Physics.PhysicsObjects.Remove(this); } return; } } if (type == PhysicsType.Cube) { Box shape = new Box(2.0f, 2.0f, 2.0f); ShapeIndex = Physics.simulator.Shapes.Add(shape); Shape = shape; } else if (type == PhysicsType.Sphere) { Sphere shape = new Sphere(2.0f); ShapeIndex = Physics.simulator.Shapes.Add(shape); Shape = shape; } Shape.ComputeInertia(Mass, out BodyInertia inertia); PhysicsDescription = BodyDescription.CreateDynamic(transform.Position, inertia, new CollidableDescription(ShapeIndex, 0.1f), new BodyActivityDescription(0.01f)); BodyHandle = Physics.simulator.Bodies.Add(PhysicsDescription); BodyReference = Physics.simulator.Bodies.GetBodyReference(BodyHandle); if (!Physics.PhysicsObjects.Contains(this)) { Physics.PhysicsObjects.Add(this); } PhysicsType = type; PhysicsBodyInitialized = true; physicsEnabled = true; }
/// <summary> /// Returns whether this shape overlaps with another somewhere if it moves by relativeSpeed. /// Returns the fraction of the speed given at which they touch and the axis closest to this touching point (from either shape). /// The fraction will be -1f if there's an overlap but no collision caused by the relativeSpeed. /// </summary> public bool IntersectsWith(IConvexShape shape, Point relativeSpeed, out float touchingAtSpeedFraction, out Point intersectionAxis) { touchingAtSpeedFraction = float.PositiveInfinity; intersectionAxis = Point.Zero; Type shape1Type = GetType(); Type shape2Type = shape.GetType(); //2 AABB's or ComplexRectangles without a rotation (so basically AABB's) if ((shape1Type == typeof(Rectangle) || shape1Type == typeof(ComplexRectangle) && _Rotation == 0f) && (shape2Type == typeof(Rectangle) || shape2Type == typeof(ComplexRectangle) && ((Shape)shape)._Rotation == 0f)) { Rectangle rect1 = (Rectangle)this; Rectangle rect2 = (Rectangle)shape; float xTouchingFraction, yTouchingFraction; if (relativeSpeed.X >= 0f) { if (rect1.Position2.X + relativeSpeed.X < rect2.Position.X || rect1.Position.X > rect2.Position2.X) { return(false); } xTouchingFraction = (rect2.Position.X - rect1.Position2.X) / relativeSpeed.X; } else { if (rect1.Position.X + relativeSpeed.X > rect2.Position2.X || rect1.Position2.X < rect2.Position.X) { return(false); } xTouchingFraction = (rect2.Position2.X - rect1.Position.X) / relativeSpeed.X; } if (relativeSpeed.Y >= 0f) { if (rect1.Position2.Y + relativeSpeed.Y < rect2.Position.Y || rect1.Position.Y > rect2.Position2.Y) { return(false); } yTouchingFraction = (rect2.Position.Y - rect1.Position2.Y) / relativeSpeed.Y; } else { if (rect1.Position.Y + relativeSpeed.Y > rect2.Position2.Y || rect1.Position2.Y < rect2.Position.Y) { return(false); } yTouchingFraction = (rect2.Position2.Y - rect1.Position.Y) / relativeSpeed.Y; } //decide which fraction and corresponding axis to return, if any if (xTouchingFraction >= 0f && xTouchingFraction <= 1f) { touchingAtSpeedFraction = xTouchingFraction; intersectionAxis = rect2.GetPerpAxes()[0]; } if (yTouchingFraction >= 0f && yTouchingFraction <= 1f && yTouchingFraction < touchingAtSpeedFraction) { touchingAtSpeedFraction = yTouchingFraction; intersectionAxis = rect2.GetPerpAxes()[1]; } if (intersectionAxis == Point.Zero) { touchingAtSpeedFraction = -1f; } return(true); } else //other shapes { touchingAtSpeedFraction = float.PositiveInfinity; Point[] shape1Points = GetPoints(); Point[] shape2Points = shape.GetPoints(); List <Point> allAxes = new List <Point>(GetPerpAxes()); allAxes.AddRange(shape.GetPerpAxes()); foreach (Point axis in allAxes) { float shape1ScalarMin = float.PositiveInfinity; float shape1ScalarMax = float.NegativeInfinity; float shape2ScalarMin = float.PositiveInfinity; float shape2ScalarMax = float.NegativeInfinity; //cast shape1's points to the axis foreach (Point point in shape1Points) { float multiplier = (float)((point.X * axis.X + point.Y * axis.Y) / (axis.X * axis.X + axis.Y * axis.Y)); float scalar = multiplier * axis.X * axis.X + multiplier * axis.Y * axis.Y; if (scalar < shape1ScalarMin) { shape1ScalarMin = scalar; } if (scalar > shape1ScalarMax) { shape1ScalarMax = scalar; } } //cast shape2's points to the axis foreach (Point point in shape2Points) { float multiplier = (float)((point.X * axis.X + point.Y * axis.Y) / (axis.X * axis.X + axis.Y * axis.Y)); float scalar = multiplier * axis.X * axis.X + multiplier * axis.Y * axis.Y; if (scalar < shape2ScalarMin) { shape2ScalarMin = scalar; } if (scalar > shape2ScalarMax) { shape2ScalarMax = scalar; } } //cast speed to axis float speedMultiplier = (float)((relativeSpeed.X * axis.X + relativeSpeed.Y * axis.Y) / (axis.X * axis.X + axis.Y * axis.Y)); float speedScalar = speedMultiplier * axis.X * axis.X + speedMultiplier * axis.Y * axis.Y; float thisTouchingAtSpeedFraction; if (speedScalar >= 0) { if (shape1ScalarMax + speedScalar < shape2ScalarMin || shape1ScalarMin > shape2ScalarMax) { return(false); } thisTouchingAtSpeedFraction = (shape2ScalarMin - shape1ScalarMax) / speedScalar; } else { if (shape1ScalarMin + speedScalar > shape2ScalarMax || shape1ScalarMax < shape2ScalarMin) { return(false); } thisTouchingAtSpeedFraction = (shape2ScalarMax - shape1ScalarMin) / speedScalar; } if (thisTouchingAtSpeedFraction >= 0f && thisTouchingAtSpeedFraction <= 1f && thisTouchingAtSpeedFraction < touchingAtSpeedFraction) { touchingAtSpeedFraction = thisTouchingAtSpeedFraction; intersectionAxis = axis; } } if (intersectionAxis == Point.Zero) { touchingAtSpeedFraction = -1f; } else //this axis is still a perpendicular axis, revert! { intersectionAxis = new Point(intersectionAxis.Y, -intersectionAxis.X); } return(true); } }
/// <summary> /// Returns whether this shape overlaps with another. /// </summary> public bool IntersectsWith(IConvexShape shape) { float touchingAtSpeedFraction; Point intersectionAxis; return IntersectsWith(shape, Point.Zero, out touchingAtSpeedFraction, out intersectionAxis); }
/// <summary> /// Returns whether this shape overlaps with another somewhere if it moves by relativeSpeed. /// Returns the fraction of the speed given at which they touch and the axis closest to this touching point (from either shape). /// The fraction will be -1f if there's an overlap but no collision caused by the relativeSpeed. /// </summary> public bool IntersectsWith(IConvexShape shape, Point relativeSpeed, out float touchingAtSpeedFraction, out Point intersectionAxis) { touchingAtSpeedFraction = float.PositiveInfinity; intersectionAxis = Point.Zero; Type shape1Type = GetType(); Type shape2Type = shape.GetType(); //2 AABB's or ComplexRectangles without a rotation (so basically AABB's) if ((shape1Type == typeof(Rectangle) || shape1Type == typeof(ComplexRectangle) && _Rotation == 0f) && (shape2Type == typeof(Rectangle) || shape2Type == typeof(ComplexRectangle) && ((Shape)shape)._Rotation == 0f)) { Rectangle rect1 = (Rectangle)this; Rectangle rect2 = (Rectangle)shape; float xTouchingFraction, yTouchingFraction; if (relativeSpeed.X >= 0f) { if (rect1.Position2.X + relativeSpeed.X < rect2.Position.X || rect1.Position.X > rect2.Position2.X) return false; xTouchingFraction = (rect2.Position.X - rect1.Position2.X) / relativeSpeed.X; } else { if (rect1.Position.X + relativeSpeed.X > rect2.Position2.X || rect1.Position2.X < rect2.Position.X) return false; xTouchingFraction = (rect2.Position2.X - rect1.Position.X) / relativeSpeed.X; } if (relativeSpeed.Y >= 0f) { if (rect1.Position2.Y + relativeSpeed.Y < rect2.Position.Y || rect1.Position.Y > rect2.Position2.Y) return false; yTouchingFraction = (rect2.Position.Y - rect1.Position2.Y) / relativeSpeed.Y; } else { if (rect1.Position.Y + relativeSpeed.Y > rect2.Position2.Y || rect1.Position2.Y < rect2.Position.Y) return false; yTouchingFraction = (rect2.Position2.Y - rect1.Position.Y) / relativeSpeed.Y; } //decide which fraction and corresponding axis to return, if any if (xTouchingFraction >= 0f && xTouchingFraction <= 1f) { touchingAtSpeedFraction = xTouchingFraction; intersectionAxis = rect2.GetPerpAxes()[0]; } if (yTouchingFraction >= 0f && yTouchingFraction <= 1f && yTouchingFraction < touchingAtSpeedFraction) { touchingAtSpeedFraction = yTouchingFraction; intersectionAxis = rect2.GetPerpAxes()[1]; } if (intersectionAxis == Point.Zero) touchingAtSpeedFraction = -1f; return true; } //other shapes touchingAtSpeedFraction = float.PositiveInfinity; Point[] shape1Points = GetPoints(); Point[] shape2Points = shape.GetPoints(); List<Point> allAxes = new List<Point>(GetPerpAxes()); allAxes.AddRange(shape.GetPerpAxes()); foreach (Point axis in allAxes) { float shape1ScalarMin = float.PositiveInfinity; float shape1ScalarMax = float.NegativeInfinity; float shape2ScalarMin = float.PositiveInfinity; float shape2ScalarMax = float.NegativeInfinity; //cast shape1's points to the axis foreach (Point point in shape1Points) { float multiplier = (float)((point.X * axis.X + point.Y * axis.Y) / (axis.X * axis.X + axis.Y * axis.Y)); float scalar = multiplier * axis.X * axis.X + multiplier * axis.Y * axis.Y; if (scalar < shape1ScalarMin) shape1ScalarMin = scalar; if (scalar > shape1ScalarMax) shape1ScalarMax = scalar; } //cast shape2's points to the axis foreach (Point point in shape2Points) { float multiplier = (float)((point.X * axis.X + point.Y * axis.Y) / (axis.X * axis.X + axis.Y * axis.Y)); float scalar = multiplier * axis.X * axis.X + multiplier * axis.Y * axis.Y; if (scalar < shape2ScalarMin) shape2ScalarMin = scalar; if (scalar > shape2ScalarMax) shape2ScalarMax = scalar; } //cast speed to axis float speedMultiplier = (float)((relativeSpeed.X * axis.X + relativeSpeed.Y * axis.Y) / (axis.X * axis.X + axis.Y * axis.Y)); float speedScalar = speedMultiplier * axis.X * axis.X + speedMultiplier * axis.Y * axis.Y; float thisTouchingAtSpeedFraction; if (speedScalar >= 0) { if (shape1ScalarMax + speedScalar < shape2ScalarMin || shape1ScalarMin > shape2ScalarMax) return false; thisTouchingAtSpeedFraction = (shape2ScalarMin - shape1ScalarMax) / speedScalar; } else { if (shape1ScalarMin + speedScalar > shape2ScalarMax || shape1ScalarMax < shape2ScalarMin) return false; thisTouchingAtSpeedFraction = (shape2ScalarMax - shape1ScalarMin) / speedScalar; } if (thisTouchingAtSpeedFraction >= 0f && thisTouchingAtSpeedFraction <= 1f && thisTouchingAtSpeedFraction < touchingAtSpeedFraction) { touchingAtSpeedFraction = thisTouchingAtSpeedFraction; intersectionAxis = axis; } } if (intersectionAxis == Point.Zero) touchingAtSpeedFraction = -1f; else //this axis is still a perpendicular axis, revert! intersectionAxis = new Point(intersectionAxis.Y, -intersectionAxis.X); return true; }
internal ConvexPhysicsMesh(IConvexShape shape, TypedIndex meshIndex) { this.ConvexShape = shape; this.MeshIndex = meshIndex; }
/// <summary> /// Create from Bepuphysics shape and mass /// </summary> /// <param name="mass"></param> /// <param name="isStatic"></param> public PrimitivePhysics(IConvexShape colliderShape, float mass, bool isStatic = false) { this.colliderShape = colliderShape; this.mass = mass; this.isStatic = isStatic; }
public bool IntersectsWith(IConvexShape shape) { //so it won't enter a call-loop of infinite proportions if (shape is Point) return this == (Point)shape; //call Shape's better suited intersection check return shape.IntersectsWith(this); }