Ejemplo n.º 1
0
        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));
                }
            }
        }
Ejemplo n.º 2
0
        /// <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));
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
 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));
     }
 }
Ejemplo n.º 5
0
        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;
        }
Ejemplo n.º 6
0
        /// <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);
            }
        }
Ejemplo n.º 7
0
 /// <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);
 }
Ejemplo n.º 8
0
        /// <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;
        }
Ejemplo n.º 9
0
 internal ConvexPhysicsMesh(IConvexShape shape, TypedIndex meshIndex)
 {
     this.ConvexShape = shape;
     this.MeshIndex   = meshIndex;
 }
Ejemplo n.º 10
0
 /// <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;
 }
Ejemplo n.º 11
0
        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);
        }