Пример #1
0
		/// <summary>
		/// If the points are not centered they will be centered with the difference being applied to the localOffset.
		/// </summary>
		/// <param name="points">Points.</param>
		public PolygonCollider( Vector2[] points )
		{
			// first and last point must not be the same. we want an open polygon
			var isPolygonClosed = points[0] == points[points.Length - 1];

			if( isPolygonClosed )
				Array.Resize( ref points, points.Length - 1 );

			var center = Polygon.findPolygonCenter( points );
			setLocalOffset( center );
			Polygon.recenterPolygonVerts( points );
			shape = new Polygon( points );
		}
Пример #2
0
        public PolygonCollider( Vector2[] points )
        {
            // first and last point must not be the same. we want an open polygon
            var isPolygonClosed = points[0] == points[points.Length - 1];

            // create the array with an extra element if we need to close the poly
            var tempPoints = new Vector2[ isPolygonClosed ? points.Length - 1 : points.Length];

            // copy our points over
            for( var i = 0; i < tempPoints.Length; i++ )
                tempPoints[i] = points[i];

            shape = new Polygon( tempPoints );
        }
Пример #3
0
		public static bool pointToPoly( Vector2 point, Polygon poly, out CollisionResult result )
		{
			result = new CollisionResult();

			if( poly.containsPoint( point ) )
			{
				float distanceSquared;
				var closestPoint = Polygon.getClosestPointOnPolygonToPoint( poly.points, point - poly.position, out distanceSquared, out result.normal );

				result.minimumTranslationVector = result.normal * Mathf.sqrt( distanceSquared );
				result.point = closestPoint + poly.position;

				return true;
			}

			return false;
		}
Пример #4
0
		public static bool lineToPoly( Vector2 start, Vector2 end, Polygon polygon, out RaycastHit hit )
		{
			hit = new RaycastHit();
			var normal = Vector2.Zero;
			var intersectionPoint = Vector2.Zero;
			var fraction = float.MaxValue;
			var hasIntersection = false;

			for( int j = polygon.points.Length - 1, i = 0; i < polygon.points.Length; j = i, i++ )
			{
				var edge1 = polygon.position + polygon.points[j];
				var edge2 = polygon.position + polygon.points[i];
				Vector2 intersection;
				if( lineToLine( edge1, edge2, start, end, out intersection ) )
				{
					hasIntersection = true;

					// TODO: is this the correct and most efficient way to get the fraction?
					// check x fraction first. if it is NaN use y instead
					var distanceFraction = ( intersection.X - start.X ) / ( end.X - start.X );
					if( float.IsNaN( distanceFraction ) )
						distanceFraction = ( intersection.Y - start.Y ) / ( end.Y - start.Y );

					if( distanceFraction < fraction )
					{
						var edge = edge2 - edge1;
						normal = new Vector2( edge.Y, -edge.X );
						fraction = distanceFraction;
						intersectionPoint = intersection;
					}
				}
			}

			if( hasIntersection )
			{
				normal.Normalize();
				float distance;
				Vector2.Distance( ref start, ref intersectionPoint, out distance );
				hit.setValues( fraction, distance, intersectionPoint, normal );
				return true;
			}

			return false;
		}
        static bool polygonToPolygon(Polygon first, Polygon second, Vector2?deltaMovement, out Vector2 responseNormal, out float timeOfCollision)
        {
            timeOfCollision = float.MinValue;
            responseNormal  = Vector2.Zero;
            // polygon verts are in local space so we need to convert one of the polys to be in the space of the other. We use the distance
            // between them to do so.
            var polygonOffset = first.position - second.position;

            // All the separation axes
            var iNumAxes = 0;


            if (deltaMovement.HasValue)
            {
                _satAxisArray[iNumAxes] = new Vector2(-deltaMovement.Value.Y, deltaMovement.Value.X);
                var fVel2 = Vector2.Dot(deltaMovement.Value, deltaMovement.Value);
                if (fVel2 > Mathf.epsilon)
                {
                    if (!intervalIntersect(first, second, ref _satAxisArray[iNumAxes], ref polygonOffset, ref deltaMovement, out _satTimerPerAxis[iNumAxes]))
                    {
                        return(false);
                    }
                    iNumAxes++;
                }
            }

            // test separation axes of A
            for (int j = first.points.Length - 1, i = 0; i < first.points.Length; j = i, i++)
            {
                // we only need to check 2 axis for boxes
                if (second.isBox && i == 2)
                {
                    break;
                }

                var point0 = first.points[j];
                var point1 = first.points[i];
                var edge   = point1 - point0;
                _satAxisArray[iNumAxes] = new Vector2(-edge.Y, edge.X);

                if (!intervalIntersect(first, second, ref _satAxisArray[iNumAxes], ref polygonOffset, ref deltaMovement, out _satTimerPerAxis[iNumAxes]))
                {
                    return(false);
                }
                iNumAxes++;
            }

            // test separation axes of B
            for (int j = second.points.Length - 1, i = 0; i < second.points.Length; j = i, i++)
            {
                // we only need to check 2 axis for boxes
                if (second.isBox && i == 2)
                {
                    break;
                }

                var point0 = second.points[j];
                var point1 = second.points[i];
                var edge   = point1 - point0;
                _satAxisArray[iNumAxes] = new Vector2(-edge.Y, edge.X);

                if (!intervalIntersect(first, second, ref _satAxisArray[iNumAxes], ref polygonOffset, ref deltaMovement, out _satTimerPerAxis[iNumAxes]))
                {
                    return(false);
                }
                iNumAxes++;
            }

            if (!findMinimumTranslationDistance(iNumAxes, out responseNormal, out timeOfCollision))
            {
                return(false);
            }

            // make sure the polygons gets pushed away from each other.
            if (Vector2.Dot(responseNormal, polygonOffset) < 0f)
            {
                responseNormal = -responseNormal;
            }

            return(true);
        }
Пример #6
0
        /// <summary>
        /// checks for a collision between first and second. deltaMovement is applied to first to see if a collision occurs in the future.
        /// - a negative timeOfCollision means we have an overlap
        /// - a positive timeOfCollision means we have a future collision
        /// based on http://elancev.name/oliver/2D%20polygon.htm
        /// </summary>
        /// <returns><c>true</c>, if to polygon was polygoned, <c>false</c> otherwise.</returns>
        /// <param name="first">First.</param>
        /// <param name="second">Second.</param>
        /// <param name="deltaMovement">Delta movement.</param>
        /// <param name="responseNormal">Response normal.</param>
        /// <param name="timeOfCollision">Time of collision.</param>
        static bool polygonToPolygon( Polygon first, Polygon second, Vector2? deltaMovement, out Vector2 responseNormal, out float timeOfCollision )
        {
            timeOfCollision = float.MinValue;
            responseNormal = Vector2.Zero;
            // polygon verts are in local space so we need to convert one of the polys to be in the space of the other. We use the distance
            // between them to do so.
            var polygonOffset = first.position - second.position;

            // All the separation axes
            var iNumAxes = 0;

            if( deltaMovement.HasValue )
            {
                _satAxisArray[iNumAxes] = new Vector2( -deltaMovement.Value.Y, deltaMovement.Value.X );
                var fVel2 = Vector2.Dot( deltaMovement.Value, deltaMovement.Value );
                if( fVel2 > Mathf.epsilon )
                {
                    if( !intervalIntersect(	first, second, ref _satAxisArray[iNumAxes], ref polygonOffset, ref deltaMovement, out _satTimerPerAxis[iNumAxes] ) )
                        return false;
                    iNumAxes++;
                }
            }

            // test separation axes of A
            for( int j = first.points.Length - 1, i = 0; i < first.points.Length; j = i, i++ )
            {
                // we only need to check 2 axis for boxes
                if( second.isBox && i == 2 )
                    break;

                var point0 = first.points[j];
                var point1 = first.points[i];
                var edge = point1 - point0;
                _satAxisArray[iNumAxes] = new Vector2( -edge.Y, edge.X );

                if( !intervalIntersect(	first, second, ref _satAxisArray[iNumAxes], ref polygonOffset, ref deltaMovement, out _satTimerPerAxis[iNumAxes] ) )
                    return false;
                iNumAxes++;
            }

            // test separation axes of B
            for( int j = second.points.Length - 1, i = 0; i < second.points.Length; j = i, i++ )
            {
                // we only need to check 2 axis for boxes
                if( second.isBox && i == 2 )
                    break;

                var point0 = second.points[j];
                var point1 = second.points[i];
                var edge = point1 - point0;
                _satAxisArray[iNumAxes] = new Vector2( -edge.Y, edge.X );

                if( !intervalIntersect(	first, second, ref _satAxisArray[iNumAxes], ref polygonOffset, ref deltaMovement, out _satTimerPerAxis[iNumAxes] ) )
                    return false;
                iNumAxes++;
            }

            if( !findMinimumTranslationDistance( iNumAxes, out responseNormal, out timeOfCollision ) )
                return false;

            // make sure the polygons gets pushed away from each other.
            if( Vector2.Dot( responseNormal, polygonOffset ) < 0f )
                responseNormal = -responseNormal;

            return true;
        }
Пример #7
0
        static bool intervalIntersect( Polygon first, Polygon second, ref Vector2 axis, ref Vector2 shapeOffset, ref Vector2? deltaMovement, out float taxis )
        {
            taxis = float.MinValue;
            float min0, max0;
            float min1, max1;
            getInterval( first, first.points.Length, axis, out min0, out max0 );
            getInterval( second, second.points.Length, axis, out min1, out max1 );

            var h = Vector2.Dot( shapeOffset, axis );
            min0 += h;
            max0 += h;

            var d0 = min0 - max1; // if overlapped, d0 < 0
            var d1 = min1 - max0; // if overlapped, d1 < 0

            // separated, test dynamic intervals
            if( d0 > 0.0f || d1 > 0.0f )
            {
                // if we have no velocity we are done
                if( !deltaMovement.HasValue )
                    return false;

                var v = Vector2.Dot( deltaMovement.Value, axis );

                // small velocity, so only the overlap test will be relevant.
                if( Math.Abs( v ) < 0.0000001f )
                    return false;

                var t0 = -d0 / v; // time of impact to d0 reaches 0
                var t1 = d1 / v; // time of impact to d0 reaches 1

                if( t0 > t1 )
                {
                    var temp = t0;
                    t0 = t1;
                    t1 = temp;
                }

                taxis = t0 > 0.0f ? t0 : t1;
                if( taxis < 0.0f || taxis > 1.0f )
                    return false;

                return true;
            }
            else
            {
                // overlap. get the interval, as a the smallest of |d0| and |d1|
                // return negative number to mark it as an overlap
                taxis = d0 > d1 ? d0 : d1;
                return true;
            }
        }
Пример #8
0
        /// <summary>
        /// calculates the projection range of a polygon along an axis
        /// </summary>
        /// <param name="A">A.</param>
        /// <param name="iNumVertices">I number vertices.</param>
        /// <param name="xAxis">X axis.</param>
        /// <param name="min">Minimum.</param>
        /// <param name="max">Max.</param>
        static void getInterval( Polygon polygon, int numVertices, Vector2 axis, out float min, out float max )
        {
            min = max = Vector2.Dot( polygon.points[0], axis );

            for( var i = 1; i < numVertices; i++ )
            {
                var d = Vector2.Dot( polygon.points[i], axis );
                if( d < min )
                    min = d;
                else if( d > max )
                    max = d;
            }
        }
Пример #9
0
        // something isnt right here with this one
        static bool circleToPolygon2( Circle circle, Polygon polygon, out CollisionResult result )
        {
            result = new CollisionResult();

            var closestPointIndex = -1;
            var poly2Circle = circle.position - polygon.position;
            var poly2CircleNormalized = Vector2.Normalize( poly2Circle );
            var max = float.MinValue;

            for( var i = 0; i < polygon.points.Length; i++ )
            {
                var projection = Vector2.Dot( polygon.points[i], poly2CircleNormalized );
                if( max < projection )
                {
                    closestPointIndex = i;
                    max = projection;
                }
            }

            var poly2CircleLength = poly2Circle.Length();
            if( poly2CircleLength - max - circle.radius > 0 && poly2CircleLength > 0 )
                return false;

            // we have a collision
            // find the closest point on the polygon. we know the closest index so we only have 2 edges to test
            var prePointIndex = closestPointIndex - 1;
            var postPointIndex = closestPointIndex + 1;

            // handle wrapping the points
            if( prePointIndex < 0 )
                prePointIndex = polygon.points.Length - 1;

            if( postPointIndex == polygon.points.Length )
                postPointIndex = 0;

            var circleCenter = circle.position - polygon.position;
            var closest1 = closestPointOnLine( polygon.points[prePointIndex], polygon.points[closestPointIndex], circleCenter );
            var closest2 = closestPointOnLine( polygon.points[closestPointIndex], polygon.points[postPointIndex], circleCenter );
            float distance1, distance2;
            Vector2.DistanceSquared( ref circleCenter, ref closest1, out distance1 );
            Vector2.DistanceSquared( ref circleCenter, ref closest2, out distance2 );

            var radiusSquared = circle.radius * circle.radius;

            float seperationDistance;
            if( distance1 < distance2 )
            {
                // make sure the squared distance is less than our radius squared else we are not colliding
                if( distance1 > radiusSquared )
                    return false;

                seperationDistance = circle.radius - Mathf.sqrt( distance1 );
                var edge = polygon.points[closestPointIndex] - polygon.points[prePointIndex];
                result.normal = new Vector2( edge.Y, -edge.X );
                result.point = polygon.position + closest1;
            }
            else
            {
                // make sure the squared distance is less than our radius squared else we are not colliding
                if( distance2 > radiusSquared )
                    return false;

                seperationDistance = circle.radius - Mathf.sqrt( distance2 );
                var edge = polygon.points[postPointIndex] - polygon.points[closestPointIndex];
                result.normal = new Vector2( edge.Y, -edge.X );
                result.point = polygon.position + closest2;
            }

            result.normal.Normalize();
            result.minimumTranslationVector = result.normal * -seperationDistance;

            return true;
        }
Пример #10
0
        // something isnt right here with this one
        static bool CircleToPolygon2(Circle circle, Polygon polygon, out CollisionResult result)
        {
            result = new CollisionResult();

            var closestPointIndex     = -1;
            var poly2Circle           = circle.position - polygon.position;
            var poly2CircleNormalized = Vector2.Normalize(poly2Circle);
            var max = float.MinValue;

            for (var i = 0; i < polygon.Points.Length; i++)
            {
                var projection = Vector2.Dot(polygon.Points[i], poly2CircleNormalized);
                if (max < projection)
                {
                    closestPointIndex = i;
                    max = projection;
                }
            }

            var poly2CircleLength = poly2Circle.Length();

            if (poly2CircleLength - max - circle.Radius > 0 && poly2CircleLength > 0)
            {
                return(false);
            }

            // we have a collision
            // find the closest point on the polygon. we know the closest index so we only have 2 edges to test
            var prePointIndex  = closestPointIndex - 1;
            var postPointIndex = closestPointIndex + 1;

            // handle wrapping the points
            if (prePointIndex < 0)
            {
                prePointIndex = polygon.Points.Length - 1;
            }

            if (postPointIndex == polygon.Points.Length)
            {
                postPointIndex = 0;
            }

            var   circleCenter = circle.position - polygon.position;
            var   closest1 = ClosestPointOnLine(polygon.Points[prePointIndex], polygon.Points[closestPointIndex], circleCenter);
            var   closest2 = ClosestPointOnLine(polygon.Points[closestPointIndex], polygon.Points[postPointIndex], circleCenter);
            float distance1, distance2;

            Vector2.DistanceSquared(ref circleCenter, ref closest1, out distance1);
            Vector2.DistanceSquared(ref circleCenter, ref closest2, out distance2);

            var radiusSquared = circle.Radius * circle.Radius;

            float seperationDistance;

            if (distance1 < distance2)
            {
                // make sure the squared distance is less than our radius squared else we are not colliding
                if (distance1 > radiusSquared)
                {
                    return(false);
                }

                seperationDistance = circle.Radius - Mathf.Sqrt(distance1);
                var edge = polygon.Points[closestPointIndex] - polygon.Points[prePointIndex];
                result.Normal = new Vector2(edge.Y, -edge.X);
                result.Point  = polygon.position + closest1;
            }
            else
            {
                // make sure the squared distance is less than our radius squared else we are not colliding
                if (distance2 > radiusSquared)
                {
                    return(false);
                }

                seperationDistance = circle.Radius - Mathf.Sqrt(distance2);
                var edge = polygon.Points[postPointIndex] - polygon.Points[closestPointIndex];
                result.Normal = new Vector2(edge.Y, -edge.X);
                result.Point  = polygon.position + closest2;
            }

            result.Normal.Normalize();
            result.MinimumTranslationVector = result.Normal * -seperationDistance;

            return(true);
        }
Пример #11
0
        /// <summary>
        /// does an overlap check of first vs second. ShapeCollisionResult retuns the data for moving first so it isn't colliding with second.
        /// </summary>
        /// <returns><c>true</c>, if to polygon was polygoned, <c>false</c> otherwise.</returns>
        /// <param name="first">First.</param>
        /// <param name="second">Second.</param>
        /// <param name="result">Result.</param>
        public static bool polygonToPolygon( Polygon first, Polygon second, out CollisionResult result )
        {
            result = new CollisionResult();
            float timeOfCollision;

            if( polygonToPolygon( first, second, null, out result.normal, out timeOfCollision ) )
            {
                result.minimumTranslationVector = result.normal * ( timeOfCollision );
                return true;
            }

            return false;
        }
Пример #12
0
        public static bool circleToPolygon( Circle circle, Polygon polygon, out CollisionResult result )
        {
            result = new CollisionResult();

            // circle position in the polygons coordinates
            var poly2Circle = circle.position - polygon.position;

            // first, we need to find the closest distance from the circle to the polygon
            float distanceSquared;
            var closestPoint = polygon.getClosestPointOnPolygonToPoint( poly2Circle, out distanceSquared, out result.normal );

            // make sure the squared distance is less than our radius squared else we are not colliding
            if( distanceSquared > circle.radius * circle.radius )
                return false;

            // figure out the mtd
            var distance = Mathf.sqrt( distanceSquared );
            var mtv = ( poly2Circle - closestPoint ) * ( ( circle.radius - distance ) / distance );

            result.minimumTranslationVector = -mtv;
            result.normal.Normalize();

            return true;
        }
Пример #13
0
		/// <summary>
		/// checks for a collision between two Polygons
		/// </summary>
		/// <returns>The collision.</returns>
		/// <param name="first">Polygon a.</param>
		/// <param name="second">Polygon b.</param>
		public static bool polygonToPolygon( Polygon first, Polygon second, out CollisionResult result )
		{
			result = new CollisionResult();
			var isIntersecting = true;

			var firstEdges = first.edgeNormals;
			var secondEdges = second.edgeNormals;
			var minIntervalDistance = float.PositiveInfinity;
			var translationAxis = new Vector2();
			var polygonOffset = first.position - second.position;
			Vector2 axis;

			// Loop through all the edges of both polygons
			for( var edgeIndex = 0; edgeIndex < firstEdges.Length + secondEdges.Length; edgeIndex++ )
			{
				// 1. Find if the polygons are currently intersecting
				// Polygons have the normalized axis perpendicular to the current edge cached for us
				if( edgeIndex < firstEdges.Length )
					axis = firstEdges[edgeIndex];
				else
					axis = secondEdges[edgeIndex - firstEdges.Length];

				// Find the projection of the polygon on the current axis
				float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
				var intervalDist = 0f;
				getInterval( axis, first, ref minA, ref maxA );
				getInterval( axis, second, ref minB, ref maxB );

				// get our interval to be space of the second Polygon. Offset by the difference in position projected on the axis.
				float relativeIntervalOffset;
				Vector2.Dot( ref polygonOffset, ref axis, out relativeIntervalOffset );
				minA += relativeIntervalOffset;
				maxA += relativeIntervalOffset;

				// check if the polygon projections are currentlty intersecting
				intervalDist = intervalDistance( minA, maxA, minB, maxB );
				if( intervalDist > 0 )
					isIntersecting = false;


				// for Poly-to-Poly casts add a Vector2? parameter called deltaMovement. In the interest of speed we do not use it here
				// 2. Now find if the polygons *will* intersect. only bother checking if we have some velocity
				//if( deltaMovement.HasValue )
				//{
				//	// Project the velocity on the current axis
				//	var velocityProjection = Vector2.Dot( axis, deltaMovement.Value );

				//	// 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
				//	intervalDist = intervalDistance( minA, maxA, minB, maxB );
				//	if( intervalDist > 0 )
				//		willIntersect = false;
				//}


				// If the polygons are not intersecting and won't intersect, exit the loop
				if( !isIntersecting )
					return false;

				// 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 vector
				intervalDist = Math.Abs( intervalDist );
				if( intervalDist < minIntervalDistance )
				{
					minIntervalDistance = intervalDist;
					translationAxis = axis;

					if( Vector2.Dot( translationAxis, polygonOffset ) < 0 )
						translationAxis = -translationAxis;
				}
			}

			// The minimum translation vector can be used to push the polygons appart.
			result.normal = translationAxis;
			result.minimumTranslationVector = -translationAxis * minIntervalDistance;

			return true;
		}
Пример #14
0
		static void getInterval( Vector2 axis, Polygon polygon, ref float min, ref float max )
		{
			// To project a point on an axis use the dot product
			float dot;
			Vector2.Dot( ref polygon.points[0], ref axis, out dot );
			min = max = dot;

			for( var i = 1; i < polygon.points.Length; i++ )
			{
				Vector2.Dot( ref polygon.points[i], ref axis, out dot );
				if( dot < min )
					min = dot;
				else if( dot > max )
					max = dot;
			}
		}
Пример #15
0
		public static bool circleToPolygon( Circle circle, Polygon polygon, out CollisionResult result )
		{
			result = new CollisionResult();

			// circle position in the polygons coordinates
			var poly2Circle = circle.position - polygon.position;

			// first, we need to find the closest distance from the circle to the polygon
			float distanceSquared;
			var closestPoint = Polygon.getClosestPointOnPolygonToPoint( polygon.points, poly2Circle, out distanceSquared, out result.normal );

			// make sure the squared distance is less than our radius squared else we are not colliding. Note that if the Circle is fully
			// contained in the Polygon the distance could be larger than the radius. Because of that we also  make sure the circle position
			// is not inside the poly.
			var circleCenterInsidePoly = polygon.containsPoint( circle.position );
			if( distanceSquared > circle.radius * circle.radius && !circleCenterInsidePoly )
				return false;

			// figure out the mtv. We have to be careful to deal with circles fully contained in the polygon or with their center contained.
			Vector2 mtv;
			if( circleCenterInsidePoly )
			{
				mtv = result.normal * ( Mathf.sqrt( distanceSquared ) - circle.radius );
			}
			else
			{
				// if we have no distance that means the circle center is on the polygon edge. Move it only by its radius
				if( distanceSquared == 0 )
				{
					mtv = result.normal * circle.radius;
				}
				else
				{
					var distance = Mathf.sqrt( distanceSquared );
					mtv = -( poly2Circle - closestPoint ) * ( ( circle.radius - distance ) / distance );
				}
			}

			result.minimumTranslationVector = mtv;
			result.point = closestPoint + polygon.position;

			return true;
		}
Пример #16
0
        /// <summary>
        /// checks for a collision between two Polygons
        /// </summary>
        /// <returns>The collision.</returns>
        /// <param name="first">Polygon a.</param>
        /// <param name="second">Polygon b.</param>
        public static bool polygonToPolygon(Polygon first, Polygon second, out CollisionResult result)
        {
            result = new CollisionResult();
            var isIntersecting = true;

            var     firstEdges          = first.edgeNormals;
            var     secondEdges         = second.edgeNormals;
            var     minIntervalDistance = float.PositiveInfinity;
            var     translationAxis     = new Vector2();
            var     polygonOffset       = first.position - second.position;
            Vector2 axis;

            // Loop through all the edges of both polygons
            for (var edgeIndex = 0; edgeIndex < firstEdges.Length + secondEdges.Length; edgeIndex++)
            {
                // 1. Find if the polygons are currently intersecting
                // Polygons have the normalized axis perpendicular to the current edge cached for us
                if (edgeIndex < firstEdges.Length)
                {
                    axis = firstEdges[edgeIndex];
                }
                else
                {
                    axis = secondEdges[edgeIndex - firstEdges.Length];
                }

                // Find the projection of the polygon on the current axis
                float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
                var   intervalDist = 0f;
                getInterval(axis, first, ref minA, ref maxA);
                getInterval(axis, second, ref minB, ref maxB);

                // get our interval to be space of the second Polygon. Offset by the difference in position projected on the axis.
                float relativeIntervalOffset;
                Vector2.Dot(ref polygonOffset, ref axis, out relativeIntervalOffset);
                minA += relativeIntervalOffset;
                maxA += relativeIntervalOffset;

                // check if the polygon projections are currentlty intersecting
                intervalDist = intervalDistance(minA, maxA, minB, maxB);
                if (intervalDist > 0)
                {
                    isIntersecting = false;
                }


                // for Poly-to-Poly casts add a Vector2? parameter called deltaMovement. In the interest of speed we do not use it here
                // 2. Now find if the polygons *will* intersect. only bother checking if we have some velocity
                //if( deltaMovement.HasValue )
                //{
                //	// Project the velocity on the current axis
                //	var velocityProjection = Vector2.Dot( axis, deltaMovement.Value );

                //	// 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
                //	intervalDist = intervalDistance( minA, maxA, minB, maxB );
                //	if( intervalDist > 0 )
                //		willIntersect = false;
                //}


                // If the polygons are not intersecting and won't intersect, exit the loop
                if (!isIntersecting)
                {
                    return(false);
                }

                // 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 vector
                intervalDist = Math.Abs(intervalDist);
                if (intervalDist < minIntervalDistance)
                {
                    minIntervalDistance = intervalDist;
                    translationAxis     = axis;

                    if (Vector2.Dot(translationAxis, polygonOffset) < 0)
                    {
                        translationAxis = -translationAxis;
                    }
                }
            }

            // The minimum translation vector can be used to push the polygons appart.
            result.normal = translationAxis;
            result.minimumTranslationVector = -translationAxis * minIntervalDistance;

            return(true);
        }
Пример #17
0
		public PolygonCollider( int vertCount, float radius )
		{
			shape = new Polygon( vertCount, radius );
		}
Пример #18
0
        /// <summary>
        /// casts first at second
        /// </summary>
        /// <returns><c>true</c>, if to polygon was polygoned, <c>false</c> otherwise.</returns>
        /// <param name="first">First.</param>
        /// <param name="second">Second.</param>
        /// <param name="deltaMovement">Delta movement.</param>
        public static bool polygonToPolygonCast( Polygon first, Polygon second, Vector2 deltaMovement, out RaycastHit hit )
        {
            hit = new RaycastHit();
            float timeOfCollision;

            if( polygonToPolygon( first, second, deltaMovement, out hit.normal, out timeOfCollision ) )
            {
                hit.fraction = timeOfCollision;

                // if timeOfCollision is less than 0 this is an overlap
                if( timeOfCollision < 0f )
                {
                    hit.centroid = first.position - hit.normal * timeOfCollision;
                }
                else
                {
                    hit.centroid = first.position + deltaMovement * timeOfCollision;
                }

                return true;
            }

            return false;
        }