Exemplo n.º 1
0
        JobHandle ExecuteSpawnRules(VegetationCell vegetationCell, Rect vegetationCellRect, int vegetationPackageIndex, int vegetationItemIndex)
        {
            int firstUnityTerrainIndex = GetFirstUnityTerrainIndex();
            VegetationItemInfoPro   vegetationItemInfoPro   = VegetationPackageProList[vegetationPackageIndex].VegetationInfoList[vegetationItemIndex];
            VegetationPackagePro    vegetationPackagePro    = VegetationPackageProList[vegetationPackageIndex];
            VegetationItemModelInfo vegetationItemModelInfo =
                VegetationPackageProModelsList[vegetationPackageIndex].VegetationItemModelList[vegetationItemIndex];
            BiomeType currentBiome          = VegetationPackageProList[vegetationPackageIndex].BiomeType;
            int       currentBiomeSortOrder = VegetationPackageProList[vegetationPackageIndex].BiomeSortOrder;

            float globalDensity =
                VegetationSettings.GetVegetationItemDensity(vegetationItemInfoPro.VegetationType);

            if (vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].LoadStateList[vegetationItemIndex] == 1)
            {
                return(default(JobHandle));
            }
            vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].LoadStateList[vegetationItemIndex] = 1;

            bool doRuntimeSpawn = !(currentBiome != BiomeType.Default && !vegetationCell.HasBiome(currentBiome));

            NativeList <MatrixInstance> matrixList =
                vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].VegetationItemMatrixList[vegetationItemIndex];

            matrixList.Clear();

            if (!vegetationItemInfoPro.EnableRuntimeSpawn)
            {
                doRuntimeSpawn = false;
            }

            if (vegetationItemInfoPro.UseVegetationMask)
            {
                bool hasVegetationTypeIndex = false;
                if (vegetationCell.VegetationMaskList != null)
                {
                    for (int k = 0; k <= vegetationCell.VegetationMaskList.Count - 1; k++)
                    {
                        if (vegetationCell.VegetationMaskList[k]
                            .HasVegetationTypeIndex(vegetationItemInfoPro.VegetationTypeIndex))
                        {
                            hasVegetationTypeIndex = true;
                            break;
                        }
                    }
                }

                if (!hasVegetationTypeIndex)
                {
                    doRuntimeSpawn = false;
                }
            }

            JobHandle vegetationItemHandle = default(JobHandle);

            if (doRuntimeSpawn)
            {
                VegetationInstanceData instanceData = VegetationInstanceDataPool.GetObject();
                instanceData.Clear();
                vegetationCell.VegetationInstanceDataList.Add(instanceData);

                float sampleDistance = vegetationItemInfoPro.SampleDistance / globalDensity;
                float density        = 1;

                float calculatedSampleDistance = Mathf.Clamp(sampleDistance / density, 0.1f,
                                                             vegetationCell.VegetationCellBounds.size.x / 2f);
                int xSamples    = Mathf.CeilToInt(vegetationCell.VegetationCellBounds.size.x / calculatedSampleDistance);
                int zSamples    = Mathf.CeilToInt(vegetationCell.VegetationCellBounds.size.z / calculatedSampleDistance);
                int sampleCount = xSamples * zSamples;

                matrixList.Capacity = sampleCount;
                instanceData.SpawnLocations.ResizeUninitialized(sampleCount);

                if (firstUnityTerrainIndex > -1)
                {
                    instanceData.ResizeUninitialized(sampleCount);
                    InitInstanceData initInstanceData = new InitInstanceData
                    {
                        HeightmapSampled = instanceData.HeightmapSampled.ToDeferredJobArray(),
                        Excluded         = instanceData.Excluded.ToDeferredJobArray()
                    };
                    vegetationItemHandle = initInstanceData.Schedule(sampleCount, 256, vegetationItemHandle);
                }
                else
                {
                    instanceData.SetCapasity(sampleCount);
                }
                float defaultSpawnChance = 0;
                if (currentBiome == BiomeType.Default)
                {
                    defaultSpawnChance = 1;
                }

                CalculateCellSpawnLocationsWideJob calculateCellSpawnLocationsWideJob =
                    new CalculateCellSpawnLocationsWideJob
                {
                    SpawnLocations = instanceData.SpawnLocations.ToDeferredJobArray(),
                    CellSize       = vegetationCell.VegetationCellBounds.size,
                    CellCorner     =
                        vegetationCell.VegetationCellBounds.center -
                        vegetationCell.VegetationCellBounds.extents,
                    SampleDistance     = sampleDistance,
                    RandomizePosition  = vegetationItemInfoPro.RandomizePosition,
                    Density            = 1,
                    DefaultSpawnChance = defaultSpawnChance,
                    RandomNumbers      = RandomNumbers,
                    CellRect           = vegetationCellRect,
                    CellIndex          = vegetationCell.Index,
                    Seed = vegetationItemInfoPro.Seed + VegetationSettings.Seed,
                    UseSamplePointOffset     = vegetationItemInfoPro.UseSamplePointOffset,
                    SamplePointMinOffset     = vegetationItemInfoPro.SamplePointMinOffset,
                    SamplePointMaxOffset     = vegetationItemInfoPro.SamplePointMaxOffset,
                    XSamples                 = xSamples,
                    ZSamples                 = zSamples,
                    CalculatedSampleDistance = calculatedSampleDistance
                };

                vegetationItemHandle = calculateCellSpawnLocationsWideJob.Schedule(sampleCount, 64, vegetationItemHandle);

                if (vegetationCell.BiomeMaskList != null)
                {
                    for (int k = 0; k <= vegetationCell.BiomeMaskList.Count - 1; k++)
                    {
                        if (vegetationCell.BiomeMaskList[k].BiomeSortOrder < currentBiomeSortOrder)
                        {
                            continue;
                        }
                        vegetationItemHandle = vegetationCell.BiomeMaskList[k]
                                               .FilterSpawnLocations(instanceData.SpawnLocations, currentBiome, sampleCount, vegetationItemHandle);
                    }
                }

                if (vegetationItemInfoPro.UseNoiseCutoff)
                {
                    PerlinNoiseCutoffJob perlinNoiseCutoffJob =
                        new PerlinNoiseCutoffJob
                    {
                        InversePerlinMask = vegetationItemInfoPro.NoiseCutoffInverse,
                        PerlinCutoff      = vegetationItemInfoPro.NoiseCutoffValue,
                        PerlinScale       = vegetationItemInfoPro.NoiseCutoffScale,
                        Offset            = vegetationItemInfoPro.NoiseCutoffOffset,
                        SpawnLocationList = instanceData.SpawnLocations.ToDeferredJobArray()
                    };

                    vegetationItemHandle = perlinNoiseCutoffJob.Schedule(sampleCount, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseNoiseDensity)
                {
                    PerlinNoiseDensityJob perlinNoiseDensityJob =
                        new PerlinNoiseDensityJob
                    {
                        InversePerlinMask = vegetationItemInfoPro.NoiseDensityInverse,
                        PerlinScale       = vegetationItemInfoPro.NoiseDensityScale,
                        Offset            = vegetationItemInfoPro.NoiseDensityOffset,
                        SpawnLocationList = instanceData.SpawnLocations.ToDeferredJobArray()
                    };
                    vegetationItemHandle = perlinNoiseDensityJob.Schedule(sampleCount, 64, vegetationItemHandle);
                }

                FilterSpawnLocationsChanceJob filterSpawnLocationsChanceJob =
                    new FilterSpawnLocationsChanceJob
                {
                    SpawnLocationList = instanceData.SpawnLocations.ToDeferredJobArray(),
                    RandomNumbers     = RandomNumbers,
                    Density           = vegetationItemInfoPro.Density
                };

                vegetationItemHandle = filterSpawnLocationsChanceJob.Schedule(sampleCount, 64, vegetationItemHandle);

                for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++)
                {
                    vegetationItemHandle = VegetationStudioTerrainList[k]
                                           .SampleTerrain(instanceData.SpawnLocations, instanceData, sampleCount, vegetationCellRect,
                                                          vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseTerrainSourceExcludeRule)
                {
                    TerrainSourceExcludeRuleJob terrainSourceExcludeRuleJob =
                        new TerrainSourceExcludeRuleJob
                    {
                        Excluded          = instanceData.Excluded.ToDeferredJobArray(),
                        TerrainSourceID   = instanceData.TerrainSourceID.ToDeferredJobArray(),
                        TerrainSourceRule = vegetationItemInfoPro.TerrainSourceExcludeRule
                    };
                    vegetationItemHandle = terrainSourceExcludeRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseTerrainSourceIncludeRule)
                {
                    TerrainSourceIncludeRuleJob terrainSourceIncludeRuleJob =
                        new TerrainSourceIncludeRuleJob
                    {
                        Excluded          = instanceData.Excluded.ToDeferredJobArray(),
                        TerrainSourceID   = instanceData.TerrainSourceID.ToDeferredJobArray(),
                        TerrainSourceRule = vegetationItemInfoPro.TerrainSourceIncludeRule
                    };
                    vegetationItemHandle = terrainSourceIncludeRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseSteepnessRule)
                {
                    InstanceSteepnessRuleJob instanceSteepnessRuleJob =
                        new InstanceSteepnessRuleJob
                    {
                        Excluded                = instanceData.Excluded.ToDeferredJobArray(),
                        TerrainNormal           = instanceData.TerrainNormal.ToDeferredJobArray(),
                        RandomNumberIndex       = instanceData.RandomNumberIndex.ToDeferredJobArray(),
                        MinSteepness            = vegetationItemInfoPro.MinSteepness,
                        MaxSteepness            = vegetationItemInfoPro.MaxSteepness,
                        Advanced                = vegetationItemInfoPro.UseAdvancedSteepnessRule,
                        SteepnessRuleCurveArray = vegetationItemModelInfo.SteepnessRuleCurveArray,
                        RandomNumbers           = RandomNumbers
                    };
                    vegetationItemHandle = instanceSteepnessRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseHeightRule)
                {
                    InstanceHeightRuleJob instanceHeightRuleJob =
                        new InstanceHeightRuleJob
                    {
                        Excluded             = instanceData.Excluded.ToDeferredJobArray(),
                        Position             = instanceData.Position.ToDeferredJobArray(),
                        RandomNumberIndex    = instanceData.RandomNumberIndex.ToDeferredJobArray(),
                        MinHeight            = vegetationItemInfoPro.MinHeight + WorldspaceSeaLevel,
                        MaxHeight            = vegetationItemInfoPro.MaxHeight + WorldspaceSeaLevel,
                        Advanced             = vegetationItemInfoPro.UseAdvancedHeightRule,
                        HeightRuleCurveArray = vegetationItemModelInfo.HeightRuleCurveArray,
                        RandomNumbers        = RandomNumbers,
                        MaxCurveHeight       = vegetationItemInfoPro.MaxCurveHeight
                    };
                    vegetationItemHandle = instanceHeightRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (!vegetationItemInfoPro.UseVegetationMask && vegetationCell.VegetationMaskList != null)
                {
                    for (int k = 0; k <= vegetationCell.VegetationMaskList.Count - 1; k++)
                    {
                        vegetationItemHandle = vegetationCell.VegetationMaskList[k].SampleMask(instanceData,
                                                                                               vegetationItemInfoPro.VegetationType, vegetationItemHandle);
                    }
                }
                else
                {
                    if (vegetationCell.VegetationMaskList != null)
                    {
                        for (int k = 0; k <= vegetationCell.VegetationMaskList.Count - 1; k++)
                        {
                            vegetationItemHandle = vegetationCell.VegetationMaskList[k].SampleIncludeVegetationMask(
                                instanceData,
                                vegetationItemInfoPro.VegetationTypeIndex, vegetationItemHandle);
                        }

                        if (vegetationCell.VegetationMaskList.Count > 0)
                        {
                            ProcessIncludeVegetationMaskJob processIncludeVegetationMaskJob =
                                new ProcessIncludeVegetationMaskJob
                            {
                                Excluded              = instanceData.Excluded.ToDeferredJobArray(),
                                Scale                 = instanceData.Scale.ToDeferredJobArray(),
                                RandomNumberIndex     = instanceData.RandomNumberIndex.ToDeferredJobArray(),
                                VegetationMaskDensity = instanceData.VegetationMaskDensity.ToDeferredJobArray(),
                                VegetationMaskScale   = instanceData.VegetationMaskScale.ToDeferredJobArray(),
                                RandomNumbers         = RandomNumbers
                            };
                            vegetationItemHandle = processIncludeVegetationMaskJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                        }
                    }
                }

                if (vegetationItemInfoPro.UseConcaveLocationRule)
                {
                    for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++)
                    {
                        vegetationItemHandle = VegetationStudioTerrainList[k].SampleConcaveLocation(instanceData,
                                                                                                    vegetationItemInfoPro.ConcaveLoactionMinHeightDifference,
                                                                                                    vegetationItemInfoPro.ConcaveLoactionDistance, vegetationItemInfoPro.ConcaveLocationInverse,
                                                                                                    vegetationItemInfoPro.ConcaveLoactionAverage, vegetationCellRect, vegetationItemHandle);
                    }
                }

                if (vegetationItemInfoPro.UseTextureMaskIncludeRules)
                {
                    for (int k = 0; k <= vegetationItemInfoPro.TextureMaskIncludeRuleList.Count - 1; k++)
                    {
                        TextureMaskGroup textureMaskGroup =
                            vegetationPackagePro.GetTextureMaskGroup(vegetationItemInfoPro
                                                                     .TextureMaskIncludeRuleList[k].TextureMaskGroupID);
                        if (textureMaskGroup != null)
                        {
                            vegetationItemHandle = textureMaskGroup.SampleIncludeMask(instanceData, vegetationCellRect,
                                                                                      vegetationItemInfoPro.TextureMaskIncludeRuleList[k], vegetationItemHandle);
                        }
                    }

                    FilterIncludeMaskJob filterIncludeMaskJob =
                        new FilterIncludeMaskJob
                    {
                        Excluded        = instanceData.Excluded.ToDeferredJobArray(),
                        TextureMaskData = instanceData.TextureMaskData.ToDeferredJobArray()
                    };
                    vegetationItemHandle = filterIncludeMaskJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseTextureMaskExcludeRules)
                {
                    for (int k = 0; k <= vegetationItemInfoPro.TextureMaskExcludeRuleList.Count - 1; k++)
                    {
                        TextureMaskGroup textureMaskGroup =
                            vegetationPackagePro.GetTextureMaskGroup(vegetationItemInfoPro
                                                                     .TextureMaskExcludeRuleList[k].TextureMaskGroupID);
                        if (textureMaskGroup != null)
                        {
                            vegetationItemHandle = textureMaskGroup.SampleExcludeMask(instanceData, vegetationCellRect,
                                                                                      vegetationItemInfoPro.TextureMaskExcludeRuleList[k], vegetationItemHandle);
                        }
                    }
                }

                OffsetAndRotateScaleVegetationInstanceMathJob offsetAndRotateScaleVegetationInstanceJob =
                    new OffsetAndRotateScaleVegetationInstanceMathJob
                {
                    RandomNumbers          = RandomNumbers,
                    Excluded               = instanceData.Excluded.ToDeferredJobArray(),
                    Scale                  = instanceData.Scale.ToDeferredJobArray(),
                    Position               = instanceData.Position.ToDeferredJobArray(),
                    Rotation               = instanceData.Rotation.ToDeferredJobArray(),
                    RandomNumberIndex      = instanceData.RandomNumberIndex.ToDeferredJobArray(),
                    TerrainNormal          = instanceData.TerrainNormal.ToDeferredJobArray(),
                    VegetationRotationType = vegetationItemInfoPro.Rotation,
                    MinScale               = vegetationItemInfoPro.MinScale,
                    MaxScale               = vegetationItemInfoPro.MaxScale,
                    Offset                 = vegetationItemInfoPro.Offset,
                    RotationOffset         = vegetationItemInfoPro.RotationOffset,
                    ScaleMultiplier        = vegetationItemInfoPro.ScaleMultiplier
                };
                vegetationItemHandle = offsetAndRotateScaleVegetationInstanceJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);


                if (vegetationItemInfoPro.UseNoiseScaleRule)
                {
                    PerlinNoiseScaleJob perlinNoiseScaleJob =
                        new PerlinNoiseScaleJob
                    {
                        Excluded          = instanceData.Excluded.ToDeferredJobArray(),
                        Position          = instanceData.Position.ToDeferredJobArray(),
                        Scale             = instanceData.Scale.ToDeferredJobArray(),
                        PerlinScale       = vegetationItemInfoPro.NoiseScaleScale,
                        MinScale          = vegetationItemInfoPro.NoiseScaleMinScale,
                        MaxScale          = vegetationItemInfoPro.NoiseScaleMaxScale,
                        InversePerlinMask = vegetationItemInfoPro.NoiseScaleInverse,
                        Offset            = vegetationItemInfoPro.NoiseScaleOffset
                    };
                    vegetationItemHandle = perlinNoiseScaleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseBiomeEdgeScaleRule && currentBiome != BiomeType.Default)
                {
                    BiomeEdgeDistanceScaleRuleJob biomeEdgeDistanceScaleRuleJob =
                        new BiomeEdgeDistanceScaleRuleJob
                    {
                        Excluded      = instanceData.Excluded.ToDeferredJobArray(),
                        Scale         = instanceData.Scale.ToDeferredJobArray(),
                        BiomeDistance = instanceData.BiomeDistance.ToDeferredJobArray(),
                        MinScale      = vegetationItemInfoPro.BiomeEdgeScaleMinScale,
                        MaxScale      = vegetationItemInfoPro.BiomeEdgeScaleMaxScale,
                        MaxDistance   = vegetationItemInfoPro.BiomeEdgeScaleDistance,
                        InverseScale  = vegetationItemInfoPro.BiomeEdgeScaleInverse
                    };
                    vegetationItemHandle = biomeEdgeDistanceScaleRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseBiomeEdgeIncludeRule && currentBiome != BiomeType.Default)
                {
                    BiomeEdgeDistanceIncludeRuleJob biomeEdgeDistanceIncludeRuleJob =
                        new BiomeEdgeDistanceIncludeRuleJob
                    {
                        Excluded      = instanceData.Excluded.ToDeferredJobArray(),
                        BiomeDistance = instanceData.BiomeDistance.ToDeferredJobArray(),
                        MaxDistance   = vegetationItemInfoPro.BiomeEdgeIncludeDistance,
                        Inverse       = vegetationItemInfoPro.BiomeEdgeIncludeInverse
                    };
                    vegetationItemHandle = biomeEdgeDistanceIncludeRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                if (vegetationItemInfoPro.UseTerrainTextureIncludeRules)
                {
                    for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++)
                    {
                        vegetationItemHandle = VegetationStudioTerrainList[k]
                                               .ProcessSplatmapRules(vegetationItemInfoPro.TerrainTextureIncludeRuleList, instanceData,
                                                                     true,
                                                                     vegetationCellRect,
                                                                     vegetationItemHandle);
                    }
                }

                if (vegetationItemInfoPro.UseTerrainTextureExcludeRules)
                {
                    for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++)
                    {
                        vegetationItemHandle = VegetationStudioTerrainList[k]
                                               .ProcessSplatmapRules(vegetationItemInfoPro.TerrainTextureExcludeRuleList, instanceData,
                                                                     false,
                                                                     vegetationCellRect,
                                                                     vegetationItemHandle);
                    }
                }

                if (vegetationItemInfoPro.UseDistanceFalloff)
                {
                    DistanceFalloffJob distanceFalloffJob =
                        new DistanceFalloffJob
                    {
                        Excluded                     = instanceData.Excluded.ToDeferredJobArray(),
                        RandomNumberIndex            = instanceData.RandomNumberIndex.ToDeferredJobArray(),
                        DistanceFalloff              = instanceData.DistanceFalloff.ToDeferredJobArray(),
                        RandomNumbers                = RandomNumbers,
                        DistanceFalloffStartDistance = vegetationItemInfoPro.DistanceFalloffStartDistance
                    };
                    vegetationItemHandle = distanceFalloffJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle);
                }

                NewCreateInstanceMatrixJob createInstanceMatrixJob =
                    new NewCreateInstanceMatrixJob
                {
                    Excluded        = instanceData.Excluded,
                    Position        = instanceData.Position,
                    Scale           = instanceData.Scale,
                    Rotation        = instanceData.Rotation,
                    DistanceFalloff = instanceData.DistanceFalloff,
                    VegetationInstanceMatrixList = matrixList
                };

                vegetationItemHandle = createInstanceMatrixJob.Schedule(vegetationItemHandle);
            }

            if (!doRuntimeSpawn)
            {
                if (PersistentVegetationStorage && !PersistentVegetationStorage.DisablePersistentStorage)
                {
                    PersistentVegetationCell persistentVegetationCell = PersistentVegetationStorage.GetPersistentVegetationCell(vegetationCell.Index);
                    PersistentVegetationInfo persistentVegetationInfo = persistentVegetationCell?.GetPersistentVegetationInfo(vegetationItemInfoPro.VegetationItemID);
                    if (persistentVegetationInfo != null && persistentVegetationInfo.VegetationItemList.Count > 0)
                    {
                        persistentVegetationInfo.CopyToNativeArray();
                        matrixList.ResizeUninitialized(persistentVegetationInfo.NativeVegetationItemArray.Length);

                        LoadPersistentStorageToMatrixWideJob loadPersistentStorageToMatrixJob =
                            new LoadPersistentStorageToMatrixWideJob
                        {
                            InstanceList = persistentVegetationInfo.NativeVegetationItemArray,
                            VegetationInstanceMatrixList = matrixList.ToDeferredJobArray(),
                            VegetationSystemPosition     = VegetationSystemPro.VegetationSystemPosition
                        };
                        vegetationItemHandle = loadPersistentStorageToMatrixJob.Schedule(matrixList, 64, vegetationItemHandle);
                    }
                }
            }
            else
            {
                if (PersistentVegetationStorage && !PersistentVegetationStorage.DisablePersistentStorage)
                {
                    PersistentVegetationCell persistentVegetationCell = PersistentVegetationStorage.GetPersistentVegetationCell(vegetationCell.Index);
                    PersistentVegetationInfo persistentVegetationInfo = persistentVegetationCell?.GetPersistentVegetationInfo(vegetationItemInfoPro.VegetationItemID);
                    if (persistentVegetationInfo != null && persistentVegetationInfo.VegetationItemList.Count > 0)
                    {
                        persistentVegetationInfo.CopyToNativeArray();
                        LoadPersistentStorageToMatrixJob loadPersistentStorageToMatrixJob =
                            new LoadPersistentStorageToMatrixJob
                        {
                            InstanceList = persistentVegetationInfo.NativeVegetationItemArray,
                            VegetationInstanceMatrixList = matrixList,
                            VegetationSystemPosition     = VegetationSystemPro.VegetationSystemPosition
                        };

                        vegetationItemHandle = loadPersistentStorageToMatrixJob.Schedule(vegetationItemHandle);
                    }
                }
            }

            Profiler.BeginSample("Schedule batched jobs");
            JobHandle.ScheduleBatchedJobs();
            Profiler.EndSample();

            return(vegetationItemHandle);
        }
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if VEGETATION_STUDIO
            if (stop != null && stop(0))
            {
                return;
            }

            //preparing and clearing storage
            if (vetStorComponents == null || vetStorComponents.Count == 0)
            {
                return;                                                                        //vs not used (process runs anyway)
            }
            PersistentVegetationStorage storage = vetStorComponents[rect];

            int cellXCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize);
            int cellZCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize);

            Noise noise = new Noise(12345, permutationCount: 128);            //to pick objects based on biome


            //clearing all of the items
            foreach (VegetationStudioOutput gen in gens.GeneratorsOfType <VegetationStudioOutput>(onlyEnabled:true, checkBiomes:true))
            {
                for (int b = 0; b < gen.layers.Length; b++)
                {
                    string id = gen.package.VegetationInfoList[b].VegetationItemID;
                    storage.RemoveVegetationItemInstances(id, VS_MM_id);
                }
                break;                 //iterating in one generator only - they use the same layers
            }

            if (stop != null && stop(0))
            {
                return;
            }

            //object outputs
            foreach (VegetationStudioOutput gen in gens.GeneratorsOfType <VegetationStudioOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //gen biome mask
                Matrix biomeMask = null;
                if (gen.biome != null)
                {
                    object biomeMaskObj = gen.biome.mask.GetObject(results);
                    if (biomeMaskObj == null)
                    {
                        continue;                                           //adding nothing if biome has no mask
                    }
                    biomeMask = (Matrix)biomeMaskObj;
                    if (biomeMask == null)
                    {
                        continue;
                    }
                    if (biomeMask.IsEmpty())
                    {
                        continue;                                          //optimizing empty biomes
                    }
                }

                //iterating in layers
                for (int b = 0; b < gen.layers.Length; b++)
                {
                    if (stop != null && stop(0))
                    {
                        return;                                            //checking stop before reading output
                    }
                    Layer layer = gen.layers[b];

                    string id = gen.package.VegetationInfoList[b].VegetationItemID;


                    //objects layer
                    if (layer.type == Layer.Type.Object)
                    {
                        //loading objects from input
                        SpatialHash hash = (SpatialHash)gen.layers[b].objInput.GetObject(results);
                        if (hash == null)
                        {
                            continue;
                        }

                        //filling instances (no need to check/add key in multidict)
                        foreach (SpatialObject obj in hash.AllObjs())
                        {
                            //skipping on biome not used
                            float biomeFactor = 0;
                            if (gen.biome == null)
                            {
                                biomeFactor = 1;
                            }
                            else if (biomeMask != null)
                            {
                                biomeFactor = biomeMask.GetInterpolated(obj.pos.x, obj.pos.y);
                            }
                            if (biomeFactor < 0.00001f)
                            {
                                continue;
                            }

                            float rnd;
                            switch (biomeBlendType)
                            {
                            case ObjectOutput.BiomeBlendType.Sharp: rnd = 0.5f; break;

                            case ObjectOutput.BiomeBlendType.AdditiveRandom:
                            case ObjectOutput.BiomeBlendType.NormalizedRandom:
                                rnd = noise.Random((int)obj.pos.x, (int)obj.pos.y);
                                if (biomeFactor > 0.5f)
                                {
                                    rnd = 1 - rnd;                                                           //test
                                }
                                break;

                            case ObjectOutput.BiomeBlendType.Scale: rnd = 0.0f; break;

                            default: rnd = 0.5f; break;
                            }

                            if (biomeFactor < rnd)
                            {
                                continue;
                            }

                            //flooring
                            float terrainHeight = 0;
                            if (layer.relativeHeight && results.heights != null)                             //if checbox enabled and heights exist (at least one height generator is in the graph)
                            {
                                terrainHeight = results.heights.GetInterpolated(obj.pos.x, obj.pos.y);
                            }
                            if (terrainHeight > 1)
                            {
                                terrainHeight = 1;
                            }


                            //terrain-space object position
                            Vector3 position = new Vector3(
                                (obj.pos.x - hash.offset.x) / hash.size * terrainSize.dimensions,
                                (obj.height + terrainHeight) * terrainSize.height,
                                (obj.pos.y - hash.offset.y) / hash.size * terrainSize.dimensions);

                            //cell number
                            int cx = (int)(position.x / cellSize);
                            int cz = (int)(position.z / cellSize);
                            PersistentVegetationCell cell = storage.PersistentVegetationStoragePackage.PersistentVegetationCellList[cz + cx * cellXCount];

                            //rotation + taking terrain normal
                            Quaternion rotation;
                            float      objRotation = layer.rotate ? obj.rotation % 360 : 0;
                            if (layer.takeTerrainNormal)
                            {
                                Vector3 terrainNormal = ObjectOutput.GetTerrainNormal(obj.pos.x, obj.pos.y, results.heights, terrainSize.height, terrainSize.pixelSize);
                                Vector3 sideVector    = new Vector3(Mathf.Sin((obj.rotation + 90) * Mathf.Deg2Rad), 0, Mathf.Cos((obj.rotation + 90) * Mathf.Deg2Rad));
                                Vector3 frontVector   = Vector3.Cross(sideVector, terrainNormal);
                                rotation = Quaternion.LookRotation(frontVector, terrainNormal);
                            }
                            else
                            {
                                rotation = objRotation.EulerToQuat();
                            }

                            //scale + biome scale mode
                            Vector3 scale = layer.scale ? new Vector3(layer.scaleY ? 1 : obj.size, obj.size, layer.scaleY ? 1 : obj.size) : Vector3.one;

                            if (biomeBlendType == ObjectOutput.BiomeBlendType.Scale && gen.biome != null)
                            {
                                float biomeVal = 1;
                                if (biomeMask != null)
                                {
                                    biomeVal = biomeMask[obj.pos];
                                }
                                if (biomeVal < 0.001f)
                                {
                                    continue;                                                     //skip zero-scaled objects
                                }
                                scale *= biomeVal;
                            }

                            //storage.AddVegetationItemInstance(id, position, scale, rotation, layer.applyMeshRotation, VS_MM_id, true);
                            cell.AddVegetationItemInstance(id, position, scale, rotation, VS_MM_id);
                        }

                        if (stop != null && stop(0))
                        {
                            return;
                        }
                    }


                    //map outputs
                    if (layer.type == Layer.Type.Map)
                    {
                        //reading output directly
                        //Output output = gen.layers[b].output;
                        //if (stop!=null && stop(0)) return; //checking stop before reading output
                        //if (!results.results.ContainsKey(output)) continue;
                        //Matrix matrix = (Matrix)results.results[output];

                        //loading from input
                        if (stop != null && stop(0))
                        {
                            return;
                        }
                        Matrix matrix = (Matrix)gen.layers[b].mapInput.GetObject(results);
                        if (matrix == null)
                        {
                            continue;
                        }
                        Matrix heights = results.heights;                         //get heights before the chunk is removed

                        //setting bush by bush using the sample dist
                        float sampleDist = 1f / layer.density;

                        //filling
                        float terrainPosX = 1f * rect.offset.x / terrainSize.resolution * terrainSize.dimensions;
                        float terrainPosZ = 1f * rect.offset.z / terrainSize.resolution * terrainSize.dimensions;



                        for (int cx = 0; cx <= cellXCount - 1; cx++)
                        {
                            for (int cz = 0; cz <= cellZCount - 1; cz++)
                            {
                                Vector3 cellCorner            = new Vector3(terrainPosX + (cellSize * cx), 0, terrainPosZ + (cellSize * cz));
                                PersistentVegetationCell cell = storage.PersistentVegetationStoragePackage.PersistentVegetationCellList[cz + cx * cellXCount];

                                for (float x = 0; x < cellSize; x += sampleDist)
                                {
                                    for (float z = 0; z < cellSize; z += sampleDist)
                                    {
                                        //world position
                                        float wx = cellSize * cx + x;
                                        float wz = cellSize * cz + z;

                                        //randomizing position
                                        wx += noise.Random((int)(wx * 10), (int)(wz * 10), 2) * sampleDist - sampleDist / 2;
                                        wz += noise.Random((int)(wx * 10), (int)(wz * 10), 3) * sampleDist - sampleDist / 2;

                                        //map position
                                        float mx = wx / terrainSize.dimensions * rect.size.x + rect.offset.x;                                    // relative (0-1) position * terrain res
                                        float mz = wz / terrainSize.dimensions * rect.size.z + rect.offset.z;

                                        float val = matrix.GetInterpolated(mx, mz);

                                        float biomeFactor = 0;
                                        if (gen.biome == null)
                                        {
                                            biomeFactor = 1;
                                        }
                                        else if (biomeMask != null)
                                        {
                                            biomeFactor = biomeMask.GetInterpolated(mx, mz);
                                        }

                                        //placing object
                                        float rnd = (noise.Random((int)(wx * 10), (int)(wz * 10)));
                                        if (rnd < val * biomeFactor)
                                        {
                                            float terrainHeight = heights.GetInterpolated(mx, mz) * terrainSize.height;

                                            //rotation + taking terrain normal
                                            Quaternion rotation;
                                            float      rotRnd      = noise.Random((int)(wx * 10), (int)(wz * 10), 1);
                                            float      objRotation = layer.rotate ? rotRnd * 360 : 0;
                                            if (layer.takeTerrainNormal)
                                            {
                                                Vector3 terrainNormal = ObjectOutput.GetTerrainNormal(mx, mz, heights, terrainSize.height, terrainSize.pixelSize);
                                                Vector3 sideVector    = new Vector3(Mathf.Sin((objRotation + 90) * Mathf.Deg2Rad), 0, Mathf.Cos((objRotation + 90) * Mathf.Deg2Rad));
                                                Vector3 frontVector   = Vector3.Cross(sideVector, terrainNormal);
                                                rotation = Quaternion.LookRotation(frontVector, terrainNormal);
                                            }
                                            else
                                            {
                                                rotation = objRotation.EulerToQuat();
                                            }

                                            //scale
                                            float rndScale = noise.Random((int)(wx * 10), (int)(wz * 10), 1);
                                            rndScale = layer.scaleMinMax.x + (layer.scaleMinMax.y - layer.scaleMinMax.x) * rndScale;
                                            Vector3 scale = new Vector3(rndScale, rndScale, rndScale);

                                            //storage.AddVegetationItemInstance(id, new Vector3(wx,terrainHeight,wz), scale, rotation, layer.applyMeshRotation, VS_MM_id, true);
                                            cell.AddVegetationItemInstance(id, new Vector3(wx, terrainHeight, wz), scale, rotation, VS_MM_id);
                                        }
                                    }
                                }

                                if (stop != null && stop(0))
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
            }

            //refreshing billboards
            //calling it from thread ruins all the billboards
            //BillboardSystem billboardSys = billboardComponents[rect];
            //if (billboardSys != null)
            //	 billboardSys.RefreshBillboards();
                        #endif

            //pushing anything to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VegetationStudioOutput), null, replace: true);
        }