public override void OnGUI(GeneratorsAsset gens)
        {
            Transform mm = MapMagic.MapMagic.instance.gameObject.transform;

            stamper = mm.GetComponentInChildren <MapMagicStamper>();


            base.OnGUI(gens);
            if ((null == stamper || null != stamper && stamper.Generator != this) && layout.Button("Show Stamper"))
            {
                if (null == stamper || stamper.Generator != this)
                {
                    if (null != stamper)
                    {
                        GameObject.DestroyImmediate(stamper.gameObject);
                    }
                    GameObject go = new GameObject("Stamper");
                    go.transform.parent    = mm;
                    stamper                = go.AddComponent <MapMagicStamper>();
                    stamper.Generator      = this;
                    Selection.activeObject = stamper;
                }
            }
            else if (null != stamper && stamper.Generator == this && layout.Button("Hide Stamper"))
            {
                GameObject.DestroyImmediate(stamper.gameObject);
            }
        }
示例#2
0
        public override void OnGUI(GeneratorsAsset gens)
        {
            layout.Par(20); maskIn.DrawIcon(layout, "Mask");
            layout.fieldSize = .6f;
            layout.Field(ref LayerName, "Layer");
            layout.fieldSize = .5f;
            layout.Field(ref patchResolution, "Patch Res", min: 4, max: 64, fieldSize: 0.35f);
            patchResolution = Mathf.ClosestPowerOfTwo(patchResolution);
            layout.Field(ref obscureLayers, "Obscure Layers", fieldSize: 0.35f);

            //layer buttons
            layout.Par(3);
            layout.Par();
            layout.Label("Layers:", layout.Inset(0.4f));

            layout.DrawArrayAdd(ref baseLayers, ref selected, rect: layout.Inset(0.15f), reverse: true, createElement: () => new Layer());
            layout.DrawArrayRemove(ref baseLayers, ref selected, rect: layout.Inset(0.15f), reverse: true, onBeforeRemove: UnlinkLayer);
            layout.DrawArrayDown(ref baseLayers, ref selected, rect: layout.Inset(0.15f), dispUp: true);
            layout.DrawArrayUp(ref baseLayers, ref selected, rect: layout.Inset(0.15f), dispDown: true);

            //layers
            layout.Par(3);
            for (int num = baseLayers.Length - 1; num >= 0; num--)
            {
                layout.DrawLayer(baseLayers[num].OnGUI, ref selected, num);
            }

            layout.fieldSize = 0.4f; layout.margin = 10; layout.rightMargin = 10;
            layout.Par(5);
        }
 public override void OnGUI(GeneratorsAsset gens)
 {
     layout.Par(20);
     input.DrawIcon(layout);
     output.DrawIcon(layout);
     layout.Field(ref kernelType, "Kernel Size");
 }
示例#4
0
 public override void OnGUI(GeneratorsAsset gens)
 {
     layout.Par(20);
     input.DrawIcon(layout);
     output.DrawIcon(layout);
     layout.Field(ref heightMin, "Height Min");
     layout.Field(ref heightMax, "Height Max");
 }
示例#5
0
        public override void OnGUI(GeneratorsAsset gens)
        {
            layout.fieldSize = .6f;
            layout.Field(ref LayerName, "Layer");
            layout.fieldSize = .5f;

            layout.Par(20); input.DrawIcon(layout, "Stencil");
            layout.Par(5);

            if (output == null)
            {
                output = new Output(InoutType.Map);
            }
        }
示例#6
0
        public override void OnGUI(GeneratorsAsset gens)
        {
            layout.fieldSize = .6f;
            layout.Field(ref LayerName, "Layer");
            layout.fieldSize = .5f;

            layout.Par(20); input.DrawIcon(layout, "Height");
            layout.Par(5);

            if (output == null)
            {
                output = new Output(InoutType.Map);
            }

            layout.Field(ref scale, "Scale", min: 1, max: 4f);
            scale = Mathf.NextPowerOfTwo(scale);
        }
示例#7
0
        public override void OnGUI(GeneratorsAsset gens)
        {
            layout.fieldSize = .6f;
            layout.Field(ref LayerName, "Layer");
            layout.fieldSize = .5f;
            //Layer buttons
            layout.Par();
            layout.Label("Layers:", layout.Inset(0.4f));

            layout.DrawArrayAdd(ref baseLayers, ref selected, rect: layout.Inset(0.15f), reverse: true, createElement: () => new Layer(), onAdded: UnlinkBaseLayer);
            layout.DrawArrayRemove(ref baseLayers, ref selected, rect: layout.Inset(0.15f), reverse: true, onBeforeRemove: UnlinkLayer, onRemoved: UnlinkBaseLayer);
            layout.DrawArrayDown(ref baseLayers, ref selected, rect: layout.Inset(0.15f), dispUp: true, onSwitch: UnlinkBaseLayer);
            layout.DrawArrayUp(ref baseLayers, ref selected, rect: layout.Inset(0.15f), dispDown: true, onSwitch: UnlinkBaseLayer);

            //layers
            layout.Par(3);
            for (int num = baseLayers.Length - 1; num >= 0; num--)
            {
                layout.DrawLayer(baseLayers[num].OnGUI, ref selected, num);
            }
        }
示例#8
0
        public override void OnGUI(GeneratorsAsset gens)
        {
                        #if VEGETATION_STUDIO_PRO
            //VegetationPackagePro package = (VegetationPackagePro)serializedPackage;
            layout.Field(ref package, "Package", fieldSize: 0.6f);
            //serializedPackage = package;

            //filling object names array for popup
            if (package != null)
            {
                objectNames = new string[package.VegetationInfoList.Count];
                for (int i = 0; i < objectNames.Length; i++)
                {
                    objectNames[i] = package.VegetationInfoList[i].Name;
                }
            }
            else
            {
                objectNames = null;
            }

            //layer buttons
            layout.Par();
            layout.Label("Layers:", layout.Inset(0.4f));

            layout.DrawArrayAdd(ref baseLayers, ref selected, rect: layout.Inset(0.15f), createElement: () => new Layer());
            layout.DrawArrayRemove(ref baseLayers, ref selected, rect: layout.Inset(0.15f), onBeforeRemove: UnlinkLayer);
            layout.DrawArrayUp(ref baseLayers, ref selected, rect: layout.Inset(0.15f));
            layout.DrawArrayDown(ref baseLayers, ref selected, rect: layout.Inset(0.15f));

            //layers
            layout.Par(3);
            for (int num = 0; num < baseLayers.Length; num++)
            {
                layout.DrawLayer(baseLayers[num].OnGUI, ref selected, num, this);
            }
                        #endif
        }
示例#9
0
        public override void OnGUI(GeneratorsAsset gens)
        {
                        #if VEGETATION_STUDIO_PRO
            layout.Field(ref package, "Package", fieldSize: 0.6f);
                        #endif
            layout.Field(ref obscureLayers, "Obscure Layers", fieldSize: 0.35f);

            //layer buttons
            layout.Par();
            layout.Label("Layers:", layout.Inset(0.4f));

            layout.DrawArrayAdd(ref baseLayers, ref selected, rect: layout.Inset(0.15f), createElement: () => new Layer());
            layout.DrawArrayRemove(ref baseLayers, ref selected, rect: layout.Inset(0.15f), onBeforeRemove: UnlinkLayer);
            layout.DrawArrayUp(ref baseLayers, ref selected, rect: layout.Inset(0.15f));
            layout.DrawArrayDown(ref baseLayers, ref selected, rect: layout.Inset(0.15f));

            //layers
            layout.Par(3);
            for (int num = 0; num < baseLayers.Length; num++)
            {
                layout.DrawLayer(baseLayers[num].OnGUI, ref selected, num, this);
            }
        }
示例#10
0
        public override void OnGUI(GeneratorsAsset gens)
        {
            layout.fieldSize = .6f;
            layout.Field(ref LayerName, "Layer");
            layout.fieldSize = .5f;

            layout.Field(ref ApplyStamps, "Apply Stamps");

            //layer buttons
            layout.Par();
            layout.Label("Layers:", layout.Inset(0.4f));

            layout.DrawArrayAdd(ref baseLayers, ref selected, rect: layout.Inset(0.15f), createElement: () => new Layer());
            layout.DrawArrayRemove(ref baseLayers, ref selected, rect: layout.Inset(0.15f), onBeforeRemove: UnlinkLayer);
            layout.DrawArrayUp(ref baseLayers, ref selected, rect: layout.Inset(0.15f));
            layout.DrawArrayDown(ref baseLayers, ref selected, rect: layout.Inset(0.15f));

            //layers
            layout.Par(3);
            for (int num = 0; num < baseLayers.Length; num++)
            {
                layout.DrawLayer(baseLayers[num].OnGUI, ref selected, num);
            }
        }
示例#11
0
        public static void Process(MapMagic.CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
            if (stop != null && stop(0))
            {
                return;
            }

            //values to calculate density
            float pixelSize   = terrainSize.pixelSize;
            float pixelSquare = pixelSize * pixelSize;

            //a random needed to convert float to int
            InstanceRandom rnd = new InstanceRandom(terrainSize.Seed(rect));

            //calculating the totoal number of prototypes
            int prototypesNum = 0;

            foreach (MadMapsGrassOutput grassOut in gens.GeneratorsOfType <MadMapsGrassOutput>())
            {
                prototypesNum += grassOut.baseLayers.Length;
            }

            //preparing results
            List <int[, ]> detailsList = new List <int[, ]>();
            List <DetailPrototypeWrapper> prototypesList = new List <DetailPrototypeWrapper>();

            //filling result
            foreach (MadMapsGrassOutput gen in gens.GeneratorsOfType <MadMapsGrassOutput>(onlyEnabled: true, checkBiomes: true))
            {
                //loading biome matrix
                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
                    }
                }

                for (int i = 0; i < gen.baseLayers.Length; i++)
                {
                    if (stop != null && stop(0))
                    {
                        return;
                    }

                    //loading objects from input
                    //Matrix matrix = (Matrix)gen.baseLayers[i].input.GetObject(chunk);
                    //if (matrix == null) continue;

                    //reading output directly
                    Output output = gen.baseLayers[i].output;
                    if (stop != null && stop(0))
                    {
                        return;                                            //checking stop before reading output
                    }
                    if (!results.results.ContainsKey(output))
                    {
                        continue;
                    }
                    Matrix matrix = (Matrix)results.results[output];

                    //filling array
                    int[,] detail = new int[matrix.rect.size.x, matrix.rect.size.z];
                    for (int x = 0; x < matrix.rect.size.x; x++)
                    {
                        for (int z = 0; z < matrix.rect.size.z; z++)
                        {
                            float val      = matrix[x + matrix.rect.offset.x, z + matrix.rect.offset.z];
                            float biomeVal = 1;
                            if (gen.biome != null)
                            {
                                if (biomeMask == null)
                                {
                                    biomeVal = 0;
                                }
                                else
                                {
                                    biomeVal = biomeMask[x + matrix.rect.offset.x, z + matrix.rect.offset.z];
                                }
                            }
                            detail[z, x] = rnd.RandomToInt(val * gen.baseLayers[i].density * pixelSquare * biomeVal);
                        }
                    }

                    //adding to arrays
                    detailsList.Add(detail);
                    prototypesList.Add(gen.baseLayers[i].Wrapper);
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }

            TupleSet <int[][, ], DetailPrototypeWrapper[]> grassTuple = new TupleSet <int[][, ], DetailPrototypeWrapper[]>(detailsList.ToArray(), prototypesList.ToArray());

            results.apply.CheckAdd(typeof(MadMapsGrassOutput), grassTuple, replace: true);
        }
示例#12
0
        public static void Process(MapMagic.CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
            if (stop != null && stop(0))
            {
                return;
            }

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

            //preparing output
            Dictionary <Transform, List <ObjectPool.Transition> > transitions = new Dictionary <Transform, List <ObjectPool.Transition> >();

            //find all of the biome masks - they will be used to determine object probability
            List <TupleSet <MadMapsObjectOutput, Matrix> > allGensMasks = new List <TupleSet <MadMapsObjectOutput, Matrix> >();

            foreach (MadMapsObjectOutput gen in gens.GeneratorsOfType <MadMapsObjectOutput>(onlyEnabled: true, checkBiomes: true))
            {
                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
                    }
                }

                allGensMasks.Add(new TupleSet <MadMapsObjectOutput, Matrix>(gen, biomeMask));
            }
            int allGensMasksCount = allGensMasks.Count;

            //biome rect to find array pos faster
            MapMagic.CoordRect biomeRect = new MapMagic.CoordRect();
            for (int g = 0; g < allGensMasksCount; g++)
            {
                if (allGensMasks[g].item2 != null)
                {
                    biomeRect = allGensMasks[g].item2.rect; break;
                }
            }

            //prepare biome mask values stack to re-use it to find per-coord biome
            float[] biomeVals = new float[allGensMasksCount];             //+1 for not using any object at all

            //iterating all gens
            for (int g = 0; g < allGensMasksCount; g++)
            {
                MadMapsObjectOutput gen = allGensMasks[g].item1;

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

                    //loading objects from input
                    SpatialHash hash = (SpatialHash)gen.baseLayers[b].input.GetObject(results);
                    if (hash == null)
                    {
                        continue;
                    }

                    //finding/creating proper transitions list
                    List <ObjectPool.Transition> transitionsList;
                    if (!transitions.ContainsKey(layer.prefab))
                    {
                        transitionsList = new List <ObjectPool.Transition>(); transitions.Add(layer.prefab, transitionsList);
                    }
                    else
                    {
                        transitionsList = transitions[layer.prefab];
                    }

                    //filling instances (no need to check/add key in multidict)
                    foreach (SpatialObject obj in hash.AllObjs())
                    {
                        //blend biomes - calling continue if improper biome
                        if (biomeBlendType == BiomeBlendType.Sharp)
                        {
                            float biomeVal = 1;
                            if (allGensMasks[g].item2 != null)
                            {
                                biomeVal = allGensMasks[g].item2[obj.pos];
                            }
                            if (biomeVal < 0.5f)
                            {
                                continue;
                            }
                        }
                        else if (biomeBlendType == BiomeBlendType.AdditiveRandom)
                        {
                            float biomeVal = 1;
                            if (allGensMasks[g].item2 != null)
                            {
                                biomeVal = allGensMasks[g].item2[obj.pos];
                            }

                            float rnd = noise.Random((int)obj.pos.x, (int)obj.pos.y);

                            if (biomeVal > 0.5f)
                            {
                                rnd = 1 - rnd;
                            }

                            if (biomeVal < rnd)
                            {
                                continue;
                            }
                        }
                        else if (biomeBlendType == BiomeBlendType.NormalizedRandom)
                        {
                            //filling biome masks values
                            int pos = biomeRect.GetPos(obj.pos);

                            for (int i = 0; i < allGensMasksCount; i++)
                            {
                                if (allGensMasks[i].item2 != null)
                                {
                                    biomeVals[i] = allGensMasks[i].item2.array[pos];
                                }
                                else
                                {
                                    biomeVals[i] = 1;
                                }
                            }

                            //calculate normalized sum
                            float sum = 0;
                            for (int i = 0; i < biomeVals.Length; i++)
                            {
                                sum += biomeVals[i];
                            }
                            if (sum > 1)                             //note that if sum is <1 usedBiomeNum can exceed total number of biomes - it means that none object is used here
                            {
                                for (int i = 0; i < biomeVals.Length; i++)
                                {
                                    biomeVals[i] = biomeVals[i] / sum;
                                }
                            }

                            //finding used biome num
                            float rnd          = noise.Random((int)obj.pos.x, (int)obj.pos.y);
                            int   usedBiomeNum = biomeVals.Length;                           //none biome by default
                            sum = 0;
                            for (int i = 0; i < biomeVals.Length; i++)
                            {
                                sum += biomeVals[i];
                                if (sum > rnd)
                                {
                                    usedBiomeNum = i; break;
                                }
                            }

                            //disable object using biome mask
                            if (usedBiomeNum != g)
                            {
                                continue;
                            }
                        }
                        //scale mode is applied a bit later


                        //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;


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

                        //rotation + taking terrain normal
                        Quaternion rotation;
                        float      objRotation = layer.rotate ? obj.rotation % 360 : 0;
                        if (layer.takeTerrainNormal)
                        {
                            Vector3 terrainNormal = 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 == BiomeBlendType.Scale)
                        {
                            float biomeVal = 1;
                            if (allGensMasks[g].item2 != null)
                            {
                                biomeVal = allGensMasks[g].item2[obj.pos];
                            }
                            if (biomeVal < 0.001f)
                            {
                                continue;
                            }
                            scale *= biomeVal;
                        }

                        transitionsList.Add(new ObjectPool.Transition()
                        {
                            pos = position, rotation = rotation, scale = scale
                        });
                    }
                }
            }

            //queue apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(MadMapsObjectOutput), transitions, replace: true);
        }
示例#13
0
        public void Process(global::MapMagic.CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
            if (stop != null && stop(0))
            {
                return;
            }

            Matrix result = new Matrix(rect);

            foreach (MadMapsStencilOutput gen in gens.GeneratorsOfType <MadMapsStencilOutput>(onlyEnabled: true, checkBiomes: true))
            {
                Matrix input = (Matrix)gen.input.GetObject(results);
                if (input == null)
                {
                    continue;
                }

                //loading biome matrix
                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
                    }
                }

                //adding to final result
                if (gen.biome == null)
                {
                    result.Add(input);
                }
                else if (biomeMask != null)
                {
                    result.Add(input, biomeMask);
                }
            }

            //creating 2d array
            if (stop != null && stop(0))
            {
                return;
            }

            int heightSize = terrainSize.resolution;
            var stencil    = new Stencil(heightSize, heightSize);
            int key        = 1;

            for (int x = 0; x < heightSize - 1; x++)
            {
                for (int z = 0; z < heightSize - 1; z++)
                {
                    float strength;
                    int   disposableKey;
                    MiscUtilities.DecompressStencil(stencil[x, z], out disposableKey, out strength);

                    var writeValue = result[x + results.heights.rect.offset.x, z + results.heights.rect.offset.z];

                    stencil[x, z] = MiscUtilities.CompressStencil(key, strength + writeValue);
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(MadMapsStencilOutput), stencil, replace: true);
        }
示例#14
0
        public static void Process(MapMagic.CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
            if (stop != null && stop(0))
            {
                return;
            }

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

            List <TreeInstance>  instancesList  = new List <TreeInstance>();
            List <TreePrototype> prototypesList = new List <TreePrototype>();

            //find all of the biome masks - they will be used to determine object probability
            List <TupleSet <MadMapsTreeOutput, Matrix> > allGensMasks = new List <TupleSet <MadMapsTreeOutput, Matrix> >();

            foreach (MadMapsTreeOutput gen in gens.GeneratorsOfType <MadMapsTreeOutput>(onlyEnabled: true, checkBiomes: true))
            {
                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
                    }
                }

                allGensMasks.Add(new TupleSet <MadMapsTreeOutput, Matrix>(gen, biomeMask));
            }
            int allGensMasksCount = allGensMasks.Count;

            //biome rect to find array pos faster
            MapMagic.CoordRect biomeRect = new MapMagic.CoordRect();
            for (int g = 0; g < allGensMasksCount; g++)
            {
                if (allGensMasks[g].item2 != null)
                {
                    biomeRect = allGensMasks[g].item2.rect; break;
                }
            }

            //prepare biome mask values stack to re-use it to find per-coord biome
            float[] biomeVals = new float[allGensMasksCount];             //+1 for not using any object at all

            //iterating all gens
            for (int g = 0; g < allGensMasksCount; g++)
            {
                MadMapsTreeOutput gen = allGensMasks[g].item1;

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

                    //loading objects from input
                    SpatialHash hash = (SpatialHash)gen.baseLayers[b].input.GetObject(results);
                    if (hash == null)
                    {
                        continue;
                    }

                    //adding prototype
//					if (layer.prefab == null) continue;
                    TreePrototype prototype = new TreePrototype()
                    {
                        prefab = layer.prefab, bendFactor = layer.bendFactor
                    };
                    prototypesList.Add(prototype);
                    int prototypeNum = prototypesList.Count - 1;

                    //filling instances (no need to check/add key in multidict)
                    foreach (SpatialObject obj in hash.AllObjs())
                    {
                        //blend biomes - calling continue if improper biome
                        if (biomeBlendType == BiomeBlendType.Sharp)
                        {
                            float biomeVal = 1;
                            if (allGensMasks[g].item2 != null)
                            {
                                biomeVal = allGensMasks[g].item2[obj.pos];
                            }
                            if (biomeVal < 0.5f)
                            {
                                continue;
                            }
                        }
                        else if (biomeBlendType == BiomeBlendType.AdditiveRandom)
                        {
                            float biomeVal = 1;
                            if (allGensMasks[g].item2 != null)
                            {
                                biomeVal = allGensMasks[g].item2[obj.pos];
                            }

                            float rnd = noise.Random((int)obj.pos.x, (int)obj.pos.y);

                            if (biomeVal > 0.5f)
                            {
                                rnd = 1 - rnd;
                            }

                            if (biomeVal < rnd)
                            {
                                continue;
                            }
                        }
                        else if (biomeBlendType == BiomeBlendType.NormalizedRandom)
                        {
                            //filling biome masks values
                            int pos = biomeRect.GetPos(obj.pos);

                            for (int i = 0; i < allGensMasksCount; i++)
                            {
                                if (allGensMasks[i].item2 != null)
                                {
                                    biomeVals[i] = allGensMasks[i].item2.array[pos];
                                }
                                else
                                {
                                    biomeVals[i] = 1;
                                }
                            }

                            //calculate normalized sum
                            float sum = 0;
                            for (int i = 0; i < biomeVals.Length; i++)
                            {
                                sum += biomeVals[i];
                            }
                            if (sum > 1)                             //note that if sum is <1 usedBiomeNum can exceed total number of biomes - it means that none object is used here
                            {
                                for (int i = 0; i < biomeVals.Length; i++)
                                {
                                    biomeVals[i] = biomeVals[i] / sum;
                                }
                            }

                            //finding used biome num
                            float rnd          = noise.Random((int)obj.pos.x, (int)obj.pos.y);
                            int   usedBiomeNum = biomeVals.Length;                           //none biome by default
                            sum = 0;
                            for (int i = 0; i < biomeVals.Length; i++)
                            {
                                sum += biomeVals[i];
                                if (sum > rnd)
                                {
                                    usedBiomeNum = i; break;
                                }
                            }

                            //disable object using biome mask
                            if (usedBiomeNum != g)
                            {
                                continue;
                            }
                        }
                        //scale mode is applied a bit later

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

                        TreeInstance tree = new TreeInstance();
                        tree.position = new Vector3(
                            (obj.pos.x - hash.offset.x) / hash.size,
                            obj.height + terrainHeight,
                            (obj.pos.y - hash.offset.y) / hash.size);
                        tree.rotation       = layer.rotate ? obj.rotation % 360 : 0;
                        tree.widthScale     = layer.widthScale ? obj.size : 1;
                        tree.heightScale    = layer.heightScale ? obj.size : 1;
                        tree.prototypeIndex = prototypeNum;
                        tree.color          = layer.color;
                        tree.lightmapColor  = layer.color;

                        if (biomeBlendType == BiomeBlendType.Scale)
                        {
                            float biomeVal = 1;
                            if (allGensMasks[g].item2 != null)
                            {
                                biomeVal = allGensMasks[g].item2[obj.pos];
                            }
                            if (biomeVal < 0.001f)
                            {
                                continue;
                            }
                            tree.widthScale  *= biomeVal;
                            tree.heightScale *= biomeVal;
                        }

                        instancesList.Add(tree);
                    }
                }
            }

            //setting output
            if (stop != null && stop(0))
            {
                return;
            }
            if (instancesList.Count == 0 && prototypesList.Count == 0)
            {
                return;                                                                    //empty, process is caused by height change
            }
            TupleSet <TreeInstance[], TreePrototype[]> treesTuple = new TupleSet <TreeInstance[], TreePrototype[]>(instancesList.ToArray(), prototypesList.ToArray());

            results.apply.CheckAdd(typeof(MadMapsTreeOutput), treesTuple, replace: true);
        }
示例#15
0
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if VEGETATION_STUDIO_PRO
            if (stop != null && stop(0))
            {
                return;
            }

            //gathering prototypes and matrices lists
            List <Layer>         prototypesList = new List <Layer>();
            List <Matrix>        matrices       = new List <Matrix>();
            List <Matrix>        biomeMasks     = new List <Matrix>();
            VegetationPackagePro package        = null;

            foreach (VSProMapsOutput gen in gens.GeneratorsOfType <VSProMapsOutput>(onlyEnabled: true, checkBiomes: true))
            {
                //loading biome matrix
                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
                    }
                }

                for (int i = 0; i < gen.baseLayers.Length; i++)
                {
                    //reading output directly
                    Output output = gen.baseLayers[i].output;
                    if (stop != null && stop(0))
                    {
                        return;                                            //checking stop before reading output
                    }
                    if (!results.results.ContainsKey(output))
                    {
                        continue;
                    }
                    Matrix matrix = (Matrix)results.results[output];
                    matrix.Clamp01();

                    //adding to lists
                    matrices.Add(matrix);
                    biomeMasks.Add(gen.biome == null ? null : biomeMask);
                    prototypesList.Add(gen.baseLayers[i]);
                    package = gen.package;
                }
            }

            //optimizing matrices list if they are not used
//			for (int i = matrices.Count - 1; i >= 0; i--)
//				if (opacities[i] < 0.001f || matrices[i].IsEmpty() || (biomeMasks[i] != null && biomeMasks[i].IsEmpty()))
//				{ prototypesList.RemoveAt(i); opacities.RemoveAt(i); matrices.RemoveAt(i); biomeMasks.RemoveAt(i); }

            int numLayers = matrices.Count;
            if (numLayers == 0)
            {
                results.apply.CheckAdd(typeof(VSProMapsOutput), new TupleSet <Color[][], int[], VegetationPackagePro>(new Color[0][], new int[0], package), replace: true); return;
            }

            int maxX = MapMagic.instance.resolution; int maxZ = MapMagic.instance.resolution;

            Dictionary <int, Color[]> grNumToColors = new Dictionary <int, Color[]>();

            for (int i = 0; i < numLayers; i++)
            {
                int grNum = prototypesList[i].maskGroup;

                if (!grNumToColors.ContainsKey(grNum))
                {
                    grNumToColors.Add(grNum, new Color[maxX * maxZ]);
                }
            }

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

            float[] values = new float[numLayers];             //row, to avoid reading/writing 3d array (it is too slow)

            for (int x = 0; x < maxX; x++)
            {
                for (int z = 0; z < maxZ; z++)
                {
                    int   pos = rect.GetPos(x + rect.offset.x, z + rect.offset.z);
                    float sum = 0;

                    //getting values
                    for (int i = 0; i < numLayers; i++)
                    {
                        float val = matrices[i].array[pos];
                        if (biomeMasks[i] != null)
                        {
                            val *= biomeMasks[i].array[pos];                                                //if mask is not assigned biome was ignored, so only main outs with mask==null left here
                        }
                        if (val < 0)
                        {
                            val = 0;
                        }
                        if (val > 1)
                        {
                            val = 1;
                        }
                        sum      += val;                    //normalizing: calculating sum
                        values[i] = val;
                    }

                    //normalizing
                    for (int i = 0; i < numLayers; i++)
                    {
                        values[i] = values[i] / sum;
                    }

                    //setting color
                    for (int i = 0; i < numLayers; i++)
                    {
                        Layer layer = prototypesList[i];

                        Color[] texColors = grNumToColors[layer.maskGroup];

                        int   texturePos = z * maxX + x;
                        float val        = values[i];
                        switch (layer.textureChannel)
                        {
                        case 0: texColors[texturePos].r = val; break;

                        case 1: texColors[texturePos].g = val; break;

                        case 2: texColors[texturePos].b = val; break;

                        case 3: texColors[texturePos].a = val; break;
                        }
                    }
                }
            }

            //creating arrays
            Color[][] colors        = new Color[grNumToColors.Count][];
            int[]     maskGroupNums = new int[grNumToColors.Count];

            int counter = 0;
            foreach (var kvp in grNumToColors)
            {
                maskGroupNums[counter] = kvp.Key;
                colors[counter]        = kvp.Value;
                counter++;
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            TupleSet <Color[][], int[], VegetationPackagePro> mapsTuple = new TupleSet <Color[][], int[], VegetationPackagePro>(colors, maskGroupNums, package);
            results.apply.CheckAdd(typeof(VSProMapsOutput), mapsTuple, replace: true);
                        #endif
        }
示例#16
0
        public static void Process(MapMagic.CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
            if (stop != null && stop(0))
            {
                return;
            }

            //gathering prototypes and matrices lists
            List <SplatPrototypeWrapper> prototypesList = new List <SplatPrototypeWrapper>();
            List <float>  opacities  = new List <float>();
            List <Matrix> matrices   = new List <Matrix>();
            List <Matrix> biomeMasks = new List <Matrix>();

            foreach (MadMapsSplatOutput gen in gens.GeneratorsOfType <MadMapsSplatOutput>(onlyEnabled: true, checkBiomes: true))
            {
                //loading biome matrix
                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
                    }
                }

                for (int i = 0; i < gen.baseLayers.Length; i++)
                {
                    if (!gen.baseLayers[i].Wrapper)
                    {
                        continue;
                    }

                    //reading output directly
                    Output output = gen.baseLayers[i].output;
                    if (stop != null && stop(0))
                    {
                        return;                                            //checking stop before reading output
                    }
                    if (!results.results.ContainsKey(output))
                    {
                        continue;
                    }
                    Matrix matrix = (Matrix)results.results[output];
                    matrix.Clamp01();

                    //adding to lists
                    matrices.Add(matrix);
                    biomeMasks.Add(gen.biome == null ? null : biomeMask);
                    prototypesList.Add(gen.baseLayers[i].Wrapper);
                    opacities.Add(gen.baseLayers[i].opacity);
                }
            }

            //optimizing matrices list if they are not used
//			for (int i = matrices.Count - 1; i >= 0; i--)
//				if (opacities[i] < 0.001f || matrices[i].IsEmpty() || (biomeMasks[i] != null && biomeMasks[i].IsEmpty()))
//				{ prototypesList.RemoveAt(i); opacities.RemoveAt(i); matrices.RemoveAt(i); biomeMasks.RemoveAt(i); }

            //creating array
            float[,,] splats3D = new float[terrainSize.resolution, terrainSize.resolution, prototypesList.Count];
            if (matrices.Count == 0)
            {
                results.apply.CheckAdd(typeof(MadMapsSplatOutput), new TupleSet <float[, , ], SplatPrototypeWrapper[]>(splats3D, new SplatPrototypeWrapper[0]), replace: true); return;
            }

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

            int numLayers = matrices.Count;
            int maxX = splats3D.GetLength(0); int maxZ = splats3D.GetLength(1);             //MapMagic.instance.resolution should not be used because of possible lods

            //MapMagic.CoordRect rect =  matrices[0].rect;

            float[] values = new float[numLayers];             //row, to avoid reading/writing 3d array (it is too slow)

            for (int x = 0; x < maxX; x++)
            {
                for (int z = 0; z < maxZ; z++)
                {
                    int   pos = rect.GetPos(x + rect.offset.x, z + rect.offset.z);
                    float sum = 0;

                    //getting values
                    for (int i = 0; i < numLayers; i++)
                    {
                        float val = matrices[i].array[pos];
                        if (biomeMasks[i] != null)
                        {
                            val *= biomeMasks[i].array[pos];                                                //if mask is not assigned biome was ignored, so only main outs with mask==null left here
                        }
                        if (val < 0)
                        {
                            val = 0;
                        }
                        if (val > 1)
                        {
                            val = 1;
                        }
                        sum      += val;                    //normalizing: calculating sum
                        values[i] = val;
                    }

                    //setting color
                    for (int i = 0; i < numLayers; i++)
                    {
                        splats3D[z, x, i] = values[i] / sum;
                    }
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            TupleSet <float[, , ], SplatPrototypeWrapper[]> splatsTuple = new TupleSet <float[, , ], SplatPrototypeWrapper[]>(splats3D, prototypesList.ToArray());

            results.apply.CheckAdd(typeof(MadMapsSplatOutput), splatsTuple, replace: true);
        }
示例#17
0
        public static void Process(MapMagic.CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
            if (stop != null && stop(0))
            {
                return;
            }

            //reading height outputs
            if (results.heights == null || results.heights.rect.size.x != rect.size.x)
            {
                results.heights = new Matrix(rect);
            }
            results.heights.rect.offset = rect.offset;
            results.heights.Clear();

            _pendingWrappers.Add(rect);

            //processing main height
            foreach (MadMapsHeightOutput gen in gens.GeneratorsOfType <MadMapsHeightOutput>(onlyEnabled: true, checkBiomes: true))
            {
                //if (stop!=null && stop(0)) return; //do not break while results.heights is empty!

                //loading inputs
                Matrix heights = (Matrix)gen.input.GetObject(results);
                if (heights == null)
                {
                    continue;
                }

                //loading biome matrix
                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
                    }
                }

                //adding to final result
                if (gen.biome == null)
                {
                    results.heights.Add(heights);
                }
                else if (biomeMask != null)
                {
                    results.heights.Add(heights, biomeMask);
                }
            }

            //creating 2d array
            if (stop != null && stop(0))
            {
                return;
            }
            int heightSize = terrainSize.resolution * scale + 1;

            float[,] heights2D = new float[heightSize, heightSize];
            for (int x = 0; x < heightSize - 1; x++)
            {
                for (int z = 0; z < heightSize - 1; z++)
                {
                    if (scale == 1)
                    {
                        heights2D[z, x] += results.heights[x + results.heights.rect.offset.x, z + results.heights.rect.offset.z];
                    }
                    else
                    {
                        float fx = 1f * x / scale; float fz = 1f * z / scale;
                        heights2D[z, x] = results.heights.GetInterpolated(fx + results.heights.rect.offset.x, fz + results.heights.rect.offset.z);
                    }
                }
            }

            //blur only original base verts
            if (scale == 2)
            {
                float blurVal = 0.2f;

                for (int z = 0; z < heightSize - 1; z += 2)
                {
                    for (int x = 2; x < heightSize - 1; x += 2)
                    {
                        heights2D[x, z] = (heights2D[x - 1, z] + heights2D[x + 1, z]) / 2 * blurVal + heights2D[x, z] * (1 - blurVal);
                    }
                }

                for (int x = 0; x < heightSize - 1; x += 2)
                {
                    for (int z = 2; z < heightSize - 1; z += 2)
                    {
                        heights2D[x, z] = (heights2D[x, z - 1] + heights2D[x, z + 1]) / 2 * blurVal + heights2D[x, z] * (1 - blurVal);
                    }
                }
            }

            //blur high scale values
            if (scale == 4)
            {
                int blurIterations = 2;

                for (int i = 0; i < blurIterations; i++)
                {
                    float prev = 0;
                    float curr = 0;
                    float next = 0;

                    for (int x = 0; x < heightSize; x++)
                    {
                        prev = heights2D[x, 0]; curr = prev;
                        for (int z = 1; z < heightSize - 2; z++)
                        {
                            next = heights2D[x, z + 1];
                            curr = (next + prev) / 2;                        // * blurVal + curr*(1-blurVal);

                            heights2D[x, z] = curr;
                            prev            = curr;
                            curr            = next;
                        }
                    }

                    for (int z = 0; z < heightSize; z++)
                    {
                        prev = heights2D[0, z]; curr = prev;
                        for (int x = 1; x < heightSize - 2; x++)
                        {
                            next = heights2D[x + 1, z];
                            curr = (next + prev) / 2;                        // * blurVal + curr*(1-blurVal);

                            heights2D[x, z] = curr;
                            prev            = curr;
                            curr            = next;
                        }
                    }
                }
            }

            //processing sides
            for (int x = 0; x < heightSize; x++)
            {
                float prevVal = heights2D[heightSize - 3, x];                 //size-2
                float currVal = heights2D[heightSize - 2, x];                 //size-1, point on border
                float nextVal = currVal - (prevVal - currVal);
                heights2D[heightSize - 1, x] = nextVal;
            }
            for (int z = 0; z < heightSize; z++)
            {
                float prevVal = heights2D[z, heightSize - 3];                 //size-2
                float currVal = heights2D[z, heightSize - 2];                 //size-1, point on border
                float nextVal = currVal - (prevVal - currVal);
                heights2D[z, heightSize - 1] = nextVal;
            }
            heights2D[heightSize - 1, heightSize - 1] = heights2D[heightSize - 1, heightSize - 2];

            for (int x = 0; x < heightSize - 1; x++)
            {
                for (int z = 0; z < heightSize - 1; z++)
                {
                    heights2D[z, x] = Mathf.Clamp01(heights2D[z, x]);
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }

            #if UN_MapMagic
            if (FoliageCore_MainManager.instance != null)
            {
                float resolutionDifferences = (float)MapMagic.instance.terrainSize / terrainSize.resolution;

                uNatureHeightTuple heightTuple = new uNatureHeightTuple(heights2D, new Vector3(rect.Min.x * resolutionDifferences, 0, rect.Min.z * resolutionDifferences)); // transform coords
                results.apply.CheckAdd(typeof(MadMapsHeightOutput), heightTuple, replace: true);
            }
            else
            {
                //Debug.LogError("uNature_MapMagic extension is enabled but no foliage manager exists on the scene.");
                //return;
                results.apply.CheckAdd(typeof(MadMapsHeightOutput), heights2D, replace: true);
            }
            #else
            results.apply.CheckAdd(typeof(MadMapsHeightOutput), heights2D, replace: true);
            #endif
        }
示例#18
0
        public override void OnGUI(GeneratorsAsset gens)
        {
            layout.Field(ref LayerName, "Layer");

                        #if VEGETATION_STUDIO
            layout.Par(30); layout.Icon("VegetationStudioSplashSmall", layout.Inset(), Layout.IconAligment.resize, Layout.IconAligment.resize);
            layout.Par(5);
            layout.fieldSize = 0.6f;
            package          = layout.Field(package, "Package");

            //layers
            if (package != null)
            {
                if (layers.Length != package.VegetationInfoList.Count)
                {
                    layers = new Layer[package.VegetationInfoList.Count];
                }

                layout.Par(5);
                for (int num = 0; num < layers.Length; num++)
                {
                    layout.DrawLayer(OnLayerGUI, ref selected, num);
                }
            }
            else
            {
                layers = new Layer[0];
            }

            //warnings
            layout.margin = 5;
            if (package != null)
            {
                if (package.UseTerrainTextures)
                {
                    layout.Par(42);
                    layout.Label("Package Update Terrain Textures On Init is turned on.", rect: layout.Inset(0.8f), helpbox: true);
                    if (layout.Button("Fix", rect: layout.Inset(0.2f)))
                    {
                        package.UseTerrainTextures = false;
                    }
                }

                bool runtimeSpawnEnabled = false;
                foreach (var v in package.VegetationInfoList)
                {
                    if (v.EnableRuntimeSpawn)
                    {
                        runtimeSpawnEnabled = true; break;
                    }
                }
                if (runtimeSpawnEnabled)
                {
                    layout.Par(42);
                    layout.Label("Runtime spawn is enabled on some Vegetetaion Items.", rect: layout.Inset(0.8f), helpbox: true);
                    if (layout.Button("Fix", rect: layout.Inset(0.2f)))
                    {
                        foreach (var v in package.VegetationInfoList)
                        {
                            v.EnableRuntimeSpawn = false;
                        }
                    }
                }
            }
                        #endif
        }
示例#19
0
        public 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;
            }
            Noise noise = new Noise(12345, permutationCount: 128);            //to pick objects based on biome

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

            List <VegetationStudioInstance> instances = new List <VegetationStudioInstance>();
            //object outputs
            foreach (MadMapsVSOutput gen in gens.GeneratorsOfType <MadMapsVSOutput>(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,
                                (obj.height + terrainHeight) * terrainSize.height,
                                (obj.pos.y - hash.offset.y) / hash.size);


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

                            instances.Add(new VegetationStudioInstance()
                            {
                                VSID     = id,
                                Guid     = System.Guid.NewGuid().ToString(),
                                Package  = package,
                                Position = position,
                                Scale    = scale,
                                Rotation = rotation.eulerAngles,
                            });
                        }

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

                    int cellXCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize);
                    int cellZCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize);
                    //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);
                                            var position = new Vector3(mx, 0, mz);
                                            instances.Add(new VegetationStudioInstance()
                                            {
                                                VSID     = id,
                                                Guid     = System.Guid.NewGuid().ToString(),
                                                Package  = package,
                                                Position = position,
                                                Scale    = scale,
                                                Rotation = rotation.eulerAngles,
                                            });
                                        }
                                    }
                                }

                                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(MadMapsVSOutput), instances, replace: true);
        }