#pragma warning restore 649
#endif

        public void ExecuteNext(LocalGroupKey internalBatchIndex, ref BatchChunkData chunkData)
        {
#if UNITY_EDITOR
            Stats[ThreadIndex].Stats[CullingStats.kLodTotal]++;
#endif
            var localIndex         = internalBatchIndex.Value;
            var chunkInstanceCount = chunkData.ChunkInstanceCount;
            var isOrtho            = LODParams.isOrtho;

            ChunkInstanceLodEnabled chunkEntityLodEnabled = chunkData.InstanceLodEnableds;
#if UNITY_EDITOR
            ChunkInstanceLodEnabled oldEntityLodEnabled = chunkEntityLodEnabled;
#endif
            var forceLowLOD = ForceLowLOD[localIndex];

            if (0 == (chunkData.Flags & BatchChunkData.kFlagHasLodData))
            {
#if UNITY_EDITOR
                Stats[ThreadIndex].Stats[CullingStats.kLodNoRequirements]++;
#endif
                chunkEntityLodEnabled.Enabled[0] = 0;
                chunkEntityLodEnabled.Enabled[1] = 0;
                chunkData.ForceLowLODPrevious    = forceLowLOD;

                for (int i = 0; i < chunkInstanceCount; ++i)
                {
                    int wordIndex = i >> 6;
                    int bitIndex  = i & 63;
                    chunkEntityLodEnabled.Enabled[wordIndex] |= 1ul << bitIndex;
                }
            }
            else
            {
                int diff = (int)chunkData.MovementGraceFixed16 - CameraMoveDistanceFixed16;
                chunkData.MovementGraceFixed16 = (ushort)math.max(0, diff);

                var graceExpired    = chunkData.MovementGraceFixed16 == 0;
                var forceLodChanged = forceLowLOD != chunkData.ForceLowLODPrevious;

                if (graceExpired || forceLodChanged || DistanceScaleChanged)
                {
                    chunkEntityLodEnabled.Enabled[0] = 0;
                    chunkEntityLodEnabled.Enabled[1] = 0;

#if UNITY_EDITOR
                    Stats[ThreadIndex].Stats[CullingStats.kLodChunksTested]++;
#endif
                    var chunk = chunkData.Chunk;

                    var rootLodRequirements     = chunk.GetNativeArray(RootLodRequirements);
                    var instanceLodRequirements = chunk.GetNativeArray(InstanceLodRequirements);

                    var   chunkInstanceIndex = 0;
                    var   rootIndex          = 0;
                    float graceDistance      = float.MaxValue;

                    while (chunkInstanceIndex < chunkInstanceCount)
                    {
                        var rootLodRequirement = rootLodRequirements[rootIndex];
                        var rootInstanceCount  = rootLodRequirement.InstanceCount;

                        var rootLodDistance = math.select(DistanceScale * math.length(LODParams.cameraPos - rootLodRequirement.LOD.WorldReferencePosition), DistanceScale, isOrtho);

                        float rootMinDist = math.select(rootLodRequirement.LOD.MinDist, 0.0f, forceLowLOD == 1);
                        float rootMaxDist = rootLodRequirement.LOD.MaxDist;

                        graceDistance = math.min(math.abs(rootLodDistance - rootMinDist), graceDistance);
                        graceDistance = math.min(math.abs(rootLodDistance - rootMaxDist), graceDistance);

                        var rootLodIntersect = (rootLodDistance < rootMaxDist) && (rootLodDistance >= rootMinDist);

                        if (rootLodIntersect)
                        {
                            for (int i = 0; i < rootInstanceCount; i++)
                            {
                                var instanceLodRequirement = instanceLodRequirements[chunkInstanceIndex + i];
                                var instanceDistance       = math.select(DistanceScale * math.length(LODParams.cameraPos - instanceLodRequirement.WorldReferencePosition), DistanceScale, isOrtho);

                                var instanceLodIntersect = (instanceDistance < instanceLodRequirement.MaxDist) && (instanceDistance >= instanceLodRequirement.MinDist);

                                graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MinDist), graceDistance);
                                graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MaxDist), graceDistance);

                                if (instanceLodIntersect)
                                {
                                    var index     = chunkInstanceIndex + i;
                                    var wordIndex = index >> 6;
                                    var bitIndex  = index & 0x3f;
                                    var lodWord   = chunkEntityLodEnabled.Enabled[wordIndex];

                                    lodWord |= 1UL << bitIndex;
                                    chunkEntityLodEnabled.Enabled[wordIndex] = lodWord;
                                }
                            }
                        }

                        chunkInstanceIndex += rootInstanceCount;
                        rootIndex++;
                    }

                    chunkData.MovementGraceFixed16 = Fixed16CamDistance.FromFloatFloor(graceDistance);
                    chunkData.ForceLowLODPrevious  = forceLowLOD;
                }
            }


#if UNITY_EDITOR
            if (oldEntityLodEnabled.Enabled[0] != chunkEntityLodEnabled.Enabled[0] || oldEntityLodEnabled.Enabled[1] != chunkEntityLodEnabled.Enabled[1])
            {
                Stats[ThreadIndex].Stats[CullingStats.kLodChanged]++;
            }
#endif
            chunkData.InstanceLodEnableds = chunkEntityLodEnabled;
        }
Exemplo n.º 2
0
#pragma warning restore 649
#endif

        public void Execute(ArchetypeChunk archetypeChunk, int chunkIndex, int firstEntityIndex)
        {
            var hybridChunkInfoArray = archetypeChunk.GetNativeArray(HybridChunkInfo);
            var chunkHeaderArray     = archetypeChunk.GetNativeArray(ChunkHeader);

            for (var entityIndex = 0; entityIndex < archetypeChunk.Count; entityIndex++)
            {
                var hybridChunkInfo = hybridChunkInfoArray[entityIndex];
                if (!hybridChunkInfo.Valid)
                {
                    continue;
                }

                var chunkHeader = chunkHeaderArray[entityIndex];

#if UNITY_EDITOR
                Stats[ThreadIndex].Stats[CullingStats.kLodTotal]++;
#endif
                var internalBatchIndex = hybridChunkInfo.InternalIndex;
                var chunkInstanceCount = chunkHeader.ArchetypeChunk.Count;
                var isOrtho            = LODParams.isOrtho;

                ref var chunkCullingData = ref hybridChunkInfo.CullingData;
                ChunkInstanceLodEnabled chunkEntityLodEnabled = chunkCullingData.InstanceLodEnableds;

#if UNITY_EDITOR
                ChunkInstanceLodEnabled oldEntityLodEnabled = chunkEntityLodEnabled;
#endif
                var forceLowLOD = ForceLowLOD[internalBatchIndex];

                if (0 == (chunkCullingData.Flags & HybridChunkCullingData.kFlagHasLodData))
                {
#if UNITY_EDITOR
                    Stats[ThreadIndex].Stats[CullingStats.kLodNoRequirements]++;
#endif
                    chunkEntityLodEnabled.Enabled[0]     = 0;
                    chunkEntityLodEnabled.Enabled[1]     = 0;
                    chunkCullingData.ForceLowLODPrevious = forceLowLOD;

                    for (int i = 0; i < chunkInstanceCount; ++i)
                    {
                        int wordIndex = i >> 6;
                        int bitIndex  = i & 63;
                        chunkEntityLodEnabled.Enabled[wordIndex] |= 1ul << bitIndex;
                    }
                }
                else
                {
                    int diff = (int)chunkCullingData.MovementGraceFixed16 - CameraMoveDistanceFixed16;
                    chunkCullingData.MovementGraceFixed16 = (ushort)math.max(0, diff);

                    var graceExpired    = chunkCullingData.MovementGraceFixed16 == 0;
                    var forceLodChanged = forceLowLOD != chunkCullingData.ForceLowLODPrevious;

                    if (graceExpired || forceLodChanged || DistanceScaleChanged)
                    {
                        chunkEntityLodEnabled.Enabled[0] = 0;
                        chunkEntityLodEnabled.Enabled[1] = 0;

#if UNITY_EDITOR
                        Stats[ThreadIndex].Stats[CullingStats.kLodChunksTested]++;
#endif
                        var chunk = chunkHeader.ArchetypeChunk;

                        var rootLodRequirements     = chunk.GetNativeArray(RootLodRequirements);
                        var instanceLodRequirements = chunk.GetNativeArray(InstanceLodRequirements);

                        float graceDistance = float.MaxValue;

                        for (int i = 0; i < chunkInstanceCount; i++)
                        {
                            var rootLodRequirement = rootLodRequirements[i];

                            var rootLodDistance =
                                math.select(
                                    DistanceScale *
                                    math.length(LODParams.cameraPos - rootLodRequirement.LOD.WorldReferencePosition),
                                    DistanceScale, isOrtho);

                            float rootMinDist = math.select(rootLodRequirement.LOD.MinDist, 0.0f, forceLowLOD == 1);
                            float rootMaxDist = rootLodRequirement.LOD.MaxDist;

                            graceDistance = math.min(math.abs(rootLodDistance - rootMinDist), graceDistance);
                            graceDistance = math.min(math.abs(rootLodDistance - rootMaxDist), graceDistance);

                            var rootLodIntersect = (rootLodDistance < rootMaxDist) && (rootLodDistance >= rootMinDist);

                            if (rootLodIntersect)
                            {
                                var instanceLodRequirement = instanceLodRequirements[i];
                                var instanceDistance       =
                                    math.select(
                                        DistanceScale *
                                        math.length(LODParams.cameraPos -
                                                    instanceLodRequirement.WorldReferencePosition), DistanceScale,
                                        isOrtho);

                                var instanceLodIntersect =
                                    (instanceDistance < instanceLodRequirement.MaxDist) &&
                                    (instanceDistance >= instanceLodRequirement.MinDist);

                                graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MinDist),
                                                         graceDistance);
                                graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MaxDist),
                                                         graceDistance);

                                if (instanceLodIntersect)
                                {
                                    var index     = i;
                                    var wordIndex = index >> 6;
                                    var bitIndex  = index & 0x3f;
                                    var lodWord   = chunkEntityLodEnabled.Enabled[wordIndex];

                                    lodWord |= 1UL << bitIndex;
                                    chunkEntityLodEnabled.Enabled[wordIndex] = lodWord;
                                }
                            }
                        }

                        chunkCullingData.MovementGraceFixed16 = Fixed16CamDistance.FromFloatFloor(graceDistance);
                        chunkCullingData.ForceLowLODPrevious  = forceLowLOD;
                    }
                }


#if UNITY_EDITOR
                if (oldEntityLodEnabled.Enabled[0] != chunkEntityLodEnabled.Enabled[0] ||
                    oldEntityLodEnabled.Enabled[1] != chunkEntityLodEnabled.Enabled[1])
                {
                    Stats[ThreadIndex].Stats[CullingStats.kLodChanged]++;
                }
#endif

                chunkCullingData.InstanceLodEnableds = chunkEntityLodEnabled;
                hybridChunkInfoArray[entityIndex]    = hybridChunkInfo;
            }