Пример #1
0
        public void DotProductTest()
        {
            Vector2 forward = new Vector2(0, 1);
            Vector2 back    = new Vector2(0, -1);
            Vector2 right   = new Vector2(1, 0);
            Vector2 left    = new Vector2(-1, 0);

            Assert.AreEqual(1, forward.DotProduct(forward));
            Assert.AreEqual(-1, forward.DotProduct(back));
            Assert.AreEqual(0, forward.DotProduct(right));
            Assert.AreEqual(0, forward.DotProduct(left));
        }
Пример #2
0
        private void AddImpulseContactPoint(PhysicsObject obj1, PhysicsObject obj2, Vector2 contactPoint, Vector2 normal, float penetration, int contactPoints, float dt)
        {
            Vector2 r0 = contactPoint - obj1.Center;
            Vector2 r1 = contactPoint - obj2.Center;

            Vector2 relativeVel = (obj1.LinearVelocity + obj1.AngularVelocity * r0.CrossProduct()) - (obj2.LinearVelocity + obj2.AngularVelocity * r1.CrossProduct());

            float contactVel = Vector2.DotProduct(relativeVel, normal);

            if (contactVel > 0)
            {
                return;
            }

            float tmp1 = Vector2.VectorProduct(r0, normal);

            tmp1 *= tmp1;
            float tmp2 = Vector2.VectorProduct(r1, normal);

            tmp2 *= tmp2;

            float invMass = obj1.InvertedMass + obj2.InvertedMass + obj1.InvertedMomentOfInertia * tmp1 + obj2.InvertedMomentOfInertia * tmp2;

            const float allowedPenetration = 0.1f;
            const float biasFactor         = 0.1f;

            float e = (dt == 0 ? 0 : 1 / dt) * System.Math.Max(0, penetration - allowedPenetration) * biasFactor;
            float j = System.Math.Max(0, (-contactVel + e) / (invMass * contactPoints));

            Vector2 impulse = j * normal;

            obj1.ApplyImpulse(impulse, r0);
        }
Пример #3
0
        private Vector2[] GetSupportPoints(Polygon polygon, Vector2 dir)
        {
            int            count     = 0;
            const float    threshold = 1.0E-8f;
            double         mind      = 0;
            List <Vector2> support   = new List <Vector2>(2);

            for (int i = 0; i < polygon.Points.Length; i++)
            {
                float d = Vector2.DotProduct(polygon.Points[i], dir);

                if (i == 0 || d < mind)
                {
                    mind = d;
                }
            }

            for (int i = 0; i < polygon.Points.Length; i++)
            {
                float d = Vector2.DotProduct(polygon.Points[i], dir);

                if (d < (mind + threshold))
                {
                    support.Add(polygon.Points[i]);
                    count++;
                    if (count >= 2)
                    {
                        return(support.ToArray());
                    }
                }
            }

            return(support.ToArray());
        }
Пример #4
0
        /// <summary>
        /// Rotates the actor to face the given position
        /// </summary>
        /// <param name="position">The position the actor should be facing</param>
        public void LookAt(Vector2 position)
        {
            //Find the direction that the actor should look in
            Vector2 direction = (position - LocalPosition).Normalized;

            //Use the dotproduct to find the angle the actor needs to rotate
            float dotProd = Vector2.DotProduct(Forward, direction);

            if (Math.Abs(dotProd) > 1)
            {
                return;
            }
            float angle = (float)Math.Acos(dotProd);

            //Find a perpindicular vector to the direction
            Vector2 perp = new Vector2(direction.Y, -direction.X);

            //Find the dot product of the perpindicular vector and the current forward
            float perpDot = Vector2.DotProduct(perp, Forward);

            //If the result isn't 0, use it to change the sign of the angle to be either positive or negative
            if (perpDot != 0)
            {
                angle *= -perpDot / Math.Abs(perpDot);
            }

            Rotate(angle);
        }
Пример #5
0
        /// <summary>
        /// Rotate this actor to face a position
        /// </summary>
        /// <param name="position">Position to face</param>
        public void LookAt(Vector2 position)
        {
            // Find the direction to look at
            Vector2 direction = (position - GlobalPosition).Normalized;

            // Get dotproduct between forward and direction to look
            float dotProduct = Vector2.DotProduct(Forward, direction);

            // If actor is already facing that direction, return
            if (dotProduct >= 1)
            {
                return;
            }

            // Get angle to face
            float angle = (float)Math.Acos(dotProduct);

            // Get perpendicular vector to direction
            Vector2 perpVector = new Vector2(-direction.Y, direction.X);

            // Get dotproduct between forward and perpendicular vector
            float perpDotProduct = Vector2.DotProduct(perpVector, Forward);

            // Negate angle if perDotProduct is negative
            if (perpDotProduct != 0)
            {
                angle *= perpDotProduct / Math.Abs(perpDotProduct);
            }

            SetRotation(angle + RotationAngle);
        }
Пример #6
0
        private void PrintStateOfBox(StringBuilder b, PhysicalParticle box)
        {
            const double RadsToDegress = 180 / (double)Math.PI;

            b.AppendLine($"   X: {box.Position.X}");
            b.AppendLine($"   Y: {box.Position.Y}");
            b.AppendLine($"   A: {box.Angle}\n");

            if (debugInfoPage == 0)
            {
                b.AppendLine($" v_x: {box.Velocity.X}");
                b.AppendLine($" v_y: {box.Velocity.Y}");
                b.AppendLine($"   w: {box.AngularVelocity}");

                b.AppendLine($"\n F_x: {box.Force.X}");
                b.AppendLine($" F_y: {box.Force.Y}");
                b.AppendLine($"   T: {box.Torque}");

                b.AppendLine($"\nFC_x: {box.ConstraintForce.X}");
                b.AppendLine($"FC_y: {box.ConstraintForce.Y}");
                b.AppendLine($"  TC: {box.ConstraintTorque}");

                var angle = RadsToDegress * Vector2.DotProduct(box.ConstraintForce, box.Velocity) /
                            (box.ConstraintForce.Magnitude * box.Velocity.Magnitude);

                b.AppendLine($"\n DOT: {angle}");
            }
            else if (debugInfoPage == 1)
            {
                solver.DebugInfo(b, debugInfoPage, box);
            }
        }
Пример #7
0
    public static long WhereVector(Vector2 beginPoint, Vector2 endPoint, Vector2 point)
    {//????????????
        Vector2 segment = endPoint - beginPoint;
        Vector2 aimVec  = point - beginPoint;

        if (Vector2.CrossProduct(segment, aimVec) > EPS)
        {
            return(1);//??????
        }
        else if (Vector2.CrossProduct(segment, aimVec) < -EPS)
        {
            return(2);//?????
        }
        else if (Vector2.DotProduct(segment, aimVec) < -1 + EPS)
        {
            return(3);//??????????
        }
        else if (segment.Length() < aimVec.Length())
        {
            return(4);//????????
        }
        else
        {
            return(5);//?????
        }
    }
Пример #8
0
    public static Vector2 Projection(Vector2 beginPoint, Vector2 endPoint, Vector2 point)//????
    {
        Vector2 segment = endPoint - beginPoint;
        decimal ratio   = Vector2.DotProduct(point - beginPoint, segment) / segment.Length();

        return(beginPoint + segment * ratio);//?????
    }
Пример #9
0
        private static int Clip(Vector2 n, float c, ref Vector2[] pFace)
        {
            int sp = 0;

            Vector2[] outV = new Vector2[] { pFace[0], pFace[1] };

            float d1 = Vector2.DotProduct(n, pFace[0]) - c;
            float d2 = Vector2.DotProduct(n, pFace[1]) - c;

            if (d1 <= 0)
            {
                outV[sp++] = pFace[0];
            }
            if (d2 <= 0)
            {
                outV[sp++] = pFace[1];
            }

            if (d1 * d2 < 0)
            {
                float alpha = d1 / (d1 - d2);
                outV[sp] = pFace[0] + alpha * (pFace[1] - pFace[0]);
                sp++;
            }

            pFace = outV;

            System.Diagnostics.Debug.Assert(sp != 3);
            return(sp);
        }
Пример #10
0
        private static void FindIncidentFace(out Vector2[] pV, PolygonMesh pRef, PolygonMesh pInc, int pIndex)
        {
            Vector2 referenceNormal = pRef.Normals[pIndex];

            var iMat = pInc.Body.GameObject.RotationMatrix;

            referenceNormal = pRef.Body.GameObject.RotationMatrix * referenceNormal;
            referenceNormal = iMat.Transpose() * referenceNormal;

            int   incidentFace = 0;
            float min          = float.MaxValue;

            for (int i = 0; i < pInc.Vertices.Length; i++)
            {
                float dot = Vector2.DotProduct(referenceNormal, pInc.Normals[i]);
                if (dot < min)
                {
                    min          = dot;
                    incidentFace = i;
                }
            }

            pV    = new Vector2[2];
            pV[0] = iMat * pInc.Vertices[incidentFace] + pInc.Body.AABB.Center;

            incidentFace = incidentFace + 1 >= pInc.Vertices.Length ? 0 : incidentFace + 1;
            pV[1]        = iMat * pInc.Vertices[incidentFace] + pInc.Body.AABB.Center;
        }
Пример #11
0
        private static float FindAxisLeastPenetration(out int pIndex, PolygonMesh pA, PolygonMesh pB)
        {
            float best = float.MinValue;

            pIndex = 0;

            var aMat = pA.Body.GameObject.RotationMatrix;
            var bMat = pB.Body.GameObject.RotationMatrix;

            for (int i = 0; i < pA.Vertices.Length; i++)
            {
                Vector2 normal         = pA.Normals[i];
                Vector2 orientedNormal = aMat * normal;

                Mathematics.Matrix2X2 buT = bMat.Transpose();
                normal = buT * orientedNormal;

                Vector2 support = pB.GetSupport(-normal);

                Vector2 vertex = pA.Vertices[i];
                vertex  = aMat * vertex + pA.Body.AABB.Center;
                vertex -= pB.Body.AABB.Center;
                vertex  = buT * vertex;

                float d = Vector2.DotProduct(normal, support - vertex);

                if (d > best)
                {
                    best   = d;
                    pIndex = i;
                }
            }

            return(best);
        }
Пример #12
0
        private void mainPB_MouseMove(object sender, MouseEventArgs e)
        {
            // GC.Collect();
            if (this.e0 != null)
            {
                if (photoCB.SelectedIndex != -1 && photoMoveRBTN.Checked)
                {
                    if (toDoObj == toDo.Move)
                    {
                        this.Scene.Photos[photoCB.SelectedIndex].Move(e.X - e0.X, e.Y - e0.Y);
                    }
                    else if (toDoObj == toDo.Resize)
                    {
                        this.Scene.Photos[photoCB.SelectedIndex].Process(
                            new ScalingFilter(this.Scene.Photos[photoCB.SelectedIndex].Width + e.X - e0.X,
                                              this.Scene.Photos[photoCB.SelectedIndex].Height + e.Y - e0.Y));
                    }
                    else
                    {
                        Vector2 p = Vector2.Normolize(new Vector2(e.X - this.Scene.Photos[photoCB.SelectedIndex].X
                                                                  , e.Y - this.Scene.Photos[photoCB.SelectedIndex].Y));
                        float  cosOX = Vector2.DotProduct(p, new Vector2(1, 0));
                        float  cosOY = Vector2.DotProduct(p, new Vector2(0, 1));
                        double angle = 0;
                        if (cosOX >= 0 && cosOY >= 0)
                        {
                            angle = Math.Acos(cosOX);
                        }

                        else if (cosOX <= 0 && cosOY >= 0)
                        {
                            angle = Math.Acos(cosOY) + Math.PI / 2;
                        }
                        else if (cosOX <= 0 && cosOY <= 0)
                        {
                            angle = 3 * Math.PI / 2 - Math.Acos(cosOX) + Math.PI / 2;
                        }
                        else
                        {
                            angle = -Math.Acos(cosOX);
                        }
                        //angle = -angle;
                        this.Scene.Photos[photoCB.SelectedIndex].Process(
                            new RotateFilter((float)angle));
                    }
                    this.Scene.UpdatePhotos();
                }
                else if (lightCB.SelectedIndex != -1 && !photoMoveRBTN.Checked)
                {
                    if (this.Scene.Map.Light[lightCB.SelectedIndex] is Spotlight)
                    {
                        (this.Scene.Map.Light[lightCB.SelectedIndex] as Spotlight).Move(e.X - e0.X, e.Y - e0.Y);
                    }
                    this.Scene.UpdateLightingMap();
                }
                Draw();
                this.e0 = e;
            }
        }
Пример #13
0
            /// <summary>
            /// Finds the angle in radians between the Vector2 and specified other Vector2.
            /// </summary>
            /// <param name="compareTo">Other Vector2 to compare to for angle calculation.</param>
            public float AngleBetween(Vector2 compareTo)
            {
                // Normalize both Vector2s
                Vector2 a = GetNormalized();
                Vector2 b = compareTo.GetNormalized();

                return((float)Math.Acos(a.DotProduct(b)));
            }
Пример #14
0
        public static Line2 FromPointAndDirection(Vector2 point, Vector2 direction)
        {
            var normal = direction.Rotate90Positive().Normalize();

            var distanceFromOriginToPointProjectedOnNormal = Vector2.DotProduct(point, normal);

            return(new Line2(normal, distanceFromOriginToPointProjectedOnNormal));
        }
Пример #15
0
    _projection Project(Vector2 onto)
    {
        float min = onto.DotProduct(points[0]);
        float max = min;

        for (int i = 1; i < points.Count; i++)
        {
            float p = onto.DotProduct(points[i]);
            if (p < min)
            {
                min = p;
            }
            else if (p > max)
            {
                max = p;
            }
        }

        return(new _projection(min, max));
    }
Пример #16
0
        public static Vector2 PointProjectionToLine(Vector2 point, Vector2 p1, Vector2 p2, out bool isInside)
        {
            var a = point - p1;
            var b = (p2 - p1) / Vector2.Distance(p1, p2);

            point    = Vector2.DotProduct(a, b) * b + p1;
            isInside =
                point.X >= Mathf.Min(p1.X, p2.X) && point.X <= Mathf.Max(p1.X, p2.X) &&
                point.Y >= Mathf.Min(p1.Y, p2.Y) && point.Y <= Mathf.Max(p1.Y, p2.Y);
            return(point);
        }
Пример #17
0
        private Vector2 Edge_GetClosestPoint(Vector2 p, Vector2 a, Vector2 b)
        {
            Vector2 ab = b - a;
            Vector2 ap = p - a;

            float ab_ab = Vector2.DotProduct(ab, ab);
            float ab_ap = Vector2.DotProduct(ab, ap);

            float t = MathHelper.Clamp(ab_ap / ab_ab, 0.0f, 1.0f);

            return(a + t * ab);
        }
Пример #18
0
 public void OperationsTest()
 {
     Assert.That(Vector2.One * Vector2.Zero, Is.EqualTo(Vector2.Zero));
     Assert.That(Vector2.One - Vector2.One, Is.EqualTo(Vector2.Zero));
     Assert.That(0.5f * (Vector2.One * 2), Is.EqualTo(Vector2.One));
     Assert.That(Vector2.Half / Vector2.Half, Is.EqualTo(Vector2.One));
     Assert.That(Vector2.One / 2, Is.EqualTo(Vector2.Half));
     Assert.That(Vector2.Half + Vector2.Half, Is.EqualTo(Vector2.One));
     Assert.That(-Vector2.One, Is.EqualTo(new Vector2(-1)));
     Assert.That(Vector2.DotProduct(Vector2.Half, Vector2.Half), Is.EqualTo(0.5f));
     Assert.That(Vector2.CrossProduct(Vector2.Half, Vector2.Half), Is.EqualTo(0));
 }
Пример #19
0
            //C++ TO C# CONVERTER TODO TASK: The implementation of the following method could not be found:
            //		bool isPointInside(Ogre::Vector2 point);
            public bool isPointInside(Vector2 point)
            {
                // Compute vectors
                Vector2 v0 = p(2) - p(0);
                Vector2 v1 = p(1) - p(0);
                Vector2 v2 = point - p(0);

                // Compute dot products
                Real dot00 = v0.SquaredLength;
                Real dot01 = v0.DotProduct(v1);
                Real dot02 = v0.DotProduct(v2);
                Real dot11 = v1.SquaredLength;
                Real dot12 = v1.DotProduct(v2);

                // Compute barycentric coordinates
                Real invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
                Real u        = (dot11 * dot02 - dot01 * dot12) * invDenom;
                Real v        = (dot00 * dot12 - dot01 * dot02) * invDenom;

                // Check if point is in triangle
                return((u >= 0) && (v >= 0) && (u + v - 1 <= 0));
            }
Пример #20
0
        public static float SqrDistanceFromPointToSegment(Vector2 v, Vector2 w, Vector2 p)
        {
            var l2 = (w - v).SqrLength;

            if (l2 == 0)
            {
                return((p - v).SqrLength);
            }
            var t    = Mathf.Max(0, Mathf.Min(1, Vector2.DotProduct(p - v, w - v) / l2));
            var proj = v + t * (w - v);

            return((p - proj).SqrLength);
        }
Пример #21
0
        public bool CheckTargetInSight()
        {
            if (Target == null)
                return false;

            Vector2 direction = Position - Target.Position;

            if (Vector2.DotProduct(Forward, direction) < 0)
                return true;
            else if (Vector2.DotProduct(Forward, direction) > 0.1)
                return false;

            return false;
        }
Пример #22
0
        //    *
        //	 * Equivalent of Ogre::Vector3::angleBetween, applied to Ogre::Vector2
        //
        public static Radian angleBetween(Vector2 v1, Vector2 v2)
        {
            float lenProduct = v1.Length * v2.Length;

            // Divide by zero check
            if (lenProduct < 1e-6f)
            {
                lenProduct = 1e-6f;
            }

            float f = v1.DotProduct(v2) / lenProduct;

            f = Math_Clamp(f, -1.0f, 1.0f);
            return(Math.ACos(f));
        }
Пример #23
0
        public PhysicsObject(float mass, Polygon polygon, Vector2 linearVelocity = default(Vector2), float angularVelocity = 0.0f)
        {
            if (mass < 0)
            {
                throw new ArgumentException("mass", "Die Masse muss positiv oder 0 sein.");
            }
            if (!polygon.IsValid)
            {
                throw new ArgumentException("polygon", "Das übergebene Polygon ist nicht gültig.");
            }

            Polygon      = polygon;
            startPolygon = polygon;
            Mass         = mass;
            forces       = new Vector2(0, 0);
            torques      = 0;

            radius      = 0;
            Center      = polygon.Center;
            startCenter = Center;
            for (int i = 0; i < polygon.Points.Length; i++)
            {
                float dist = (Center - polygon.Points[i]).Length;
                if (dist > radius)
                {
                    radius = dist;
                }
            }

            float denom = 0;
            float num   = 0;

            for (int i = 0; i < polygon.Points.Length - 1; i++)
            {
                Vector2 a = polygon.Points[i + 1] - Center;
                Vector2 b = polygon.Points[i] - Center;
                float   f = System.Math.Abs(a.X * b.Y - a.Y * b.X);
                denom += f * (Vector2.DotProduct(a, a) + Vector2.DotProduct(a, b) + Vector2.DotProduct(b, b));
                num   += f;
            }
            MomentOfInertia = (mass * denom) / (6 * num);

            InvertedMass            = mass == 0 ? 0 : 1.0f / mass;
            InvertedMomentOfInertia = MomentOfInertia == 0 ? 0 : 1.0f / MomentOfInertia;

            LinearVelocity  = linearVelocity;
            AngularVelocity = angularVelocity;
        }
Пример #24
0
        public bool CheckTargetInSight()
        {
            if (Target == null)
            {
                return(false);
            }

            Vector2 direction = Vector2.Normalize(LocalPosition - Target.LocalPosition);

            if (Vector2.DotProduct(Forward, direction) > 1)
            {
                return(true);
            }

            return(false);
        }
Пример #25
0
        public bool CheckTargetInSight()
        {
            if (Target == null)
            {
                return(false);
            }

            Vector3 direction = Vector3.Normalize(Transform.Position - Target.Transform.Position);

            if (Vector2.DotProduct(Forward, direction) > 0)
            {
                return(true);
            }

            return(false);
        }
Пример #26
0
 public override void HandleColliding(PlatformObject obj, Vector2 move)
 {
     if (obj is ChemBlock)
     {
         ChemBlock block = (ChemBlock)obj;
         if (!IsBondedWith(block) && nailDuration > 0)
         {
             Vector2 moveDir = move;
             moveDir.Normalize();
             if (nailDirection.DotProduct(moveDir) > 0.5f)
             {
                 NailOnto(block);
                 nailDuration = 0;
             }
         }
     }
 }
Пример #27
0
        /// <summary>
        /// Calculates the squared distance between a given point and a given ray.
        /// </summary>
        /// <param name="point">A <see cref="Vector2"/> instance.</param>
        /// <param name="ray">A <see cref="Ray"/> instance.</param>
        /// <returns>The squared distance between the point and the ray.</returns>
        public static double SquaredDistance(Vector2 point, Ray ray)
        {
            Vector2 diff = point - ray.Origin;
            double  t    = Vector2.DotProduct(diff, ray.Direction);

            if (t <= 0.0f)
            {
                t = 0.0f;
            }
            else
            {
                t    /= ray.Direction.GetLengthSquared();
                diff -= t * ray.Direction;
            }

            return(diff.GetLengthSquared());
        }
Пример #28
0
        /// <summary>
        /// Find the intersection of a ray and a sphere.
        /// Only works with unit rays (normalized direction)!!!
        /// </summary>
        /// <remarks>
        /// This is the optimized Ray-Sphere intersection algorithms described in "Real-Time Rendering".
        /// </remarks>
        /// <param name="ray">The ray to test.</param>
        /// <param name="t">
        /// If intersection accurs, the function outputs the distance from the ray's origin
        /// to the closest intersection point to this parameter.
        /// </param>
        /// <returns>Returns True if the ray intersects the sphere. otherwise, <see langword="false"/>.</returns>
        public bool FindIntersections(Ray ray, ref double t)
        {
            // Only gives correct result for unit rays.
            //Debug.Assert(MathUtils.ApproxEquals(1.0f, ray.Direction.GetLength()), "Ray direction should be normalized!");

            // Calculates a vector from the ray origin to the sphere center.
            Vector2 diff = this.center - ray.Origin;
            // Compute the projection of diff onto the ray direction
            double d = Vector2.DotProduct(diff, ray.Direction);

            double diffSquared   = diff.GetLengthSquared();
            double radiusSquared = this.radius * this.radius;

            // First rejection test :
            // if d<0 and the ray origin is outside the sphere than the sphere is behind the ray
            if ((d < 0.0f) && (diffSquared > radiusSquared))
            {
                return(false);
            }

            // Compute the distance from the sphere center to the projection
            double mSquared = diffSquared - d * d;

            // Second rejection test:
            // if mSquared > radiusSquared than the ray misses the sphere
            if (mSquared > radiusSquared)
            {
                return(false);
            }

            double q = (double)System.Math.Sqrt(radiusSquared - mSquared);

            // We are interested only in the first intersection point:
            if (diffSquared > radiusSquared)
            {
                // If the origin is outside the sphere t = d - q is the first intersection point
                t = d - q;
            }
            else
            {
                // If the origin is inside the sphere t = d + q is the first intersection point
                t = d + q;
            }
            return(true);
        }
        public void LookAt(Vector2 position)
        {
            Vector2 direction = (position - LocalPosition).Normalized;

            float dotProd = Vector2.DotProduct(Forward, direction);
            if (Math.Abs(dotProd) > 1)
                return;
            float angle = (float)Math.Acos(dotProd);

            Vector2 perp = new Vector2(direction.Y, -direction.X);

            float perpDot = Vector2.DotProduct(perp, Forward);

            if (perpDot != 0)
                angle *= -perpDot / Math.Abs(perpDot);

            Rotate(angle);
        }
Пример #30
0
        //allows the enemy to detect a target
        public bool GetTargetInSight(float maxAngle, float maxDistance)
        {
            if (Target == null)
            {
                return(false);
            }

            Vector2 direction = Target.LocalPosition - LocalPosition;
            float   distance  = (Target.LocalPosition - LocalPosition).Magnitude;
            float   angle     = (float)Math.Acos(Vector2.DotProduct(Forward, direction.Normalized));

            if (angle <= maxAngle && distance <= maxDistance)
            {
                return(true);
            }


            return(false);
        }
Пример #31
0
 // Calculate the projection of a polygon on an axis and returns it as a [min, max] interval
 public static void ProjectPolygon(Vector2 axis, Polygon polygon, ref float min, ref float max)
 {
     // To project a point on an axis use the dot product
     float d = axis.DotProduct(polygon.Points[0]);
     min = d;
     max = d;
     for (int i = 0; i < polygon.Points.Count; i++) {
         d = polygon.Points[i].DotProduct(axis);
         if (d < min) {
             min = d;
         } else {
             if (d > max) {
                 max = d;
             }
         }
     }
 }
Пример #32
0
    // Check if polygon A is going to collide with polygon B for the given velocity
    public static PolygonCollisionResult PolygonCollision(Polygon polygonA, Polygon polygonB, Vector2 velocity)
    {
        PolygonCollisionResult result = new PolygonCollisionResult();
        result.Intersect = true;
        result.WillIntersect = true;

        int edgeCountA = polygonA.Edges.Count;
        int edgeCountB = polygonB.Edges.Count;
        float minIntervalDistance = float.PositiveInfinity;
        Vector2 translationAxis = new Vector2();
        Vector2 edge;

        // Loop through all the edges of both polygons
        for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) {
            if (edgeIndex < edgeCountA) {
                edge = polygonA.Edges[edgeIndex];
            } else {
                edge = polygonB.Edges[edgeIndex - edgeCountA];
            }

            // ===== 1. Find if the polygons are currently intersecting =====

            // Find the axis perpendicular to the current edge
            Vector2 axis = new Vector2(-edge.y, edge.x);
            axis.Normalize();

            // Find the projection of the polygon on the current axis
            float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
            ProjectPolygon(axis, polygonA, ref minA, ref maxA);
            ProjectPolygon(axis, polygonB, ref minB, ref maxB);

            // Check if the polygon projections are currentlty intersecting
            if (IntervalDistance(minA, maxA, minB, maxB) > 0) result.Intersect = false;

            // ===== 2. Now find if the polygons *will* intersect =====

            // Project the velocity on the current axis
            float velocityProjection = axis.DotProduct(velocity);

            // Get the projection of polygon A during the movement
            if (velocityProjection < 0) {
                minA += velocityProjection;
            } else {
                maxA += velocityProjection;
            }

            // Do the same test as above for the new projection
            float intervalDistance = IntervalDistance(minA, maxA, minB, maxB);
            if (intervalDistance > 0) result.WillIntersect = false;

            // If the polygons are not intersecting and won't intersect, exit the loop
            if (!result.Intersect && !result.WillIntersect) break;

            // Check if the current interval distance is the minimum one. If so store
            // the interval distance and the current distance.
            // This will be used to calculate the minimum translation Vector2
            intervalDistance = Mathf.Abs(intervalDistance);
            if (intervalDistance < minIntervalDistance) {
                minIntervalDistance = intervalDistance;
                translationAxis = axis;

                Vector2 d = polygonA.Center - polygonB.Center;
                if (d.DotProduct(translationAxis) < 0) translationAxis = -translationAxis;
            }
        }

        // The minimum translation Vector2 can be used to push the polygons appart.
        // First moves the polygons by their velocity
        // then move polygonA by MinimumTranslationVector2.
        if (result.WillIntersect) result.MinimumTranslation = translationAxis * minIntervalDistance;

        return result;
    }