コード例 #1
0
ファイル: Generator.cs プロジェクト: Quintavius/Journeys
        public override void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
        {
            object obj = null;

            if (input.link != null && enabled)
            {
                obj = input.GetObject(results);
            }
            else
            {
                if (type == InoutType.Map)
                {
                    obj = new Matrix(rect);
                }
                if (type == InoutType.Objects)
                {
                    obj = new SpatialHash(new Vector2(rect.offset.x, rect.offset.z), rect.size.x, 16);
                }
            }

            if (stop != null && stop(0))
            {
                return;
            }
            output.SetObject(results, obj);
        }
コード例 #2
0
        public override void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
        {
            Matrix src = (Matrix)input.GetObject(results);

            if (src == null || (stop != null && stop(0)))
            {
                return;
            }
            if (!enabled)
            {
                output.SetObject(results, src); return;
            }

            Matrix dst = new Matrix(src.rect);

            Coord min = src.rect.Min; Coord max = src.rect.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    float val = level - src[x, z];
                    dst[x, z] = val > 0? val : 0;
                }
            }

            if (stop != null && stop(0))
            {
                return;
            }
            output.SetObject(results, dst);
        }
コード例 #3
0
        public override void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
        {
            //getting input
            Matrix src = (Matrix)input.GetObject(results);

            //return on stop/disable/null input
            if (stop != null && stop(0))
            {
                return;
            }
            if (!enabled || src == null)
            {
                output.SetObject(results, src); return;
            }

            //preparing output
            Matrix dst = src.Copy(null);

            float minClamp = min / MapMagic.instance.terrainHeight;
            float maxClamp = max / MapMagic.instance.terrainHeight;

            for (int i = 0; i < dst.array.Length; i++)
            {
                if (!unitClamp)
                {
                    if (dst.array[i] < minClamp)
                    {
                        dst.array[i] = minClamp;
                    }
                    if (dst.array[i] > maxClamp)
                    {
                        dst.array[i] = maxClamp;
                    }
                }
                else
                {
                    dst.array[i] = dst.array[i] > minClamp && dst.array[i] < maxClamp ? 1 : 0;
                }
            }

            //mask and safe borders
            if (stop != null && stop(0))
            {
                return;
            }
            Matrix mask = (Matrix)maskIn.GetObject(results);

            if (mask != null)
            {
                Matrix.Mask(src, dst, mask);
            }

            //setting output
            if (stop != null && stop(0))
            {
                return;
            }
            output.SetObject(results, dst);
        }
コード例 #4
0
        public override void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
        {
                        #if RTP
            if ((stop != null && stop(0)) || !enabled)
            {
                return;
            }

            //loading inputs
            Matrix[] matrices = new Matrix[baseLayers.Length];
            for (int i = 0; i < baseLayers.Length; i++)
            {
                if (baseLayers[i].input != null)
                {
                    matrices[i] = (Matrix)baseLayers[i].input.GetObject(results);
                    if (matrices[i] != null)
                    {
                        matrices[i] = matrices[i].Copy(null);
                    }
                }
                if (matrices[i] == null)
                {
                    matrices[i] = new Matrix(rect);
                }
            }
            if (matrices.Length == 0)
            {
                return;
            }

            //background matrix
            //matrices[0] = terrain.defaultMatrix; //already created
            matrices[0].Fill(1);

            //populating opacity array
            float[] opacities = new float[matrices.Length];
            for (int i = 0; i < baseLayers.Length; i++)
            {
                opacities[i] = baseLayers[i].opacity;
            }
            opacities[0] = 1;

            //blending layers
            Matrix.BlendLayers(matrices, opacities);

            //saving changed matrix results
            for (int i = 0; i < baseLayers.Length; i++)
            {
                if (stop != null && stop(0))
                {
                    return;                //do not write object is generating is stopped
                }
                baseLayers[i].output.SetObject(results, matrices[i]);
            }
                        #endif
        }
コード例 #5
0
ファイル: Generator.cs プロジェクト: Quintavius/Journeys
 public object GetObject(Chunk.Results tw)
 {
     if (link == null)
     {
         return(null);
     }
     if (!tw.results.ContainsKey(link))
     {
         return(null);
     }
     return(tw.results[link]);
 }
コード例 #6
0
		public Chunk.Results ClosestResults (Vector3 camPos)
		{
			float minDist = Mathf.Infinity;
			Chunk.Results closestResults = null;
			foreach (Chunk chunk in chunks.All())
			{
				float dist = (chunk.rect.Center.vector3 - camPos).sqrMagnitude;
				if (dist<minDist)
				{
					dist = minDist;
					closestResults = chunk.results;
				}
			}
			return closestResults;
		}
コード例 #7
0
ファイル: Generator.cs プロジェクト: Quintavius/Journeys
            public T GetObject <T> (Chunk.Results tw) where T : class
            {
                if (!tw.results.ContainsKey(this))
                {
                    return(null);
                }
                object obj = tw.results[this];

                if (obj == null)
                {
                    return(null);
                }
                else
                {
                    return((T)obj);
                }
            }
コード例 #8
0
ファイル: Generator.cs プロジェクト: Quintavius/Journeys
 public void SetObject(Chunk.Results tw, object obj)                      //TODO: maybe better replace with CheckAdd
 {
     if (tw.results.ContainsKey(this))
     {
         if (obj == null)
         {
             tw.results.Remove(this);
         }
         else
         {
             tw.results[this] = obj;
         }
     }
     else
     {
         if (obj != null)
         {
             tw.results.Add(this, obj);
         }
     }
 }
コード例 #9
0
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if VOXELAND
            if (stop != null && stop(0))
            {
                return;
            }
            if (voxeland == null)
            {
                return;
            }

            //finding area by rect offset
            Coord areaCoord          = Coord.PickCell(rect.offset.x, rect.offset.z, voxeland.data.areaSize);
            Voxeland5.Data.Area area = voxeland.data.areas[areaCoord.x, areaCoord.z];

            //clearing grass
            area.ClearGrass();

            //preparing random
            //Noise noise = new Noise(12345); //to switch grass depending on it's opacity

            //processing
            foreach (VoxelandGrassOutput gen in gens.GeneratorsOfType <VoxelandGrassOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //reading output directly
                if (stop != null && stop(0))
                {
                    return;                                        //checking stop before reading output
                }
                //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
                    }
                }

                //iterating layers
                for (int l = 0; l < gen.layers.Length; l++)
                {
                    Layer layer = gen.layers[l];

                    //loading inputs
                    Matrix src = (Matrix)layer.input.GetObject(results);
                    if (src == null)
                    {
                        continue;
                    }
                    //multiplying with biome mask - in SetGrassLayer

                    //apply
                    //area.SetGrassLayer(src, (byte)l, layer.density, noise:noise, layerNum:l, mask:biomeMask);
                    area.SetGrassLayer(src.rect.offset.x, src.rect.offset.z, src.rect.size.x, src.array, (byte)l, layer.density, l, biomeMask == null? null : biomeMask.array);
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VoxelandOutput), null, replace: true);
                        #endif
        }
コード例 #10
0
ファイル: Generator.cs プロジェクト: Quintavius/Journeys
 public virtual void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
 {
 }
コード例 #11
0
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if RTP
            if (stop != null && stop(0))
            {
                return;
            }

            //finding number of layers
            int layersCount = 0;
            foreach (RTPOutput gen in MapMagic.instance.gens.GeneratorsOfType <RTPOutput>(onlyEnabled:true, checkBiomes:true))
            {
                layersCount = gen.baseLayers.Length; break;
            }

            //creating color arrays
            RTPTuple result = new RTPTuple();
            result.colorsA = new Color[MapMagic.instance.resolution * MapMagic.instance.resolution];
            if (layersCount > 4)
            {
                result.colorsB = new Color[MapMagic.instance.resolution * MapMagic.instance.resolution];
            }

            //filling color arrays
            foreach (RTPOutput gen in MapMagic.instance.gens.GeneratorsOfType <RTPOutput>(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];
                    if (matrix.IsEmpty())
                    {
                        continue;
                    }

                    for (int x = 0; x < rect.size.x; x++)
                    {
                        for (int z = 0; z < rect.size.z; z++)
                        {
                            int pos = matrix.rect.GetPos(x + matrix.rect.offset.x, z + matrix.rect.offset.z);                 //pos should be the same for colors array and matrix array

                            //get value and adjust with biome mask
                            float val      = matrix.array[pos];
                            float biomeVal = biomeMask != null? biomeMask.array[pos] : 1;
                            val *= biomeVal;

                            //save value to colors array
                            switch (gen.baseLayers[i].index)
                            {
                            case 0: result.colorsA[pos].r += val; break;

                            case 1: result.colorsA[pos].g += val; break;

                            case 2: result.colorsA[pos].b += val; break;

                            case 3: result.colorsA[pos].a += val; break;

                            case 4: result.colorsB[pos].r += val; break;

                            case 5: result.colorsB[pos].g += val; break;

                            case 6: result.colorsB[pos].b += val; break;

                            case 7: result.colorsB[pos].a += val; break;
                            }
                        }
                    }

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

            //TODO: normalizing color arrays (if needed)

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(RTPOutput), result, replace: true);
                        #endif
        }
コード例 #12
0
        public static Voxeland5.Voxeland voxeland;         //TODO static is not serialized
        //TODO: somehow assign voxeland on data asssign or window open
                #endif

        //[System.Diagnostics.Conditional("VOXELAND")] //wtf it does not work!
        public override void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
        {
                        #if VOXELAND
            if (stop != null && stop(0))
            {
                return;
            }

            //finding instance
            //Voxeland5.Voxeland voxeland = null;
            //foreach (Voxeland5.Voxeland v in Voxeland5.Voxeland.instances)
            //	if (v.data.generator.mapMagicGens.ContainsGenerator(this)) voxeland = v;
            if (voxeland == null)
            {
                return;
            }

            //preparing random
            //Noise noise = new Noise(123, permutationCount:512); //random to floor floats

            //preparing area
            Voxeland5.Data.Area area = new Voxeland5.Data.Area();
            area.Init(rect.offset.x / terrainSize.resolution, rect.offset.z / terrainSize.resolution, terrainSize.resolution, null);

            //TODO get height factor
            int heightFactor = 200;

            //iterating layers
            for (int l = 0; l < layers.Length; l++)
            {
                Layer layer = layers[l];
                if (!layer.enabled)
                {
                    continue;
                }

                int blockType = layer.blockType;
                if (blockType >= voxeland.landTypes.array.Length)
                {
                    blockType = Voxeland5.Data.emptyByte;
                }

                //loading inputs
                Matrix src       = (Matrix)layer.input.GetObject(results);
                Matrix heightSrc = (Matrix)layer.heightInput.GetObject(results);
                //SpatialHash objectsSrc = (SpatialHash)layer.objectInput.GetObject(results);
                if (src == null)
                {
                    continue;
                }

                //apply
                switch (layer.applyType)
                {
                //case Voxeland5.Generator.LayerOverlayType.add: area.AddLayer(src, blockType, heightFactor:heightFactor, noise:noise); break;
                //case Voxeland5.Generator.LayerOverlayType.clampAppend: area.ClampAppendLayer(src, blockType, heightFactor:heightFactor, noise:noise); break;
                //case Voxeland5.Generator.LayerOverlayType.absolute: area.SetLayer(src, heightSrc, blockType, heightFactor:heightFactor, noise:noise); break;
                //case Voxeland5.Generator.LayerOverlayType.paint: area.PaintLayer(src, blockType, paintThickness:layer.paintThickness, noise:noise); break;
                case Voxeland5.Generator.LayerOverlayType.add: area.AddLayer(src.rect.offset.x, src.rect.offset.z, src.rect.size.x, src.array, blockType, heightFactor: heightFactor); break;

                case Voxeland5.Generator.LayerOverlayType.clampAppend: area.ClampAppendLayer(src.rect.offset.x, src.rect.offset.z, src.rect.size.x, src.array, blockType, heightFactor: heightFactor); break;

                case Voxeland5.Generator.LayerOverlayType.absolute: area.SetLayer(src.rect.offset.x, src.rect.offset.z, src.rect.size.x, src.array, heightSrc != null? heightSrc.array : null, blockType, heightFactor: heightFactor); break;

                case Voxeland5.Generator.LayerOverlayType.paint: area.PaintLayer(src.rect.offset.x, src.rect.offset.z, src.rect.size.x, src.array, blockType, paintThickness: layer.paintThickness); break;
                }
            }

            //getting outputs
            MultiDict <int, int> typeToLayer = new MultiDict <int, int>();
            for (int l = 0; l < layers.Length; l++)
            {
                typeToLayer.Add(layers[l].blockType, l);
            }

            Matrix[] layerMatrices = new Matrix[layers.Length];
            for (int l = 0; l < layerMatrices.Length; l++)
            {
                layerMatrices[l] = new Matrix(rect);
            }

            for (int x = 0; x < rect.size.x; x++)
            {
                Voxeland5.Data.Area.Line line = area.lines[x];
                for (int z = 0; z < rect.size.z; z++)
                {
                    int topType = line.columns[z].topType;
                    if (topType == Voxeland5.Data.emptyByte)
                    {
                        continue;                                                          //empty column
                    }
                    List <int> typeLayerNums = typeToLayer[topType];

                                        #if WDEBUG
                    if (typeLayerNums == null)
                    {
                        Debug.LogError("This should not happen " + topType);
                    }
                                        #endif

                    int matrixPos = z * rect.size.x + x;
                    for (int m = 0; m < typeLayerNums.Count; m++)
                    {
                        layerMatrices[typeLayerNums[m]].array[matrixPos] = 1;
                    }
                }
            }

            for (int l = 0; l < layers.Length; l++)
            {
                layers[l].output.SetObject(results, layerMatrices[l]);
            }


            //saving results
            areaOutput.SetObject(results, area);
                        #endif
        }
コード例 #13
0
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if VOXELAND
            if (stop != null && stop(0))
            {
                return;
            }
            if (voxeland == null)
            {
                return;
            }

            //TODO get height factor
            int heightFactor = 200;

            //finding area by rect offset
            Coord areaCoord          = Coord.PickCell(rect.offset.x, rect.offset.z, voxeland.data.areaSize);
            Voxeland5.Data.Area area = voxeland.data.areas[areaCoord.x, areaCoord.z];

            //clearing objects
            area.ClearObjects();

            //preparing random
            Noise noise = new Noise(12345);             //to disable biome objects

            //processing
            foreach (VoxelandObjectsOutput gen in gens.GeneratorsOfType <VoxelandObjectsOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //reading output directly
                //Output output = gen.areaOutput;
                if (stop != null && stop(0))
                {
                    return;                                        //checking stop before reading output
                }
                //if (!results.results.ContainsKey(output)) continue;
                //Voxeland5.Data.Area genArea = (Voxeland5.Data.Area)results.results[output];

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

                //iterating layers
                for (int l = 0; l < gen.layers.Length; l++)
                {
                    Layer layer = gen.layers[l];

                    //loading inputs
                    SpatialHash src = (SpatialHash)layer.input.GetObject(results);
                    if (src == null)
                    {
                        continue;
                    }

                    foreach (SpatialObject obj in src.AllObjs())
                    {
                        int objX = (int)(obj.pos.x + 0.5f);
                        int objZ = (int)(obj.pos.y + 0.5f);

                        //biome masking
                        float biomeVal = 1;
                        if (gen.biome != null)
                        {
                            if (biomeMask == null)
                            {
                                biomeVal = 0;
                            }
                            else
                            {
                                biomeVal = biomeMask[objX, objZ];
                            }
                        }
                        if (biomeVal < noise.Random(objX, objZ))
                        {
                            continue;
                        }

                        //flooring
                        float terrainHeight = layer.relativeHeight? results.heights[objX, objZ] : 0;
                        int   objHeight     = (int)((obj.height + terrainHeight) * heightFactor + 0.5f);

                        //area.AddObject(new CoordDir(objX, objHeight, objZ), (short)l);
                        area.AddObject(objX, objHeight, objZ, 0, (short)l);
                    }
                }
            }

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

            //TODO get height factor
            int heightFactor = 200;

            //finding area by rect offset
            Coord areaCoord          = Coord.PickCell(rect.offset.x, rect.offset.z, voxeland.data.areaSize);
            Voxeland5.Data.Area area = voxeland.data.areas[areaCoord.x, areaCoord.z];

            //clearing area
            area.ClearLand();

            //finding a list of areas and their opacities
            List <Voxeland5.Data.Area> areas = new List <Voxeland5.Data.Area>();
            List <Matrix> opacities          = new List <Matrix>();
            foreach (VoxelandOutput gen in gens.GeneratorsOfType <VoxelandOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //reading output directly
                Output output = gen.areaOutput;
                if (stop != null && stop(0))
                {
                    return;                                        //checking stop before reading output
                }
                if (!results.results.ContainsKey(output))
                {
                    continue;
                }
                Voxeland5.Data.Area genArea = (Voxeland5.Data.Area)results.results[output];

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

                areas.Add(genArea);
                opacities.Add(biomeMask);
            }

            //merge areas using biome mask
            if (areas.Count >= 2)
            //area.MixAreas(areas.ToArray(), opacities.ToArray());
            {
                float[][] opacityArrays = new float[opacities.Count][];
                for (int i = 0; i < opacityArrays.Length; i++)
                {
                    if (opacities[i] != null)
                    {
                        opacityArrays[i] = opacities[i].array;
                    }
                }
                area.MixAreas(areas.ToArray(), rect.offset.x, rect.offset.z, rect.size.x, opacityArrays);
            }
            else
            {
                Voxeland5.Data.Area.CopyLand(areas[0], area);
            }

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

            for (int x = 0; x < results.heights.rect.size.x; x++)
            {
                for (int z = 0; z < results.heights.rect.size.z; z++)
                {
                    results.heights[x + results.heights.rect.offset.x, z + results.heights.rect.offset.z] = 1f * area.lines[x].columns[z].topLevel / heightFactor;
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VoxelandOutput), null, replace: true);
                        #endif
        }
コード例 #15
0
        void OnGUI()
        {
            //finding the preiew object
            if (mapMagic == null)
            {
                mapMagic = FindObjectOfType <MapMagic>();
            }
            if (mapMagic == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "No MapMagic object found, re-open the window."); return;
            }

            Vector3 camPos = new Vector3();

            if (UnityEditor.SceneView.lastActiveSceneView != null)
            {
                camPos = UnityEditor.SceneView.lastActiveSceneView.camera.transform.position;
            }

            Chunk.Results closestResults = mapMagic.ClosestResults(camPos);
            if (closestResults == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "No terrains are pinned for preview"); return;
            }

            if (Preview.previewOutput == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "No preview output is selected"); return;
            }

            object currentObj = Preview.previewOutput.GetObject <object>(closestResults);

            if (currentObj == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "Please wait until preview \nobject is being generated."); return;
            }

            if (currentObj != lastUsedObject)
            {
                Repaint();
            }

            //updating layouts
            if (baseLayout == null)
            {
                baseLayout = new Layout();
            }
            baseLayout.maxZoom = 8; baseLayout.minZoom = 0.125f; baseLayout.zoomStep = 0.125f;
            baseLayout.Zoom(); baseLayout.Scroll();                     //scrolling and zooming

            if (infoLayout == null)
            {
                infoLayout = new Layout();
            }
            infoLayout.cursor = new Rect();
            infoLayout.margin = 10; infoLayout.rightMargin = 10;
            infoLayout.field  = new Rect(this.position.width - 200 - 10, this.position.height - 80 - 10, 200, 80);



            //drawing hash preview
            if (currentObj is SpatialHash)
            {
                SpatialHash spatialHash = (SpatialHash)currentObj;

                for (int i = 0; i < spatialHash.cells.Length; i++)
                {
                    SpatialHash.Cell cell = spatialHash.cells[i];

                    //drawing grid
                    UnityEditor.Handles.color = Color.gray;
                    UnityEditor.Handles.DrawPolyLine(
                        baseLayout.ToDisplay((cell.min - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((new Vector2(cell.max.x, cell.min.y) - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((cell.max - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((new Vector2(cell.min.x, cell.max.y) - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((cell.min - spatialHash.offset) / spatialHash.size * 1000));

                    //drawing objects
                    UnityEditor.Handles.color = new Color(0.4f, 0.9f, 0.2f);
                    for (int j = 0; j < cell.objs.Count; j++)
                    {
                        DrawCircle(baseLayout.ToDisplay((cell.objs[j].pos - spatialHash.offset) / spatialHash.size * 1000), 5);
                    }
                }

                //drawing info
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                infoLayout.Par();
                infoLayout.fieldSize = 0.7f;                         //infoLayout.inputSize = 0.3f;
                infoLayout.Label("Count: " + spatialHash.Count);
            }

            //drawing matrix preview
            else if (currentObj is Matrix)
            {
                Matrix matrix = (Matrix)currentObj;

                //refreshing texture if matrix has changed
                if (matrix != lastUsedObject || (range - lastUsedRange).sqrMagnitude > 0.01f)
                {
                    lastUsedObject     = matrix; lastUsedRange = range;
                    texture            = new Texture2D(matrix.rect.size.x, matrix.rect.size.z);
                    texture.filterMode = FilterMode.Point;
                    matrix.SimpleToTexture(texture, rangeMin: range.x, rangeMax: range.y);
                }

                //drawing texture
                UnityEditor.EditorGUI.DrawPreviewTexture(baseLayout.ToDisplay(new Rect(0, 0, texture.width, texture.height)), texture);

                //drawing texture info
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                infoLayout.fieldSize = 0.7f;                         //infoLayout.inputSize = 0.3f;
                infoLayout.Label("Size: " + texture.width + "x" + texture.height);
                infoLayout.Field(ref baseLayout.zoom, "Zoom: ", min: baseLayout.minZoom, max: baseLayout.maxZoom, slider: true, quadratic: true);
                if (matrix != null)
                {
                    infoLayout.Field(ref range, "Range: ", min: 0, max: 1, slider: true);

                    infoLayout.Par(3);
                    if (infoLayout.Button("Save To Texture"))
                    {
                                                        #if !UNITY_WEBPLAYER
                        string path = UnityEditor.EditorUtility.SaveFilePanel(
                            "Save Output Texture",
                            "Assets",
                            "OutputTexture.png",
                            "png");
                        if (path != null && path.Length != 0)
                        {
                            byte[] bytes = texture.EncodeToPNG();
                            System.IO.File.WriteAllBytes(path, bytes);
                        }
                                                        #endif
                    }
                }
            }
        }
コード例 #16
0
		public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func<float,bool> stop = null)
		{
			#if __MEGASPLAT__
			if (stop!=null && stop(0)) return;

			//using the first texture list for all
			MegaSplatTextureList textureList = null;
			bool smoothFallof = false;
         float clusterScale = 0.05f;
			foreach (MegaSplatOutput gen in gens.GeneratorsOfType<MegaSplatOutput>(onlyEnabled: true, checkBiomes: true))
			{
				if (gen.textureList != null) textureList = gen.textureList;
				smoothFallof = gen.smoothFallof;
            clusterScale = gen.clusterNoiseScale;
			}

			//creating color arrays
			MegaSplatData result = new MegaSplatData();

			result.control = new Color[MapMagic.instance.resolution * MapMagic.instance.resolution];
			result.param = new Color[MapMagic.instance.resolution * MapMagic.instance.resolution];
			
			//creating all and special layers/biomes lists
			List<Layer> allLayers = new List<Layer>(); //all layers count = gen num * layers num in each gen (excluding empty biomes, matrices, etc)
			List<Matrix> allMatrices = new List<Matrix>();
			List<Matrix> allBiomeMasks = new List<Matrix>();

			List<Matrix> specialWetnessMatrices = new List<Matrix>(); //special count = number of generators (excluding empty biomes only)
			List<Matrix> specialPuddlesMatrices = new List<Matrix>();
			List<Matrix> specialDampeningMatrices = new List<Matrix>();
			List<Matrix> specialBiomeMasks = new List<Matrix>();

			//filling all layers/biomes
			foreach (MegaSplatOutput gen in gens.GeneratorsOfType<MegaSplatOutput>(onlyEnabled: true, checkBiomes: true))
			{
				gen.textureList = textureList;

				//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];
					if (matrix.IsEmpty()) continue;

					if (i >= textureList.clusters.Length)
					{
						Debug.LogError("Cluster out of range");
						continue;
					}

					//adding to lists
					allLayers.Add(gen.baseLayers[i]);
					allMatrices.Add(matrix);
					allBiomeMasks.Add(gen.biome == null ? null : biomeMask);
				}

				//adding special
				object wetnessObj = gen.wetnessIn.GetObject(results);
				specialWetnessMatrices.Add( wetnessObj!=null? (Matrix)wetnessObj : null );

				object puddlesObj = gen.puddlesIn.GetObject(results);
				specialPuddlesMatrices.Add( puddlesObj!=null? (Matrix)puddlesObj : null );

				object dampeingObj = gen.displaceDampenIn.GetObject(results);
				specialDampeningMatrices.Add( dampeingObj!=null? (Matrix)dampeingObj : null );

				specialBiomeMasks.Add(gen.biome == null ? null : biomeMask);
			}

			//if no texture list found in any of generators - returning
			if (textureList == null || allLayers.Count==0) return;

			//processing
			int allLayersCount = allLayers.Count;
			int specialCount = specialWetnessMatrices.Count;
			for (int x = 0; x<rect.size.x; x++)
				for (int z = 0; z<rect.size.z; z++)
				{
					int pos = rect.GetPos(x + rect.offset.x, z + rect.offset.z);

					// doesn't use height, normal, but I'm not sure how to get that here..
					Vector3 worldPos = new Vector3(
						1f * (x+rect.offset.x) / MapMagic.instance.resolution * rect.size.x,
						0,
						1f * (z+rect.offset.z) / MapMagic.instance.resolution * rect.size.z);
					float heightRatio = results.heights!=null? results.heights.array[pos] : 0.5f; //0 is the bottom point, 1 is the maximum top
					Vector3 normal = new Vector3(0,1,0);

					// find highest two layers
					int botIdx = 0;
					int topIdx = 0;
					float botWeight = 0;
					float topWeight = 0;

					for (int i = 0; i<allLayersCount; i++)
					{
						float val = allMatrices[i].array[pos];
						if (allBiomeMasks[i] != null) val *= allBiomeMasks[i].array[pos];

						// really want world position, Normal, and height ratio for brushes, but for now, just use x/z..

						if (val > botWeight)
						{
							topWeight = botWeight;
							topIdx = botIdx;

							botWeight = val;
							botIdx = i;
						}
						else if (val > topWeight)
						{
							topIdx = i;
							topWeight = val;
						}
					}

					//converting layer index to texture index
               topIdx = textureList.clusters[ allLayers[topIdx].index ].GetIndex(worldPos *  clusterScale, normal, heightRatio);
               botIdx = textureList.clusters[ allLayers[botIdx].index ].GetIndex(worldPos * clusterScale, normal, heightRatio);

					//swapping indexes to make topIdx always on top
					if (botIdx > topIdx) 
					{
						int tempIdx = topIdx;
						topIdx = botIdx;
						botIdx = tempIdx;

						float tempWeight = topWeight;
						topWeight = botWeight;
						botWeight = tempWeight;
					}

					//finding blend
					float totalWeight = topWeight + botWeight;	if (totalWeight<0.01f) totalWeight = 0.01f; //Mathf.Max and Clamp are slow
					float blend = botWeight / totalWeight;		if (blend>1) blend = 1;

					//adjusting blend curve
					if (smoothFallof) blend = (Mathf.Sqrt(blend) * (1-blend)) + blend*blend*blend;  //Magic secret formula! Inverse to 3*x^2 - 2*x^3

					//setting color
					result.control[pos] = new Color(botIdx / 255.0f, topIdx / 255.0f, 1.0f - blend, 1.0f);

					//params
					for (int i = 0; i<specialCount; i++)
					{
						float biomeVal = specialBiomeMasks[i]!=null? specialBiomeMasks[i].array[pos] : 1;

						if (specialWetnessMatrices[i]!=null) result.param[pos].b = specialWetnessMatrices[i].array[pos] * biomeVal;
						if (specialPuddlesMatrices[i]!=null) 
						{
							result.param[pos].a = specialPuddlesMatrices[i].array[pos] * biomeVal;
							result.param[pos].r = 0.5f;
							result.param[pos].g = 0.5f;
						}
						if (specialDampeningMatrices[i]!=null) result.control[pos].a = specialDampeningMatrices[i].array[pos] * biomeVal;
					}
						
				}
			
			//pushing to apply
			if (stop!=null && stop(0))
				return;
			results.apply.CheckAdd(typeof(MegaSplatOutput), result, replace: true);
			#endif
		}
コード例 #17
0
        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);
        }
コード例 #18
0
ファイル: CTSOutputGenerator.cs プロジェクト: KeriN0s/Arazi
        public static new void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if CTS_PRESENT
            if (stop != null && stop(0))
            {
                return;
            }

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

            foreach (CTSOutput gen in gens.GeneratorsOfType <CTSOutput>(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);
                    indexesList.Add(gen.baseLayers[i].index);
                    opacities.Add(gen.baseLayers[i].opacity);
                }
            }

            //optimizing matrices list if they are not used
            //CTS always use 16 channels, so this optimization is useless (and does not work when layer order changed)
            //for (int i = matrices.Count - 1; i >= 0; i--)
            //	if (opacities[i] < 0.001f || matrices[i].IsEmpty() || (biomeMasks[i] != null && biomeMasks[i].IsEmpty()))
            //	{ indexesList.RemoveAt(i); opacities.RemoveAt(i); matrices.RemoveAt(i); biomeMasks.RemoveAt(i); }

            //creating array
            float[,,] splats3D = new float[terrainSize.resolution, terrainSize.resolution, 16];             //TODO: use max index
            if (matrices.Count == 0)
            {
                results.apply.CheckAdd(typeof(CTSOutput), splats3D, replace: true); return;
            }

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

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

            float[] values = new float[numPrototypes];             //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;

                    //clearing values
                    for (int i = 0; i < numPrototypes; i++)
                    {
                        values[i] = 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[indexesList[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;
            }
            results.apply.CheckAdd(typeof(CTSOutput), splats3D, replace: true);
                        #endif
        }