Exemple #1
0
        // --------------------------------------------------
        // BAKE

#if UNITY_EDITOR
        private IEnumerator BakePortalData()
        {
            // Generate Portal data
            m_Completion    = 0.0f;
            m_BakeTime      = 0.0f;
            m_BakeStartTime = Time.realtimeSinceStartup;
            m_BakeState     = BakeState.Occluders;
            var occluders = PortalPrepareUtil.GetOccluderData();

            m_BakeState = BakeState.Volumes;
            var volumes = PortalPrepareUtil.GetVolumeData(m_VolumeMode, m_Subdivisions);

            m_BakeState = BakeState.Visibility;
            List <VisbilityData> visibilityTable = null;

            yield return(EditorCoroutines.StartCoroutine(GenerateVisibilityTable(occluders, volumes, value => visibilityTable = value), this));

            // Serialize
            m_PortalData = new SerializablePortalData()
            {
                occluders       = occluders,
                volumes         = volumes,
                visibilityTable = visibilityTable
            };

            // Finalize
            m_BakeState  = BakeState.Active;
            m_Completion = 1.0f;
            m_BakeTime   = Time.realtimeSinceStartup - m_BakeStartTime;
            UnityEditor.SceneView.RepaintAll();
            UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
        }
Exemple #2
0
        private void DrawVolumeGizmos()
        {
            // Check draw toggle
            if (m_DrawVolumes == false)
            {
                return;
            }

            // Draw gizmos for all Volumes
            foreach (SerializableVolume volume in PortalPrepareUtil.FilterVolumeDataNoChildren(m_PortalData.volumes))
            {
                PortalDebugUtil.DrawCube(volume.positionWS, volume.rotationWS, volume.scaleWS, PortalDebugColors.volume);
            }
        }
        // -------------------------------------------------- //
        //                   PUBLIC METHODS                   //
        // -------------------------------------------------- //

        /// <summary>
        /// Get all renderers from the VisibilityTable
        /// </summary>
        public Dictionary <int, MeshRenderer> GetAllRenderers()
        {
            // Get lowest subdivision volumes
            var lowestSubdivisionVolumes  = PortalPrepareUtil.FilterVolumeDataNoChildren(volumes);
            List <MeshRenderer> renderers = new List <MeshRenderer>();

            foreach (SerializableVolume volume in lowestSubdivisionVolumes)
            {
                // Iterate all volumes
                MeshRenderer[] volumeRenderers;
                if (visibilityTable.TryGetRenderers(volume, out volumeRenderers))
                {
                    // Get renderers from VisbilityTable
                    foreach (MeshRenderer r in volumeRenderers)
                    {
                        renderers.Add(r);
                    }
                }
            }
            // Store as dictionary with instanceID
            return(renderers.Distinct().ToDictionary(s => s.GetInstanceID()));
        }
Exemple #4
0
        private IEnumerator GenerateVisibilityTable(SerializableOccluder[] occluders, SerializableVolume[] volumes, Action <List <VisbilityData> > result)
        {
            // Abort bake if input data is invalid
            if (occluders == null || volumes == null)
            {
                Debug.LogError("Bake prepare data is invalid. Check bake output and retry.");
                m_BakeState  = BakeState.Empty;
                m_Completion = 0;
                yield return(null);
            }

            // Setup
            m_BakeState = BakeState.Visibility;
            var visibilityTable = new List <VisbilityData>();
            int totalRays       = 0;
            int passedRays      = 0;
            int occludedRays    = 0;

            // Get Occluder proxies, volumes and occludees
            var occluderProxies          = PortalPrepareUtil.GetOccluderProxies(occluders);
            var lowestSubdivisionVolumes = PortalPrepareUtil.FilterVolumeDataNoChildren(volumes);
            var occludees = PortalPrepareUtil.GetStaticOccludeeRenderers();

            // Build Visibility for Volumes
            for (int v = 0; v < lowestSubdivisionVolumes.Length; v++)
            {
                // Setup
                m_Completion = (float)(v + 1) / (float)lowestSubdivisionVolumes.Length;
                var volume        = lowestSubdivisionVolumes[v];
                var passedObjects = new List <GameObject>();
                var debugData     = new List <VisbilityData.Debug>();

                // Iterate random rays based on volume density
                var rayCount = PortalVisibilityUtil.CalculateRayCount(m_RayDensity, volume.scaleWS);
                totalRays += rayCount;
                for (int r = 0; r < rayCount; r++)
                {
                    // Get a random ray and a list of cone filtered renderers to test
                    var rayPosition       = PortalVisibilityUtil.GetRandomPointWithinVolume(volume);
                    var rayDirection      = PortalVisibilityUtil.RandomSphericalDistributionVector();
                    var filteredOccludees = PortalVisibilityUtil.FilterRenderersByConeAngle(occludees, rayPosition, rayDirection, m_ConeAngle);
                    for (int f = 0; f < filteredOccludees.Length; f++)
                    {
                        // Test ray against renderer AABB
                        if (PortalVisibilityUtil.CheckAABBIntersection(rayPosition, rayDirection, filteredOccludees[f].bounds))
                        {
                            // Test ray against occluders
                            Vector3 hitPos;
                            bool    passed = PortalVisibilityUtil.CheckOcclusion(occluderProxies, filteredOccludees[f], rayPosition, rayDirection, out hitPos);
                            switch (passed)
                            {
                            case true:
                                passedObjects.AddIfUnique(filteredOccludees[f].gameObject);
                                passedRays++;
                                break;

                            case false:
                                occludedRays++;
                                break;
                            }

                            // Track visibility debug data
                            debugData.Add(new VisbilityData.Debug()
                            {
                                source    = rayPosition,
                                hit       = hitPos,
                                direction = rayDirection,
                                distance  = Vector3.Distance(rayPosition, filteredOccludees[f].transform.position),
                                isHit     = !passed,
                            });
                        }
                    }
                }

                // Add to VisibilityTable
                visibilityTable.Add(new VisbilityData(volume, passedObjects.ToArray(), debugData.ToArray()));
                yield return(null);
            }

            // Clear Occluder proxies
            for (int i = 0; i < occluderProxies.Length; i++)
            {
                PortalCoreUtil.Destroy(occluderProxies[i].gameObject);
            }

            // Save statistics
            var occludeeCount = PortalCoreUtil.GetUniqueOccludeeCount(visibilityTable);

            m_OccludeeStatistics = new Vector2(occludeeCount, occludees.Length);
            m_RayStatistics      = new Vector3(passedRays, occludedRays, totalRays);

            // Finalize
            result(visibilityTable);
        }