static protected int RenderersToVolumes(ref Renderer[] renderers, ref ProbeReferenceVolume.Volume cellVolume, ref List <ProbeReferenceVolume.Volume> volumes, ref Dictionary <Scene, int> sceneRefs) { int num = 0; foreach (Renderer r in renderers) { var flags = GameObjectUtility.GetStaticEditorFlags(r.gameObject) & StaticEditorFlags.ContributeGI; bool contributeGI = (flags & StaticEditorFlags.ContributeGI) != 0; if (!r.enabled || !r.gameObject.activeSelf || !contributeGI) { continue; } ProbeReferenceVolume.Volume v = ToVolume(r.bounds); if (ProbeVolumePositioning.OBBIntersect(ref cellVolume, ref v)) { volumes.Add(v); TrackSceneRefs(r.gameObject.scene, ref sceneRefs); num++; } } return(num); }
public static void SubdivisionAlgorithm(ProbeReferenceVolume.Volume cellVolume, List <ProbeReferenceVolume.Volume> probeVolumes, List <ProbeReferenceVolume.Volume> influenceVolumes, RefTrans refTrans, List <Brick> inBricks, int subdivisionLevel, List <Flags> outFlags) { Flags f = new Flags(); for (int i = 0; i < inBricks.Count; i++) { ProbeReferenceVolume.Volume brickVolume = ProbeVolumePositioning.CalculateBrickVolume(ref refTrans, inBricks[i]); // Find the local max from all overlapping probe volumes: float localMaxSubdiv = 0; float localMinSubdiv = 0; bool overlap = false; foreach (ProbeReferenceVolume.Volume v in probeVolumes) { ProbeReferenceVolume.Volume vol = v; if (ProbeVolumePositioning.OBBIntersect(ref vol, ref brickVolume)) { overlap = true; localMaxSubdiv = Mathf.Max(localMaxSubdiv, vol.maxSubdivisionMultiplier); // Do we use max for min subdiv too? localMinSubdiv = Mathf.Max(localMinSubdiv, vol.minSubdivisionMultiplier); } } bool belowMaxSubdiv = subdivisionLevel <= ProbeReferenceVolume.instance.GetMaxSubdivision(localMaxSubdiv); bool belowMinSubdiv = subdivisionLevel <= ProbeReferenceVolume.instance.GetMaxSubdivision(localMinSubdiv); // Keep bricks that overlap at least one probe volume, and at least one influencer (mesh) if ((belowMinSubdiv && overlap) || (belowMaxSubdiv && ShouldKeepBrick(probeVolumes, brickVolume) && ShouldKeepBrick(influenceVolumes, brickVolume))) { f.subdivide = true; // Transform into refvol space brickVolume.Transform(refTrans.refSpaceToWS.inverse); ProbeReferenceVolume.Volume cellVolumeTrans = new ProbeReferenceVolume.Volume(cellVolume); cellVolumeTrans.Transform(refTrans.refSpaceToWS.inverse); cellVolumeTrans.maxSubdivisionMultiplier = localMaxSubdiv; // Discard parent brick if it extends outside of the cell, to prevent duplicates var brickVolumeMax = brickVolume.corner + brickVolume.X + brickVolume.Y + brickVolume.Z; var cellVolumeMax = cellVolumeTrans.corner + cellVolumeTrans.X + cellVolumeTrans.Y + cellVolumeTrans.Z; f.discard = brickVolumeMax.x > cellVolumeMax.x || brickVolumeMax.y > cellVolumeMax.y || brickVolumeMax.z > cellVolumeMax.z || brickVolume.corner.x < cellVolumeTrans.corner.x || brickVolume.corner.y < cellVolumeTrans.corner.y || brickVolume.corner.z < cellVolumeTrans.corner.z; } else { f.discard = true; f.subdivide = false; } outFlags.Add(f); } }
// converts a volume into bricks, subdivides the bricks and culls subdivided volumes falling outside the original volume private void ConvertVolume(Volume cellVolume, List <Volume> subVolumes, SubdivisionDel subdivider, List <Brick> outSortedBricks) { Profiler.BeginSample("ConvertVolume"); m_TmpBricks[0].Clear(); Transform(cellVolume, out Volume vol); // rasterize bricks according to the coarsest grid Rasterize(vol, m_TmpBricks[0]); int subDivCount = 0; // iterative subdivision while (m_TmpBricks[0].Count > 0 && subDivCount <= GetMaxSubdivision(cellVolume.maxSubdivisionMultiplier)) { m_TmpBricks[1].Clear(); m_TmpFlags.Clear(); m_TmpFlags.Capacity = Mathf.Max(m_TmpFlags.Capacity, m_TmpBricks[0].Count); Profiler.BeginSample("Subdivider"); subdivider(m_Transform, subDivCount, m_TmpBricks[0], m_TmpFlags); Profiler.EndSample(); Debug.Assert(m_TmpBricks[0].Count == m_TmpFlags.Count); for (int i = 0; i < m_TmpFlags.Count; i++) { if (!m_TmpFlags[i].discard) { outSortedBricks.Add(m_TmpBricks[0][i]); } if (m_TmpFlags[i].subdivide) { m_TmpBricks[1].Add(m_TmpBricks[0][i]); } } m_TmpBricks[0].Clear(); if (m_TmpBricks[1].Count > 0) { SubdivideBricks(m_TmpBricks[1], m_TmpBricks[0]); // Cull out of bounds bricks Profiler.BeginSample("Cull bricks"); for (int i = m_TmpBricks[0].Count - 1; i >= 0; i--) { if (!ProbeVolumePositioning.OBBIntersect(ref m_Transform, m_TmpBricks[0][i], ref cellVolume)) { m_TmpBricks[0].RemoveAt(i); } } Profiler.EndSample(); } subDivCount++; } Profiler.EndSample(); }
internal static bool ShouldKeepBrick(List <ProbeReferenceVolume.Volume> volumes, ProbeReferenceVolume.Volume brick) { foreach (ProbeReferenceVolume.Volume v in volumes) { ProbeReferenceVolume.Volume vol = v; if (ProbeVolumePositioning.OBBIntersect(ref vol, ref brick)) { return(true); } } return(false); }
static protected void CullVolumes(ref List <ProbeReferenceVolume.Volume> cullees, ref List <ProbeReferenceVolume.Volume> cullers, ref List <ProbeReferenceVolume.Volume> result) { foreach (ProbeReferenceVolume.Volume v in cullers) { ProbeReferenceVolume.Volume lv = v; foreach (ProbeReferenceVolume.Volume c in cullees) { if (result.Contains(c)) { continue; } ProbeReferenceVolume.Volume lc = c; if (ProbeVolumePositioning.OBBIntersect(ref lv, ref lc)) { result.Add(c); } } } }
static protected int ProbeVolumesToVolumes(ref ProbeVolume[] probeVolumes, ref ProbeReferenceVolume.Volume cellVolume, ref List <ProbeReferenceVolume.Volume> volumes, ref Dictionary <Scene, int> sceneRefs) { int num = 0; foreach (ProbeVolume pv in probeVolumes) { if (!pv.isActiveAndEnabled) { continue; } ProbeReferenceVolume.Volume indicatorVolume = new ProbeReferenceVolume.Volume(Matrix4x4.TRS(pv.transform.position, pv.transform.rotation, pv.GetExtents()), pv.parameters.maxSubdivisionMultiplier, pv.parameters.minSubdivisionMultiplier); if (ProbeVolumePositioning.OBBIntersect(ref cellVolume, ref indicatorVolume)) { cellVolume.maxSubdivisionMultiplier = Mathf.Max(cellVolume.maxSubdivisionMultiplier, pv.parameters.maxSubdivisionMultiplier, pv.parameters.minSubdivisionMultiplier); volumes.Add(indicatorVolume); TrackSceneRefs(pv.gameObject.scene, ref sceneRefs); num++; } } return(num); }