Ejemplo n.º 1
0
    /// <summary>
    /// Export the HMesh as a number of meshes, split into a number of subregions.
    /// If the parameter used material is provided, the mesh only contains submeshes with geometry and the submesh index
    /// is added to the used material.
    /// Is a mesh does not contain any vertices it is skipped.
    /// </summary>
    public List <Mesh> ExportSplit(Vector3i axisSplit, List <List <int> > usedMaterials = null, double sharpEdgeAngle = 360)
    {
        var bounds = ComputeBoundsD();


        bounds.extents += Vector3D.one * 0.000001; // add delta size to ensure no vertex is on bounds

        var resList = new List <Mesh>();

        // Enumerate vertices
        for (int i = 0; i < vertices.Count; i++)
        {
            vertices[i].label = i;
        }

        var maxFaceLabel = 0;

        foreach (var face in faces)
        {
            maxFaceLabel = Mathf.Max(maxFaceLabel, face.label);
        }

        int clusterCount = 0;

        MarkSharpEdges(sharpEdgeAngle);
        var faceClusters = SeparateMeshByGeometry(out clusterCount);

        Debug.Log("Face clusters: " + clusterCount);

        var remap = new int[vertices.Count];

        for (var i = 0; i < axisSplit[0]; i++)
        {
            double minX = bounds.min.x + i * (bounds.size.x / axisSplit[0]);
            double maxX = bounds.min.x + (i + 1) * (bounds.size.x / axisSplit[0]);
            for (var j = 0; j < axisSplit[1]; j++)
            {
                double minY = bounds.min.y + j * (bounds.size.y / axisSplit[1]);
                double maxY = bounds.min.y + (j + 1) * (bounds.size.y / axisSplit[1]);
                for (var k = 0; k < axisSplit[2]; k++)
                {
                    double minZ = bounds.min.z + k * (bounds.size.z / axisSplit[2]);
                    double maxZ = bounds.min.z + (k + 1) * (bounds.size.z / axisSplit[2]);

                    // DebugExt.DrawBox(new Vector3D(minX, minY, minZ).ToVector3(), new Vector3D(maxX, maxY, maxZ).ToVector3(),Color.white, 10);

                    var min = new Vector3D(minX, minY, minZ);
                    var max = new Vector3D(maxX, maxY, maxZ);

                    var res = new Mesh();
                    res.name = "HMesh_" + i + "," + j + "," + k;
                    var vertexArray = new List <Vector3>();
                    var normalArray = new List <Vector3>();
                    var uv1         = new List <Vector2>();
                    var uv2         = new List <Vector2>();

                    res.subMeshCount = maxFaceLabel + 1;
                    List <Face> facesInRegion = new List <Face>();

                    foreach (var face in faces)
                    {
                        var center = face.GetCenter();
                        if (Vector3D.AllLessThan(min, center) && Vector3D.AllLessEqualThan(center, max))
                        {
                            facesInRegion.Add(face);
                        }
                    }
                    var triangles = new List <List <int> >();
                    for (int ii = 0; ii <= maxFaceLabel; ii++)
                    {
                        triangles.Add(new List <int>());
                    }

                    for (int clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++)
                    {
                        // clear remap
                        for (int x = 0; x < remap.Length; x++)
                        {
                            remap[x] = -1;
                        }

                        for (var faceLabel = 0; faceLabel <= maxFaceLabel; faceLabel++)
                        {
                            foreach (var face in facesInRegion)
                            {
                                if (faceClusters[face.id] != clusterIndex)
                                {
                                    continue;
                                }
                                if (face.label == faceLabel)
                                {
                                    if (face.NoEdges() != 3)
                                    {
                                        Debug.LogError("Only triangles supported. Was " + face.NoEdges() + "-gon");
                                        continue;
                                    }
                                    var he    = face.halfedge;
                                    var first = true;
                                    while (he != face.halfedge || first)
                                    {
                                        var indexOfVertex         = he.vert.label;
                                        var indexOfVertexRemapped = remap[indexOfVertex];
                                        if (indexOfVertexRemapped == -1)
                                        {
                                            indexOfVertexRemapped = vertexArray.Count;
                                            remap[indexOfVertex]  = indexOfVertexRemapped;
                                            vertexArray.Add(vertices[indexOfVertex].position);
                                            uv1.Add(vertices[indexOfVertex].uv1);
                                            uv2.Add(vertices[indexOfVertex].uv2);

                                            // compute normal
                                            Vector3D n     = Vector3D.zero;
                                            int      count = 0;
                                            foreach (var vertHe in he.vert.CirculateAllIngoing())
                                            {
                                                if (faceClusters[vertHe.face.id] == clusterIndex)
                                                {
                                                    double angle = Vector3D.Angle(-vertHe.GetDirection(), vertHe.next.GetDirection());
                                                    n += angle * vertHe.face.GetNormal();
                                                    count++;
                                                }
                                            }
                                            if (n.sqrMagnitude <= 0 || double.IsNaN(Vector3D.Dot(n, n)))
                                            {
                                                Debug.LogWarning("Cannot compute normal n is " + n.ToString("R") + " edges of vertex " + he.vert.Circulate().Count + " same cluster " + count + " " + he.face.ToString());
                                                foreach (var vertHe in he.vert.CirculateAllIngoing())
                                                {
                                                    if (faceClusters[vertHe.face.id] == clusterIndex)
                                                    {
                                                        Debug.Log(vertHe.face.ToString());
                                                    }
                                                }
                                                n = new Vector3D(0, 1, 0);
                                            }
                                            else
                                            {
                                                n.Normalize();
                                            }
                                            normalArray.Add(n.ToVector3());
                                        }
                                        triangles[faceLabel].Add(indexOfVertexRemapped);
                                        he    = he.next;
                                        first = false;
                                    }
                                }
                            }
                        }
                    }
                    if (vertexArray.Count == 0)
                    {
                        // empty mesh - skip
                        continue;
                    }
                    resList.Add(res);
                    if (vertexArray.Count > 65000)
                    {
                        Debug.LogWarning("Vertex count was " + vertexArray.Count);
                    }
                    res.vertices = vertexArray.ToArray();
                    res.uv       = uv1.ToArray();
                    res.uv2      = uv2.ToArray();
                    res.normals  = normalArray.ToArray();

                    // add mesh indices
                    // if usedMaterials exists then filter out any empty submesh
                    List <int> materialIndices = null;
                    if (usedMaterials != null)
                    {
                        materialIndices = new List <int>();
                        usedMaterials.Add(materialIndices);
                    }
                    for (int ii = 0; ii < triangles.Count; ii++)
                    {
                        if (materialIndices != null)
                        {
                            if (triangles[ii].Count > 0)
                            {
                                res.SetIndices(triangles[ii].ToArray(), MeshTopology.Triangles, materialIndices.Count, true);
                                materialIndices.Add(ii);
                            }
                        }
                        else
                        {
                            res.SetIndices(triangles[ii].ToArray(), MeshTopology.Triangles, ii, true);
                        }
                    }
                    res.RecalculateBounds();
                }
            }
        }
        return(resList);
    }