コード例 #1
0
        //
        // Line-plane intersection
        //

        //2d
        public static bool LinePlane(Plane2 plane, Edge2 line)
        {
            //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(-plane.normal, lineDir);

            //Debug.Log(denominator);

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

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

                MyVector2 intersectionPoint = line.p1 + lineDir * t;

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

                if (_Geometry.IsPointBetweenPoints(line.p1, line.p2, intersectionPoint))
                {
                    areIntersecting = true;
                }
            }

            return(areIntersecting);
        }
コード例 #2
0
        //
        // Ray-plane intersection
        // http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection
        //

        //2d
        public static bool RayPlane(Plane2 plane, Ray2 ray)
        {
            //To avoid floating point precision issues we can add a small value
            float epsilon = MathUtility.EPSILON;

            bool areIntersecting = false;

            float denominator = MyVector2.Dot(plane.normal * -1f, ray.dir);

            //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 = plane.pos - ray.origin;

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

                //Debug.Log(t);

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

            return(areIntersecting);
        }
コード例 #3
0
        //If we know two planes are intersecting, what's the point of intersection?
        //2d
        public static MyVector2 GetPlanePlaneIntersectionPoint(Plane2 plane_1, Plane2 plane_2)
        {
            MyVector2 lineDir = MyVector2.Normalize(new MyVector2(plane_2.normal.y, -plane_2.normal.x));

            Ray2 ray = new Ray2(plane_2.pos, lineDir);

            MyVector2 intersectionPoint = GetIntersectionCoordinate(plane_1, ray);

            return(intersectionPoint);
        }
コード例 #4
0
        //We know a line plane is intersecting and now we want the coordinate of intersection
        //2d
        public static MyVector2 GetLinePlaneIntersectionPoint(Plane2 plane, Edge2 line)
        {
            MyVector2 lineDir = MyVector2.Normalize(line.p1 - line.p2);

            Ray2 ray = new Ray2(line.p1, lineDir);

            MyVector2 intersectionPoint = GetIntersectionCoordinate(plane, ray);

            return(intersectionPoint);
        }
コード例 #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);
        }
コード例 #6
0
        //Find the point which is furthest away from an edge
        private static MyVector2 FindPointFurthestFromEdge(MyVector2 p1, MyVector2 p2, HashSet <MyVector2> points)
        {
            //Just init the third point
            MyVector2 p3 = new MyVector2(0f, 0f);

            //Set max distance to something small
            float maxDistanceToEdge = -Mathf.Infinity;

            //The direction of the edge so we can create the normal (doesnt matter in which way it points)
            MyVector2 edgeDir = p2 - p1;

            //We dont need to normalize this normal
            MyVector2 edgeNormal = new MyVector2(edgeDir.y, -edgeDir.x);

            //Find the actual third point
            foreach (MyVector2 p in points)
            {
                //The distance between this point and the edge is the same as the distance between
                //the point and the plane
                Plane2 plane = new Plane2(p1, edgeNormal);

                float distanceToEdge = _Geometry.GetSignedDistanceFromPointToPlane(plane, p);

                //The distance can be negative if we are behind the plane
                //and because we just picked a normal out of nowhere, we have to make sure
                //the distance is positive
                if (distanceToEdge < 0f)
                {
                    distanceToEdge *= -1f;
                }

                //This point is better
                if (distanceToEdge > maxDistanceToEdge)
                {
                    maxDistanceToEdge = distanceToEdge;

                    p3 = p;
                }
            }

            return(p3);
        }
コード例 #7
0
        //
        // Plane-plane intersection
        //
        //2d
        public static bool PlanePlane(Plane2 plane_1, Plane2 plane_2)
        {
            bool areIntersecting = false;

            float dot = MyVector2.Dot(plane_1.normal, plane_2.normal);

            //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);
        }
コード例 #8
0
        //Assumes the polygons are oriented counter clockwise
        //poly is the polygon we want to cut
        //Assumes the polygon we want to remove from the other polygon is convex, so clipPolygon has to be convex
        //We will end up with the intersection of the polygons
        public static List <MyVector2> ClipPolygon(List <MyVector2> poly, List <Plane2> clippingPlanes)
        {
            //Clone the vertices because we will remove vertices from this list
            List <MyVector2> vertices = new List <MyVector2>(poly);

            //Save the new vertices temporarily in this list before transfering them to vertices
            List <MyVector2> vertices_tmp = new List <MyVector2>();

            //Clip the polygon
            for (int i = 0; i < clippingPlanes.Count; i++)
            {
                Plane2 plane = clippingPlanes[i];

                for (int j = 0; j < vertices.Count; j++)
                {
                    int jPlusOne = MathUtility.ClampListIndex(j + 1, vertices.Count);

                    MyVector2 v1 = vertices[j];
                    MyVector2 v2 = vertices[jPlusOne];

                    //Calculate the distance to the plane from each vertex
                    //This is how we will know if they are inside or outside
                    //If they are inside, the distance is positive, which is why the planes normals have to be oriented to the inside
                    float dist_to_v1 = _Geometry.DistanceFromPointToPlane(plane.normal, plane.pos, v1);
                    float dist_to_v2 = _Geometry.DistanceFromPointToPlane(plane.normal, plane.pos, v2);

                    //TODO: What will happen if they are exactly 0? Should maybe use a tolerance of 0.001

                    //Case 1. Both are outside (= to the right), do nothing

                    //Case 2. Both are inside (= to the left), save v2
                    if (dist_to_v1 >= 0f && dist_to_v2 >= 0f)
                    {
                        vertices_tmp.Add(v2);
                    }
                    //Case 3. Outside -> Inside, save intersection point and v2
                    else if (dist_to_v1 < 0f && dist_to_v2 >= 0f)
                    {
                        MyVector2 rayDir = MyVector2.Normalize(v2 - v1);

                        MyVector2 intersectionPoint = _Intersections.GetRayPlaneIntersectionPoint(plane.pos, plane.normal, v1, rayDir);

                        vertices_tmp.Add(intersectionPoint);

                        vertices_tmp.Add(v2);
                    }
                    //Case 4. Inside -> Outside, save intersection point
                    else if (dist_to_v1 >= 0f && dist_to_v2 < 0f)
                    {
                        MyVector2 rayDir = MyVector2.Normalize(v2 - v1);

                        MyVector2 intersectionPoint = _Intersections.GetRayPlaneIntersectionPoint(plane.pos, plane.normal, v1, rayDir);

                        vertices_tmp.Add(intersectionPoint);
                    }
                }

                //Add the new vertices to the list of vertices
                vertices.Clear();

                vertices.AddRange(vertices_tmp);

                vertices_tmp.Clear();
            }

            return(vertices);
        }
コード例 #9
0
        //Get the coordinate if we know a ray-plane is intersecting
        //2d
        public static MyVector2 GetRayPlaneIntersectionPoint(Plane2 plane, Ray2 ray)
        {
            MyVector2 intersectionPoint = GetIntersectionCoordinate(plane, ray);

            return(intersectionPoint);
        }
コード例 #10
0
        //The original algorithm calculates the intersection between two polygons, this will instead get the outside
        //Assumes the polygons are oriented counter clockwise
        //poly is the polygon we want to cut
        //Assumes the polygon we want to remove from the other polygon is convex, so clipPolygon has to be convex
        //We will end up with the !intersection of the polygons
        public static List <List <MyVector2> > ClipPolygonInverted(List <MyVector2> poly, List <Plane2> clippingPlanes)
        {
            //The result may be more than one polygons
            List <List <MyVector2> > finalPolygons = new List <List <MyVector2> >();

            List <MyVector2> vertices = new List <MyVector2>(poly);

            //The remaining polygon after each cut
            List <MyVector2> vertices_tmp = new List <MyVector2>();

            //Clip the polygon
            for (int i = 0; i < clippingPlanes.Count; i++)
            {
                Plane2 plane = clippingPlanes[i];

                //A new polygon which is the part of the polygon which is outside of this plane
                List <MyVector2> outsidePolygon = new List <MyVector2>();

                for (int j = 0; j < vertices.Count; j++)
                {
                    int jPlusOne = MathUtility.ClampListIndex(j + 1, vertices.Count);

                    MyVector2 v1 = vertices[j];
                    MyVector2 v2 = vertices[jPlusOne];

                    //Calculate the distance to the plane from each vertex
                    //This is how we will know if they are inside or outside
                    //If they are inside, the distance is positive, which is why the planes normals have to be oriented to the inside
                    float dist_to_v1 = _Geometry.GetSignedDistanceFromPointToPlane(v1, plane);
                    float dist_to_v2 = _Geometry.GetSignedDistanceFromPointToPlane(v2, plane);

                    //TODO: What will happen if they are exactly 0?

                    //Case 1. Both are inside (= to the left), save v2 to the other polygon
                    if (dist_to_v1 >= 0f && dist_to_v2 >= 0f)
                    {
                        vertices_tmp.Add(v2);
                    }
                    //Case 2. Both are outside (= to the right), save v1
                    else if (dist_to_v1 < 0f && dist_to_v2 < 0f)
                    {
                        outsidePolygon.Add(v2);
                    }
                    //Case 3. Outside -> Inside, save intersection point
                    else if (dist_to_v1 < 0f && dist_to_v2 >= 0f)
                    {
                        MyVector2 rayDir = MyVector2.Normalize(v2 - v1);

                        Ray2 ray = new Ray2(v1, rayDir);

                        MyVector2 intersectionPoint = _Intersections.GetRayPlaneIntersectionPoint(plane, ray);

                        outsidePolygon.Add(intersectionPoint);

                        vertices_tmp.Add(intersectionPoint);

                        vertices_tmp.Add(v2);
                    }
                    //Case 4. Inside -> Outside, save intersection point and v2
                    else if (dist_to_v1 >= 0f && dist_to_v2 < 0f)
                    {
                        MyVector2 rayDir = MyVector2.Normalize(v2 - v1);

                        Ray2 ray = new Ray2(v1, rayDir);

                        MyVector2 intersectionPoint = _Intersections.GetRayPlaneIntersectionPoint(plane, ray);

                        outsidePolygon.Add(intersectionPoint);

                        outsidePolygon.Add(v2);

                        vertices_tmp.Add(intersectionPoint);
                    }
                }

                //Add the polygon outside of this plane to the list of all polygons that are outside of all planes
                if (outsidePolygon.Count > 0)
                {
                    finalPolygons.Add(outsidePolygon);
                }

                //Add the polygon which was inside of this and previous planes to the polygon we want to test
                vertices.Clear();

                vertices.AddRange(vertices_tmp);

                vertices_tmp.Clear();
            }

            return(finalPolygons);
        }
コード例 #11
0
        //2d
        public static float GetSignedDistanceFromPointToPlane(Plane2 plane, MyVector2 pointPos)
        {
            float distance = MyVector2.Dot(plane.normal, pointPos - plane.pos);

            return(distance);
        }