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); }