//
        // Line, plane, ray intersection with plane
        //

        //Ray-plane intersection
        //http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection
        public static bool RayPlane(MyVector2 planePos, MyVector2 planeNormal, MyVector2 rayStart, MyVector2 rayDir)
        {
            //To avoid floating point precision issues we can add a small value
            float epsilon = MathUtility.EPSILON;

            bool areIntersecting = false;

            float denominator = MyVector2.Dot(planeNormal * -1f, rayDir);

            //Debug.Log(denominator);

            //The ray has to point at the surface of the plane
            //The surface of the plane is determined by the normal
            if (denominator > epsilon)
            {
                //Now we have to figur out of the ray starts "inside" of the plane
                //meaning on the other side of the normal
                //If so it can't hit the plane
                MyVector2 vecBetween = planePos - rayStart;

                float t = MyVector2.Dot(vecBetween, planeNormal * -1f) / denominator;

                //Debug.Log(t);

                if (t >= 0f)
                {
                    areIntersecting = true;
                }
            }

            return(areIntersecting);
        }
Example #2
0
        //
        // Find the closest point on a line segment from a point
        //
        //From https://www.youtube.com/watch?v=KHuI9bXZS74
        //Maybe better version https://stackoverflow.com/questions/3120357/get-closest-point-to-a-line
        public static MyVector2 GetClosestPointOnLineSegment(MyVector2 a, MyVector2 b, MyVector2 p)
        {
            MyVector2 a_p = p - a;
            MyVector2 a_b = b - a;

            //This is using vector projections???

            //Square magnitude of AB vector
            float sqrMagnitudeAB = MyVector2.SqrMagnitude(a_b);

            //The DOT product of a_p and a_b
            float ABAPproduct = MyVector2.Dot(a_p, a_b);

            //The normalized "distance" from a to the closest point
            float distance = ABAPproduct / sqrMagnitudeAB;

            //This point may not be on the line segment, if so return one of the end points
            //Check if P projection is over vectorAB
            if (distance < 0)
            {
                return(a);
            }
            else if (distance > 1)
            {
                return(b);
            }
            else
            {
                return(a + a_b * distance);
            }
        }
        //Line-plane intersection
        public static bool LinePlane(MyVector2 planePos, MyVector2 planeNormal, MyVector2 line_p1, MyVector2 line_p2)
        {
            //To avoid floating point precision issues we can add a small value
            float epsilon = MathUtility.EPSILON;

            bool areIntersecting = false;

            MyVector2 lineDir = MyVector2.Normalize(line_p1 - line_p2);

            float denominator = MyVector2.Dot(-planeNormal, lineDir);

            //Debug.Log(denominator);

            //No intersection if the line and plane are perpendicular
            if (denominator > epsilon || denominator < -epsilon)
            {
                MyVector2 vecBetween = planePos - line_p1;

                float t = MyVector2.Dot(vecBetween, -planeNormal) / denominator;

                MyVector2 intersectionPoint = line_p1 + lineDir * t;

                //Gizmos.DrawWireSphere(intersectionPoint, 0.5f);

                if (_Geometry.IsPointBetweenPoints(line_p1, line_p2, intersectionPoint))
                {
                    areIntersecting = true;
                }
            }

            return(areIntersecting);
        }
Example #4
0
        //
        // Is a point to the left, to the right, or on a plane
        //
        //https://gamedevelopment.tutsplus.com/tutorials/understanding-sutherland-hodgman-clipping-for-physics-engines--gamedev-11917
        //Notice that the plane normal doesnt have to be normalized
        //public static float DistanceFromPointToPlane(Vector3 planeNormal, Vector3 planePos, Vector3 pointPos)
        //{
        //    //Positive distance denotes that the point p is on the front side of the plane
        //    //Negative means it's on the back side
        //    float distance = Vector3.Dot(planeNormal, pointPos - planePos);

        //    return distance;
        //}

        public static float DistanceFromPointToPlane(MyVector2 planeNormal, MyVector2 planePos, MyVector2 pointPos)
        {
            //Positive distance denotes that the point p is on the front side of the plane
            //Negative means it's on the back side
            float distance = MyVector2.Dot(planeNormal, pointPos - planePos);

            return(distance);
        }
Example #5
0
        //
        // Line, plane, ray intersection with plane
        //

        //This is a useful method to find the intersection coordinate if we know we are intersecting
        //Is used for ray-plane, line-plane, plane-plane
        //2d
        private static MyVector2 GetIntersectionCoordinate(Plane2 plane, Ray2 ray)
        {
            float denominator = MyVector2.Dot(-plane.normal, ray.dir);

            MyVector2 vecBetween = plane.pos - ray.origin;

            float t = MyVector2.Dot(vecBetween, -plane.normal) / denominator;

            MyVector2 intersectionPoint = ray.origin + ray.dir * t;

            return(intersectionPoint);
        }
        //This is a useful method to find the intersection coordinate if we know we are intersecting
        //Is used for ray-plane, line-plane, plane-plane
        private static MyVector2 GetIntersectionCoordinate(MyVector2 planePos, MyVector2 planeNormal, MyVector2 rayStart, MyVector2 rayDir)
        {
            float denominator = MyVector2.Dot(-planeNormal, rayDir);

            MyVector2 vecBetween = planePos - rayStart;

            float t = MyVector2.Dot(vecBetween, -planeNormal) / denominator;

            MyVector2 intersectionPoint = rayStart + rayDir * t;

            return(intersectionPoint);
        }
Example #7
0
        //The angle between two vectors 0 <= angle <= 180
        //Same as Vector2.Angle() but we are using MyVector2
        public static float AngleBetween(MyVector2 from, MyVector2 to)
        {
            //dot(a_normalized, b_normalized) = cos(alpha) -> acos(dot(a_normalized, b_normalized)) = alpha
            float dot = MyVector2.Dot(MyVector2.Normalize(from), MyVector2.Normalize(to));

            //This shouldn't happen but may happen because of floating point precision issues
            dot = Mathf.Clamp(dot, -1f, 1f);

            float angleRad = Mathf.Acos(dot);

            return(angleRad);
        }
        //
        // Line-point calculations
        //
        //From https://stackoverflow.com/questions/3120357/get-closest-point-to-a-line
        //and https://www.youtube.com/watch?v=_ENEsV_kNx8
        public static MyVector2 GetClosestPointOnLine(Edge2 e, MyVector2 p, bool withinSegment)
        {
            MyVector2 a = e.p1;
            MyVector2 b = e.p2;

            //Assume the line goes from a to b
            MyVector2 ab = b - a;
            //Vector from "start" of the line to the point outside of line
            MyVector2 ap = p - a;

            //Scalar projection https://en.wikipedia.org/wiki/Scalar_projection
            //The scalar projection is a scalar, equal to the length of the orthogonal projection of ap on ab, with a negative sign if the projection has an opposite direction with respect to ab.
            //scalarProjection = Dot(ap, ab) / Magnitude(ab) where the magnitude of ab is the distance between a and b
            //If ab is normalized, we get scalarProjection = Dot(ap, ab)

            //The distance from a to q (the closes point on the line):
            //float aq_distance = MyVector2.Dot(ap, ab) / MyVector2.Magnitude(ab);

            //To get the closest point on the line:
            //MyVector2 q = a + MyVector2.Normalize(ab) * aq_distance;


            //Can we do better?
            //Magnitude is defined as: Mathf.Sqrt((ab * ab))
            //Normalization is defined as (ab / magnitude(ab))
            //We get: q = a + (ab / magnitude(ab)) * (1 / magnitude(ab)) * dot(ap, ab)
            //Ignore the q and the dot and we get: (ab / Mathf.Sqrt((ab * ab))) * (1 / Mathf.Sqrt((ab * ab))) = ab / (ab * ab)
            //So we can use the square magnitude of ab and then we don't need to normalize ab (to get q), so we save two square roots, which is good because square root is a slow operation

            //The normalized "distance" from a to the closest point, so between 0 and 1 if we are within the line segment
            float distance = MyVector2.Dot(ap, ab) / MyVector2.SqrMagnitude(ab);

            //This point may not be on the line segment, if so return one of the end points
            float epsilon = MathUtility.EPSILON;

            if (withinSegment && distance < 0f - epsilon)
            {
                return(a);
            }
            else if (withinSegment && distance > 1f + epsilon)
            {
                return(b);
            }
            else
            {
                //This works because a_b is not normalized and distance is [0,1] if distance is within ab
                return(a + ab * distance);
            }
        }
Example #9
0
        //Help method to calculate the intersection point between two planes offset in normal direction by a width
        private static MyVector2 GetIntersectionPoint(MyVector2 a, MyVector2 b, MyVector2 c, float halfWidth, bool isTopPoint)
        {
            //Direction of the lines going to and from point b
            MyVector2 beforeDir = MyVector2.Normalize(b - a);

            MyVector2 afterDir = MyVector2.Normalize(c - b);

            MyVector2 beforeNormal = GetNormal(a, b);

            MyVector2 afterNormal = GetNormal(b, c);

            //Compare the normals!

            //normalDirFactor is used to determine if we want to top point (same direction as normal)
            float normalDirFactor = isTopPoint ? 1f : -1f;

            //If they are the same it means we have a straight line and thus we cant do plane-plane intersection
            //if (beforeNormal.Equals(afterNormal))
            //When comparing the normals, we cant use the regular small value because then
            //the line width goes to infinity when doing plane-plane intersection
            float dot = MyVector2.Dot(beforeNormal, afterNormal);

            //Dot is 1 if the point in the same dir and -1 if the point in the opposite dir
            float one = 1f - 0.01f;

            if (dot > one || dot < -one)
            {
                MyVector2 averageNormal = MyVector2.Normalize((afterNormal + beforeNormal) * 0.5f);

                MyVector2 intersectionPoint = b + averageNormal * halfWidth * normalDirFactor;

                return(intersectionPoint);
            }
            else
            {
                //Now we can calculate where the plane starts
                MyVector2 beforePlanePos = b + beforeNormal * halfWidth * normalDirFactor;

                MyVector2 afterPlanePos = b + afterNormal * halfWidth * normalDirFactor;

                //Calculate the intersection point
                //We know they are intersecting, so we don't need to test that
                MyVector2 intersectionPoint = Intersections.GetPlanePlaneIntersectionPoint(beforePlanePos, beforeNormal, afterPlanePos, afterNormal);

                return(intersectionPoint);
            }
        }
Example #10
0
        //
        // Is a point p between point a and b (we assume all 3 are on the same line)
        //
        public static bool IsPointBetweenPoints(MyVector2 a, MyVector2 b, MyVector2 p)
        {
            bool isBetween = false;

            //Entire line segment
            MyVector2 ab = b - a;
            //The intersection and the first point
            MyVector2 ap = p - a;

            //Need to check 2 things:
            //1. If the vectors are pointing in the same direction = if the dot product is positive
            //2. If the length of the vector between the intersection and the first point is smaller than the entire line
            if (MyVector2.Dot(ab, ap) > 0f && MyVector2.SqrMagnitude(ab) >= MyVector2.SqrMagnitude(ap))
            {
                isBetween = true;
            }

            return(isBetween);
        }
        //The angle between two vectors 0 <= angle <= 180
        //Same as Vector2.Angle() but we are using MyVector2
        public static float AngleBetween(MyVector2 from, MyVector2 to, bool shouldNormalize = true)
        {
            //from and to should be normalized
            //But sometimes they are already normalized and then we dont need to do it again
            if (shouldNormalize)
            {
                from = MyVector2.Normalize(from);
                to   = MyVector2.Normalize(to);
            }

            //dot(a_normalized, b_normalized) = cos(alpha) -> acos(dot(a_normalized, b_normalized)) = alpha
            float dot = MyVector2.Dot(from, to);

            //This shouldn't happen but may happen because of floating point precision issues
            dot = Mathf.Clamp(dot, -1f, 1f);

            float angleRad = Mathf.Acos(dot);

            return(angleRad);
        }
        //Plane-plane intersection
        public static bool PlanePlane(MyVector2 planePos_1, MyVector2 planeNormal_1, MyVector2 planePos_2, MyVector2 planeNormal_2)
        {
            bool areIntersecting = false;

            float dot = MyVector2.Dot(planeNormal_1, planeNormal_2);

            //Debug.Log(dot);

            //No intersection if the planes are parallell
            //The are parallell if the dot product is 1 or -1

            //To avoid floating point precision issues we can add a small value
            float one = 1f - MathUtility.EPSILON;

            if (dot < one && dot > -one)
            {
                areIntersecting = true;
            }

            return(areIntersecting);
        }
        //2d
        public static float GetSignedDistanceFromPointToPlane(Plane2 plane, MyVector2 pointPos)
        {
            float distance = MyVector2.Dot(plane.normal, pointPos - plane.pos);

            return(distance);
        }