예제 #1
0
        //Each point defines a plane,
        //we get polyhedra enclosed by all such planes
        public List <List <Vector3> > GetPlaneCutPolygons(Vector3[] points)
        {
            List <List <Vector3> > polys = new List <List <Vector3> >();

            for (int i = 0; i < points.Length; i++)
            {
                Vector3 p = points[i];

                Plane plane = new Plane(p.normalized, p);

                //Project everything on a point-based plane
                //and find 2d rays of intersection with other planes
                Vector3 planeBasisX = p.GetSomeOrthogonal().normalized;
                Vector3 planeBasisY = Vector3.Cross(p, p.GetSomeOrthogonal()).normalized;

                List <Ray2D> intersWithOther = new List <Ray2D>();
                for (int j = 0; j < points.Length; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    Plane other         = new Plane(points[j].normalized, points[j]);
                    Ray?  possibleInter = plane.GetIntersection(other);
                    if (possibleInter == null)
                    {
                        continue;
                    }
                    Ray inter = possibleInter.Value;

                    Ray2D interInPlane = new Ray2D(
                        Extensions.ProjectOnPlanarBasis(planeBasisX, planeBasisY, inter.origin - p),
                        Extensions.ProjectOnPlanarBasis(planeBasisX, planeBasisY, inter.direction)
                        );

                    //Set winding dir
                    if (Extensions.PerpDot(interInPlane.direction, interInPlane.origin) > 0)
                    {
                        interInPlane.direction = -interInPlane.direction;
                    }

                    intersWithOther.Add(interInPlane);
                }

                //Find nearest ray
                float   smallestSqrDist = float.MaxValue;
                Vector2 nearestPoint    = Vector2.zero;
                int     nearestRayIndex = -1;

                for (int j = 0; j < intersWithOther.Count; j++)
                {
                    Ray2D   r = intersWithOther[j];
                    Vector2 candidateNearestPoint = r.GetNearestPointOnRay(Vector2.zero);
                    if (candidateNearestPoint.sqrMagnitude < smallestSqrDist)
                    {
                        smallestSqrDist = candidateNearestPoint.sqrMagnitude;
                        nearestPoint    = candidateNearestPoint;
                        nearestRayIndex = j;
                    }
                }

                List <Vector2> polyVertices = new List <Vector2>();

                //Go clockwise searching nearest intersections between current ray and others
                int     startRayIndex = nearestRayIndex;
                int     rayIndex      = startRayIndex;
                int     prevRayIndex  = rayIndex;
                Vector2 position      = nearestPoint;

                do
                {
                    Ray2D ray = intersWithOther[rayIndex];
                    smallestSqrDist = float.MaxValue;
                    Vector2 nearestNextPosition = Vector2.zero;

                    for (int j = 0; j < intersWithOther.Count; j++)
                    {
                        Ray2D otherRay = intersWithOther[j];
                        if (j == rayIndex || j == prevRayIndex)
                        {
                            continue;
                        }

                        Vector2 inters = ray.GetIntersection(otherRay);
                        if ((inters - position).sqrMagnitude < smallestSqrDist && Vector2.Dot(ray.direction, inters - position) > 0)
                        {
                            smallestSqrDist     = (inters - position).sqrMagnitude;
                            nearestNextPosition = inters;
                            nearestRayIndex     = j;
                        }
                    }

                    position = nearestNextPosition;
                    polyVertices.Add(position);
                    prevRayIndex = rayIndex;
                    rayIndex     = nearestRayIndex;
                } while (rayIndex != startRayIndex);

                List <Vector3> polyVertices3D = new List <Vector3>();
                foreach (Vector2 v in polyVertices)
                {
                    polyVertices3D.Add(p + v.x * planeBasisX + v.y * planeBasisY);
                }

                polys.Add(polyVertices3D);
            }

            return(polys);
        }