// -------------------------------------------------- // 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(); }
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())); }
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); }