Exemple #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);
        }
Exemple #2
0
        private DisposableList <HLODBuildInfo> CreateBuildInfo()
        {
            List <GameObject> hlodTargets = ObjectUtils.HLODTargets(m_hlodComponent.gameObject);
            ISpaceSplitter    spliter     = new QuadTreeSpaceSplitter(0.0f);
            SpaceNode         rootNode    = spliter.CreateSpaceTree(m_hlodComponent.GetBounds(), 10.0f, m_hlodComponent.transform.position, hlodTargets, null);

            return((DisposableList <HLODBuildInfo>)m_buildInfoFunc.Invoke(null, new object[] { rootNode, 0.0f }));
        }
Exemple #3
0
        public void SpaceSplitTestSize10()
        {
            List <GameObject> hlodTargets = ObjectUtils.HLODTargets(m_hlodComponent.gameObject);

            ISpaceSplitter spliter  = new QuadTreeSpaceSplitter(0.0f);
            SpaceNode      rootNode = spliter.CreateSpaceTree(m_hlodComponent.GetBounds(), 10.0f, m_hlodComponent.transform.position, hlodTargets, null);

            Assert.AreEqual(CalcLevel(rootNode), 3);
            Assert.AreEqual(GetTargetCount(rootNode), 9);
        }
        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);
        }
        private DisposableList <HLODBuildInfo> CreateBuildInfo(HLOD hlod)
        {
            MethodInfo buildInfoFunc = typeof(HLODCreator).GetMethod("CreateBuildInfo", BindingFlags.Static | BindingFlags.NonPublic);

            List <GameObject> hlodTargets = ObjectUtils.HLODTargets(hlod.gameObject);

            ISpaceSplitter spliter  = new QuadTreeSpaceSplitter(0.0f);
            SpaceNode      rootNode = spliter.CreateSpaceTree(hlod.GetBounds(), 5.0f, hlod.transform.position, hlodTargets, null);

            return((DisposableList <HLODBuildInfo>)buildInfoFunc.Invoke(null, new object[] { rootNode, 0.0f }));
        }
Exemple #6
0
        public void Build(SpaceNode rootNode, List <HLODBuildInfo> infos, Action <float> onProgress)
        {
            string      path  = "";
            PrefabStage stage = PrefabStageUtility.GetPrefabStage(m_hlod.gameObject);

            path = stage.prefabAssetPath;
            path = Path.GetDirectoryName(path) + "/";

            var          defaultController = m_hlod.gameObject.AddComponent <DefaultController>();
            HLODTreeNode convertedRootNode = ConvertNode(rootNode);

            if (onProgress != null)
            {
                onProgress(0.0f);
            }

            //I think it is better to do when convert nodes.
            //But that is not easy because of the structure.
            for (int i = 0; i < infos.Count; ++i)
            {
                var spaceNode    = infos[i].target;
                var hlodTreeNode = convertedTable[infos[i].target];

                for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                {
                    int highId = defaultController.AddHighObject(spaceNode.Objects[oi]);
                    hlodTreeNode.HighObjectIds.Add(highId);
                }

                for (int oi = 0; oi < infos[i].combinedGameObjects.Count; ++oi)
                {
                    List <HLODMesh> createdMeshes = ObjectUtils.SaveHLODMesh(path, m_hlod.name, infos[i].combinedGameObjects[oi]);
                    m_hlod.GeneratedObjects.AddRange(createdMeshes);

                    foreach (var mesh in createdMeshes)
                    {
                        int lowId = defaultController.AddLowObject(mesh);
                        hlodTreeNode.LowObjectIds.Add(lowId);
                    }
                }

                if (onProgress != null)
                {
                    onProgress((float)i / (float)infos.Count);
                }
            }

            m_hlod.Root = convertedRootNode;
        }
        private HLODTreeNode ConvertNode(HLODTreeNodeContainer container, SpaceNode rootNode)
        {
            HLODTreeNode root = new HLODTreeNode();

            root.SetContainer(container);

            Queue <HLODTreeNode> hlodTreeNodes = new Queue <HLODTreeNode>();
            Queue <SpaceNode>    spaceNodes    = new Queue <SpaceNode>();
            Queue <int>          levels        = new Queue <int>();

            hlodTreeNodes.Enqueue(root);
            spaceNodes.Enqueue(rootNode);
            levels.Enqueue(0);

            while (hlodTreeNodes.Count > 0)
            {
                var hlodTreeNode = hlodTreeNodes.Dequeue();
                var spaceNode    = spaceNodes.Dequeue();
                int level        = levels.Dequeue();

                convertedTable[spaceNode] = hlodTreeNode;

                hlodTreeNode.Level  = level;
                hlodTreeNode.Bounds = spaceNode.Bounds;
                if (spaceNode.HasChild() == true)
                {
                    List <HLODTreeNode> childTreeNodes = new List <HLODTreeNode>(spaceNode.GetChildCount());
                    for (int i = 0; i < spaceNode.GetChildCount(); ++i)
                    {
                        var treeNode = new HLODTreeNode();
                        treeNode.SetContainer(container);
                        childTreeNodes.Add(treeNode);

                        hlodTreeNodes.Enqueue(treeNode);
                        spaceNodes.Enqueue(spaceNode.GetChild(i));
                        levels.Enqueue(level + 1);
                    }

                    hlodTreeNode.SetChildTreeNode(childTreeNodes);
                }
            }

            return(root);
        }
    public SimpleBuilder AddSpacedRange(float space, IEnumerable <ISimpleNode> nodes)
    {
        AssertState();
        SpaceNode?n = null;

        foreach (ISimpleNode node in nodes)
        {
            if (n == null)
            {
                n = new SpaceNode(Layout, false, space);
            }
            else
            {
                Nodes.Add(n);
            }
            Nodes.Add(node);
        }
        return(this);
    }
Exemple #9
0
        private static int GetTargetCount(SpaceNode node)
        {
            int count = 0;
            Stack <SpaceNode> searchNodes = new Stack <SpaceNode>();

            searchNodes.Push(node);

            while (searchNodes.Count > 0)
            {
                SpaceNode curNode = searchNodes.Pop();
                count += curNode.Objects.Count;

                for (int i = 0; i < curNode.GetChildCount(); ++i)
                {
                    searchNodes.Push(curNode.GetChild(i));
                }
            }

            return(count);
        }
Exemple #10
0
        private static int CalcLevel(SpaceNode node)
        {
            SpaceNode curNode = node;
            int       level   = 0;

            while (curNode != null)
            {
                level += 1;
                if (curNode.HasChild() == true)
                {
                    curNode = curNode.GetChild(0);
                }
                else
                {
                    curNode = null;
                }
            }

            return(level);
        }
Exemple #11
0
        private HLODTreeNode ConvertNode(SpaceNode rootNode)
        {
            HLODTreeNode root = new HLODTreeNode();

            Queue <HLODTreeNode> hlodTreeNodes = new Queue <HLODTreeNode>();
            Queue <SpaceNode>    spaceNodes    = new Queue <SpaceNode>();

            hlodTreeNodes.Enqueue(root);
            spaceNodes.Enqueue(rootNode);

            while (hlodTreeNodes.Count > 0)
            {
                var hlodTreeNode = hlodTreeNodes.Dequeue();
                var spaceNode    = spaceNodes.Dequeue();

                convertedTable[spaceNode] = hlodTreeNode;

                hlodTreeNode.Bounds = spaceNode.Bounds;
                if (spaceNode.ChildTreeNodes != null)
                {
                    List <HLODTreeNode> childTreeNodes = new List <HLODTreeNode>(spaceNode.ChildTreeNodes.Count);
                    for (int i = 0; i < spaceNode.ChildTreeNodes.Count; ++i)
                    {
                        var treeNode = new HLODTreeNode();
                        childTreeNodes.Add(treeNode);

                        hlodTreeNodes.Enqueue(treeNode);
                        spaceNodes.Enqueue(spaceNode.ChildTreeNodes[i]);
                    }

                    hlodTreeNode.ChildNodes = childTreeNodes;
                }
            }

            return(root);
        }
Exemple #12
0
        public void Build(SpaceNode rootNode, DisposableList <HLODBuildInfo> infos, GameObject root,
                          float cullDistance, float lodDistance, bool writeNoPrefab, bool extractMaterial, Action <float> onProgress)
        {
            dynamic options = m_streamingOptions;
            string  path    = options.OutputDirectory;

            HLODTreeNodeContainer container         = new HLODTreeNodeContainer();
            HLODTreeNode          convertedRootNode = ConvertNode(container, rootNode);

            if (onProgress != null)
            {
                onProgress(0.0f);
            }

            HLODData.TextureCompressionData compressionData;
            compressionData.PCTextureFormat      = options.PCCompression;
            compressionData.WebGLTextureFormat   = options.WebGLCompression;
            compressionData.AndroidTextureFormat = options.AndroidCompression;
            compressionData.iOSTextureFormat     = options.iOSCompression;
            compressionData.tvOSTextureFormat    = options.tvOSCompression;

            string filename = $"{path}{root.name}.hlod";

            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }

            using (Stream stream = new FileStream(filename, FileMode.Create))
            {
                HLODData data = new HLODData();
                data.CompressionData = compressionData;

                for (int i = 0; i < infos.Count; ++i)
                {
                    data.AddFromWokringObjects(infos[i].Name, infos[i].WorkingObjects);
                    data.AddFromWorkingColliders(infos[i].Name, infos[i].Colliders);
                    if (onProgress != null)
                    {
                        onProgress((float)i / (float)infos.Count);
                    }
                }

                if (writeNoPrefab)
                {
                    for (int ii = 0; ii < infos.Count; ++ii)
                    {
                        var spaceNode = infos[ii].Target;

                        for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                        {
                            if (PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]) == false)
                            {
                                data.AddFromGameObject(spaceNode.Objects[oi]);
                            }
                        }
                    }
                }

                if (extractMaterial == true)
                {
                    ExtractMaterial(data, $"{path}{root.name}");
                }

                HLODDataSerializer.Write(stream, data);
            }

            AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
            RootData rootData = AssetDatabase.LoadAssetAtPath <RootData>(filename);

            m_manager.AddGeneratedResource(rootData);

            var        defaultController = root.AddComponent <DefaultHLODController>();
            GameObject hlodRoot          = new GameObject("HLODRoot");

            hlodRoot.transform.SetParent(root.transform, false);
            m_manager.AddGeneratedResource(hlodRoot);

            for (int ii = 0; ii < infos.Count; ++ii)
            {
                var spaceNode    = infos[ii].Target;
                var hlodTreeNode = convertedTable[infos[ii].Target];

                for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                {
                    GameObject obj            = spaceNode.Objects[oi];
                    GameObject rootGameObject = rootData.GetRootObject(obj.name);
                    if (rootGameObject != null)
                    {
                        GameObject go = PrefabUtility.InstantiatePrefab(rootGameObject) as GameObject;
                        go.transform.SetParent(obj.transform.parent);
                        go.transform.localPosition = obj.transform.localPosition;
                        go.transform.localRotation = obj.transform.localRotation;
                        go.transform.localScale    = obj.transform.localScale;

                        int highId = defaultController.AddHighObject(go);
                        hlodTreeNode.HighObjectIds.Add(highId);

                        if (m_manager.IsGeneratedResource(obj))
                        {
                            m_manager.AddGeneratedResource(go);
                        }
                        else
                        {
                            m_manager.AddConvertedPrefabResource(go);
                        }

                        Object.DestroyImmediate(obj);
                    }
                    else
                    {
                        int highId = defaultController.AddHighObject(obj);
                        hlodTreeNode.HighObjectIds.Add(highId);
                    }
                }


                if (infos[ii].WorkingObjects.Count > 0)
                {
                    GameObject prefab = rootData.GetRootObject(infos[ii].Name);
                    if (prefab == null)
                    {
                        Debug.LogError("Prefab not found: " + infos[ii].Name);
                    }
                    else
                    {
                        GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                        go.transform.SetParent(hlodRoot.transform, false);
                        go.SetActive(false);
                        int lowId = defaultController.AddLowObject(go);
                        hlodTreeNode.LowObjectIds.Add(lowId);
                        m_manager.AddGeneratedResource(go);
                    }
                }
            }

            defaultController.Container    = container;
            defaultController.Root         = convertedRootNode;
            defaultController.CullDistance = cullDistance;
            defaultController.LODDistance  = lodDistance;
        }
        public static IEnumerator Create(HLOD hlod)
        {
            try
            {
                Stopwatch sw = new Stopwatch();

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

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

                Bounds bounds = hlod.GetBounds();

                List <GameObject> hlodTargets = ObjectUtils.HLODTargets(hlod.gameObject);
                ISpaceSplitter    spliter     = new QuadTreeSpaceSplitter(hlod.transform.position, 5.0f, hlod.MinSize);
                SpaceNode         rootNode    = spliter.CreateSpaceTree(bounds, hlodTargets, progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Splitting space", progress * 0.25f);
                });

                List <HLODBuildInfo> buildInfos = CreateBuildInfo(rootNode, hlod.ThresholdSize);

                Debug.Log("[HLOD] Splite space: " + sw.Elapsed.ToString("g"));
                sw.Reset();
                sw.Start();

                ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(hlod.SimplifierType, new object[] { hlod });
                for (int i = 0; i < buildInfos.Count; ++i)
                {
                    yield return(new BranchCoroutine(simplifier.Simplify(buildInfos[i])));
                }

                yield return(new WaitForBranches(progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes", 0.25f + progress * 0.25f);
                }));

                Debug.Log("[HLOD] Simplify: " + sw.Elapsed.ToString("g"));
                sw.Reset();
                sw.Start();


                IBatcher batcher = (IBatcher)Activator.CreateInstance(hlod.BatcherType, new object[] { hlod });
                batcher.Batch(buildInfos, progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Generating combined static meshes.", 0.5f + progress * 0.25f);
                });
                Debug.Log("[HLOD] Batch: " + sw.Elapsed.ToString("g"));
                sw.Reset();
                sw.Start();

                try
                {
                    AssetDatabase.StartAssetEditing();
                    IStreamingBuilder builder =
                        (IStreamingBuilder)Activator.CreateInstance(hlod.StreamingType, new object[] { hlod });
                    builder.Build(rootNode, buildInfos, progress =>
                    {
                        EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.", 0.75f + progress * 0.25f);
                    });
                    Debug.Log("[HLOD] Build: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();
                    Debug.Log("[HLOD] Importing: " + sw.Elapsed.ToString("g"));
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
            //hlod.Root = rootNode;
        }
Exemple #14
0
        public static IEnumerator Create(HLOD hlod)
        {
            try
            {
                Stopwatch sw = new Stopwatch();

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

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

                hlod.ConvertedPrefabObjects.Clear();
                hlod.GeneratedObjects.Clear();

                Bounds bounds = hlod.GetBounds();

                List <GameObject> hlodTargets = ObjectUtils.HLODTargets(hlod.gameObject);
                ISpaceSplitter    spliter     = new QuadTreeSpaceSplitter(5.0f);
                SpaceNode         rootNode    = spliter.CreateSpaceTree(bounds, hlod.ChunkSize, hlod.transform.position, hlodTargets, progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Splitting space", progress * 0.25f);
                });

                if (hlodTargets.Count == 0)
                {
                    EditorUtility.DisplayDialog("Empty HLOD sources.",
                                                "There are no objects to be included in the HLOD.",
                                                "Ok");
                    yield break;
                }


                using (DisposableList <HLODBuildInfo> buildInfos = CreateBuildInfo(rootNode, hlod.MinObjectSize))
                {
                    if (buildInfos.Count == 0 || buildInfos[0].WorkingObjects.Count == 0)
                    {
                        EditorUtility.DisplayDialog("Empty HLOD sources.",
                                                    "There are no objects to be included in the HLOD.",
                                                    "Ok");
                        yield break;
                    }


                    Debug.Log("[HLOD] Splite space: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();

                    ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(hlod.SimplifierType,
                                                                                   new object[] { hlod.SimplifierOptions });
                    for (int i = 0; i < buildInfos.Count; ++i)
                    {
                        yield return(new BranchCoroutine(simplifier.Simplify(buildInfos[i])));
                    }

                    yield return(new WaitForBranches(progress =>
                    {
                        EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes",
                                                         0.25f + progress * 0.25f);
                    }));

                    Debug.Log("[HLOD] Simplify: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();


                    using (IBatcher batcher =
                               (IBatcher)Activator.CreateInstance(hlod.BatcherType, new object[] { hlod.BatcherOptions }))
                    {
                        batcher.Batch(hlod.transform.position, buildInfos,
                                      progress =>
                        {
                            EditorUtility.DisplayProgressBar("Bake HLOD", "Generating combined static meshes.",
                                                             0.5f + progress * 0.25f);
                        });
                    }
                    Debug.Log("[HLOD] Batch: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();


                    IStreamingBuilder builder =
                        (IStreamingBuilder)Activator.CreateInstance(hlod.StreamingType,
                                                                    new object[] { hlod, hlod.StreamingOptions });
                    builder.Build(rootNode, buildInfos, hlod.gameObject, hlod.CullDistance, hlod.LODDistance, false, true,
                                  progress =>
                    {
                        EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.",
                                                         0.75f + progress * 0.25f);
                    });
                    Debug.Log("[HLOD] Build: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();

                    EditorUtility.SetDirty(hlod.gameObject);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }
        public void Build(SpaceNode rootNode, DisposableList <HLODBuildInfo> infos, GameObject root,
                          float cullDistance, float lodDistance, bool writeNoPrefab, bool extractMaterial, Action <float> onProgress)
        {
            dynamic options = m_streamingOptions;
            string  path    = options.OutputDirectory;

            HLODTreeNodeContainer container         = new HLODTreeNodeContainer();
            HLODTreeNode          convertedRootNode = ConvertNode(container, rootNode);

            //create settings if there is no settings.
            if (AddressableAssetSettingsDefaultObject.Settings == null)
            {
                AddressableAssetSettings.Create(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder, AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName, true, true);
            }


            var settings = AddressableAssetSettingsDefaultObject.GetSettings(true);
            var group    = GetGroup(settings, options.AddressablesGroupName);

            m_shaderGuids.Clear();

            if (onProgress != null)
            {
                onProgress(0.0f);
            }

            HLODData.TextureCompressionData compressionData;
            compressionData.PCTextureFormat      = options.PCCompression;
            compressionData.WebGLTextureFormat   = options.WebGLCompression;
            compressionData.AndroidTextureFormat = options.AndroidCompression;
            compressionData.iOSTextureFormat     = options.iOSCompression;
            compressionData.tvOSTextureFormat    = options.tvOSCompression;


            string filenamePrefix = $"{path}{root.name}";

            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }

            Dictionary <int, HLODData> hlodDatas = new Dictionary <int, HLODData>();

            for (int i = 0; i < infos.Count; ++i)
            {
                if (hlodDatas.ContainsKey(infos[i].ParentIndex) == false)
                {
                    HLODData newData = new HLODData();
                    newData.CompressionData = compressionData;
                    hlodDatas.Add(infos[i].ParentIndex, newData);
                }

                HLODData data = hlodDatas[infos[i].ParentIndex];
                data.AddFromWokringObjects(infos[i].Name, infos[i].WorkingObjects);
                data.AddFromWorkingColliders(infos[i].Name, infos[i].Colliders);

                if (writeNoPrefab)
                {
                    if (hlodDatas.ContainsKey(i) == false)
                    {
                        HLODData newData = new HLODData();
                        newData.CompressionData = compressionData;
                        hlodDatas.Add(i, newData);
                    }

                    HLODData prefabData = hlodDatas[i];
                    var      spaceNode  = infos[i].Target;

                    for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                    {
                        if (PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]) == false)
                        {
                            prefabData.AddFromGameObject(spaceNode.Objects[oi]);
                        }
                    }
                }


                if (onProgress != null)
                {
                    onProgress((float)i / (float)infos.Count);
                }
            }


            if (extractMaterial)
            {
                ExtractMaterial(hlodDatas, filenamePrefix);
            }

            Dictionary <int, RootData> rootDatas = new Dictionary <int, RootData>();

            foreach (var item in hlodDatas)
            {
                string filename = $"{filenamePrefix}_group{item.Key}.hlod";
                using (Stream stream = new FileStream(filename, FileMode.Create))
                {
                    HLODDataSerializer.Write(stream, item.Value);
                    stream.Close();
                }

                AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
                RootData rootData = AssetDatabase.LoadAssetAtPath <RootData>(filename);
                m_manager.AddGeneratedResource(rootData);
                AddAddress(settings, group, rootData);

                rootDatas.Add(item.Key, rootData);
            }



            var addressableController = root.AddComponent <AddressableHLODController>();

            for (int i = 0; i < infos.Count; ++i)
            {
                var spaceNode    = infos[i].Target;
                var hlodTreeNode = convertedTable[infos[i].Target];

                for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                {
                    int        highId = -1;
                    GameObject obj    = spaceNode.Objects[oi];

                    if (PrefabUtility.IsPartOfAnyPrefab(obj) == false)
                    {
                        GameObject rootGameObject = null;

                        if (rootDatas.ContainsKey(i))
                        {
                            rootGameObject = rootDatas[i].GetRootObject(obj.name);
                        }

                        if (rootGameObject != null)
                        {
                            GameObject go = PrefabUtility.InstantiatePrefab(rootGameObject) as GameObject;
                            go.transform.SetParent(obj.transform.parent);
                            go.transform.localPosition = obj.transform.localPosition;
                            go.transform.localRotation = obj.transform.localRotation;
                            go.transform.localScale    = obj.transform.localScale;

                            if (m_manager.IsGeneratedResource(obj))
                            {
                                m_manager.AddGeneratedResource(go);
                            }
                            else
                            {
                                m_manager.AddConvertedPrefabResource(go);
                            }

                            spaceNode.Objects.Add(go);

                            Object.DestroyImmediate(obj);
                            continue;
                        }
                    }

                    var address = GetAddress(spaceNode.Objects[oi]);
                    if (string.IsNullOrEmpty(address) && PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]))
                    {
                        AddAddress(settings, group, spaceNode.Objects[oi]);
                        address = GetAddress(spaceNode.Objects[oi]);
                    }

                    if (address != null)
                    {
                        highId = addressableController.AddHighObject(address, spaceNode.Objects[oi]);
                    }
                    else
                    {
                        highId = addressableController.AddHighObject(spaceNode.Objects[oi]);
                    }

                    hlodTreeNode.HighObjectIds.Add(highId);
                }

                {
                    if (rootDatas[infos[i].ParentIndex].GetRootObject(infos[i].Name) != null)
                    {
                        string filename = $"{filenamePrefix}_group{infos[i].ParentIndex}.hlod";
                        int    lowId    = addressableController.AddLowObject(filename + "[" + infos[i].Name + "]");
                        hlodTreeNode.LowObjectIds.Add(lowId);
                    }
                }
            }

            var shaderEntriesAdded = new List <AddressableAssetEntry>();

            foreach (var shaderGuid in m_shaderGuids)
            {
                if (IsExistsInAddressables(shaderGuid) == false)
                {
                    shaderEntriesAdded.Add(settings.CreateOrMoveEntry(shaderGuid, group, false, false));
                }
            }
            settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, shaderEntriesAdded, true);
            m_shaderGuids.Clear();

            addressableController.Container    = container;
            addressableController.Root         = convertedRootNode;
            addressableController.CullDistance = cullDistance;
            addressableController.LODDistance  = lodDistance;
        }
Exemple #16
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);
        }
Exemple #17
0
        public void CreateBuildInfoTest()
        {
            List <GameObject> hlodTargets = ObjectUtils.HLODTargets(m_hlodComponent.gameObject);

            ISpaceSplitter spliter  = new QuadTreeSpaceSplitter(0.0f);
            SpaceNode      rootNode = spliter.CreateSpaceTree(m_hlodComponent.GetBounds(), 5.0f, m_hlodComponent.transform.position, hlodTargets, null);

            using (DisposableList <HLODBuildInfo> ret = (DisposableList <HLODBuildInfo>)m_buildInfoFunc.Invoke(null, new object[] { rootNode, 0.0f }))
            {
                //only exists nodes are creating info.
                Assert.AreEqual(ret.Count, 11);

                Assert.AreEqual(ret[0].Name, "");
                Assert.AreEqual(ret[0].ParentIndex, -1);
                Assert.AreEqual(ret[0].WorkingObjects.Count, 9);

                Assert.AreEqual(ret[1].Name, "_1");
                Assert.AreEqual(ret[1].ParentIndex, 0);
                Assert.AreEqual(ret[1].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[2].Name, "_2");
                Assert.AreEqual(ret[2].ParentIndex, 0);
                Assert.AreEqual(ret[2].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[3].Name, "_3");
                Assert.AreEqual(ret[3].ParentIndex, 0);
                Assert.AreEqual(ret[3].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[4].Name, "_4");
                Assert.AreEqual(ret[4].ParentIndex, 0);
                Assert.AreEqual(ret[4].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[5].Name, "_1_1");
                Assert.AreEqual(ret[5].ParentIndex, 1);
                Assert.AreEqual(ret[5].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[6].Name, "_1_4");
                Assert.AreEqual(ret[6].ParentIndex, 1);
                Assert.AreEqual(ret[6].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[7].Name, "_2_2");
                Assert.AreEqual(ret[7].ParentIndex, 2);
                Assert.AreEqual(ret[7].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[8].Name, "_2_3");
                Assert.AreEqual(ret[8].ParentIndex, 2);
                Assert.AreEqual(ret[8].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[9].Name, "_3_3");
                Assert.AreEqual(ret[9].ParentIndex, 3);
                Assert.AreEqual(ret[9].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[10].Name, "_4_4");
                Assert.AreEqual(ret[10].ParentIndex, 4);
                Assert.AreEqual(ret[10].WorkingObjects.Count, 1);
            }

            //exclude object smaller than 0.5.
            using (DisposableList <HLODBuildInfo> ret = (DisposableList <HLODBuildInfo>)m_buildInfoFunc.Invoke(null, new object[] { rootNode, 0.5f }))
            {
                //only exists nodes are creating info.
                Assert.AreEqual(ret.Count, 10);

                Assert.AreEqual(ret[0].Name, "");
                Assert.AreEqual(ret[0].ParentIndex, -1);
                Assert.AreEqual(ret[0].WorkingObjects.Count, 8);

                Assert.AreEqual(ret[1].Name, "_1");
                Assert.AreEqual(ret[1].ParentIndex, 0);
                Assert.AreEqual(ret[1].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[2].Name, "_2");
                Assert.AreEqual(ret[2].ParentIndex, 0);
                Assert.AreEqual(ret[2].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[3].Name, "_3");
                Assert.AreEqual(ret[3].ParentIndex, 0);
                Assert.AreEqual(ret[3].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[4].Name, "_4");
                Assert.AreEqual(ret[4].ParentIndex, 0);
                Assert.AreEqual(ret[4].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[5].Name, "_1_1");
                Assert.AreEqual(ret[5].ParentIndex, 1);
                Assert.AreEqual(ret[5].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[6].Name, "_2_2");
                Assert.AreEqual(ret[6].ParentIndex, 2);
                Assert.AreEqual(ret[6].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[7].Name, "_2_3");
                Assert.AreEqual(ret[7].ParentIndex, 2);
                Assert.AreEqual(ret[7].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[8].Name, "_3_3");
                Assert.AreEqual(ret[8].ParentIndex, 3);
                Assert.AreEqual(ret[8].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[9].Name, "_4_4");
                Assert.AreEqual(ret[9].ParentIndex, 4);
                Assert.AreEqual(ret[9].WorkingObjects.Count, 1);
            }

            //exclude object smaller than 1.
            using (DisposableList <HLODBuildInfo> ret = (DisposableList <HLODBuildInfo>)m_buildInfoFunc.Invoke(null, new object[] { rootNode, 1.0f }))
            {
                //only exists nodes are creating info.
                Assert.AreEqual(ret.Count, 9);

                Assert.AreEqual(ret[0].Name, "");
                Assert.AreEqual(ret[0].ParentIndex, -1);
                Assert.AreEqual(ret[0].WorkingObjects.Count, 7);

                Assert.AreEqual(ret[1].Name, "_1");
                Assert.AreEqual(ret[1].ParentIndex, 0);
                Assert.AreEqual(ret[1].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[2].Name, "_2");
                Assert.AreEqual(ret[2].ParentIndex, 0);
                Assert.AreEqual(ret[2].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[3].Name, "_3");
                Assert.AreEqual(ret[3].ParentIndex, 0);
                Assert.AreEqual(ret[3].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[4].Name, "_4");
                Assert.AreEqual(ret[4].ParentIndex, 0);
                Assert.AreEqual(ret[4].WorkingObjects.Count, 2);

                Assert.AreEqual(ret[5].Name, "_1_1");
                Assert.AreEqual(ret[5].ParentIndex, 1);
                Assert.AreEqual(ret[5].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[6].Name, "_2_2");
                Assert.AreEqual(ret[6].ParentIndex, 2);
                Assert.AreEqual(ret[6].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[7].Name, "_3_3");
                Assert.AreEqual(ret[7].ParentIndex, 3);
                Assert.AreEqual(ret[7].WorkingObjects.Count, 1);

                Assert.AreEqual(ret[8].Name, "_4_4");
                Assert.AreEqual(ret[8].ParentIndex, 4);
                Assert.AreEqual(ret[8].WorkingObjects.Count, 1);
            }
        }
Exemple #18
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();
            }
        }