示例#1
0
文件: CSGPlane.cs 项目: pisipo/CTB
        /// <summary>
        /// split polygon by plane and push the results to polygon lists
        /// </summary>
        /// <param name="polygon">polygon to split</param>
        /// <param name="coplanarFront">list of coplanar polygons in front plane</param>
        /// <param name="coplanarBack">list of coplanar polygons in back plane</param>
        /// <param name="front">list of polygons in front plane</param>
        /// <param name="back">list of polygons in back plane</param>
        public void Split(CSGPolygon polygon, List<CSGPolygon> coplanarFront, List<CSGPolygon> coplanarBack, List<CSGPolygon> front, List<CSGPolygon> back)
        {
            var verticesCount = polygon.Vertices.Count;

            var classes = new Plane.PointClass[verticesCount];
            var polygonClass = Plane.PointClass.Coplanar;

            for (int i = 0; i < verticesCount; i++)
            {
                var t = Vector3.Dot(Normal, polygon.Vertices[i].P) - Distance;
                var type = (t < -epsylon
                                ? Plane.PointClass.Back
                                : (t > epsylon ? Plane.PointClass.Front : Plane.PointClass.Coplanar));
                //classes[i] = ClassifyPoint(polygon.Vertices[i].P);

                polygonClass |= type; //classes[i];
                classes[i] = type;
            }

            switch (polygonClass)
            {
                case Plane.PointClass.Coplanar:
                    {
                        if (Vector3.Dot(Normal, polygon.Plane.Normal) > 0)
                        {
                            coplanarFront.Add(polygon);
                        }
                        else
                        {
                            coplanarBack.Add(polygon);
                        }
                    }
                    break;

                case Plane.PointClass.Front:
                    {
                        front.Add(polygon);
                    }
                    break;

                case Plane.PointClass.Back:
                    {
                        back.Add(polygon);
                    }
                    break;

                case Plane.PointClass.Intersection:
                    {
                        var frontList = new List<CSGVertex>(4);
                        var backList = new List<CSGVertex>(4);

                        for (int i = 0; i < verticesCount; i++)
                        {
                            var j = (i + 1) % verticesCount;

                            var class0 = classes[i];
                            var class1 = classes[j];

                            var v0 = polygon.Vertices[i];
                            var v1 = polygon.Vertices[j];

                            if (class0 != Plane.PointClass.Back)
                            {
                                frontList.Add(v0);
                            }

                            if (class0 != Plane.PointClass.Front)
                            {
                                backList.Add(class0 != Plane.PointClass.Back ? new CSGVertex(v0) : v0);
                            }

                            if ((class0 | class1) == Plane.PointClass.Intersection)
                            {
                                var q = new CSGVertex(polygon.Vertices[0]);

                                // find intersection point
                                //IntersectSegment(v0.P, v1.P, out t, out q.P);
                                var t = (this.Distance - Vector3.Dot(this.Normal, v0.P)) / Vector3.Dot(this.Normal, v1.P - v0.P);

                                // interpolate
                                q.P = Vector3.Lerp(v0.P, v1.P, t);
                                q.N = Vector3.Lerp(v0.N, v1.N, t);
                                q.UV = Vector2.Lerp(v0.UV, v1.UV, t);

                                frontList.Add(q);
                                backList.Add(new CSGVertex(q));
                            }
                        }

                        if (frontList.Count >= 3)
                        {
                            front.Add(new CSGPolygon(polygon.Id, frontList));
                        }

                        if (backList.Count >= 3)
                        {
                            back.Add(new CSGPolygon(polygon.Id, backList));
                        }
                    }
                    break;
            }
        }
示例#2
0
        /// <summary>
        /// split polygon by plane and push the results to polygon lists
        /// </summary>
        /// <param name="polygon">polygon to split</param>
        /// <param name="coplanarFront">list of coplanar polygons in front plane</param>
        /// <param name="coplanarBack">list of coplanar polygons in back plane</param>
        /// <param name="front">list of polygons in front plane</param>
        /// <param name="back">list of polygons in back plane</param>
        public void Split(CSGPolygon polygon, List <CSGPolygon> coplanarFront, List <CSGPolygon> coplanarBack, List <CSGPolygon> front, List <CSGPolygon> back)
        {
            var verticesCount = polygon.Vertices.Count;

            var classes      = new Plane.PointClass[verticesCount];
            var polygonClass = Plane.PointClass.Coplanar;

            for (int i = 0; i < verticesCount; i++)
            {
                var t    = Vector3.Dot(Normal, polygon.Vertices[i].P) - Distance;
                var type = (t < -epsylon
                                ? Plane.PointClass.Back
                                : (t > epsylon ? Plane.PointClass.Front : Plane.PointClass.Coplanar));
                //classes[i] = ClassifyPoint(polygon.Vertices[i].P);

                polygonClass |= type; //classes[i];
                classes[i]    = type;
            }

            switch (polygonClass)
            {
            case Plane.PointClass.Coplanar:
            {
                if (Vector3.Dot(Normal, polygon.Plane.Normal) > 0)
                {
                    coplanarFront.Add(polygon);
                }
                else
                {
                    coplanarBack.Add(polygon);
                }
            }
            break;

            case Plane.PointClass.Front:
            {
                front.Add(polygon);
            }
            break;

            case Plane.PointClass.Back:
            {
                back.Add(polygon);
            }
            break;

            case Plane.PointClass.Intersection:
            {
                var frontList = new List <CSGVertex>(4);
                var backList  = new List <CSGVertex>(4);

                for (int i = 0; i < verticesCount; i++)
                {
                    var j = (i + 1) % verticesCount;

                    var class0 = classes[i];
                    var class1 = classes[j];

                    var v0 = polygon.Vertices[i];
                    var v1 = polygon.Vertices[j];

                    if (class0 != Plane.PointClass.Back)
                    {
                        frontList.Add(v0);
                    }

                    if (class0 != Plane.PointClass.Front)
                    {
                        backList.Add(class0 != Plane.PointClass.Back ? new CSGVertex(v0) : v0);
                    }

                    if ((class0 | class1) == Plane.PointClass.Intersection)
                    {
                        var q = new CSGVertex(polygon.Vertices[0]);

                        // find intersection point
                        //IntersectSegment(v0.P, v1.P, out t, out q.P);
                        var t = (this.Distance - Vector3.Dot(this.Normal, v0.P)) / Vector3.Dot(this.Normal, v1.P - v0.P);

                        // interpolate
                        q.P  = Vector3.Lerp(v0.P, v1.P, t);
                        q.N  = Vector3.Lerp(v0.N, v1.N, t);
                        q.UV = Vector2.Lerp(v0.UV, v1.UV, t);

                        frontList.Add(q);
                        backList.Add(new CSGVertex(q));
                    }
                }

                if (frontList.Count >= 3)
                {
                    front.Add(new CSGPolygon(polygon.Id, frontList));
                }

                if (backList.Count >= 3)
                {
                    back.Add(new CSGPolygon(polygon.Id, backList));
                }
            }
            break;
            }
        }