예제 #1
0
 public void CalculatePlane(ref CSGPlane plane)
 {
     plane = GeometryUtility.CalcPolygonPlane(curve.Points);
 }
예제 #2
0
        public void UpdatePoints(ControlMesh controlMesh, Vector3[] vertices = null)
        {
            if (controlMesh == null ||
                controlMesh.Vertices == null ||
                controlMesh.Edges == null ||
                controlMesh.Polygons == null ||
                PolygonPointIndices == null)
            {
                return;
            }

            if (vertices == null)
            {
                vertices = controlMesh.Vertices;
            }

            if (!BrushTransform)
            {
                return;
            }


            var pointCount = vertices.Length;

            if (WorldPoints.Length != pointCount)
            {
                AllocatePoints(pointCount);
            }

            var edgeCount = controlMesh.Edges.Length;

            if (Edges.Length != edgeCount)
            {
                AllocateEdges(edgeCount);
            }

            var polygonCount = controlMesh.Polygons.Length;

            if (PolygonControlId.Length != polygonCount)
            {
                AllocatePolygons(polygonCount);
            }


            var localToWorldMatrix = BrushTransform.localToWorldMatrix;

            for (var p = 0; p < pointCount; p++)
            {
                var worldPoint = localToWorldMatrix.MultiplyPoint(vertices[p]);
                WorldPoints[p] = worldPoint;
            }


            var brushTotalLength = 0.0f;

            BrushCenter = MathConstants.zeroVector3;
            for (var p = 0; p < polygonCount; p++)
            {
                var localCenterPoint = MathConstants.zeroVector3;
                var totalLength      = 0.0f;
                var polygon          = controlMesh.Polygons[p];
                if (polygon == null)
                {
                    continue;
                }

                var edgeIndices = polygon.EdgeIndices;
                if (edgeIndices == null ||
                    edgeIndices.Length == 0)
                {
                    continue;
                }

                var halfEdgeIndex0 = edgeIndices[edgeIndices.Length - 1];
                if (halfEdgeIndex0 < 0 || halfEdgeIndex0 >= controlMesh.Edges.Length)
                {
                    continue;
                }

                var vertexIndex0 = controlMesh.Edges[halfEdgeIndex0].VertexIndex;
                if (vertexIndex0 < 0 || vertexIndex0 >= vertices.Length)
                {
                    continue;
                }

                var vertex0 = vertices[vertexIndex0];

                if (PolygonPointIndices[p] == null ||
                    PolygonPointIndices[p].Length != edgeIndices.Length)
                {
                    PolygonPointIndices[p] = new int[edgeIndices.Length];
                }

                var newPointIndices = PolygonPointIndices[p];
                for (var i = 0; i < edgeIndices.Length; i++)
                {
                    var halfEdgeIndex1 = edgeIndices[i];
                    if (halfEdgeIndex1 < 0 ||
                        halfEdgeIndex1 >= controlMesh.Edges.Length)
                    {
                        continue;
                    }

                    var vertexIndex1 = controlMesh.Edges[halfEdgeIndex1].VertexIndex;
                    if (vertexIndex1 < 0 ||
                        vertexIndex1 >= vertices.Length)
                    {
                        continue;
                    }

                    var vertex1 = vertices[vertexIndex1];
                    newPointIndices[i] = vertexIndex1;

                    var length = (vertex1 - vertex0).sqrMagnitude;
                    localCenterPoint += (vertex1 + vertex0) * 0.5f * length;
                    totalLength      += length;
                    brushTotalLength += length;

                    vertex0 = vertex1;
                }

                var worldCenterPoint = Mathf.Abs(totalLength) < MathConstants.EqualityEpsilon ?
                                       localToWorldMatrix.MultiplyPoint(vertex0) :
                                       localToWorldMatrix.MultiplyPoint(localCenterPoint / totalLength);
                BrushCenter           += localCenterPoint;
                PolygonCenterPoints[p] = worldCenterPoint;
                PolygonCenterPlanes[p] = GeometryUtility.CalcPolygonPlane(controlMesh, (short)p);
            }
            if (Mathf.Abs(brushTotalLength) >= MathConstants.EqualityEpsilon)
            {
                BrushCenter /= brushTotalLength;
            }
            BrushCenter = localToWorldMatrix.MultiplyPoint(BrushCenter);
        }
예제 #3
0
        public static bool GenerateControlMeshFromVertices(ShapePolygon shape2DPolygon,
                                                           Matrix4x4 localToWorld,
                                                           Vector3 direction,
                                                           float height,
                                                           Material capMaterial,
                                                           TexGen capTexgen,
                                                           bool?smooth,
                                                           bool singleSurfaceEnds,                                                                                 //Plane buildPlane,
                                                           out ControlMesh controlMesh,
                                                           out Shape shape)
        {
            if (shape2DPolygon == null)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }

            var vertices = shape2DPolygon.Vertices;

            if (vertices.Length < 3)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }
            if (height == 0.0f)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }

            Vector3 from;
            Vector3 to;

            if (height > 0)
            {
                @from = direction * height;                // buildPlane.normal * height;
                to    = MathConstants.zeroVector3;
            }
            else
            {
                @from = MathConstants.zeroVector3;
                to    = direction * height;               //buildPlane.normal * height;
            }

            var count           = vertices.Length;
            var doubleCount     = (count * 2);
            var extraPoints     = 0;
            var extraEdges      = 0;
            var endsPolygons    = 2;
            var startEdgeOffset = doubleCount;

            if (!singleSurfaceEnds)
            {
                extraPoints      = 2;
                extraEdges       = (4 * count);
                endsPolygons     = doubleCount;
                startEdgeOffset += extraEdges;
            }


            var dstPoints   = new Vector3 [doubleCount + extraPoints];
            var dstEdges    = new HalfEdge[(count * 6) + extraEdges];
            var dstPolygons = new Polygon [count + endsPolygons];

            var center1 = MathConstants.zeroVector3;
            var center2 = MathConstants.zeroVector3;


            for (int i = 0; i < count; i++)
            {
                var point1 = vertices[i];
                var point2 = vertices[(count + i - 1) % count];

                point1 += @from;
                point2 += to;

                // swap y/z to solve texgen issues
                dstPoints[i].x = point1.x;
                dstPoints[i].y = point1.y;
                dstPoints[i].z = point1.z;

                center1 += dstPoints[i];

                dstEdges [i].VertexIndex = (short)i;
                dstEdges [i].HardEdge    = true;

                // swap y/z to solve texgen issues
                dstPoints[i + count].x = point2.x;
                dstPoints[i + count].y = point2.y;
                dstPoints[i + count].z = point2.z;
                center2 += dstPoints[i + count];

                dstEdges [i + count].VertexIndex = (short)(i + count);
                dstEdges [i + count].HardEdge    = true;
            }

            if (!singleSurfaceEnds)
            {
                dstPoints[doubleCount]     = center1 / count;
                dstPoints[doubleCount + 1] = center2 / count;

                int   edge_offset   = doubleCount;
                short polygon_index = (short)count;

                // 'top'
                for (int i = 0, j = count - 1; i < count; j = i, i++)
                {
                    var jm = (j) % count;
                    var im = (i) % count;

                    var edgeOut0 = edge_offset + (jm * 2) + 1;
                    var edgeIn0  = edge_offset + (im * 2) + 0;
                    var edgeOut1 = edge_offset + (im * 2) + 1;

                    dstEdges[edgeIn0].VertexIndex = (short)(doubleCount);
                    dstEdges[edgeIn0].HardEdge    = true;
                    dstEdges[edgeIn0].TwinIndex   = edgeOut1;

                    dstEdges[edgeOut1].VertexIndex = (short)im;
                    dstEdges[edgeOut1].HardEdge    = true;
                    dstEdges[edgeOut1].TwinIndex   = edgeIn0;

                    dstEdges[im].PolygonIndex       = polygon_index;
                    dstEdges[edgeIn0].PolygonIndex  = polygon_index;
                    dstEdges[edgeOut0].PolygonIndex = polygon_index;

                    dstPolygons[polygon_index] = new Polygon(new int[] { im, edgeIn0, edgeOut0 }, polygon_index);
                    polygon_index++;
                }

                edge_offset = doubleCount * 2;
                // 'bottom'
                for (int i = 0, j = count - 1; j >= 0; i = j, j--)
                {
                    var jm = (count + count - j) % count;
                    var im = (count + count - i) % count;

                    var edgeOut0 = edge_offset + (jm * 2) + 1;
                    var edgeIn0  = edge_offset + (im * 2) + 0;
                    var edgeOut1 = edge_offset + (im * 2) + 1;

                    dstEdges[edgeIn0].VertexIndex = (short)(doubleCount + 1);
                    dstEdges[edgeIn0].HardEdge    = true;
                    dstEdges[edgeIn0].TwinIndex   = edgeOut1;

                    dstEdges[edgeOut1].VertexIndex = (short)(im + count);
                    dstEdges[edgeOut1].HardEdge    = true;
                    dstEdges[edgeOut1].TwinIndex   = edgeIn0;

                    dstEdges[im + count].PolygonIndex = polygon_index;
                    dstEdges[edgeIn0].PolygonIndex    = polygon_index;
                    dstEdges[edgeOut0].PolygonIndex   = polygon_index;

                    dstPolygons[polygon_index] = new Polygon(new int[] { im + count, edgeIn0, edgeOut0 }, polygon_index);
                    polygon_index++;
                }
            }
            else
            {
                var polygon0Edges = new int[count];
                var polygon1Edges = new int[count];
                for (var i = 0; i < count; i++)
                {
                    dstEdges [i].PolygonIndex         = (short)(count + 0);
                    dstEdges [i + count].PolygonIndex = (short)(count + 1);
                    polygon0Edges[i] = i;
                    polygon1Edges[count - (i + 1)] = i + count;
                }
                dstPolygons[count + 0] = new Polygon(polygon0Edges, count + 0);
                dstPolygons[count + 1] = new Polygon(polygon1Edges, count + 1);
            }


            for (int v0 = count - 1, v1 = 0; v1 < count; v0 = v1, v1++)
            {
                var polygonIndex = (short)(v1);

                var nextOffset = startEdgeOffset + (((v1 + 1) % count) * 4);
                var currOffset = startEdgeOffset + (((v1)) * 4);
                var prevOffset = startEdgeOffset + (((v1 + count - 1) % count) * 4);

                var nextTwin = nextOffset + 1;
                var prevTwin = prevOffset + 3;

                dstEdges[v1].TwinIndex         = currOffset + 0;
                dstEdges[v1 + count].TwinIndex = currOffset + 2;

                dstEdges[currOffset + 0].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 1].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 2].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 3].PolygonIndex = polygonIndex;

                dstEdges[currOffset + 0].TwinIndex = (v1);
                dstEdges[currOffset + 1].TwinIndex = prevTwin;
                dstEdges[currOffset + 2].TwinIndex = (v1 + count);
                dstEdges[currOffset + 3].TwinIndex = nextTwin;

                dstEdges[currOffset + 0].VertexIndex = (short)(v0);
                dstEdges[currOffset + 1].VertexIndex = (short)(v1 + count);
                dstEdges[currOffset + 2].VertexIndex = (short)(((v1 + 1) % count) + count);
                dstEdges[currOffset + 3].VertexIndex = (short)(v1);

                dstEdges[currOffset + 0].HardEdge = true;
                dstEdges[currOffset + 1].HardEdge = true;
                dstEdges[currOffset + 2].HardEdge = true;
                dstEdges[currOffset + 3].HardEdge = true;

                dstPolygons[polygonIndex] = new Polygon(new [] { currOffset + 0,
                                                                 currOffset + 1,
                                                                 currOffset + 2,
                                                                 currOffset + 3 }, polygonIndex);
            }

            for (int i = 0; i < dstPoints.Length; i++)
            {
                dstPoints[i] = localToWorld.MultiplyPoint(dstPoints[i]);
            }

            controlMesh = new ControlMesh
            {
                Vertices = dstPoints,
                Edges    = dstEdges,
                Polygons = dstPolygons
            };
            controlMesh.SetDirty();

            shape = new Shape
            {
                Materials   = new Material[dstPolygons.Length],
                Surfaces    = new Surface[dstPolygons.Length],
                TexGenFlags = new TexGenFlags[dstPolygons.Length],
                TexGens     = new TexGen[dstPolygons.Length]
            };


            var smoothinggroup = (smooth.HasValue && smooth.Value) ? SurfaceUtility.FindUnusedSmoothingGroupIndex() : 0;


            var containedMaterialCount = 0;

            if (shape2DPolygon.EdgeMaterials != null &&
                shape2DPolygon.EdgeTexgens != null /* &&
                                                    * shape2DPolygon.edgeTexgenFlags != null*/)
            {
                containedMaterialCount = Mathf.Min(shape2DPolygon.EdgeMaterials.Length,
                                                   shape2DPolygon.EdgeTexgens.Length /*,
                                                                                      *                        shape2DPolygon.edgeTexgenFlags.Length*/);
            }

            if (!capMaterial)
            {
                capMaterial = CSGSettings.DefaultMaterial;
                capTexgen   = new TexGen(-1);
            }

            for (var i = 0; i < dstPolygons.Length; i++)
            {
                if (i < containedMaterialCount)
                {
                    //shape.TexGenFlags[i] = shape2DPolygon.edgeTexgenFlags[i];
                    shape.Materials  [i]             = shape2DPolygon.EdgeMaterials[i];
                    shape.TexGens    [i]             = shape2DPolygon.EdgeTexgens[i];
                    shape.Surfaces   [i].TexGenIndex = i;
                    shape.TexGens[i].MaterialIndex   = -1;
                }
                else
                {
                    shape.Materials[i] = capMaterial;
                    shape.TexGens[i]   = capTexgen;
                    //shape.TexGenFlags[i]			= TexGenFlags.None;
                    shape.Surfaces[i].TexGenIndex  = i;
                    shape.TexGens[i].MaterialIndex = -1;
                }
                if (smooth.HasValue)
                {
                    if (i < count)
                    {
                        shape.TexGens[i].SmoothingGroup = smoothinggroup;
                    }
                    else
                    {
                        shape.TexGens[i].SmoothingGroup = 0;
                    }
                }
            }

            for (var s = 0; s < dstPolygons.Length; s++)
            {
                var normal = shape.Surfaces[s].Plane.normal;
                shape.Surfaces[s].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, (short)s);
                Vector3 tangent, binormal;
                GeometryUtility.CalculateTangents(normal, out tangent, out binormal);
                //var tangent		= Vector3.Cross(GeometryUtility.CalculateTangent(normal), normal).normalized;
                //var binormal	= Vector3.Cross(normal, tangent);
                shape.Surfaces[s].Tangent     = tangent;
                shape.Surfaces[s].BiNormal    = binormal;
                shape.Surfaces[s].TexGenIndex = s;
            }

            controlMesh.IsValid = ControlMeshUtility.Validate(controlMesh, shape);
            if (controlMesh.IsValid)
            {
                return(true);
            }

            controlMesh = null;
            shape       = null;
            return(false);
        }
예제 #4
0
        internal static bool CreateCubeControlMesh(out ControlMesh controlMesh, out Shape shape, Vector3 min, Vector3 max)
        {
            if (min.x > max.x)
            {
                float x = min.x; min.x = max.x; max.x = x;
            }
            if (min.y > max.y)
            {
                float y = min.y; min.y = max.y; max.y = y;
            }
            if (min.z > max.z)
            {
                float z = min.z; min.z = max.z; max.z = z;
            }

            if (min.x == max.x || min.y == max.y || min.z == max.z)
            {
                shape       = null;
                controlMesh = null;
                return(false);
            }

            controlMesh          = new ControlMesh();
            controlMesh.Vertices = new Vector3[]
            {
                new Vector3(min.x, min.y, min.z),
                new Vector3(min.x, max.y, min.z),
                new Vector3(max.x, max.y, min.z),
                new Vector3(max.x, min.y, min.z),

                new Vector3(min.x, min.y, max.z),
                new Vector3(min.x, max.y, max.z),
                new Vector3(max.x, max.y, max.z),
                new Vector3(max.x, min.y, max.z)
            };

            controlMesh.Edges = new HalfEdge[]
            {
                new HalfEdge(0, 21, 0, true),                   //  0
                new HalfEdge(0, 9, 1, true),                    //  1
                new HalfEdge(0, 13, 2, true),                   //  2
                new HalfEdge(0, 17, 3, true),                   //  3

                new HalfEdge(1, 23, 7, true),                   //  4
                new HalfEdge(1, 19, 6, true),                   //  5
                new HalfEdge(1, 15, 5, true),                   //  6
                new HalfEdge(1, 11, 4, true),                   //  7

                new HalfEdge(2, 14, 1, true),                   //  8
                new HalfEdge(2, 1, 0, true),                    //  9
                new HalfEdge(2, 20, 4, true),                   // 10
                new HalfEdge(2, 7, 5, true),                    // 11

                new HalfEdge(3, 18, 2, true),                   // 12
                new HalfEdge(3, 2, 1, true),                    // 13
                new HalfEdge(3, 8, 5, true),                    // 14
                new HalfEdge(3, 6, 6, true),                    // 15

                new HalfEdge(4, 22, 3, true),                   // 16
                new HalfEdge(4, 3, 2, true),                    // 17
                new HalfEdge(4, 12, 6, true),                   // 18
                new HalfEdge(4, 5, 7, true),                    // 19

                new HalfEdge(5, 10, 0, true),                   // 20
                new HalfEdge(5, 0, 3, true),                    // 21
                new HalfEdge(5, 16, 7, true),                   // 22
                new HalfEdge(5, 4, 4, true)                     // 23
            };

            controlMesh.Polygons = new Polygon[]
            {
                // left/right
                new Polygon(new int[] { 0, 1, 2, 3 }, 0),                       // 0
                new Polygon(new int[] { 7, 4, 5, 6 }, 1),                       // 1

                // front/back
                new Polygon(new int[] { 9, 10, 11, 8 }, 2),                     // 2
                new Polygon(new int[] { 13, 14, 15, 12 }, 3),                   // 3

                // top/down
                new Polygon(new int[] { 16, 17, 18, 19 }, 4),                   // 4
                new Polygon(new int[] { 20, 21, 22, 23 }, 5)                    // 5
            };

            shape = new Shape();

            shape.Surfaces = new Surface[6];
            shape.Surfaces[0].TexGenIndex = 0;
            shape.Surfaces[1].TexGenIndex = 1;
            shape.Surfaces[2].TexGenIndex = 2;
            shape.Surfaces[3].TexGenIndex = 3;
            shape.Surfaces[4].TexGenIndex = 4;
            shape.Surfaces[5].TexGenIndex = 5;

            shape.Surfaces[0].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 0);
            shape.Surfaces[1].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 1);
            shape.Surfaces[2].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 2);
            shape.Surfaces[3].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 3);
            shape.Surfaces[4].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 4);
            shape.Surfaces[5].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 5);

            GeometryUtility.CalculateTangents(shape.Surfaces[0].Plane.normal, out shape.Surfaces[0].Tangent, out shape.Surfaces[0].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[1].Plane.normal, out shape.Surfaces[1].Tangent, out shape.Surfaces[1].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[2].Plane.normal, out shape.Surfaces[2].Tangent, out shape.Surfaces[2].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[3].Plane.normal, out shape.Surfaces[3].Tangent, out shape.Surfaces[3].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[4].Plane.normal, out shape.Surfaces[4].Tangent, out shape.Surfaces[4].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[5].Plane.normal, out shape.Surfaces[5].Tangent, out shape.Surfaces[5].BiNormal);

            var defaultMaterial = CSGSettings.DefaultMaterial;

            shape.TexGens = new TexGen[6];

            shape.TexGens[0].RenderMaterial = defaultMaterial;
            shape.TexGens[1].RenderMaterial = defaultMaterial;
            shape.TexGens[2].RenderMaterial = defaultMaterial;
            shape.TexGens[3].RenderMaterial = defaultMaterial;
            shape.TexGens[4].RenderMaterial = defaultMaterial;
            shape.TexGens[5].RenderMaterial = defaultMaterial;

            shape.TexGens[0].Scale = MathConstants.oneVector3;
            shape.TexGens[1].Scale = MathConstants.oneVector3;
            shape.TexGens[2].Scale = MathConstants.oneVector3;
            shape.TexGens[3].Scale = MathConstants.oneVector3;
            shape.TexGens[4].Scale = MathConstants.oneVector3;
            shape.TexGens[5].Scale = MathConstants.oneVector3;


            shape.TexGens[0].Color = Color.white;
            shape.TexGens[1].Color = Color.white;
            shape.TexGens[2].Color = Color.white;
            shape.TexGens[3].Color = Color.white;
            shape.TexGens[4].Color = Color.white;
            shape.TexGens[5].Color = Color.white;


            shape.TexGenFlags    = new TexGenFlags[6];
            shape.TexGenFlags[0] = TexGenFlags.None;
            shape.TexGenFlags[1] = TexGenFlags.None;
            shape.TexGenFlags[2] = TexGenFlags.None;
            shape.TexGenFlags[3] = TexGenFlags.None;
            shape.TexGenFlags[4] = TexGenFlags.None;
            shape.TexGenFlags[5] = TexGenFlags.None;

            //controlMesh.Validate();
            ShapeUtility.EnsureInitialized(shape);
            controlMesh.IsValid = ControlMeshUtility.Validate(controlMesh, shape);

            return(controlMesh.IsValid);
        }
예제 #5
0
        internal static void CreateCubeControlMesh(out ControlMesh controlMesh, out Shape shape, Vector3 size)
        {
            size                *= 0.5f;
            controlMesh          = new ControlMesh();
            controlMesh.Vertices = new Vector3[]
            {
                new Vector3(-size.x, -size.y, -size.z),
                new Vector3(-size.x, size.y, -size.z),
                new Vector3(size.x, size.y, -size.z),
                new Vector3(size.x, -size.y, -size.z),

                new Vector3(-size.x, -size.y, size.z),
                new Vector3(-size.x, size.y, size.z),
                new Vector3(size.x, size.y, size.z),
                new Vector3(size.x, -size.y, size.z)
            };

            controlMesh.Edges = new HalfEdge[]
            {
                new HalfEdge(0, 21, 0, true),                   //  0
                new HalfEdge(0, 9, 1, true),                    //  1
                new HalfEdge(0, 13, 2, true),                   //  2
                new HalfEdge(0, 17, 3, true),                   //  3

                new HalfEdge(1, 23, 7, true),                   //  4
                new HalfEdge(1, 19, 6, true),                   //  5
                new HalfEdge(1, 15, 5, true),                   //  6
                new HalfEdge(1, 11, 4, true),                   //  7

                new HalfEdge(2, 14, 1, true),                   //  8
                new HalfEdge(2, 1, 0, true),                    //  9
                new HalfEdge(2, 20, 4, true),                   // 10
                new HalfEdge(2, 7, 5, true),                    // 11

                new HalfEdge(3, 18, 2, true),                   // 12
                new HalfEdge(3, 2, 1, true),                    // 13
                new HalfEdge(3, 8, 5, true),                    // 14
                new HalfEdge(3, 6, 6, true),                    // 15

                new HalfEdge(4, 22, 3, true),                   // 16
                new HalfEdge(4, 3, 2, true),                    // 17
                new HalfEdge(4, 12, 6, true),                   // 18
                new HalfEdge(4, 5, 7, true),                    // 19

                new HalfEdge(5, 10, 0, true),                   // 20
                new HalfEdge(5, 0, 3, true),                    // 21
                new HalfEdge(5, 16, 7, true),                   // 22
                new HalfEdge(5, 4, 4, true)                     // 23
            };

            controlMesh.Polygons = new Polygon[]
            {
                // left/right
                new Polygon(new int[] { 0, 1, 2, 3 }, 0),                       // 0
                new Polygon(new int[] { 7, 4, 5, 6 }, 1),                       // 1

                // front/back
                new Polygon(new int[] { 9, 10, 11, 8 }, 2),                     // 2
                new Polygon(new int[] { 13, 14, 15, 12 }, 3),                   // 3

                // top/down
                new Polygon(new int[] { 16, 17, 18, 19 }, 4),                   // 4
                new Polygon(new int[] { 20, 21, 22, 23 }, 5)                    // 5
            };

            shape = new Shape();

            shape.Surfaces = new Surface[6];
            shape.Surfaces[0].TexGenIndex = 0;
            shape.Surfaces[1].TexGenIndex = 1;
            shape.Surfaces[2].TexGenIndex = 2;
            shape.Surfaces[3].TexGenIndex = 3;
            shape.Surfaces[4].TexGenIndex = 4;
            shape.Surfaces[5].TexGenIndex = 5;

            shape.Surfaces[0].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 0);
            shape.Surfaces[1].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 1);
            shape.Surfaces[2].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 2);
            shape.Surfaces[3].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 3);
            shape.Surfaces[4].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 4);
            shape.Surfaces[5].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 5);

            GeometryUtility.CalculateTangents(shape.Surfaces[0].Plane.normal, out shape.Surfaces[0].Tangent, out shape.Surfaces[0].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[1].Plane.normal, out shape.Surfaces[1].Tangent, out shape.Surfaces[1].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[2].Plane.normal, out shape.Surfaces[2].Tangent, out shape.Surfaces[2].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[3].Plane.normal, out shape.Surfaces[3].Tangent, out shape.Surfaces[3].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[4].Plane.normal, out shape.Surfaces[4].Tangent, out shape.Surfaces[4].BiNormal);
            GeometryUtility.CalculateTangents(shape.Surfaces[5].Plane.normal, out shape.Surfaces[5].Tangent, out shape.Surfaces[5].BiNormal);

            shape.TexGens          = new TexGen[6];
            shape.TexGens[0].Scale = MathConstants.oneVector3;
            shape.TexGens[1].Scale = MathConstants.oneVector3;
            shape.TexGens[2].Scale = MathConstants.oneVector3;
            shape.TexGens[3].Scale = MathConstants.oneVector3;
            shape.TexGens[4].Scale = MathConstants.oneVector3;
            shape.TexGens[5].Scale = MathConstants.oneVector3;


            shape.TexGens[0].Color = Color.white;
            shape.TexGens[1].Color = Color.white;
            shape.TexGens[2].Color = Color.white;
            shape.TexGens[3].Color = Color.white;
            shape.TexGens[4].Color = Color.white;
            shape.TexGens[5].Color = Color.white;


            shape.TexGenFlags    = new TexGenFlags[6];
            shape.TexGenFlags[0] = TexGenFlags.None;
            shape.TexGenFlags[1] = TexGenFlags.None;
            shape.TexGenFlags[2] = TexGenFlags.None;
            shape.TexGenFlags[3] = TexGenFlags.None;
            shape.TexGenFlags[4] = TexGenFlags.None;
            shape.TexGenFlags[5] = TexGenFlags.None;

            shape.Materials    = new Material[6];
            shape.Materials[0] = CSGSettings.DefaultMaterial;
            shape.Materials[1] = CSGSettings.DefaultMaterial;
            shape.Materials[2] = CSGSettings.DefaultMaterial;
            shape.Materials[3] = CSGSettings.DefaultMaterial;
            shape.Materials[4] = CSGSettings.DefaultMaterial;
            shape.Materials[5] = CSGSettings.DefaultMaterial;

            //controlMesh.Validate();
            ShapeUtility.CreateCutter(shape, controlMesh);
            ShapeUtility.EnsureInitialized(shape);
            controlMesh.IsValid = ControlMeshUtility.Validate(controlMesh, shape);
        }