Example #1
0
        private DisposableList <HLODBuildInfo> CreateBuildInfo(TerrainData data, SpaceNode root)
        {
            DisposableList <HLODBuildInfo> results = new DisposableList <HLODBuildInfo>();
            Queue <SpaceNode> trevelQueue          = new Queue <SpaceNode>();
            Queue <int>       parentQueue          = new Queue <int>();
            Queue <string>    nameQueue            = new Queue <string>();
            Queue <int>       depthQueue           = new Queue <int>();

            int maxDepth = 0;

            trevelQueue.Enqueue(root);
            parentQueue.Enqueue(-1);
            nameQueue.Enqueue("HLOD");
            depthQueue.Enqueue(0);


            while (trevelQueue.Count > 0)
            {
                int           currentNodeIndex = results.Count;
                string        name             = nameQueue.Dequeue();
                SpaceNode     node             = trevelQueue.Dequeue();
                int           depth            = depthQueue.Dequeue();
                HLODBuildInfo info             = new HLODBuildInfo
                {
                    Name        = name,
                    ParentIndex = parentQueue.Dequeue(),
                    Target      = node,
                };

                for (int i = 0; i < node.GetChildCount(); ++i)
                {
                    trevelQueue.Enqueue(node.GetChild(i));
                    parentQueue.Enqueue(currentNodeIndex);
                    nameQueue.Enqueue(name + "_" + (i + 1));
                    depthQueue.Enqueue(depth + 1);
                }

                info.Heightmap = CreateSubHightmap(node.Bounds);
                info.WorkingObjects.Add(CreateBakedTerrain(name, node.Bounds, info.Heightmap, depth, node.GetChildCount() == 0));
                info.Distances.Add(depth);
                results.Add(info);

                if (depth > maxDepth)
                {
                    maxDepth = depth;
                }
            }

            //convert depth to distance
            for (int i = 0; i < results.Count; ++i)
            {
                HLODBuildInfo info = results[i];
                for (int di = 0; di < info.Distances.Count; ++di)
                {
                    info.Distances[di] = maxDepth - info.Distances[di];
                }
            }

            return(results);
        }
Example #2
0
        private void Combine(HLODBuildInfo info, dynamic options)
        {
            var renderers   = info.renderers;
            var atlas       = m_Packer.GetAtlas(info);
            var atlasLookup = new Dictionary <Texture2D, Rect>();

            for (int i = 0; i < atlas.MultipleTextures.Length; ++i)
            {
                atlasLookup[atlas.MultipleTextures[i].textureList[0]] = atlas.UVs[i];
            }

            List <TextureInfo> textureInfoList = options.TextureInfoList;
            var combineInstances = new List <CombineInstance>();
            var combinedMesh     = new Mesh();

            for (int i = 0; i < info.renderers.Count; ++i)
            {
                var mf = info.renderers[i].GetComponent <MeshFilter>();
                if (mf == null)
                {
                    continue;
                }

                var mesh = ConvertMesh(mf, info.simplifiedMeshes[i], atlasLookup, textureInfoList[0]);

                for (int j = 0; j < mesh.subMeshCount; ++j)
                {
                    var ci = new CombineInstance();
                    ci.mesh         = mesh;
                    ci.subMeshIndex = j;

                    Matrix4x4 mat      = mf.transform.localToWorldMatrix;
                    Vector3   position = m_hlod.transform.position;
                    mat.m03     -= position.x;
                    mat.m13     -= position.y;
                    mat.m23     -= position.z;
                    ci.transform = mat;
                    combineInstances.Add(ci);
                }
            }

            combinedMesh.indexFormat = IndexFormat.UInt32;
            combinedMesh.CombineMeshes(combineInstances.ToArray());
            combinedMesh.RecalculateBounds();

            var go           = new GameObject(info.name);
            var meshRenderer = go.AddComponent <MeshRenderer>();
            var meshFilter   = go.AddComponent <MeshFilter>();

            go.transform.SetParent(m_hlod.transform);
            meshFilter.sharedMesh = combinedMesh;
            meshRenderer.material = GetMaterial(options, atlas.PackedTexture);

            info.combinedGameObjects.Add(go);
        }
Example #3
0
        private static List <HLODBuildInfo> CreateBuildInfo(SpaceNode root, float thresholdSize)
        {
            List <HLODBuildInfo> results     = new List <HLODBuildInfo>();
            Queue <SpaceNode>    trevelQueue = new Queue <SpaceNode>();
            Queue <int>          parentQueue = new Queue <int>();
            Queue <string>       nameQueue   = new Queue <string>();

            trevelQueue.Enqueue(root);
            parentQueue.Enqueue(-1);
            nameQueue.Enqueue("");


            while (trevelQueue.Count > 0)
            {
                int           currentNodeIndex = results.Count;
                string        name             = nameQueue.Dequeue();
                SpaceNode     node             = trevelQueue.Dequeue();
                HLODBuildInfo info             = new HLODBuildInfo
                {
                    name        = name,
                    parentIndex = parentQueue.Dequeue(),
                    target      = node
                };

                if (node.ChildTreeNodes != null)
                {
                    for (int i = 0; i < node.ChildTreeNodes.Count; ++i)
                    {
                        trevelQueue.Enqueue(node.ChildTreeNodes[i]);
                        parentQueue.Enqueue(currentNodeIndex);
                        nameQueue.Enqueue(name + "_" + (i + 1));
                    }
                }

                results.Add(info);

                //it should add to every parent.
                List <MeshRenderer> meshRenderers = GetMeshRenderers(node.Objects, thresholdSize);
                int distance = 0;

                while (currentNodeIndex >= 0)
                {
                    var curInfo = results[currentNodeIndex];

                    curInfo.renderers.AddRange(meshRenderers);
                    curInfo.distances.AddRange(Enumerable.Repeat(distance, meshRenderers.Count));

                    currentNodeIndex = curInfo.parentIndex;
                    distance        += 1;
                }
            }

            return(results);
        }
Example #4
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);
                }
            }
        }
        private void Combine(HLODBuildInfo info)
        {
            var instancesTable = new Dictionary <Material, List <CombineInstance> >();

            for (int i = 0; i < info.renderers.Count; ++i)
            {
                if (info.renderers[i] == null)
                {
                    continue;
                }

                var materials = info.renderers[i].sharedMaterials;

                for (int m = 0; m < materials.Length; ++m)
                {
                    if (instancesTable.ContainsKey(materials[m]) == false)
                    {
                        instancesTable.Add(materials[m], new List <CombineInstance>());
                    }
                    var       instance = new CombineInstance();
                    Matrix4x4 mat      = info.renderers[i].localToWorldMatrix;
                    Vector3   position = m_hlod.transform.position;
                    mat.m03              -= position.x;
                    mat.m13              -= position.y;
                    mat.m23              -= position.z;
                    instance.transform    = mat;
                    instance.mesh         = info.simplifiedMeshes[i];
                    instance.subMeshIndex = m;

                    instancesTable[materials[m]].Add(instance);
                }
            }

            foreach (var instances in instancesTable)
            {
                var mesh = new Mesh();
                mesh.indexFormat = IndexFormat.UInt32;
                mesh.CombineMeshes(instances.Value.ToArray(), true, true, false);
                mesh.name = instances.Key.name;

                var go = new GameObject(info.name + instances.Key.name, typeof(MeshRenderer), typeof(MeshFilter));
                go.GetComponent <MeshFilter>().sharedMesh       = mesh;
                go.GetComponent <MeshRenderer>().sharedMaterial = instances.Key;

                go.transform.SetParent(m_hlod.transform);

                info.combinedGameObjects.Add(go);
            }
        }
Example #6
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);
        }
Example #7
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();
            }
        }
Example #8
0
        private static DisposableList <HLODBuildInfo> CreateBuildInfo(SpaceNode root, float minObjectSize)
        {
            List <HLODBuildInfo> resultsCandidates = new List <HLODBuildInfo>();
            Queue <SpaceNode>    trevelQueue       = new Queue <SpaceNode>();
            Queue <int>          parentQueue       = new Queue <int>();
            Queue <string>       nameQueue         = new Queue <string>();
            Queue <int>          levelQueue        = new Queue <int>();

            trevelQueue.Enqueue(root);
            parentQueue.Enqueue(-1);
            levelQueue.Enqueue(0);
            nameQueue.Enqueue("");


            while (trevelQueue.Count > 0)
            {
                int           currentNodeIndex = resultsCandidates.Count;
                string        name             = nameQueue.Dequeue();
                SpaceNode     node             = trevelQueue.Dequeue();
                HLODBuildInfo info             = new HLODBuildInfo
                {
                    Name        = name,
                    ParentIndex = parentQueue.Dequeue(),
                    Target      = node
                };


                for (int i = 0; i < node.GetChildCount(); ++i)
                {
                    trevelQueue.Enqueue(node.GetChild(i));
                    parentQueue.Enqueue(currentNodeIndex);
                    nameQueue.Enqueue(name + "_" + (i + 1));
                }


                resultsCandidates.Add(info);

                //it should add to every parent.
                List <MeshRenderer> meshRenderers = GetMeshRenderers(node.Objects, minObjectSize);
                List <Collider>     colliders     = GetColliders(node.Objects, minObjectSize);
                int distance = 0;

                while (currentNodeIndex >= 0)
                {
                    var curInfo = resultsCandidates[currentNodeIndex];

                    for (int i = 0; i < meshRenderers.Count; ++i)
                    {
                        curInfo.WorkingObjects.Add(meshRenderers[i].ToWorkingObject(Allocator.Persistent));
                        curInfo.Distances.Add(distance);
                    }

                    for (int i = 0; i < colliders.Count; ++i)
                    {
                        curInfo.Colliders.Add(colliders[i].ToWorkingCollider());
                    }



                    currentNodeIndex = curInfo.ParentIndex;
                    distance        += 1;
                }
            }


            DisposableList <HLODBuildInfo> results = new DisposableList <HLODBuildInfo>();

            for (int i = 0; i < resultsCandidates.Count; ++i)
            {
                if (resultsCandidates[i].WorkingObjects.Count > 0)
                {
                    results.Add(resultsCandidates[i]);
                }
                else
                {
                    resultsCandidates[i].Dispose();
                }
            }

            return(results);
        }