예제 #1
0
        public static bool OBBIntersect(ref ProbeReferenceVolume.Volume a, ref ProbeReferenceVolume.Volume b)
        {
            // First we test if the bounding spheres intersects, in which case we case do the more complex OBB test
            a.CalculateCenterAndSize(out var aCenter, out var aSize);
            b.CalculateCenterAndSize(out var bCenter, out var bSize);

            var aRadius = aSize.sqrMagnitude / 2.0f;
            var bRadius = bSize.sqrMagnitude / 2.0f;

            if (Vector3.SqrMagnitude(aCenter - bCenter) > aRadius + bRadius)
            {
                return(false);
            }

            m_Axes[0] = a.X.normalized;
            m_Axes[1] = a.Y.normalized;
            m_Axes[2] = a.Z.normalized;
            m_Axes[3] = b.X.normalized;
            m_Axes[4] = b.Y.normalized;
            m_Axes[5] = b.Z.normalized;

            foreach (Vector3 axis in m_Axes)
            {
                Vector2 aProj = ProjectOBB(ref a, axis);
                Vector2 bProj = ProjectOBB(ref b, axis);

                if (aProj.y < bProj.x || bProj.y < aProj.x)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #2
0
        static IEnumerable <(ProbeReferenceVolume.Volume volume, Vector3 parentPosition)> SubdivideVolumeIntoSubVolume(GPUSubdivisionContext ctx, ProbeReferenceVolume.Volume volume)
        {
            volume.CalculateCenterAndSize(out var center, out var size);
            float maxBrickInSubCell = Mathf.Pow(3, k_MaxSubdivisionInSubCell);
            float subdivisionCount  = ctx.maxBrickCountPerAxis / (float)ctx.maxBrickCountPerAxisInSubCell;
            var   subVolumeSize     = size / subdivisionCount;

            for (int x = 0; x < (int)subdivisionCount; x++)
            {
                for (int y = 0; y < (int)subdivisionCount; y++)
                {
                    for (int z = 0; z < (int)subdivisionCount; z++)
                    {
                        var subVolume = new ProbeReferenceVolume.Volume()
                        {
                            corner = volume.corner + new Vector3(x * subVolumeSize.x, y * subVolumeSize.y, z * subVolumeSize.z),
                            X      = volume.X / subdivisionCount,
                            Y      = volume.Y / subdivisionCount,
                            Z      = volume.Z / subdivisionCount,
                            maxSubdivisionMultiplier = volume.maxSubdivisionMultiplier,
                            minSubdivisionMultiplier = volume.minSubdivisionMultiplier,
                        };
                        var parentCellPosition = new Vector3(x, y, z);

                        yield return(subVolume, parentCellPosition);
                    }
                }
            }
        }
예제 #3
0
        private static Vector2 ProjectOBB(ref ProbeReferenceVolume.Volume a, Vector3 axis)
        {
            float min = Vector3.Dot(axis, a.corner);
            float max = min;

            for (int x = 0; x < 2; x++)
            {
                for (int y = 0; y < 2; y++)
                {
                    for (int z = 0; z < 2; z++)
                    {
                        Vector3 vert = a.corner + a.X * x + a.Y * y + a.Z * z;

                        float proj = Vector3.Dot(axis, vert);

                        if (proj < min)
                        {
                            min = proj;
                        }
                        else if (proj > max)
                        {
                            max = proj;
                        }
                    }
                }
            }

            return(new Vector2(min, max));
        }
예제 #4
0
        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);
        }
예제 #5
0
        public static void Subdivide(ProbeReferenceVolume.Volume cellVolume, ProbeReferenceVolume refVol, List <ProbeReferenceVolume.Volume> influencerVolumes,
                                     ref Vector3[] positions, ref List <ProbeBrickIndex.Brick> bricks)
        {
            // TODO move out
            var indicatorVolumes = new List <ProbeReferenceVolume.Volume>();

            foreach (ProbeVolume pv in UnityEngine.Object.FindObjectsOfType <ProbeVolume>())
            {
                if (!pv.enabled)
                {
                    continue;
                }

                indicatorVolumes.Add(new ProbeReferenceVolume.Volume(Matrix4x4.TRS(pv.transform.position, pv.transform.rotation, pv.GetExtents()), pv.parameters.maxSubdivisionMultiplier, pv.parameters.minSubdivisionMultiplier));
            }

            ProbeReferenceVolume.SubdivisionDel subdivDel =
                (RefTrans refTrans, int subdivisionLevel, List <Brick> inBricks, List <Flags> outFlags) =>
            { SubdivisionAlgorithm(cellVolume, indicatorVolumes, influencerVolumes, refTrans, inBricks, subdivisionLevel, outFlags); };

            bricks = new List <ProbeBrickIndex.Brick>();

            // get a list of bricks for this volume
            int numProbes;

            refVol.CreateBricks(new List <ProbeReferenceVolume.Volume>()
            {
                cellVolume
            }, influencerVolumes, subdivDel, bricks, out numProbes);

            positions = new Vector3[numProbes];
            refVol.ConvertBricks(bricks, positions);
        }
예제 #6
0
 static public ProbeReferenceVolume.Volume ToVolume(Bounds bounds)
 {
     ProbeReferenceVolume.Volume v = new ProbeReferenceVolume.Volume();
     v.corner = bounds.center - bounds.size * 0.5f;
     v.X      = new Vector3(bounds.size.x, 0, 0);
     v.Y      = new Vector3(0, bounds.size.y, 0);
     v.Z      = new Vector3(0, 0, bounds.size.z);
     return(v);
 }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        // TODO: Take refvol translation and rotation into account
        public static ProbeReferenceVolume.Volume CalculateBrickVolume(ref RefTrans refTrans, Brick brick)
        {
            float   scaledSize = Mathf.Pow(3, brick.subdivisionLevel);
            Vector3 scaledPos  = refTrans.refSpaceToWS.MultiplyPoint(brick.position);

            var bounds = new ProbeReferenceVolume.Volume(
                scaledPos,
                refTrans.refSpaceToWS.GetColumn(0) * scaledSize,
                refTrans.refSpaceToWS.GetColumn(1) * scaledSize,
                refTrans.refSpaceToWS.GetColumn(2) * scaledSize
                );

            return(bounds);
        }
예제 #10
0
        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);
                    }
                }
            }
        }
예제 #11
0
        static public void CreateInfluenceVolumes(ref ProbeReferenceVolume.Volume cellVolume, Renderer[] renderers, ProbeVolume[] probeVolumes,
                                                  out List <ProbeReferenceVolume.Volume> culledVolumes, out Dictionary <Scene, int> sceneRefs)
        {
            // Keep track of volumes and which scene they originated from
            sceneRefs = new Dictionary <Scene, int>();

            // Extract all influencers inside the cell
            List <ProbeReferenceVolume.Volume> influenceVolumes = new List <ProbeReferenceVolume.Volume>();

            RenderersToVolumes(ref renderers, ref cellVolume, ref influenceVolumes, ref sceneRefs);
            NavPathsToVolumes(ref cellVolume, ref influenceVolumes, ref sceneRefs);
            ImportanceVolumesToVolumes(ref cellVolume, ref influenceVolumes, ref sceneRefs);
            LightsToVolumes(ref cellVolume, ref influenceVolumes, ref sceneRefs);

            // Extract all ProbeVolumes inside the cell
            List <ProbeReferenceVolume.Volume> indicatorVolumes = new List <ProbeReferenceVolume.Volume>();

            ProbeVolumesToVolumes(ref probeVolumes, ref cellVolume, ref indicatorVolumes, ref sceneRefs);

            // Cull all influencers against ProbeVolumes
            culledVolumes = new List <ProbeReferenceVolume.Volume>();
            CullVolumes(ref influenceVolumes, ref indicatorVolumes, ref culledVolumes);
        }
예제 #12
0
        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);
        }
예제 #13
0
 public static List <Brick> SubdivideCell(ProbeReferenceVolume.Volume cellVolume, ProbeSubdivisionContext subdivisionCtx, GPUSubdivisionContext ctx, List <(Renderer component, ProbeReferenceVolume.Volume volume)> renderers, List <(ProbeVolume component, ProbeReferenceVolume.Volume volume)> probeVolumes)
예제 #14
0
        public static bool OBBIntersect(ref RefTrans refTrans, Brick brick, ref ProbeReferenceVolume.Volume volume)
        {
            var transformed = CalculateBrickVolume(ref refTrans, brick);

            return(OBBIntersect(ref transformed, ref volume));
        }
예제 #15
0
 internal Bounds GetBounds()
 {
     ProbeReferenceVolume.Volume volume = new ProbeReferenceVolume.Volume(Matrix4x4.TRS(transform.position, transform.rotation, GetExtents()), 0, 0);
     return(volume.CalculateAABB());
 }
예제 #16
0
 static protected int LightsToVolumes(ref ProbeReferenceVolume.Volume cellVolume, ref List <ProbeReferenceVolume.Volume> volumes, ref Dictionary <Scene, int> sceneRefs)
 {
     // TODO
     return(0);
 }