예제 #1
0
        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;
        }
예제 #2
0
        private void Combine(Vector3 rootPosition, HLODBuildInfo info)
        {
            var materialTable = new Dictionary <string, WorkingMaterial>();
            var combineInfos  = new Dictionary <string, List <MeshCombiner.CombineInfo> >();

            for (int i = 0; i < info.WorkingObjects.Count; ++i)
            {
                var materials = info.WorkingObjects[i].Materials;
                for (int m = 0; m < materials.Count; ++m)
                {
                    //var mat = materials[m];
                    MeshCombiner.CombineInfo combineInfo = new MeshCombiner.CombineInfo();

                    combineInfo.Transform      = info.WorkingObjects[i].LocalToWorld;
                    combineInfo.Transform.m03 -= rootPosition.x;
                    combineInfo.Transform.m13 -= rootPosition.y;
                    combineInfo.Transform.m23 -= rootPosition.z;
                    combineInfo.Mesh           = info.WorkingObjects[i].Mesh;
                    combineInfo.MeshIndex      = m;

                    if (combineInfos.ContainsKey(materials[m].Identifier) == false)
                    {
                        combineInfos.Add(materials[m].Identifier, new List <MeshCombiner.CombineInfo>());
                        materialTable.Add(materials[m].Identifier, materials[m]);
                    }

                    combineInfos[materials[m].Identifier].Add(combineInfo);
                }
            }

            using (var originWorkingObject = info.WorkingObjects)
            {
                DisposableList <WorkingObject> combinedObjects = new DisposableList <WorkingObject>();
                info.WorkingObjects = combinedObjects;

                MeshCombiner combiner = new MeshCombiner();
                foreach (var pair in combineInfos)
                {
                    WorkingMesh     combinedMesh   = combiner.CombineMesh(Allocator.Persistent, pair.Value);
                    WorkingObject   combinedObject = new WorkingObject(Allocator.Persistent);
                    WorkingMaterial material       = materialTable[pair.Key].Clone();

                    combinedMesh.name   = info.Name + "_Mesh" + pair.Key;
                    combinedObject.Name = info.Name;
                    combinedObject.SetMesh(combinedMesh);
                    combinedObject.Materials.Add(material);

                    combinedObjects.Add(combinedObject);
                }
            }
        }
예제 #3
0
        private void ReampUV(WorkingMesh mesh, Heightmap heightmap)
        {
            var vertices = mesh.vertices;
            var uvs      = mesh.uv;

            for (int i = 0; i < mesh.vertexCount; ++i)
            {
                Vector2 uv;
                uv.x   = (vertices[i].x - heightmap.Offset.x) / heightmap.Size.x;
                uv.y   = (vertices[i].z - heightmap.Offset.z) / heightmap.Size.z;
                uvs[i] = uv;
                //vertices[i].
            }

            mesh.uv = uvs;
        }
예제 #4
0
        private void Combine(Vector3 rootPosition, TexturePacker packer, HLODBuildInfo info, dynamic options)
        {
            var atlas = packer.GetAtlas(info);

            if (atlas == null)
            {
                return;
            }

            List <TextureInfo> textureInfoList           = options.TextureInfoList;
            List <MeshCombiner.CombineInfo> combineInfos = new List <MeshCombiner.CombineInfo>();

            for (int i = 0; i < info.WorkingObjects.Count; ++i)
            {
                var obj = info.WorkingObjects[i];
                ConvertMesh(obj.Mesh, obj.Materials, atlas, textureInfoList[0].InputName);

                for (int si = 0; si < obj.Mesh.subMeshCount; ++si)
                {
                    var ci = new MeshCombiner.CombineInfo();
                    ci.Mesh      = obj.Mesh;
                    ci.MeshIndex = si;

                    ci.Transform      = obj.LocalToWorld;
                    ci.Transform.m03 -= rootPosition.x;
                    ci.Transform.m13 -= rootPosition.y;
                    ci.Transform.m23 -= rootPosition.z;

                    combineInfos.Add(ci);
                }
            }

            MeshCombiner combiner     = new MeshCombiner();
            WorkingMesh  combinedMesh = combiner.CombineMesh(Allocator.Persistent, combineInfos);

            WorkingObject   newObj = new WorkingObject(Allocator.Persistent);
            WorkingMaterial newMat = m_createdMaterials[atlas].Clone();

            combinedMesh.name = info.Name + "_Mesh";
            newObj.Name       = info.Name;
            newObj.SetMesh(combinedMesh);
            newObj.Materials.Add(newMat);

            info.WorkingObjects.Dispose();
            info.WorkingObjects = new DisposableList <WorkingObject>();
            info.WorkingObjects.Add(newObj);
        }
예제 #5
0
            public void From(WorkingMesh mesh)
            {
                m_name = mesh.name;

                m_vertices = ArrayToBytes(mesh.vertices);
                m_normals  = ArrayToBytes(mesh.normals);
                m_tangents = ArrayToBytes(mesh.tangents);
                m_uvs      = ArrayToBytes(mesh.uv);
                m_uvs2     = ArrayToBytes(mesh.uv2);
                m_uvs3     = ArrayToBytes(mesh.uv3);
                m_uvs4     = ArrayToBytes(mesh.uv4);
                m_colors   = ArrayToBytes(mesh.colors);
                m_indices  = new List <int[]>();
                for (int i = 0; i < mesh.subMeshCount; ++i)
                {
                    m_indices.Add(mesh.GetTriangles(i));
                }
            }
예제 #6
0
        private Mesh SimplifyMesh(Mesh source, float quality, Action <Mesh> complete)
        {
            var simplifiedMesh = new Mesh();

            var inputMesh  = source.ToWorkingMesh();
            var outputMesh = new WorkingMesh();

            var meshSimplifier = (IMeshSimplifier)Activator.CreateInstance(AutoLOD.meshSimplifierType);

            meshSimplifier.Simplify(inputMesh, outputMesh, quality, () =>
            {
                outputMesh.ApplyToMesh(simplifiedMesh);
                simplifiedMesh.RecalculateBounds();
                if (complete != null)
                {
                    complete(simplifiedMesh);
                }
            });

            return(simplifiedMesh);
        }
예제 #7
0
        private WorkingObject CreateBakedTerrain(string name, Bounds bounds, Heightmap heightmap, int distance)
        {
            WorkingObject wo = new WorkingObject(Allocator.Persistent);

            wo.Name = name;


            m_queue.EnqueueJob(() =>
            {
                WorkingMesh mesh = CreateBakedGeometry(name, heightmap, bounds, distance);
                wo.SetMesh(mesh);
            });

            m_queue.EnqueueJob(() =>
            {
                WorkingMaterial material = CreateBakedMaterial(name, bounds);
                wo.Materials.Add(material);
            });


            return(wo);
        }
예제 #8
0
        private void ConvertMesh(WorkingMesh mesh, DisposableList <WorkingMaterial> materials, TexturePacker.TextureAtlas atlas, string mainTextureName)
        {
            var uv      = mesh.uv;
            var updated = new bool[uv.Length];
            // Some meshes have submeshes that either aren't expected to render or are missing a material, so go ahead and skip
            int subMeshCount = Mathf.Min(mesh.subMeshCount, materials.Count);

            for (int mi = 0; mi < subMeshCount; ++mi)
            {
                int[] indices = mesh.GetTriangles(mi);
                foreach (var i in indices)
                {
                    if (updated[i] == false)
                    {
                        var uvCoord = uv[i];
                        var texture = materials[mi].GetTexture(mainTextureName);

                        if (texture == null || texture.GetGUID() == Guid.Empty)
                        {
                            // Sample at center of white texture to avoid sampling edge colors incorrectly
                            uvCoord.x = 0.5f;
                            uvCoord.y = 0.5f;
                        }
                        else
                        {
                            var uvOffset = atlas.GetUV(texture.GetGUID());

                            uvCoord.x = Mathf.Lerp(uvOffset.xMin, uvOffset.xMax, uvCoord.x);
                            uvCoord.y = Mathf.Lerp(uvOffset.yMin, uvOffset.yMax, uvCoord.y);
                        }

                        uv[i]      = uvCoord;
                        updated[i] = true;
                    }
                }
            }

            mesh.uv = uv;
        }
예제 #9
0
        private WorkingObject CreateBakedTerrain(string name, Bounds bounds, Heightmap heightmap, int distance, bool isLeaf)
        {
            WorkingObject wo = new WorkingObject(Allocator.Persistent);

            wo.Name            = name;
            wo.LightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;

            m_queue.EnqueueJob(() =>
            {
                WorkingMesh mesh = CreateBakedGeometry(name, heightmap, bounds, distance);
                wo.SetMesh(mesh);
            });

            m_queue.EnqueueJob(() =>
            {
                WorkingMaterial material = CreateBakedMaterial(name, bounds, isLeaf);
                wo.Materials.Add(material);
            });


            return(wo);
        }
예제 #10
0
        public IEnumerator CreateImpl()
        {
            try
            {
                using (m_queue = new JobQueue(8))
                {
                    Stopwatch sw = new Stopwatch();

                    AssetDatabase.Refresh();
                    AssetDatabase.SaveAssets();

                    sw.Reset();
                    sw.Start();

                    EditorUtility.DisplayProgressBar("Bake HLOD", "Initialize Bake", 0.0f);


                    TerrainData data = m_hlod.TerrainData;

                    m_size = data.size;

                    m_heightmap = new Heightmap(data.heightmapResolution, data.heightmapResolution, data.size,
                                                data.GetHeights(0, 0, data.heightmapResolution, data.heightmapResolution));

                    string materialPath = AssetDatabase.GUIDToAssetPath(m_hlod.MaterialGUID);
                    m_terrainMaterial = AssetDatabase.LoadAssetAtPath <Material>(materialPath);
                    if (m_terrainMaterial == null)
                    {
                        m_terrainMaterial = new Material(Shader.Find("Standard"));
                    }

                    m_terrainMaterialInstanceId = m_terrainMaterial.GetInstanceID();
                    m_terrainMaterialName       = m_terrainMaterial.name;

                    using (m_alphamaps = new DisposableList <WorkingTexture>())
                        using (m_layers = new DisposableList <Layer>())
                        {
                            for (int i = 0; i < data.alphamapTextures.Length; ++i)
                            {
                                m_alphamaps.Add(new WorkingTexture(Allocator.Persistent, data.alphamapTextures[i]));
                            }

                            for (int i = 0; i < data.terrainLayers.Length; ++i)
                            {
                                m_layers.Add(new Layer(data.terrainLayers[i]));
                            }


                            QuadTreeSpaceSplitter splitter =
                                new QuadTreeSpaceSplitter(0.0f);

                            SpaceNode rootNode = splitter.CreateSpaceTree(m_hlod.GetBounds(), m_hlod.ChunkSize * 2.0f,
                                                                          m_hlod.transform.position, null, progress => { });

                            EditorUtility.DisplayProgressBar("Bake HLOD", "Create mesh", 0.0f);

                            using (DisposableList <HLODBuildInfo> buildInfos = CreateBuildInfo(data, rootNode))
                            {
                                yield return(m_queue.WaitFinish());

                                //Write material & textures

                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    int curIndex = i;
                                    m_queue.EnqueueJob(() =>
                                    {
                                        ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(m_hlod.SimplifierType,
                                                                                                       new object[] { m_hlod.SimplifierOptions });
                                        simplifier.SimplifyImmidiate(buildInfos[curIndex]);
                                    });
                                }

                                EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes", 0.0f);
                                yield return(m_queue.WaitFinish());

                                Debug.Log("[TerrainHLOD] Simplify: " + sw.Elapsed.ToString("g"));
                                sw.Reset();
                                sw.Start();
                                EditorUtility.DisplayProgressBar("Bake HLOD", "Make border", 0.0f);

                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    HLODBuildInfo info = buildInfos[i];
                                    m_queue.EnqueueJob(() =>
                                    {
                                        for (int oi = 0; oi < info.WorkingObjects.Count; ++oi)
                                        {
                                            WorkingObject o       = info.WorkingObjects[oi];
                                            int borderVertexCount = m_hlod.BorderVertexCount * Mathf.RoundToInt(Mathf.Pow(2.0f, (float)info.Distances[oi]));
                                            using (WorkingMesh m = MakeBorder(o.Mesh, info.Heightmap, borderVertexCount))
                                            {
                                                ReampUV(m, info.Heightmap);
                                                o.SetMesh(MakeFillHoleMesh(m));
                                            }
                                        }
                                    });
                                }
                                yield return(m_queue.WaitFinish());

                                Debug.Log("[TerrainHLOD] Make Border: " + sw.Elapsed.ToString("g"));
                                sw.Reset();
                                sw.Start();


                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    SpaceNode     node = buildInfos[i].Target;
                                    HLODBuildInfo info = buildInfos[i];
                                    if (node.HasChild() == false)
                                    {
                                        SpaceNode parent = node.ParentNode;
                                        node.ParentNode = null;

                                        GameObject go = new GameObject(buildInfos[i].Name);

                                        for (int wi = 0; wi < info.WorkingObjects.Count; ++wi)
                                        {
                                            WorkingObject wo       = info.WorkingObjects[wi];
                                            GameObject    targetGO = null;
                                            if (wi == 0)
                                            {
                                                targetGO = go;
                                            }
                                            else
                                            {
                                                targetGO = new GameObject(wi.ToString());
                                                targetGO.transform.SetParent(go.transform, false);
                                            }

                                            List <Material> materials = new List <Material>();
                                            for (int mi = 0; mi < wo.Materials.Count; ++mi)
                                            {
                                                WorkingMaterial wm = wo.Materials[mi];
                                                if (wm.NeedWrite() == false)
                                                {
                                                    materials.Add(wm.ToMaterial());
                                                    continue;
                                                }

                                                Material mat          = new Material(wm.ToMaterial());
                                                string[] textureNames = wm.GetTextureNames();
                                                for (int ti = 0; ti < textureNames.Length; ++ti)
                                                {
                                                    WorkingTexture wt  = wm.GetTexture(textureNames[ti]);
                                                    Texture2D      tex = wt.ToTexture();
                                                    tex.wrapMode = wt.WrapMode;
                                                    mat.name     = targetGO.name + "_Mat";
                                                    mat.SetTexture(textureNames[ti], tex);
                                                }
                                                mat.EnableKeyword("_NORMALMAP");
                                                materials.Add(mat);
                                            }

                                            targetGO.AddComponent <MeshFilter>().sharedMesh        = wo.Mesh.ToMesh();
                                            targetGO.AddComponent <MeshRenderer>().sharedMaterials = materials.ToArray();
                                        }

                                        go.transform.SetParent(m_hlod.transform, false);
                                        m_hlod.AddGeneratedResource(go);

                                        parent.Objects.Add(go);
                                        buildInfos.RemoveAt(i);
                                        i -= 1;
                                    }
                                }

                                //controller
                                IStreamingBuilder builder =
                                    (IStreamingBuilder)Activator.CreateInstance(m_hlod.StreamingType,
                                                                                new object[] { m_hlod, m_hlod.StreamingOptions });

                                builder.Build(rootNode, buildInfos, m_hlod.gameObject, m_hlod.CullDistance, m_hlod.LODDistance, true, false,
                                              progress =>
                                {
                                    EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.",
                                                                     0.75f + progress * 0.25f);
                                });

                                Debug.Log("[TerrainHLOD] Build: " + sw.Elapsed.ToString("g"));
                            }
                        }

                    EditorUtility.SetDirty(m_hlod.gameObject);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                GC.Collect();
            }
        }
예제 #11
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);
        }
예제 #12
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);
        }
예제 #13
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);
        }
예제 #14
0
        public void Simplify(WorkingMesh inputMesh, WorkingMesh outputMesh, float quality)
        {
            var isMainThread = MonoBehaviourHelper.IsMainThread();

            Renderer renderer = null;

            UnityCloudJob job     = null;
            string        jobName = null;

            var assembly     = typeof(SharedData).Assembly;
            var cloudJobType = assembly.GetType("Simplygon.Cloud.Yoda.IntegrationClient.CloudJob");
            var jobNameField = cloudJobType.GetField("name", BindingFlags.NonPublic | BindingFlags.Instance);

            lock (executionLock)
            {
                const int kSimultaneousJobs = 4;
                //var processSubscriptionRestrictionsType = assembly.GetType("Simplygon.Cloud.Yoda.Client.ProcessSubscriptionRestrictions23");
                //var simultaneousJobsProperty = processSubscriptionRestrictionsType.GetProperty("SimultaneousJobs");
                //var accountType = assembly.GetType("Simplygon.Cloud.Yoda.Client.User23");
                //var processSubscriptionsRestrictionsProperty = accountType.GetProperty("ProcessSubscriptionRestrictions");
                //var processSubscriptionRestrictions = processSubscriptionsRestrictionsProperty.GetValue(SharedData.Instance.Account, null);
                //var simultaneousJobs = (int)simultaneousJobsProperty.GetValue(processSubscriptionRestrictions, null);

                while (SharedData.Instance.GeneralManager.JobManager.ProcessingJobCount >= kSimultaneousJobs)
                {
                    if (!isMainThread)
                    {
                        Thread.Sleep(1000);
                    }
                }

                MonoBehaviourHelper.ExecuteOnMainThread(() =>
                {
                    var go   = EditorUtility.CreateGameObjectWithHideFlags("Temp", HideFlags.HideAndDontSave, typeof(MeshRenderer), typeof(MeshFilter));
                    var mf   = go.GetComponent <MeshFilter>();
                    var mesh = new Mesh();
                    inputMesh.ApplyToMesh(mesh);
                    mf.sharedMesh       = mesh;
                    renderer            = go.GetComponent <MeshRenderer>();
                    var material        = new Material(Shader.Find("Standard"));
                    var sharedMaterials = new Material[mesh.subMeshCount];
                    for (int i = 0; i < mesh.subMeshCount; i++)
                    {
                        sharedMaterials[i] = material;
                    }
                    renderer.sharedMaterials = sharedMaterials;
                    renderer.enabled         = false;

                    EditorWindow.GetWindow <Window>(); // Must be visible for background processing

                    SharedData.Instance.Settings.SetDownloadAssetsAutomatically(true);

                    var lodChainProperty = typeof(SharedData).GetProperty("LODChain");
                    var lodChainList     = lodChainProperty.GetValue(SharedData.Instance, null) as IList;
                    var lodChain         = lodChainList[0];

                    var processNodeType   = assembly.GetType("Simplygon.SPL.v80.Node.ProcessNode");
                    var processorProperty = processNodeType.GetProperty("Processor");
                    var processor         = processorProperty.GetValue(lodChain, null);

                    var reductionProcessorType    = assembly.GetType("Simplygon.SPL.v80.Processor.ReductionProcessor");
                    var reductionSettingsProperty = reductionProcessorType.GetProperty("ReductionSettings");
                    var reductionSettingsType     = assembly.GetType("Simplygon.SPL.v80.Settings.ReductionSettings");
                    var reductionSettings         = reductionSettingsProperty.GetValue(processor, null);

                    var triangleRatioProperty = reductionSettingsType.GetProperty("TriangleRatio");
                    triangleRatioProperty.SetValue(reductionSettings, quality, null);

                    jobName        = Path.GetRandomFileName().Replace(".", string.Empty);
                    var prefabList = PrefabUtilityEx.GetPrefabsForSelection(new List <GameObject>()
                    {
                        go
                    });
                    var generalManager = SharedData.Instance.GeneralManager;
                    generalManager.CreateJob(jobName, "myPriority", prefabList, () =>
                    {
                        foreach (var j in generalManager.JobManager.Jobs)
                        {
                            var name = (string)jobNameField.GetValue(j.CloudJob);
                            if (name == jobName)
                            {
                                job = j;
                            }
                        }
                    });
                });

                while (job == null)
                {
                    if (!isMainThread)
                    {
                        Thread.Sleep(100);
                    }
                }
            }

            while (string.IsNullOrEmpty(job.AssetDirectory))
            {
                if (!isMainThread)
                {
                    Thread.Sleep(100);
                }
            }

            MonoBehaviourHelper.ExecuteOnMainThread(() =>
            {
                var customDataType            = assembly.GetType("Simplygon.Cloud.Yoda.IntegrationClient.CloudJob+CustomData");
                var pendingFolderNameProperty = customDataType.GetProperty("UnityPendingLODFolderName");
                var jobCustomDataProperty     = cloudJobType.GetProperty("JobCustomData");
                var jobCustomData             = jobCustomDataProperty.GetValue(job.CloudJob, null);
                var jobFolderName             = pendingFolderNameProperty.GetValue(jobCustomData, null) as string;

                var lodAssetDir = "Assets/LODs/" + job.AssetDirectory;
                var mesh        = AssetDatabase.LoadAssetAtPath <Mesh>(string.Format("{0}/{1}_LOD1.prefab", lodAssetDir, jobName));
                mesh.ApplyToWorkingMesh(outputMesh);

                //job.CloudJob.StateHandler.RequestJobDeletion();
                AssetDatabaseEx.DeletePendingLODFolder(jobFolderName);
                AssetDatabase.DeleteAsset(lodAssetDir);

                UnityObject.DestroyImmediate(renderer.gameObject);
            });
        }
        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;
        }
예제 #16
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);
        }
        static void GenerateMeshLOD(MeshLOD meshLOD, HashSet <int> preprocessMeshes)
        {
            // A NOP to make sure we have an instance before launching into threads that may need to execute on the main thread
            MonoBehaviourHelper.ExecuteOnMainThread(() => { });

            WorkingMesh inputMesh   = null;
            var         inputMeshID = meshLOD.inputMesh.GetInstanceID();

            if (!preprocessMeshes.Contains(inputMeshID))
            {
                inputMesh = meshLOD.inputMesh.ToWorkingMesh();
            }

            var meshSimplifier = (IMeshSimplifier)Activator.CreateInstance(meshSimplifierType);

#if !SINGLE_THREADED
            var worker = new BackgroundWorker();
            worker.DoWork += (sender, args) =>
            {
                // If this mesh is dependent on another mesh, then let it complete first
                if (inputMesh == null)
                {
                    while (preprocessMeshes.Contains(inputMeshID))
                    {
                        Thread.Sleep(100);
                    }

                    MonoBehaviourHelper.ExecuteOnMainThread(() => inputMesh = meshLOD.inputMesh.ToWorkingMesh());
                }
#endif

            var outputMesh = new WorkingMesh();
#if UNITY_2017_3_OR_NEWER
            outputMesh.indexFormat = inputMesh.indexFormat;
#endif
            meshSimplifier.Simplify(inputMesh, outputMesh, meshLOD.quality);
#if !SINGLE_THREADED
            args.Result = outputMesh;
        };
#endif

#if !SINGLE_THREADED
            worker.RunWorkerCompleted += (sender, args) =>
#endif
            {
                var outMesh = meshLOD.outputMesh;
                Debug.Log("Completed LOD " + outMesh.name);
#if !SINGLE_THREADED
                var resultMesh = (WorkingMesh)args.Result;
#else
                var resultMesh = outputMesh;
#endif
                resultMesh.name = outMesh.name;
                resultMesh.ApplyToMesh(outMesh);
                outMesh.RecalculateBounds();

                var outputMeshID = outMesh.GetInstanceID();
                if (preprocessMeshes.Remove(outputMeshID))
                {
                    Debug.Log("Pre-process mesh complete: " + outputMeshID);
                }
            };

#if !SINGLE_THREADED
            worker.RunWorkerAsync();
#endif
        }
예제 #18
0
        public void Simplify(WorkingMesh inputMesh, WorkingMesh outputMesh, float quality)
        {
            Renderer renderer = null;

            MonoBehaviourHelper.ExecuteOnMainThread(() =>
            {
                var go   = EditorUtility.CreateGameObjectWithHideFlags("Temp", HideFlags.HideAndDontSave, typeof(MeshRenderer), typeof(MeshFilter));
                var mf   = go.GetComponent <MeshFilter>();
                var mesh = new Mesh();
                inputMesh.ApplyToMesh(mesh);
                mf.sharedMesh       = mesh;
                renderer            = go.GetComponent <MeshRenderer>();
                var material        = new Material(Shader.Find("Standard"));
                var sharedMaterials = new Material[mesh.subMeshCount];
                for (int i = 0; i < mesh.subMeshCount; i++)
                {
                    sharedMaterials[i] = material;
                }
                renderer.sharedMaterials = sharedMaterials;
                renderer.enabled         = false;
            });

            var settings = new InstaLODOptimizeSettings(quality);

            settings.PercentTriangles = quality;
            var nativeMeshSettings = new InstaLODNativeMeshOperationSettings(true);

            nativeMeshSettings.hideSourceGameObjects = false;

            lock (executionLock)
            {
                if (!MonoBehaviourHelper.IsMainThread())
                {
                    while (InstaLODNative.currentMeshOperationState != null)
                    {
                        Thread.Sleep(100);
                    }
                }

                MonoBehaviourHelper.ExecuteOnMainThread(() =>
                {
                    EditorWindow.GetWindow <InstaLODToolkitWindow>(); // Necessary for background processing
                    InstaLODNative.Optimize(new List <Renderer>()
                    {
                        renderer
                    }, settings, nativeMeshSettings);
                    Selection.activeGameObject = null; // Necessary to avoid errors from InstaLOD trying to add settings component to imported model
                });
            }

            while (InstaLODNative.currentMeshOperationState != null)
            {
                if (MonoBehaviourHelper.IsMainThread())
                {
                    InstaLODMainThreadAction.RunMainThreadActions();
                }
                else
                {
                    Thread.Sleep(100);
                }
            }

            MonoBehaviourHelper.ExecuteOnMainThread(() =>
            {
                var mf = renderer.GetComponent <MeshFilter>();
                mf.sharedMesh.ApplyToWorkingMesh(outputMesh);
                UnityObject.DestroyImmediate(mf.gameObject);
            });
        }