protected override IEnumerator GetSimplifiedMesh(Utils.WorkingMesh origin, float quality, Action <Utils.WorkingMesh> resultCallback)
        {
            var meshSimplifier = new global::UnityMeshSimplifier.MeshSimplifier();

            meshSimplifier.Vertices = origin.vertices;
            meshSimplifier.Normals  = origin.normals;
            meshSimplifier.Tangents = origin.tangents;
            meshSimplifier.UV1      = origin.uv;
            meshSimplifier.UV2      = origin.uv2;
            meshSimplifier.UV3      = origin.uv3;
            meshSimplifier.UV4      = origin.uv4;
            meshSimplifier.Colors   = origin.colors;

            var triangles = new int[origin.subMeshCount][];

            for (var submesh = 0; submesh < origin.subMeshCount; submesh++)
            {
                triangles[submesh] = origin.GetTriangles(submesh);
            }

            meshSimplifier.AddSubMeshTriangles(triangles);

            meshSimplifier.SimplifyMesh(quality);

            int triCount = 0;

            for (int i = 0; i < meshSimplifier.SubMeshCount; ++i)
            {
                triCount += meshSimplifier.GetSubMeshTriangles(i).Length;
            }

            Utils.WorkingMesh nwm = new WorkingMesh(Allocator.Persistent, meshSimplifier.Vertices.Length, triCount, meshSimplifier.SubMeshCount, 0);
            nwm.name         = origin.name;
            nwm.vertices     = meshSimplifier.Vertices;
            nwm.normals      = meshSimplifier.Normals;
            nwm.tangents     = meshSimplifier.Tangents;
            nwm.uv           = meshSimplifier.UV1;
            nwm.uv2          = meshSimplifier.UV2;
            nwm.uv3          = meshSimplifier.UV3;
            nwm.uv4          = meshSimplifier.UV4;
            nwm.colors       = meshSimplifier.Colors;
            nwm.subMeshCount = meshSimplifier.SubMeshCount;
            for (var submesh = 0; submesh < nwm.subMeshCount; submesh++)
            {
                nwm.SetTriangles(meshSimplifier.GetSubMeshTriangles(submesh), submesh);
            }

            if (resultCallback != null)
            {
                resultCallback(nwm);
            }
            yield break;
        }
        protected override IEnumerator GetSimplifiedMesh(Utils.WorkingMesh origin, float quality, Action <Utils.WorkingMesh> resultCallback)
        {
            var meshSimplifier = new global::UnityMeshSimplifier.MeshSimplifier();

            meshSimplifier.SimplificationOptions = new global::UnityMeshSimplifier.SimplificationOptions
            {
                PreserveBorderEdges      = m_options.PreserveBorderEdges,
                PreserveUVSeamEdges      = m_options.PreserveUVSeamEdges,
                PreserveUVFoldoverEdges  = m_options.PreserveUVFoldoverEdges,
                PreserveSurfaceCurvature = m_options.PreserveSurfaceCurvature,
                EnableSmartLink          = m_options.EnableSmartLink,
                VertexLinkDistance       = m_options.VertexLinkDistance,
                MaxIterationCount        = m_options.MaxIterationCount,
                Agressiveness            = m_options.Agressiveness,
                ManualUVComponentCount   = m_options.ManualUVComponentCount,
                UVComponentCount         = m_options.UVComponentCount,
            };
            meshSimplifier.Vertices = origin.vertices;
            meshSimplifier.Normals  = origin.normals;
            meshSimplifier.Tangents = origin.tangents;
            meshSimplifier.UV1      = origin.uv;
            meshSimplifier.UV2      = origin.uv2;
            meshSimplifier.UV3      = origin.uv3;
            meshSimplifier.UV4      = origin.uv4;
            meshSimplifier.Colors   = origin.colors;

            var triangles = new int[origin.subMeshCount][];

            for (var submesh = 0; submesh < origin.subMeshCount; submesh++)
            {
                triangles[submesh] = origin.GetTriangles(submesh);
            }

            meshSimplifier.AddSubMeshTriangles(triangles);

            meshSimplifier.SimplifyMesh(quality);

            int triCount = 0;

            for (int i = 0; i < meshSimplifier.SubMeshCount; ++i)
            {
                triCount += meshSimplifier.GetSubMeshTriangles(i).Length;
            }

            Utils.WorkingMesh nwm = new WorkingMesh(Allocator.Persistent, meshSimplifier.Vertices.Length, triCount, meshSimplifier.SubMeshCount, 0);
            nwm.name         = origin.name;
            nwm.vertices     = meshSimplifier.Vertices;
            nwm.normals      = meshSimplifier.Normals;
            nwm.tangents     = meshSimplifier.Tangents;
            nwm.uv           = meshSimplifier.UV1;
            nwm.uv2          = meshSimplifier.UV2;
            nwm.uv3          = meshSimplifier.UV3;
            nwm.uv4          = meshSimplifier.UV4;
            nwm.colors       = meshSimplifier.Colors;
            nwm.subMeshCount = meshSimplifier.SubMeshCount;
            for (var submesh = 0; submesh < nwm.subMeshCount; submesh++)
            {
                nwm.SetTriangles(meshSimplifier.GetSubMeshTriangles(submesh), submesh);
            }

            if (resultCallback != null)
            {
                resultCallback(nwm);
            }
            yield break;
        }
Beispiel #3
0
        private WorkingMesh MakeFillHoleMesh(WorkingMesh source)
        {
            int          totalTris = 0;
            List <int[]> newTris   = new List <int[]>();

            for (int si = 0; si < source.subMeshCount; ++si)
            {
                List <int>        tris     = source.GetTriangles(si).ToList();
                List <Vector2Int> edgeList = GetEdgeList(tris);


                List <EdgeGroup> groups = new List <EdgeGroup>();
                for (int i = 0; i < edgeList.Count; ++i)
                {
                    EdgeGroup group = new EdgeGroup();
                    group.Begin = edgeList[i].x;
                    group.End   = edgeList[i].y;
                    group.EdgeList.Add(edgeList[i]);

                    groups.Add(group);
                }

                bool isFinish = false;

                while (isFinish == false)
                {
                    isFinish = true;

                    for (int gi1 = 0; gi1 < groups.Count; ++gi1)
                    {
                        for (int gi2 = gi1 + 1; gi2 < groups.Count; ++gi2)
                        {
                            EdgeGroup g1 = groups[gi1];
                            EdgeGroup g2 = groups[gi2];

                            if (g1.End == g2.Begin)
                            {
                                g1.End = g2.End;
                                g1.EdgeList.AddRange(g2.EdgeList);

                                groups[gi2] = groups[groups.Count - 1];
                                groups.RemoveAt(groups.Count - 1);

                                gi2     -= 1;
                                isFinish = false;
                            }
                            else if (g1.Begin == g2.End)
                            {
                                g2.End = g1.End;
                                g2.EdgeList.AddRange(g1.EdgeList);

                                groups[gi1] = groups[gi2];
                                groups[gi2] = groups[groups.Count - 1];
                                groups.RemoveAt(groups.Count - 1);

                                gi2     -= 1;
                                isFinish = false;
                            }
                        }
                    }
                }

                for (int gi = 0; gi < groups.Count; ++gi)
                {
                    EdgeGroup group = groups[gi];
                    for (int ei1 = 1; ei1 < group.EdgeList.Count - 1; ++ei1)
                    {
                        for (int ei2 = ei1 + 1; ei2 < group.EdgeList.Count; ++ei2)
                        {
                            if (group.EdgeList[ei1].x == group.EdgeList[ei2].y)
                            {
                                EdgeGroup ng = new EdgeGroup();
                                ng.Begin = group.EdgeList[ei1].x;
                                ng.End   = group.EdgeList[ei2].y;

                                for (int i = ei1; i <= ei2; ++i)
                                {
                                    ng.EdgeList.Add(group.EdgeList[i]);
                                }

                                for (int i = ei2; i >= ei1; --i)
                                {
                                    group.EdgeList.RemoveAt(i);
                                }

                                groups.Add(ng);

                                ei1 = 0; // goto first
                                break;
                            }
                        }
                    }
                }

                if (groups.Count == 0)
                {
                    continue;
                }

                groups.Sort((g1, g2) => { return(g2.EdgeList.Count - g1.EdgeList.Count); });

                //first group( longest group ) is outline.
                for (int i = 1; i < groups.Count; ++i)
                {
                    EdgeGroup group = groups[i];
                    for (int ei = 1; ei < group.EdgeList.Count - 1; ++ei)
                    {
                        tris.Add(group.Begin);
                        tris.Add(group.EdgeList[ei].y);
                        tris.Add(group.EdgeList[ei].x);
                    }
                }

                totalTris += tris.Count;
                newTris.Add(tris.ToArray());
            }

            WorkingMesh mesh = new WorkingMesh(Allocator.Persistent, source.vertexCount, totalTris, source.subMeshCount, 0);

            mesh.name     = source.name;
            mesh.vertices = source.vertices;
            mesh.normals  = source.normals;
            mesh.uv       = source.uv;

            for (int i = 0; i < newTris.Count; ++i)
            {
                mesh.SetTriangles(newTris[i], i);
            }

            return(mesh);
        }
Beispiel #4
0
        private WorkingMesh MakeBorder(WorkingMesh source, Heightmap heightmap, int borderCount)
        {
            List <Vector3> vertices    = source.vertices.ToList();
            List <Vector3> normals     = source.normals.ToList();
            List <Vector2> uvs         = source.uv.ToList();
            List <int[]>   subMeshTris = new List <int[]>();

            int maxTris = 0;

            for (int si = 0; si < source.subMeshCount; ++si)
            {
                List <int>          tris         = source.GetTriangles(si).ToList();
                List <Vector2Int>   edges        = GetEdgeList(tris);
                HashSet <int>       vertexIndces = new HashSet <int>();
                List <BorderVertex> edgeVertices = new List <BorderVertex>();

                for (int ei = 0; ei < edges.Count; ++ei)
                {
                    vertexIndces.Add(edges[ei].x);
                    vertexIndces.Add(edges[ei].y);
                }

                List <BorderVertex> borderVertices = GenerateBorderVertices(heightmap, borderCount);

                //calculate closest vertex from border vertices.
                for (int i = 0; i < borderVertices.Count; ++i)
                {
                    float        closestDistance = Single.MaxValue;
                    BorderVertex v = borderVertices[i];
                    foreach (var index in vertexIndces)
                    {
                        Vector3 pos  = vertices[index];
                        float   dist = Vector3.SqrMagnitude(pos - borderVertices[i].Pos);
                        if (dist < closestDistance)
                        {
                            closestDistance = dist;
                            v.ClosestIndex  = index;
                        }
                    }

                    borderVertices[i] = v;
                }

                //generate tris
                int startAddIndex = vertices.Count;
                for (int bi = 0; bi < borderVertices.Count; ++bi)
                {
                    int next = (bi == borderVertices.Count - 1) ? 0 : bi + 1;

                    tris.Add(bi + startAddIndex);
                    tris.Add(borderVertices[bi].ClosestIndex);
                    tris.Add(next + startAddIndex);

                    Vector2 uv;
                    uv.x = (borderVertices[bi].Pos.x - heightmap.Offset.x) / heightmap.Size.x;
                    uv.y = (borderVertices[bi].Pos.z - heightmap.Offset.z) / heightmap.Size.z;
                    vertices.Add(borderVertices[bi].Pos);

                    if (m_hlod.UseNormal)
                    {
                        normals.Add(Vector3.up);
                    }
                    else
                    {
                        normals.Add(heightmap.GetInterpolatedNormal(uv.x, uv.y));
                    }

                    uvs.Add(uv);

                    if (borderVertices[bi].ClosestIndex == borderVertices[next].ClosestIndex)
                    {
                        continue;
                    }

                    tris.Add(borderVertices[bi].ClosestIndex);
                    tris.Add(borderVertices[next].ClosestIndex);
                    tris.Add(next + startAddIndex);
                }

                maxTris += tris.Count;
                subMeshTris.Add(tris.ToArray());
            }

            WorkingMesh mesh = new WorkingMesh(Allocator.Persistent, vertices.Count, maxTris, subMeshTris.Count, 0);

            mesh.name     = source.name;
            mesh.vertices = vertices.ToArray();
            mesh.normals  = normals.ToArray();
            mesh.uv       = uvs.ToArray();

            for (int i = 0; i < subMeshTris.Count; ++i)
            {
                mesh.SetTriangles(subMeshTris[i], i);
            }

            return(mesh);
        }
Beispiel #5
0
        private WorkingMesh CreateBakedGeometry(string name, Heightmap heightmap, Bounds bounds, int distance)
        {
            int borderWidth   = CalcBorderWidth(heightmap, distance);
            int borderWidth2x = borderWidth * 2;

            WorkingMesh mesh =
                new WorkingMesh(Allocator.Persistent, heightmap.Width * heightmap.Height,
                                (heightmap.Width - borderWidth2x - 1) * (heightmap.Height - borderWidth2x - 1) * 6, 1, 0);

            mesh.name = name + "_Mesh";


            Vector3[] vertices  = new Vector3[(heightmap.Width - borderWidth2x) * (heightmap.Height - borderWidth2x)];
            Vector3[] normals   = new Vector3[(heightmap.Width - borderWidth2x) * (heightmap.Height - borderWidth2x)];
            Vector2[] uvs       = new Vector2[(heightmap.Width - borderWidth2x) * (heightmap.Height - borderWidth2x)];
            int[]     triangles = new int[(heightmap.Width - borderWidth2x - 1) * (heightmap.Height - borderWidth2x - 1) * 6];


            int vi = 0;

            //except boder line
            for (int z = borderWidth; z < heightmap.Height - borderWidth; ++z)
            {
                for (int x = borderWidth; x < heightmap.Width - borderWidth; ++x)
                {
                    int index = vi++;

                    vertices[index].x = bounds.size.x * (x) / (heightmap.Width - 1) + bounds.min.x;
                    vertices[index].y = heightmap.Size.y * heightmap[z, x];
                    vertices[index].z = bounds.size.z * (z) / (heightmap.Height - 1) + bounds.min.z;

                    uvs[index].x = (float)x / (heightmap.Width - 1);
                    uvs[index].y = (float)z / (heightmap.Height - 1);

                    if (m_hlod.UseNormal)
                    {
                        normals[index] = Vector3.up;
                    }
                    else
                    {
                        normals[index] = heightmap.GetInterpolatedNormal(uvs[index].x, uvs[index].y);
                    }
                }
            }

            int ii = 0;

            for (int z = 0; z < heightmap.Height - borderWidth2x - 1; ++z)
            {
                for (int x = 0; x < heightmap.Width - borderWidth2x - 1; ++x)
                {
                    int i00 = z * (heightmap.Width - borderWidth2x) + x;
                    int i10 = z * (heightmap.Width - borderWidth2x) + x + 1;
                    int i01 = (z + 1) * (heightmap.Width - borderWidth2x) + x;
                    int i11 = (z + 1) * (heightmap.Width - borderWidth2x) + x + 1;

                    triangles[ii + 0] = i00;
                    triangles[ii + 1] = i11;
                    triangles[ii + 2] = i10;
                    triangles[ii + 3] = i11;
                    triangles[ii + 4] = i00;
                    triangles[ii + 5] = i01;
                    ii += 6;
                }
            }

            mesh.vertices = vertices;
            mesh.normals  = normals;
            mesh.uv       = uvs;
            mesh.SetTriangles(triangles, 0);

            return(mesh);
        }
Beispiel #6
0
        public WorkingMesh CombineMesh(Allocator allocator, List <CombineInfo> infos)
        {
            //I didn't consider animation mesh combine.
            int verticesCount = 0;
            int normalCount   = 0;
            int tangentCount  = 0;
            int UV1Count      = 0;
            int UV2Count      = 0;
            int UV3Count      = 0;
            int UV4Count      = 0;
            int colorCount    = 0;

            int trianglesCount = 0;

            List <Dictionary <int, int> > remappers = new List <Dictionary <int, int> >(infos.Count);

            for (int i = 0; i < infos.Count; ++i)
            {
                int[] meshIndices = infos[i].Mesh.GetTriangles(infos[i].MeshIndex);
                Dictionary <int, int> remapper = CalculateMeshRemap(meshIndices);

                verticesCount += (infos[i].Mesh.vertices.Length > 0) ? remapper.Count : 0;
                normalCount   += (infos[i].Mesh.normals.Length > 0) ? remapper.Count : 0;
                tangentCount  += (infos[i].Mesh.tangents.Length > 0) ? remapper.Count : 0;
                UV1Count      += (infos[i].Mesh.uv.Length > 0) ? remapper.Count : 0;
                UV2Count      += (infos[i].Mesh.uv2.Length > 0) ? remapper.Count : 0;
                UV3Count      += (infos[i].Mesh.uv3.Length > 0) ? remapper.Count : 0;
                UV4Count      += (infos[i].Mesh.uv4.Length > 0) ? remapper.Count : 0;
                colorCount    += (infos[i].Mesh.colors.Length > 0) ? remapper.Count : 0;

                trianglesCount += meshIndices.Length;

                remappers.Add(remapper);
            }

            WorkingMesh combinedMesh = new WorkingMesh(allocator, verticesCount, trianglesCount, 1, 0);

            List <Vector3> vertices = new List <Vector3>(verticesCount);
            List <Vector3> normals  = new List <Vector3>(verticesCount);
            List <Vector4> tangents = new List <Vector4>(verticesCount);
            List <Vector2> uv1s     = new List <Vector2>(verticesCount);
            List <Vector2> uv2s     = new List <Vector2>(verticesCount);
            List <Vector2> uv3s     = new List <Vector2>(verticesCount);
            List <Vector2> uv4s     = new List <Vector2>(verticesCount);
            List <Color>   colors   = new List <Color>(colorCount);

            List <int> triangles = new List <int>(trianglesCount);

            for (int i = 0; i < infos.Count; ++i)
            {
                WorkingMesh           mesh     = infos[i].Mesh;
                Dictionary <int, int> remapper = remappers[i];
                int startIndex = vertices.Count;

                if (verticesCount > 0)
                {
                    FillBuffer(ref vertices, mesh.vertices, remapper, Vector3.zero);
                    for (int vi = startIndex; vi < vertices.Count; ++vi)
                    {
                        vertices[vi] = infos[i].Transform.MultiplyPoint(vertices[vi]);
                    }
                }

                if (normalCount > 0)
                {
                    FillBuffer(ref normals, mesh.normals, remapper, Vector3.up);
                    for (int ni = startIndex; ni < normals.Count; ++ni)
                    {
                        normals[ni] = infos[i].Transform.MultiplyVector(normals[ni]);
                    }
                }

                if (tangentCount > 0)
                {
                    FillBuffer(ref tangents, mesh.tangents, remapper, new Vector4(1, 0, 0, 1));
                    for (int ti = startIndex; ti < tangents.Count; ++ti)
                    {
                        Vector3 tanVec = new Vector3(tangents[ti].x, tangents[ti].y, tangents[ti].z);
                        tanVec = infos[i].Transform.MultiplyVector(tanVec);
                        Vector4 transTan = new Vector4(tanVec.x, tanVec.y, tanVec.z, tangents[ti].w);
                        tangents[ti] = transTan;
                    }
                }

                if (UV1Count > 0)
                {
                    FillBuffer(ref uv1s, mesh.uv, remapper, Vector2.zero);
                }
                if (UV2Count > 0)
                {
                    FillBuffer(ref uv2s, mesh.uv2, remapper, Vector2.zero);
                }
                if (UV3Count > 0)
                {
                    FillBuffer(ref uv3s, mesh.uv3, remapper, Vector2.zero);
                }
                if (UV4Count > 0)
                {
                    FillBuffer(ref uv4s, mesh.uv4, remapper, Vector2.zero);
                }
                if (colorCount > 0)
                {
                    FillBuffer(ref colors, mesh.colors, remapper, Color.white);
                }

                FillIndices(ref triangles, mesh.GetTriangles(infos[i].MeshIndex), remapper, startIndex);
            }

            combinedMesh.name     = "CombinedMesh";
            combinedMesh.vertices = vertices.ToArray();
            combinedMesh.normals  = normals.ToArray();
            combinedMesh.tangents = tangents.ToArray();
            combinedMesh.uv       = uv1s.ToArray();
            combinedMesh.uv2      = uv2s.ToArray();
            combinedMesh.uv3      = uv3s.ToArray();
            combinedMesh.uv4      = uv4s.ToArray();
            combinedMesh.colors   = colors.ToArray();

            combinedMesh.SetTriangles(triangles.ToArray(), 0);

            return(combinedMesh);
        }