Exemple #1
0
        static void HLODApply(bool stream, LODVolume node)
        {
            s_LODVolume.Clear();
            s_LODVolume.Enqueue(node);
            while (s_LODVolume.Count > 0)
            {
                LODVolume lodVolume = s_LODVolume.Dequeue();

                foreach (var child in lodVolume.childVolumes)
                {
                    if (child.combined == null && child.childVolumes.Count < 1)
                    {
                        continue;
                    }
                    s_LODVolume.Enqueue(child);
                }
                if (lodVolume.combined != null)
                {
                    if (stream)
                    {
                        if (!lodVolume.combined.CheckState())
                        {
                            ChoiceQueue(lodVolume, lodVolume.combined);
                        }
                        continue;
                    }
                    lodVolume.combined.ApplyEnable();
                }
            }
        }
Exemple #2
0
 static void SetHLODEnable(LODVolume node, bool bEnable)
 {
     if (node.combined != null)
     {
         SetLOGGroupEnable(node.combined, bEnable);
     }
 }
Exemple #3
0
        public static LODVolume Create(HLODGenerate hlodGenerate)
        {
            int        volumeCount = hlodGenerate.m_LODVolumeCount++;
            GameObject go          = new GameObject(k_DefaultName + volumeCount, typeof(LODVolume));
            LODVolume  volume      = go.GetComponent <LODVolume>();

            volume.m_CurrHLODGenerate = hlodGenerate ? hlodGenerate : volume.m_CurrHLODGenerate;
            return(volume);
        }
Exemple #4
0
 static void SetLODEnable(LODVolume node, bool bEnable)
 {
     if (node.combined == null)
     {
         // 由于有一种情况是单个模型时,不会合并
         // 所以这里如果没有合并的模型,就看看有没有单独的模型需要设置
         foreach (var lodGroup in node.lodGroups)
         {
             SetLOGGroupEnable(lodGroup, bEnable);
         }
     }
 }
 //检查是否为所在树的贴图集
 bool CheckInCurrLittleOctree(LODVolume lodVolume, TextureAtlasData rootData)
 {
     LODVolume[] parents = lodVolume.GetComponentsInParent <LODVolume>();
     foreach (LODVolume p in parents)
     {
         if (p.gameObject == rootData.m_Root)//找到我是该大贴图的孩子
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #6
0
 //选择卸载或加载队列
 static void ChoiceQueue(LODVolume node, UnityLODGroupFast fast)
 {
     if (node.childTreeRoot == null)
     {
         node.childTreeRoot = node.gameObject.AddComponent <ChildTreeRoot>();
     }
     if (fast.EnabledVirtual)
     {
         node.childTreeRoot.AddLoadAsset(fast);
     }
     else
     {
         node.childTreeRoot.AddUnLoadAsset(fast);
     }
 }
Exemple #7
0
        /*生成SceneLOD接口,指定hlodGenerate*/
        public void GenerateSceneLODByHLODGenerate(HLODGenerate hlodGenerate, Action <GameObject, GameObject> endCall = null)
        {
            m_CurrHLODGenerate = hlodGenerate;
#if UNITY_EDITOR
            if (hlodGenerate.m_RootLODVolume)
            {
                m_RootVolume = hlodGenerate.m_RootLODVolume.GetComponent <LODVolume>();
            }
            else
            {
                m_RootVolume = null;
            }
            m_CreateRootVolumeForScene = SceneManager.GetActiveScene().name;
            MonoBehaviourHelper.StartCoroutine(GenerateHLOD(hlodGenerate.m_Targets, endCall));
#endif
        }
Exemple #8
0
        IEnumerator SetRootLODVolume()
        {
            if (m_RootVolume)
            {
                var rootVolumeTransform = m_RootVolume.transform;
                var transformRoot       = rootVolumeTransform.root;

                if (transformRoot.GetComponent <HLODGenerate>())//已经是根节点
                {
                    yield break;
                }

                // Handle the case where the BVH has grown
                if (rootVolumeTransform != transformRoot)
                {
                    m_RootVolume = transformRoot.GetComponent <LODVolume>();
                }

                yield break;
            }

            // Handle initialization or the case where the BVH has shrunk
            LODVolume lodVolume       = null;
            var       scene           = SceneManager.GetActiveScene();
            var       rootGameObjects = scene.GetRootGameObjects();

            foreach (var go in rootGameObjects)
            {
                if (!go)
                {
                    continue;
                }

                lodVolume = go.GetComponent <LODVolume>();
                if (lodVolume)
                {
                    break;
                }

                yield return(null);
            }

            if (lodVolume)
            {
                m_RootVolume = lodVolume;
            }
        }
        /*是否重新生成*/
        bool IsReGenerate(LODVolume lodVolume, Texture2D[] textures, TextureAtlas atlas)
        {
            //父节点有使用不删除
            Transform currParent   = lodVolume.transform.parent;
            LODVolume parentVolume = currParent.GetComponent <LODVolume>();

            //自己是root,贴图数量不一样更新
            //父节点没有合并,说明自己是子树的父节点,从自己开始
            if (parentVolume == null || parentVolume.combined == null)
            {
                IEnumerable <Texture2D> residueOld = atlas.textures.Except(textures);
                IEnumerable <Texture2D> residueNew = textures.Except(atlas.textures);

                return(residueOld.Any() | residueNew.Any());
            }

            return(false);
        }
Exemple #10
0
        //还原HLOD
        public static void ComeBackHLODAsset(this HLODGenerate hlodGenerate, HLODGenerateEditor editor)
        {
#if UNITY_EDITOR
            if (hlodGenerate.m_RootLODVolume == null)
            {
                return;
            }
#endif
            Queue <LODVolume> queue = new Queue <LODVolume>();
#if UNITY_EDITOR
            queue.Enqueue(hlodGenerate.m_RootLODVolume.GetComponent <LODVolume>());
#endif
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();
                foreach (var child in lodVolume.childVolumes)
                {
                    queue.Enqueue(child);
                }
                if (lodVolume.combined == null)
                {
                    continue;
                }
                GameObject obj = AssetDatabase.LoadAssetAtPath <GameObject>(lodVolume.combined._assetPath);
                if (obj)
                {
#if UNITY_EDITOR
                    obj = PrefabUtility.InstantiatePrefab(obj, hlodGenerate.m_HLODS.transform) as GameObject;
#endif
                    obj.transform.SetPositionAndRotation(lodVolume.combined.Pose.position, lodVolume.combined.Pose.rotation);
                    obj.transform.localScale = lodVolume.combined.Pose.scale;
                    obj.GetComponent <MeshRenderer>().enabled = false;
                    lodVolume.combined._hlodRoot = obj;
                    lodVolume.combined._lodGroup = obj.GetComponent <LODGroup>();

                    if (editor.m_DeleteStreamingAsset)
                    {
                        PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
                    }
                }
            }
        }
Exemple #11
0
        void SetChildDirty(LODVolume lv)
        {
            Queue <LODVolume> queue = new Queue <LODVolume>();

            queue.Enqueue(lv);
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();
                foreach (LODVolume l in lodVolume.childVolumes)
                {
                    if (l.lodGroups.Count <= 1)
                    {
                        continue;
                    }
                    l.dirty = true;
                    EditorUtility.DisplayProgressBar("设置需要更改的节点", l.name, 0.8f);
                    queue.Enqueue(l);
                }
            }
        }
Exemple #12
0
        //还远原始资源
        public static void ComeBackOriginalAsset(this HLODGenerate hlodGenerate)
        {
#if UNITY_EDITOR
            LODVolume root = hlodGenerate.m_RootLODVolume.GetComponent <LODVolume>();
            foreach (var lodGroup in root.lodGroups)
            {
                GameObject obj = AssetDatabase.LoadAssetAtPath <GameObject>(lodGroup._assetPath);
                if (obj)
                {
                    obj = PrefabUtility.InstantiatePrefab(obj, hlodGenerate.m_HLODS.transform) as GameObject;
                    obj.transform.parent = lodGroup._hlodRoot.transform;//生成流式资源后_hlodRoot引用的是父节点
                    obj.transform.SetPositionAndRotation(lodGroup.Pose.position, lodGroup.Pose.rotation);
                    obj.transform.localScale = lodGroup.Pose.scale;
                    lodGroup._hlodRoot       = obj;
                    lodGroup._lodGroup       = obj.GetComponent <LODGroup>();
                    lodGroup.Enabled         = true;
                }
            }
#endif
        }
Exemple #13
0
        /*生成prefab*/
        void GeneratePrefab(LODVolume lodVolume, string savePath)
        {
            if (lodVolume.combined._hlodRoot == null)
            {
                return;
            }
            string namePath = null;

            if (PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(lodVolume.combined._hlodRoot) == "")
            {
                lodVolume.combined._hlodRoot.GetComponent <MeshRenderer>().enabled = true;
                namePath = Path.Combine(savePath, lodVolume.combined._hlodRoot.name + ".prefab");
                PrefabUtility.SaveAsPrefabAsset(lodVolume.combined._hlodRoot, namePath);
                lodVolume.combined._assetPath = namePath.Replace("\\", "/");
            }

            DestroyImmediate(lodVolume.combined._hlodRoot);
            lodVolume.combined._hlodRoot = null;
            lodVolume.combined._lodGroup = null;
        }
Exemple #14
0
        IEnumerator ShrinkByLodGroup()
        {
            var populatedChildrenNodes = 0;

            foreach (Transform child in transform)
            {
                var lodVolume = child.GetComponent <LODVolume>();
                if (lodGroups != null && lodGroups.Count > 0 && lodGroups.Count(r => r != null) > 0)
                {
                    populatedChildrenNodes++;
                }

                yield return(null);
            }

            if (populatedChildrenNodes <= 1)
            {
                var       lodVolumes    = GetComponentsInChildren <LODVolume>();
                LODVolume newRootVolume = null;
                if (lodVolumes.Length > 0)
                {
                    newRootVolume = lodVolumes[lodVolumes.Length - 1];
                    newRootVolume.transform.parent = null;
                }

                // Clean up child HLODs before destroying the GameObject; Otherwise, we'd leak into the scene
                foreach (var lodVolume in lodVolumes)
                {
                    if (lodVolume != newRootVolume)
                    {
                        lodVolume.CleanupHLOD();
                    }
                }
                DestroyImmediate(gameObject);

                if (newRootVolume)
                {
                    yield return(newRootVolume.ShrinkByLodGroup());
                }
            }
        }
Exemple #15
0
 /*将精细用资源地址引用,并删除,把自己的位置存放父节点,以便还原使用*/
 void GenrateFineModelRef(LODVolume rootLODVolume)
 {
     foreach (var fast in rootLODVolume.lodGroups)
     {
         if (fast._hlodRoot == null)
         {
             continue;
         }
         string path = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(fast._hlodRoot);
         if (path == "")
         {
             Debug.LogError("找不到预制体!!");
             continue;
         }
         Transform parent = fast._hlodRoot.transform.parent;
         DestroyImmediate(fast._hlodRoot);
         fast._assetPath = path.Replace("\\", "/");
         fast._hlodRoot  = parent ? parent.gameObject : null;
         fast._lodGroup  = null;
         fast.Enabled    = false;
     }
 }
Exemple #16
0
        /*更新流式资源*/
        void UpdataStreamingAsset(HLODGenerate hlodGenerate)
        {
            string savePath = Path.Combine(hlodGenerate.m_StreamingAssetPath, s_StreamingDirectory);

            if (!Directory.Exists(savePath))
            {
                Directory.CreateDirectory(savePath);
            }

            LODVolume         rootLODVolume = hlodGenerate.m_RootLODVolume.GetComponent <LODVolume>();
            Queue <LODVolume> queue         = new Queue <LODVolume>();

            queue.Enqueue(rootLODVolume);

            AssetDatabase.StartAssetEditing();
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();
                foreach (var child in lodVolume.childVolumes)
                {
                    queue.Enqueue(child);
                }
                if (lodVolume.combined == null)
                {
                    continue;
                }

                //导出资源
                GeneratePrefab(lodVolume, savePath);
            }
            AssetDatabase.StopAssetEditing();
            GenrateFineModelRef(hlodGenerate.m_RootLODVolume.GetComponent <LODVolume>());

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
Exemple #17
0
        /*更新合批网格*/
        void UpdataCombineMesh(HLODGenerate hlodGenerate)
        {
            if (!hlodGenerate.m_IsExportMesh)
            {
                return;
            }

            if (hlodGenerate.m_MeshAssetPath == "")
            {
                EditorUtility.DisplayDialog("警告", "没有选择mesh路径,请先选择路径", "是");
                hlodGenerate.m_IsExportMesh = false;
                return;
            }
            Queue <LODVolume> queue = new Queue <LODVolume>();

            queue.Enqueue(hlodGenerate.m_RootLODVolume.GetComponent <LODVolume>());
            //AssetDatabase.StartAssetEditing();
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();

                if (lodVolume.combined != null && lodVolume.combined._hlodRoot != null)
                {
                    string path = AssetDatabase.GetAssetPath(lodVolume.combined._hlodRoot.GetComponent <MeshFilter>().sharedMesh);

                    if (lodVolume.lodGroups.Count < 1)//删除多出来的资源
                    {
                        if (path == "")
                        {
                            path = Path.Combine(hlodGenerate.m_MeshAssetPath, ExportHLODsByMesh.s_DirectoryName, lodVolume.combined._hlodRoot.name);
                            path = Path.ChangeExtension(path, "asset");
                        }
                        DestroyImmediate(lodVolume.GetComponent <LODGroup>());
                        DestroyImmediate(lodVolume.combined._hlodRoot);
                        lodVolume.combined._hlodRoot = null;

                        if (path != "")
                        {
                            AssetDatabase.DeleteAsset(path);
                        }
                    }
                    else if (path == "")//更新资源
                    {
                        //ExportHLODsByMesh.PersistHLODs(lodVolume.hlodRoot.transform, hlodGenerate.m_MeshAssetPath);
                        ExportHLODsByMesh.PersistHLODOfFbx(lodVolume.combined._hlodRoot.transform, hlodGenerate.m_MeshAssetPath);
                        if (!hlodGenerate.StreamUpdate.Contains(lodVolume))
                        {
                            hlodGenerate.StreamUpdate.Add(lodVolume);
                        }
                    }
                    EditorUtility.SetDirty(lodVolume);
                }

                foreach (LODVolume lv in lodVolume.childVolumes)
                {
                    queue.Enqueue(lv);
                }
            }
            //AssetDatabase.StopAssetEditing();
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
Exemple #18
0
        static void OnCameraPreCull(Camera camera)
        {
            if (!Application.isPlaying)
            {
                return;
            }
            if (camera.cameraType != CameraType.Game || camera.tag != "MainCamera")
            {
                return;
            }


            // 刷新间隔没到,不做任何处理
            if (CullData.m_lastCullTime + s_CullInterval > Time.realtimeSinceStartup && s_delayEnable)
            {
                return;
            }
            CullData.m_lastCullTime = Time.realtimeSinceStartup;
            //判断摄像机参数是否有变化
            var cameraTransform = camera.transform;
            var cameraPosition  = cameraTransform.position;
            var cameraRotation  = cameraTransform.rotation;



            if (CullData.m_LastCameraPosition != cameraPosition)
            {
                CullData.m_LastCameraPosition = cameraPosition;
                m_SceneDirty = true;
            }

            /*
             * if (CullData.m_LastCameraRotation != cameraRotation)
             * {
             *  CullData.m_LastCameraRotation = cameraRotation;
             *  m_SceneDirty = true;
             * }
             */
            if (CullData.m_LastFOV != camera.fieldOfView)
            {
                CullData.m_LastFOV = camera.fieldOfView;
                m_SceneDirty       = true;
            }

            //判断LOD精度设置是否有变化
            if (CullData.m_LastLODBias != UnityEngine.QualitySettings.lodBias)
            {
                CullData.m_LastLODBias = UnityEngine.QualitySettings.lodBias;
                m_SceneDirty           = true;
            }
            if (CullData.m_LastHLODBias != s_HLOD_Bias)
            {
                CullData.m_LastHLODBias = s_HLOD_Bias;
                m_SceneDirty            = true;
            }

            if (m_SceneDirty)
            {
                foreach (var tree in Alls)
                {
                    //判断是否超过距离缓冲,超过了再改变状态
                    if (Vector3.Distance(tree.m_LastCameraPosition, cameraPosition) < tree.s_CacheDistance)
                    {
                        continue;
                    }
                    tree.m_LastCameraPosition = cameraPosition;

                    LODVolume rootLODVolume = tree.m_RootVolume;
                    if (rootLODVolume == null)
                    {
                        continue;
                    }

                    tree.HLODPreCull(camera, camera.transform.position);
                    HLODApply(tree.m_Stream, rootLODVolume);

                    foreach (var lodGroup in rootLODVolume.lodGroups)
                    {
                        if (tree.m_Stream)
                        {
                            if (!lodGroup.CheckState())
                            {
                                ChoiceQueue(lodGroup._lodVolume, lodGroup);
                            }
                            continue;
                        }
                        lodGroup.ApplyEnable();
                    }
                }
                CullData.m_LastCameraPosition = cameraPosition;
                CullData.m_LastCameraRotation = cameraRotation;
                m_SceneDirty = false;
            }
        }
Exemple #19
0
        //TODO 准备将这一步移植到Job System
        void HLODPreCull(Camera camera, Vector3 cameraPos)
        {
            s_AuxStack.Clear();
            List <LODVolume> backSort = m_BackSort;

            if (!s_HLODEnabled)//不开HLOD
            {
                foreach (var lv in backSort)
                {
                    if (lv.combined)
                    {
                        SetLOGGroupEnable(lv.combined, false);
                    }
                }
                foreach (var lodGroup in m_RootVolume.lodGroups)
                {
                    SetLOGGroupEnable(lodGroup, true);
                }
                return;
            }
            for (int index = 0; index < backSort.Count - 1; index++)
            {
                LODVolume curLv  = backSort[index];
                LODVolume nextLv = backSort[index + 1];

                s_AuxStack.Push(curLv);
                if (curLv.deep <= nextLv.deep)
                {
                    //表示后续遍历还没遍历到当前节点的父节点,继续入栈
                    continue;
                }
                bool parentVisible = true;
                //下降,表示遍历到了父节点,把栈顶前面几个相同的兄弟节点处理,然后将当前节点入栈
                while (s_AuxStack.Count > 0)
                {
                    LODVolume node = s_AuxStack.Pop();
                    if (node.combined == null && node.childVolumes.Count > 0)
                    {
                        //遇到没有合并的父节点
                        continue;
                    }
                    bool allChildInvisible = false;
                    if (node.childVolumes.Count == 0)
                    {
                        foreach (var lodGroup in node.lodGroups)
                        {
                            if (lodGroup.GetCurrentLOD(camera, cameraPos) != lodGroup.lodCount - 1)
                            {
                                // 只要有一个显示最精细模型
                                // 就认为不能显示HLOD对象
                                allChildInvisible = true;
                                parentVisible     = false;
                                break;
                            }
                        }
                        // 修改所有原始模型的显示状态
                        foreach (var lodGroup in node.lodGroups)
                        {
                            SetLOGGroupEnable(lodGroup, allChildInvisible);
                        }
                        //设置合批模型状态
                        if (node.combined)
                        {
                            SetLOGGroupEnable(node.combined, !allChildInvisible);
                        }
                    }
                    else if (parentVisible != false)      //不是叶子节点,且兄弟节点没有显示
                    {
                        if (node.combined.EnabledVirtual) //如果当前节点显示就不管,否则自己显示了,那么父节点需要隐藏
                        {
                            continue;
                        }
                        parentVisible = false;
                    }

                    LODVolume who = null;
                    if (s_AuxStack.Count > 0)
                    {
                        who = s_AuxStack.Peek();
                    }
                    else
                    {
                        break;
                    }

                    //下一个是上层节点
                    if (who.deep != node.deep)
                    {
                        break;
                    }
                }
                if (nextLv.combined != null)
                {
                    s_AuxStack.Push(nextLv);

                    if (parentVisible)
                    {
                        //孩子合批都显示,所以隐藏孩子显示自己
                        foreach (var child in nextLv.childVolumes)
                        {
                            SetHLODEnable(child, false);
                        }
                    }
                    else
                    {
                        //父节点不能显示,激活叶子没有合并的LODGroup
                        foreach (var child in nextLv.childVolumes)
                        {
                            SetLODEnable(child, true);
                        }
                    }
                    SetLOGGroupEnable(nextLv.combined, parentVisible);
                }
            }
        }
        public IEnumerator GetTextureAtlas(HLODGenerate hg, LODVolume lodVolume, Texture2D[] textures, Texture2D[] normals, Action <TextureAtlasData> callback)
        {
            TextureAtlasData atlasData = null;

            List <TextureAtlasData> atlasesData = null;

            GetTextureAtlasList(hg, out atlasesData);

            yield return(null);

            foreach (var a in atlasesData)
            {
                if (a.m_State == TextureAtlasData.State.Delete)
                {
                    continue;
                }
                //检查是否为所在树的贴图集
                if (!CheckInCurrLittleOctree(lodVolume, a))
                {
                    continue;
                }
                //是否重新生成
                if (IsReGenerate(lodVolume, textures, a.m_Atlases))
                {
                    a.m_State = TextureAtlasData.State.Delete;
                    break;
                }
                // At a minimum the atlas should have all of the textures requested, but can be a superset
                if (!textures.Except(a.m_Atlases.textures).Any())
                {
                    atlasData = a;
                    break;
                }

                yield return(null);
            }
            //m_Atlases.Remove(deleteAtlas);
            if (atlasData == null)//没有找到图集就创建一个
            {
                atlasData            = new TextureAtlasData(null, TextureAtlasData.State.Add);
                atlasData.m_Material = new Material(Shader.Find("Standard"));
                /*先序遍历,所有根节点就是第一个创建的对象,子节点会找到这个图集而不会继续创建*/
                atlasData.m_Root = lodVolume.gameObject;
            }
            if (!atlasData.m_Atlases)
            {
                atlasData.m_Atlases = ScriptableObject.CreateInstance <TextureAtlas>();

                TextureReadableSetting(textures);
                //TextureReadableSetting(normals);

                CombineTexture(textures, atlasData.m_Atlases, false, callback);
                //CombineTexture(normals, atlasData.m_Atlases, true, callback);

                atlasData.m_Material.mainTexture = atlasData.m_Atlases.textureAtlas;
                //material.SetTexture("_NormalMap", atlasData.m_Atlases.textureAtlas_N);
                atlasesData.Add(atlasData);
                yield return(null);
            }

            if (callback != null)
            {
                callback(atlasData);
            }
        }
Exemple #21
0
        /*更新BVH后一些检查操作*/
        public IEnumerator CheckAfterBVHUpdata(int treeHeight)
        {
            Queue <LODVolume> queue = new Queue <LODVolume>();

            //将没用合批的父节点dirty设置成false
            queue.Enqueue(this);
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();
                int       deep      = lodVolume.ChildDeep();
                if (lodVolume.combined != null || deep <= treeHeight)
                {
                    continue;
                }
                lodVolume.dirty = false;
                foreach (LODVolume lv in lodVolume.childVolumes)
                {
                    queue.Enqueue(lv);
                }
                EditorUtility.DisplayProgressBar("剔除不必要更改的节点", lodVolume.name, 0.3f);
            }

            yield return(null);

            /*剔除空引用,广度遍历*/
            queue.Clear();
            queue = new Queue <LODVolume>();
            queue.Enqueue(this);
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();

                lodVolume.lodGroups.RemoveAll(r =>
                {//有物体删除了
                    if (r == null)
                    {
                        if (lodVolume.combined != null)
                        {
                            lodVolume.deleteDirty = true;
                        }

                        return(true);
                    }

                    return(false);
                });

                if (lodVolume.deleteDirty || lodVolume.dirty)
                {
                    EditorUtility.DisplayProgressBar("设置需要更改的节点", lodVolume.name, 0.5f);
                    lodVolume.dirty = true;
                    SetChildDirty(lodVolume);
                }
                if (lodVolume.lodGroups.Count <= 1 && !lodVolume.deleteDirty)
                {
                    lodVolume.dirty = false;
                    continue;
                }
                lodVolume.deleteDirty = false;
                foreach (LODVolume lv in lodVolume.childVolumes)
                {
                    queue.Enqueue(lv);
                }
            }
        }
Exemple #22
0
        IEnumerator UpdateOctreeByLodGroup(GameObject[] gameObjects = null)
        {
            if (gameObjects == null || gameObjects.Count() < 1)
            {
                yield break;
            }

            if (!m_RootVolume)
            {
                if (m_CreateRootVolumeForScene == SceneManager.GetActiveScene().name)
                {
#if UNITY_EDITOR
                    m_RootVolume = LODVolume.Create(m_CurrHLODGenerate);
#endif
                }

                else
                {
                    yield break;
                }
            }

            var lodGroups = m_FoundLODGroups;
            lodGroups.Clear();

            foreach (var objRoot in gameObjects)
            {
                LODGroup [] childGroups = objRoot.GetComponentsInChildren <LODGroup>();
                lodGroups.AddRange(childGroups);
            }

            // Remove any renderers that should not be there (e.g. HLODs)
            lodGroups.RemoveAll(r =>
                                m_ExcludedLODGroups.Contains(r)
                                );
            lodGroups.RemoveAll(l =>
            {
                if (l)
                {
                    // Check against previous collection
                    if (m_ExcludedLODGroups.Contains(l))
                    {
                        return(false);
                    }

                    var rds = l.GetLODs()[0].renderers;
                    foreach (var r in rds)
                    {
                        if (r == null)
                        {
                            return(false);
                        }

                        var mf = r.GetComponent <MeshFilter>();
                        if (!mf || (mf.sharedMesh && mf.sharedMesh.GetTopology(0) != MeshTopology.Triangles))
                        {
                            m_ExcludedLODGroups.Add(l);
                            return(true);
                        }
#if UNITY_EDITOR
                        //根据包围盒直径进行剔除不需要计算的模型
                        if (m_CurrHLODGenerate.m_BVHDivide.m_Cull)
                        {
                            bool result = m_CurrHLODGenerate.m_BVHDivide.CullByMesh(r.transform);
                            if (result)
                            {
                                m_ExcludedLODGroups.Add(l);
                                return(true);
                            }
                        }
#endif
                    }
                }

                return(false);
            });

            var existingLODGroups = m_ExistingLODGroups;
            existingLODGroups.Clear();
            existingLODGroups.UnionWith(m_RootVolume.lodGroups.Select(l => l._lodGroup));

            var removed = m_RemovedLODGroups;
            removed.Clear();
            removed.UnionWith(m_ExistingLODGroups);
            removed.ExceptWith(lodGroups);

            var added = m_AddedLODGroups;
            added.Clear();
            added.UnionWith(lodGroups);
            added.ExceptWith(existingLODGroups);

            int count = 1;
            foreach (var l in removed)
            {
                if (existingLODGroups.Contains(l))
                {
#if UNITY_EDITOR
                    yield return(m_RootVolume.RemoveLodGroup(l));
#endif
                    // Check if the BVH shrunk
                    yield return(SetRootLODVolume());
                }
            }
            count = 1;
            foreach (var l in added)
            {
                EditorUtility.DisplayProgressBar("网格划分", l.name, (float)count++ / added.Count);
                if (!existingLODGroups.Contains(l))
                {
                    UnityLODGroupFast lodGroupFast = CreateInstance <UnityLODGroupFast>();
#if UNITY_EDITOR
                    lodGroupFast.Init(l, l.gameObject);
                    //UnityLODGroupFast lodGroupFast = new UnityLODGroupFast(l, l.gameObject);
                    yield return(m_RootVolume.AddLodGroup(lodGroupFast));
#endif
                    l.transform.hasChanged = false;

                    // Check if the BVH grew
                    yield return(SetRootLODVolume());
                }
            }
        }
Exemple #23
0
        public IEnumerator Batch(HLODGenerate hg, LODVolume lodVolume)
        {
            GameObject go        = lodVolume.combined._hlodRoot;
            var        renderers = go.GetComponentsInChildren <Renderer>();
            var        materials = new HashSet <Material>(renderers.SelectMany(r => r.sharedMaterials));

            List <Texture2D> textures = new List <Texture2D>();
            List <Texture2D> normals  = new List <Texture2D>();


            textures = new HashSet <Texture2D>(materials.Select(m =>
            {
                if (m)
                {
                    return(m.mainTexture as Texture2D);
                }

                return(null);
            }).Where(t => t != null)).ToList();
            textures.Add(whiteTexture);

            /*
             * foreach(var t2d in textures)
             * {
             *  foreach(var rd in renderers)
             *  {
             *      if(rd.sharedMaterial.mainTexture == t2d)
             *      {
             *          Texture2D t = rd.sharedMaterial.GetTexture("_BumpMap") as Texture2D;
             *          if (t == null)
             *          {
             *              var texture = new Texture2D(rd.sharedMaterial.mainTexture.width, rd.sharedMaterial.mainTexture.height, TextureFormat.RGB24, false, PlayerSettings.colorSpace == ColorSpace.Linear);
             *
             *              t = texture;
             *              //texture.Apply();
             *          }
             *          else if(t.width != rd.sharedMaterial.mainTexture.width || t.height != rd.sharedMaterial.mainTexture.height)
             *          {
             *              int width = rd.sharedMaterial.mainTexture.width;
             *              int height = rd.sharedMaterial.mainTexture.height;
             *              var texture = new Texture2D(rd.sharedMaterial.mainTexture.width, rd.sharedMaterial.mainTexture.height, t.format, false, PlayerSettings.colorSpace == ColorSpace.Linear);
             *
             *
             *              for(int i = 0; i < height; i++)
             *              {
             *                  for(int j = 0; j <width; j++)
             *                  {
             *                      //EditorUtility.DisplayProgressBar("fsdfasd", (height * width).ToString(), (float)(i * j) / (height * width));
             *                     // Color newColor = t.GetPixelBilinear(j / width, i / height);
             *                      texture.SetPixel(j, i, Color.white);
             *                  }
             *              }
             *              //EditorUtility.ClearProgressBar();
             *              texture.Apply();
             *              t = texture;
             *          }
             *          normals.Add(t);
             *          break;
             *      }
             *  }
             * }
             * normals.Add(whiteTexture);
             */

            TextureAtlasData atlasData = null;

            yield return(TextureAtlasModule.instance.GetTextureAtlas(hg, lodVolume, textures.ToArray(), normals.ToArray(), a => atlasData = a));

            var mainAtlasLookup = new Dictionary <Texture2D, Rect>();
            //var normalAtlasLookup = new Dictionary<Texture2D, Rect>();
            var atlasTextures = atlasData.m_Atlases.textures;

            for (int i = 0; i < atlasTextures.Length; i++)
            {
                mainAtlasLookup[atlasTextures[i]] = atlasData.m_Atlases.uvs[i];
            }

            MeshFilter[] meshFilters = go.GetComponentsInChildren <MeshFilter>();
            var          combine     = new List <CombineInstance>();

            for (int i = 0; i < meshFilters.Length; i++)
            {
                var mf         = meshFilters[i];
                var sharedMesh = mf.sharedMesh;

                if (!sharedMesh)
                {
                    continue;
                }

                if (!sharedMesh.isReadable)
                {
                    var assetPath = AssetDatabase.GetAssetPath(sharedMesh);
                    if (!string.IsNullOrEmpty(assetPath))
                    {
                        var importer = AssetImporter.GetAtPath(assetPath) as ModelImporter;
                        if (importer)
                        {
                            importer.isReadable = true;
                            importer.SaveAndReimport();
                        }
                    }
                }

                var ci = new CombineInstance();

                var mesh = UnityEngine.Object.Instantiate(sharedMesh);

                var mr = mf.GetComponent <MeshRenderer>();
                var sharedMaterials = mr.sharedMaterials;
                var uv = mesh.uv;
                if (uv == null)
                {
                    uv = mesh.uv2;
                }
                var colors = mesh.colors;
                if (colors == null || colors.Length == 0)
                {
                    colors = new Color[uv.Length];
                }
                var updated   = new bool[uv.Length];
                var triangles = new List <int>();

                // Some meshes have submeshes that either aren't expected to render or are missing a material, so go ahead and skip
                var subMeshCount = Mathf.Min(mesh.subMeshCount, sharedMaterials.Length);
                for (int j = 0; j < subMeshCount; j++)
                {
                    var sharedMaterial = sharedMaterials[Mathf.Min(j, sharedMaterials.Length - 1)];
                    var mainTexture    = whiteTexture;
                    var materialColor  = Color.white;

                    if (sharedMaterial)
                    {
                        var texture = sharedMaterial.mainTexture as Texture2D;
                        //sharedMaterial.texture
                        if (texture)
                        {
                            mainTexture = texture;
                        }

                        if (sharedMaterial.HasProperty("_Color"))
                        {
                            materialColor = sharedMaterial.color;
                        }
                    }

                    if (mesh.GetTopology(j) != MeshTopology.Triangles)
                    {
                        Debug.LogWarning("Mesh must have triangles", mf);
                        continue;
                    }

                    triangles.Clear();
                    mesh.GetTriangles(triangles, j);
                    var uvOffset = mainAtlasLookup[mainTexture];
                    foreach (var t in triangles)
                    {
                        if (!updated[t])
                        {
                            var uvCoord = uv[t];
                            if (mainTexture == whiteTexture)
                            {
                                // Sample at center of white texture to avoid sampling edge colors incorrectly
                                uvCoord.x = 0.5f;
                                uvCoord.y = 0.5f;
                            }

                            while (uvCoord.x < 0)
                            {
                                uvCoord.x += 1;
                            }
                            while (uvCoord.y < 0)
                            {
                                uvCoord.y += 1;
                            }
                            while (uvCoord.x > 1)
                            {
                                uvCoord.x -= 1;
                            }
                            while (uvCoord.y > 1)
                            {
                                uvCoord.y -= 1;
                            }

                            uvCoord.x = Mathf.Lerp(uvOffset.xMin, uvOffset.xMax, uvCoord.x);
                            uvCoord.y = Mathf.Lerp(uvOffset.yMin, uvOffset.yMax, uvCoord.y);
                            uv[t]     = uvCoord;

                            if (mainTexture == whiteTexture)
                            {
                                colors[t] = materialColor;
                            }
                            else
                            {
                                colors[t] = Color.white;
                            }

                            updated[t] = true;
                        }
                    }

                    yield return(null);
                }
                mesh.uv     = uv;
                mesh.uv2    = null;
                mesh.colors = colors;

                ci.mesh      = mesh;
                ci.transform = mf.transform.localToWorldMatrix;
                combine.Add(ci);

                mf.gameObject.SetActive(false);

                yield return(null);
            }
            var combinedMesh = new Mesh();

#if UNITY_2017_3_OR_NEWER
            combinedMesh.indexFormat = IndexFormat.UInt32;
#endif
            combinedMesh.CombineMeshes(combine.ToArray(), true, true);
            combinedMesh.RecalculateBounds();
            var meshFilter = go.AddComponent <MeshFilter>();
            meshFilter.sharedMesh = combinedMesh;

            for (int i = 0; i < meshFilters.Length; i++)
            {
                UnityEngine.Object.DestroyImmediate(meshFilters[i].gameObject);
            }

            var meshRenderer = go.AddComponent <MeshRenderer>();

            meshRenderer.sharedMaterial = atlasData.m_Material;

            atlasData.m_MeshRenderers.Add(meshRenderer);
        }
Exemple #24
0
        /*更新BVH,对生成的BVH做后处理,广度遍历*/
        public IEnumerator UpdateRootVolume(Action <List <LODVolume> > action)
        {
            Queue <LODVolume> queue = new Queue <LODVolume>();

            //给每个子树添加ChildTreeRoot
            queue.Enqueue(this);
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();
                if (lodVolume.combined != null)
                {
                    ChildTreeRoot treeRoot = lodVolume.gameObject.AddComponent <ChildTreeRoot>();
                    continue;
                }
                foreach (LODVolume lv in lodVolume.childVolumes)
                {
                    queue.Enqueue(lv);
                }
                EditorUtility.DisplayProgressBar("添加ChildTreeRoot", lodVolume.name, 0.3f);
            }

            //叶子节点,给每个UnityLODGroup做引用,同时所有子树的节点引用ChildTreeRoot
            queue.Enqueue(this);
            while (queue.Count > 0)
            {
                LODVolume lodVolume = queue.Dequeue();
                foreach (LODVolume lv in lodVolume.childVolumes)
                {
                    queue.Enqueue(lv);
                }
                if (lodVolume.childVolumes.Count < 1)
                {
                    foreach (var fast in lodVolume.lodGroups)
                    {
                        fast._lodVolume = lodVolume;
                    }
                }
                lodVolume.childTreeRoot = lodVolume.GetComponentInParent <ChildTreeRoot>();
                EditorUtility.DisplayProgressBar("引用ChildTreeRoot", lodVolume.name, 0.6f);
            }

            //设置节点深度
            int curLevelNum = 0; //当前层的节点数
            int curLevel    = 1; //层数

            queue.Enqueue(this);
            while (queue.Count > 0)
            {
                curLevelNum = queue.Count;
                while (curLevelNum-- > 0)
                {
                    LODVolume lodVolume = queue.Dequeue();
                    lodVolume.deep = curLevel;

                    foreach (LODVolume lv in lodVolume.childVolumes)
                    {
                        queue.Enqueue(lv);
                    }
                    EditorUtility.DisplayProgressBar("深度设置", lodVolume.name, 0.8f);
                }
                curLevel++;
            }

            //构造后续遍历列表
            List <LODVolume>  backSort = new List <LODVolume>();
            Stack <LODVolume> stack    = new Stack <LODVolume>();

            stack.Push(this);
            while (stack.Count > 0)
            {
                LODVolume lodVolume = stack.Pop();
                backSort.Add(lodVolume);
                foreach (LODVolume lv in lodVolume.childVolumes)
                {
                    stack.Push(lv);
                }
                EditorUtility.DisplayProgressBar("构造后续遍历列表", lodVolume.name, 0.9f);
            }
            backSort.Reverse();

            if (action != null)
            {
                action.Invoke(backSort);
            }

            yield return(null);
        }