Ejemplo n.º 1
0
        public void Create(Action finishAction)
        {
            MonoBehaviourHelper.maxSharedExecutionTimeMS = 50.0f;

            //Assets should be saved which changed.
            AssetDatabase.SaveAssets();

            var lodGroups = FindAllGroups();

            if (lodGroups.Count == 0)
            {
                return;
            }

            //find biggest bounds including all groups.
            var    lodGroupList = lodGroups.Values.ToList();
            Bounds bounds       = CalcBounds(lodGroupList[0]);

            for (int i = 1; i < lodGroupList.Count; ++i)
            {
                bounds.Encapsulate(CalcBounds(lodGroupList[i]));
            }

            var rootVolume = LODVolume.Create();

            rootVolume.SetLODGroups(lodGroups);
            rootVolume.Bounds = bounds;

            m_HLODRootContainer = new GameObject(k_HLODRootContainer);
            m_HLODRootContainer.AddComponent <SceneLODUpdater>();

            m_GroupHLODRootContainer = new Dictionary <string, GameObject>();

            StartCustomCoroutine(BuildOctree(rootVolume), CoroutineOrder.BuildTree);
            StartCustomCoroutine(BuildBatch(), CoroutineOrder.Batch);

            StartCustomCoroutine(EnqueueAction(finishAction), CoroutineOrder.Finish);
            StartCustomCoroutine(EnqueueAction(() =>
            {
                if (rootVolume != null)
                {
                    rootVolume.ResetLODGroup();

                    if (m_HLODRootContainer != null)
                    {
                        var updater = m_HLODRootContainer.GetComponent <SceneLODUpdater>();
                        updater.Build(rootVolume);

                        DestroyImmediate(rootVolume.gameObject);
                    }
                }
            }), CoroutineOrder.Finish);

            currentJobCount = 0;
            maxJobCount     = m_JobContainer.First().Value.Count;
            currentProgress = 0;
            maxProgress     = (int)CoroutineOrder.Finish + 1;
        }
Ejemplo n.º 2
0
        IEnumerator UpdateOctree()
        {
            if (!m_RootVolume)
            {
                yield return(SetRootLODVolume());

                if (!m_RootVolume)
                {
                    if (m_CreateRootVolumeForScene == SceneManager.GetActiveScene().name)
                    {
                        Dbg.Log("Creating root volume");
                        m_RootVolume = LODVolume.Create();
                    }
                    else
                    {
                        yield break;
                    }
                }
            }

            var renderers = m_FoundRenderers;

            renderers.Clear();

            yield return(ObjectUtils.FindObjectsOfType(renderers));

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

                    if (r.gameObject.layer == LayerMask.NameToLayer(LODVolume.HLODLayer))
                    {
                        m_ExcludedRenderers.Add(r);
                        return(true);
                    }

                    var mf = r.GetComponent <MeshFilter>();
                    if (!mf || (mf.sharedMesh && mf.sharedMesh.GetTopology(0) != MeshTopology.Triangles))
                    {
                        m_ExcludedRenderers.Add(r);
                        return(true);
                    }

                    var lodGroup = r.GetComponentInParent <LODGroup>();
                    if (lodGroup)
                    {
                        var lods = lodGroup.GetLODs();

                        // Skip LOD0, so that we keep the original renderers in the list
                        for (int i = 1; i < lods.Length; i++)
                        {
                            if (lods[i].renderers.Contains(r))
                            {
                                m_ExcludedRenderers.Add(r);
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        // HLODs should come after traditional LODs, so exclude any standalone renderers
                        m_ExcludedRenderers.Add(r);
                        return(true);
                    }
                }

                return(false);
            });

            var existingRenderers = m_ExistingRenderers;

            existingRenderers.Clear();
            existingRenderers.UnionWith(m_RootVolume.renderers);

            var removed = m_RemovedRenderers;

            removed.Clear();
            removed.UnionWith(m_ExistingRenderers);
            removed.ExceptWith(renderers);

            var added = m_AddedRenderers;

            added.Clear();
            added.UnionWith(renderers);
            added.ExceptWith(existingRenderers);

            foreach (var r in removed)
            {
                if (existingRenderers.Contains(r))
                {
                    yield return(m_RootVolume.RemoveRenderer(r));

                    // Check if the BVH shrunk
                    yield return(SetRootLODVolume());
                }
            }

            foreach (var r in added)
            {
                if (!existingRenderers.Contains(r))
                {
                    yield return(m_RootVolume.AddRenderer(r));

                    r.transform.hasChanged = false;

                    // Check if the BVH grew
                    yield return(SetRootLODVolume());
                }
            }
        }
Ejemplo n.º 3
0
        IEnumerator BuildOctree(LODVolume volume)
        {
            var   bounds     = volume.Bounds;
            float boundsSize = Mathf.Max(bounds.extents.x, Mathf.Max(bounds.extents.y, bounds.extents.z));

            yield return(BuildHLOD(volume));

            //reserve logic.
            //UpdateLODGroup should be run after batch.
            StartCustomCoroutine(UpdateLODGroup(volume), CoroutineOrder.UpdateLOD);

            //Make a child if necessary.
            if (boundsSize < Config.VolumeSize)
            {
                yield break;
            }

            //Volume doesn't have any group for a split.
            if (volume.VolumeGroups.Count == 0)
            {
                yield break;
            }
            ;

            Vector3 size = bounds.size;

            size.x /= k_Splits;
            size.y /= k_Splits;
            size.z /= k_Splits;

            for (int i = 0; i < k_Splits; i++)
            {
                for (int j = 0; j < k_Splits; j++)
                {
                    for (int k = 0; k < k_Splits; k++)
                    {
                        var lodVolume          = LODVolume.Create();
                        var lodVolumeTransform = lodVolume.transform;
                        lodVolumeTransform.parent = volume.transform;
                        var center = bounds.min + size * 0.5f + Vector3.Scale(size, new Vector3(i, j, k));
                        lodVolumeTransform.position = center;

                        lodVolume.Bounds = new Bounds(center, size);

                        foreach (var volumeGroup in volume.VolumeGroups)
                        {
                            List <LODGroup> lodGroups = new List <LODGroup>(volumeGroup.LODGroups.Count);

                            foreach (LODGroup group in volumeGroup.LODGroups)
                            {
                                if (WithinBounds(group, lodVolume.Bounds))
                                {
                                    lodGroups.Add(group);
                                }
                            }

                            if (lodGroups.Count > 0)
                            {
                                lodVolume.SetLODGroups(volumeGroup.GroupName, lodGroups);
                            }
                        }

                        volume.AddChild(lodVolume);
                        yield return(BuildOctree(lodVolume));
                    }
                }
            }
        }