Ejemplo n.º 1
0
			public Matrix TestResize (CoordRect newRect)
			{
				Matrix result = new Matrix(newRect);

				Coord min = result.rect.Min; Coord max = result.rect.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
				{
					float percentX = 1f*(x-result.rect.offset.x)/result.rect.size.x; float origX = percentX*this.rect.size.x + this.rect.offset.x; 
					float percentZ = 1f*(z-result.rect.offset.z)/result.rect.size.z; float origZ = percentZ*this.rect.size.z + this.rect.offset.z; 
					result[x,z] = this.OutdatedGetInterpolated(origX, origZ);
				}

				return result;
			}
Ejemplo n.º 2
0
        public CoordRect Approximate(int val)
        {
            CoordRect approx = new CoordRect();

            approx.size.x = (size.x / val + 1) * val;
            approx.size.z = (size.z / val + 1) * val;

            approx.offset.x = offset.x - (approx.size.x - size.x) / 2;
            approx.offset.z = offset.z - (approx.size.z - size.z) / 2;

            approx.offset.x = (int)(approx.offset.x / val + 0.5f) * val;
            approx.offset.z = (int)(approx.offset.z / val + 0.5f) * val;

            return(approx);
        }
Ejemplo n.º 3
0
 public Matrix2(int x, int z, T[] array = null)
 {
     rect  = new CoordRect(0, 0, x, z);
     count = x * z;
     if (array != null && array.Length < count)
     {
         Debug.Log("Array length: " + array.Length + " is lower then matrix capacity: " + count);
     }
     if (array != null && array.Length >= count)
     {
         this.array = array;
     }
     else
     {
         this.array = new T[count];
     }
 }
Ejemplo n.º 4
0
 public Matrix2(Coord offset, Coord size, T[] array = null)
 {
     rect  = new CoordRect(offset, size);
     count = rect.size.x * rect.size.z;
     if (array != null && array.Length < count)
     {
         Debug.Log("Array length: " + array.Length + " is lower then matrix capacity: " + count);
     }
     if (array != null && array.Length >= count)
     {
         this.array = array;
     }
     else
     {
         this.array = new T[count];
     }
 }
Ejemplo n.º 5
0
			/*public void FromTexture (Texture2D texture, Coord textureOffset=new Coord(), bool fillBorders=false)
			{
				Coord textureSize = new Coord(texture.width, texture.height);
				CoordRect textureRect = new CoordRect(textureOffset, textureSize);
				CoordRect intersection = CoordRect.Intersect(textureRect, rect);

				Color[] colors = texture.GetPixels(intersection.offset.x - textureOffset.x, intersection.offset.z - textureOffset.z, intersection.size.x, intersection.size.z);

				Coord min = intersection.Min; Coord max = intersection.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
				{
					int tx = x-min.x; int tz = z-min.z;
					Color col = colors[tz*(max.x-min.x) + tx];

					this[x,z] = (col.r+col.g+col.b)/3;
				}

				if (fillBorders) RemoveBorders(intersection);
			}*/

			public void FromTexture (Texture2D texture)
			{
				CoordRect textureRect = new CoordRect(0,0, texture.width, texture.height);
				CoordRect intersection = CoordRect.Intersect(textureRect, rect);

				Color[] colors = texture.GetPixels(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z);

				Coord min = intersection.Min; Coord max = intersection.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
				{
					int tx = x-min.x; int tz = z-min.z;
					Color col = colors[tz*(max.x-min.x) + tx];

					this[x,z] = (col.r+col.g+col.b)/3;
				}
			}
Ejemplo n.º 6
0
        public void Fill(Matrix2 <T> m, bool removeBorders = false)
        {
            CoordRect intersection = CoordRect.Intersect(rect, m.rect);
            Coord     min = intersection.Min; Coord max = intersection.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    this[x, z] = m[x, z];
                }
            }
            if (removeBorders)
            {
                RemoveBorders(intersection);
            }
        }
Ejemplo n.º 7
0
			public float[,] ReadHeighmap (TerrainData data, float height=1)
			{
				CoordRect intersection = CoordRect.Intersect(rect, new CoordRect(0,0,data.heightmapResolution, data.heightmapResolution));
				
				//get heights
				float[,] array = data.GetHeights(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z); //returns x and z swapped

				//reading 2d array
				Coord min = intersection.Min; Coord max = intersection.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
						this[x,z] = array[z-min.z, x-min.x] * height;

				//removing borders
				RemoveBorders(intersection);

				return array;
			}
Ejemplo n.º 8
0
			public float[,,] ReadSplatmap (TerrainData data, int channel, float[,,] array=null)
			{
				CoordRect intersection = CoordRect.Intersect(rect, new CoordRect(0,0,data.alphamapResolution, data.alphamapResolution));
				
				//get heights
				if (array==null) array = data.GetAlphamaps(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z); //returns x and z swapped

				//reading array
				Coord min = intersection.Min; Coord max = intersection.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
						this[x,z] = array[z-min.z, x-min.x, channel];

				//removing borders
				RemoveBorders(intersection);

				return array;
			}
Ejemplo n.º 9
0
			public Matrix Resize (CoordRect newRect, float smoothness=1, Matrix result=null)
			{
				//calculating ratio
				int upscaleRatio = newRect.size.x / rect.size.x;
				int downscaleRatio = rect.size.x / newRect.size.x;

				//checking if rect could be rescaled
				if (upscaleRatio > 1 && !newRect.Divisible(upscaleRatio)) Debug.LogError("Matrix rect " + rect + " could not be upscaled to " + newRect + " with factor " + upscaleRatio);
				if (downscaleRatio > 1 && !rect.Divisible(downscaleRatio)) Debug.LogError("Matrix rect " + rect + " could not be downscaled to " + newRect + " with factor " + downscaleRatio);

				//scaling
				if (upscaleRatio > 1) result = Upscale(upscaleRatio, result:result);
				if (downscaleRatio > 1) result = Downscale(downscaleRatio, smoothness:smoothness, result:result);

				//returning clone if all ratios are 1
				if (upscaleRatio <= 1 && downscaleRatio <= 1) return Clone(result);
				else return result;
			}
Ejemplo n.º 10
0
				public Stacker (CoordRect smallRect, CoordRect bigRect)
				{
					this.smallRect = smallRect; this.bigRect = bigRect;
					isDownscaled = false;

					//do not create additional matrices if rect sizes are the same
					if (bigRect==smallRect)
					{
						upscaled = downscaled = new Matrix(bigRect);
					}

					else
					{
						downscaled = new Matrix(smallRect);
						upscaled = new Matrix(bigRect);
						difference = new Matrix(bigRect);
						//once arrays created they should not be resized
					}
				}
Ejemplo n.º 11
0
 public void ClampByRect(CoordRect rect)
 {
     if (x < rect.offset.x)
     {
         x = rect.offset.x;
     }
     if (x >= rect.offset.x + rect.size.x)
     {
         x = rect.offset.x + rect.size.x - 1;
     }
     if (z < rect.offset.z)
     {
         z = rect.offset.z;
     }
     if (z >= rect.offset.z + rect.size.z)
     {
         z = rect.offset.z + rect.size.z - 1;
     }
 }
Ejemplo n.º 12
0
        public IEnumerable <Coord> DistanceArea(CoordRect rect)         //same as distance are, but clamped by rect
        {
            int maxDist = Mathf.Max(x - rect.offset.x, rect.Max.x - x, z - rect.offset.z, rect.Max.z - z) + 1;

            if (rect.CheckInRange(this))
            {
                yield return(this);
            }
            for (int i = 0; i < maxDist; i++)
            {
                foreach (Coord c in DistancePerimeter(i))
                {
                    if (rect.CheckInRange(c))
                    {
                        yield return(c);
                    }
                }
            }
        }
Ejemplo n.º 13
0
			public void WriteHeightmap (TerrainData data, float[,] array=null, float brushFallof=0.5f)
			{
				CoordRect intersection = CoordRect.Intersect(rect, new CoordRect(0,0,data.heightmapResolution, data.heightmapResolution));
				
				//checking ref array
				if (array == null || array.Length != intersection.size.x*intersection.size.z) array = new float[intersection.size.z,intersection.size.x]; //x and z swapped

				//write to 2d array
				Coord min = intersection.Min; Coord max = intersection.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
				{
					float fallofFactor = Fallof(x,z,brushFallof);
					if (Mathf.Approximately(fallofFactor,0)) continue;
					array[z-min.z, x-min.x] = this[x,z]*fallofFactor + array[z-min.z, x-min.x]*(1-fallofFactor);
					//array[z-min.z, x-min.x] += this[x,z];
				}

				data.SetHeights(intersection.offset.x, intersection.offset.z, array);
			}
Ejemplo n.º 14
0
			public void ToTexture (Texture2D texture=null, Color[] colors=null, float rangeMin=0, float rangeMax=1, bool resizeTexture=false)
			{
				//creating or resizing texture
				if (texture == null) texture = new Texture2D(rect.size.x, rect.size.z);
				if (resizeTexture) texture.Resize(rect.size.x, rect.size.z);
				
				//finding matrix-texture intersection
				Coord textureSize = new Coord(texture.width, texture.height);
				CoordRect textureRect = new CoordRect(new Coord(0,0), textureSize);
				CoordRect intersection = CoordRect.Intersect(textureRect, rect);
				
				//checking ref color array
				if (colors == null || colors.Length != intersection.size.x*intersection.size.z) colors = new Color[intersection.size.x*intersection.size.z];

				//filling texture
				Coord min = intersection.Min; Coord max = intersection.Max;
				for (int x=min.x; x<max.x; x++)
					for (int z=min.z; z<max.z; z++)
				{
					float val = this[x,z];

					//adjusting value to range
					val -= rangeMin;
					val /= rangeMax-rangeMin;

					//making color gradient
					float byteVal = val * 256;
					int flooredByteVal = (int)byteVal;
					float remainder = byteVal - flooredByteVal;

					float flooredVal = flooredByteVal/256f;
					float ceiledVal = (flooredByteVal+1)/256f;
					
					//saving to colors
					int tx = x-min.x; int tz = z-min.z;
					colors[tz*(max.x-min.x) + tx] = new Color(flooredVal, remainder>0.333f ? ceiledVal : flooredVal, remainder>0.666f ? ceiledVal : flooredVal);
				}
			
				texture.SetPixels(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z, colors);
				texture.Apply();
			}
Ejemplo n.º 15
0
        public void GetHeight(Matrix matrix, Terrain terrain)
        {
            CoordRect terrainRect  = terrain.GetHeightRect();
            CoordRect intersection = CoordRect.Intersect(terrainRect, matrix.rect);

            if (intersection.size.x <= 0 || intersection.size.z <= 0)
            {
                return;
            }

            float[,] heights = terrain.terrainData.GetHeights(intersection.offset.x - terrainRect.offset.x, intersection.offset.z - terrainRect.offset.z, intersection.size.x, intersection.size.z);

            Coord min = intersection.Min; Coord max = intersection.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    matrix[x, z] = heights[z - min.z, x - min.x];                //x and z switched
                }
            }
        }
Ejemplo n.º 16
0
        public void AddSplat(Matrix matrix, Terrain terrain, int channel)
        {
            CoordRect terrainRect  = terrain.GetSplatRect();
            CoordRect intersection = CoordRect.Intersect(terrainRect, matrix.rect);

            if (intersection.size.x <= 0 || intersection.size.z <= 0)
            {
                return;
            }

            float[,,] splats = terrain.terrainData.GetAlphamaps(intersection.offset.x - terrainRect.offset.x, intersection.offset.z - terrainRect.offset.z, intersection.size.x, intersection.size.z);
            int numSplats = splats.GetLength(2);

            Coord min = intersection.Min; Coord max = intersection.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    int   sx = z - min.z;  int sz = x - min.x;               //x and z switched
                    float val    = matrix[x, z];
                    float invVal = 1 - matrix[x, z];

                    //multiplying all splats on inverse value
                    for (int s = 0; s < numSplats; s++)
                    {
                        splats[sx, sz, s] *= invVal;
                    }

                    //adding val
                    splats[sx, sz, channel] += val;
                }
            }

            terrain.terrainData.SetAlphamaps(intersection.offset.x - terrainRect.offset.x, intersection.offset.z - terrainRect.offset.z, splats);
        }
Ejemplo n.º 17
0
 public Matrix(Coord offset, Coord size)
 {
     this.rect = new CoordRect(offset, size);
         array = new float[rect.size.x*rect.size.z];
 }
Ejemplo n.º 18
0
        public static void AddSplatmaps(TerrainData data, Matrix[] matrices, int[] channels, float[] opacity, float[,,] array=null, float brushFallof=0.5f)
        {
            int numChannels = data.alphamapLayers;
                bool[] usedChannels = new bool[numChannels];
                for (int i=0; i<channels.Length; i++) usedChannels[channels[i]] = true;
                float[] slice = new float[numChannels];

                Coord dataSize = new Coord(data.alphamapResolution, data.alphamapResolution);
                CoordRect dataRect = new CoordRect(new Coord(0,0), dataSize);
                CoordRect intersection = CoordRect.Intersect(dataRect, matrices[0].rect);

                if (array==null) array = data.GetAlphamaps(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z);

                Coord min = intersection.Min; Coord max = intersection.Max;
                for (int x=min.x; x<max.x; x++)
                    for (int z=min.z; z<max.z; z++)
                {
                    //calculating fallof and opacity
                    float fallofFactor = matrices[0].Fallof(x,z,brushFallof);
                    if (Mathf.Approximately(fallofFactor,0)) continue;

                    //reading slice
                    for (int c=0; c<numChannels; c++) slice[c] = array[z-min.z, x-min.x, c];

                    //converting matrices to additive
                    for (int i=0; i<matrices.Length; i++) matrices[i][x,z] = Mathf.Max(0, matrices[i][x,z] - slice[channels[i]]);

                    //apply fallof
                    for (int i=0; i<matrices.Length; i++) matrices[i][x,z] *= fallofFactor * opacity[i];

                    //calculating sum of adding values
                    float addedSum = 0; //the sum of adding channels
                    for (int i=0; i<matrices.Length; i++) addedSum += matrices[i][x,z];
                    //if (addedSum < 0.00001f) continue; //no need to do anything

                    //if addedsum exceeds 1 - equalizing matrices
                    if (addedSum > 1f)
                        { for (int i=0; i<matrices.Length; i++) matrices[i][x,z] /= addedSum; addedSum=1; }

                    //multiplying all values on a remaining amount
                    float multiplier = 1-addedSum;
                    for (int c=0; c<numChannels; c++) slice[c] *= multiplier;

                    //adding matrices
                    for (int i=0; i<matrices.Length; i++) slice[channels[i]] += matrices[i][x,z];

                    //saving slice
                    for (int c=0; c<numChannels; c++) array[z-min.z, x-min.x, c] = slice[c];
                }

                data.SetAlphamaps(intersection.offset.x, intersection.offset.z, array);
        }
Ejemplo n.º 19
0
 //will re-create array only if it is needed
 public void ChangeRect(CoordRect newRect)
 {
     rect.offset.x = newRect.offset.x;
         rect.offset.z = newRect.offset.z;
         if (rect.size.x != newRect.size.x || rect.size.z != newRect.size.z)
         {
             rect = newRect;
             array = new float[rect.size.x*rect.size.z];
         }
 }
Ejemplo n.º 20
0
        public void FromTexture(Texture2D texture, bool fillBorders=false)
        {
            Coord textureSize = new Coord(texture.width, texture.height);
                CoordRect textureRect = new CoordRect(new Coord(0,0), textureSize);
                CoordRect intersection = CoordRect.Intersect(textureRect, rect);

                Color[] colors = texture.GetPixels(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z);

                Coord min = intersection.Min; Coord max = intersection.Max;
                for (int x=min.x; x<max.x; x++)
                    for (int z=min.z; z<max.z; z++)
                {
                    int tx = x-min.x; int tz = z-min.z;
                    Color col = colors[tz*(max.x-min.x) + tx];

                    this[x,z] = (col.r+col.g+col.b)/3;
                }

                if (fillBorders) RemoveBorders(intersection);
        }
Ejemplo n.º 21
0
        public void ApplyBrush(Rect worldRect, bool useFallof=true, bool newUndo=false)
        {
            TerrainData data = terrain.terrainData;
            //if (data.heightmapResolution-1 > 512 || data.alphamapResolution > 512) return;

            //preparing useful values
            bool paintSplat = preset.paintSplat;
            if (data.alphamapLayers==0) paintSplat = false;

            //finding minimum resolution
            int smallerRes = Mathf.Min(data.heightmapResolution-1, data.alphamapResolution);
            int largerRes = Mathf.Max(data.heightmapResolution-1, data.alphamapResolution);
            int downscaledRes = largerRes / preset.downscale;
            int minRes = Mathf.Min(smallerRes, downscaledRes);

            //scale factors (relative to min res)
            int heightFactor = (data.heightmapResolution-1) / minRes;
            int splatFactor = data.alphamapResolution / minRes;
            int downscaledFactor = downscaledRes / minRes;

            //creating rects
            CoordRect minRect = new CoordRect(worldRect.x*minRes, worldRect.y*minRes, worldRect.width*minRes, worldRect.height*minRes);
            CoordRect heightsRect = minRect * heightFactor;
            CoordRect splatsRect = minRect * splatFactor;
            CoordRect downscaledRect = minRect * downscaledFactor;

            //checking stackers
            if (heights==null || heights.smallRect!=downscaledRect || heights.bigRect!=heightsRect)
                heights = new Matrix.Stacker(downscaledRect, heightsRect);

            if (splats==null || splats.smallRect!=downscaledRect || splats.bigRect != splatsRect)
                splats = new Matrix.Stacker(downscaledRect, splatsRect);

            if (sediments==null || sediments.smallRect != downscaledRect || sediments.bigRect != splatsRect)
                sediments = new Matrix.Stacker(downscaledRect, splatsRect);

            heights.preserveDetail=preserveDetail; splats.preserveDetail=preserveDetail; sediments.preserveDetail = preserveDetail;

            //creating original arrays
            heights.matrix.ChangeRect(heightsRect);
            float[,] heights2d = heights.matrix.ReadHeighmap(data);

            splats.matrix.ChangeRect(splatsRect); sediments.matrix.ChangeRect(splatsRect);
            float[,,] splats3d = null;
            if (paintSplat)
            {
                splats3d = splats.matrix.ReadSplatmap(data, preset.foreground.num);
                sediments.matrix.ReadSplatmap(data, preset.background.num, splats3d);
            }

            //downscaling arrays
            heights.ToSmall();
            if (paintSplat) { splats.ToSmall(); sediments.ToSmall(); }

            //generating
            #if UNITY_EDITOR
            if (!preset.isErosion)
            {
                Matrix heightsMatrix = heights.matrix; Matrix splatsMatrix = splats.matrix; Matrix sedimentsMatrix = sediments.matrix;

                Coord min = heightsMatrix.rect.Min; Coord max = heightsMatrix.rect.Max;
                for (int x=min.x; x<max.x; x++)
                    for (int z=min.z; z<max.z; z++)
                {
                    float noise = ErosionBrushPlugin.Noise.Fractal(x, z, preset.noise_size);
                    //noise = 1f*(x-min.x)/(max.x-min.x);
                    noise = (noise-(1-preset.noise_uplift)) * preset.noise_amount;
                    heightsMatrix[x,z] += noise / data.size.y;

                    if (paintSplat)
                    {
                        float splatNoise = Mathf.Max(0,noise);
                        splatsMatrix[x,z] = Mathf.Sqrt(splatNoise)*0.3f;

                        float sedimentNoise = Mathf.Max(0,-noise);
                        sedimentsMatrix[x,z] = Mathf.Sqrt(sedimentNoise)*0.3f;
                    }

                    //test
                    //splatsMatrix[x,z] += 0.5f; //1f * (x-min.x) / (max.x-min.x);
                    //sediments.matrix[x,z] += 0.5f;// 1f * (z-min.z) / (max.z-min.z);
                }
            }
            else
            {
                ErosionBrushPlugin.Erosion.ErosionIteration (heights.matrix.array, paintSplat? splats.matrix.array:null, paintSplat? sediments.matrix.array:null,
                    heights.matrix.rect.size.x, heights.matrix.rect.size.z,
                    erosionDurability:preset.erosion_durability, erosionAmount:preset.erosion_amount, sedimentAmount:preset.sediment_amount, erosionFluidityIterations:preset.erosion_fluidityIterations);

                //blurring heights
                heights.matrix.Blur(intensity:preset.erosion_smooth);

                //increasing splat
                splats.matrix.Multiply(1.3f);
                sediments.matrix.Multiply(1.3f);
            }
            #endif

            //upscaling arrays (+blur)
            heights.ToBig(); splats.ToBig(); sediments.ToBig();

            //record undo. Undo.RecordObject and SetDirty are done in editor
            if (recordUndo)
            {
                if (newUndo)
                {
                    if (undoList.Count > 10) undoList.RemoveAt(0);
                    undoList.Add(new List<UndoStep>());
                }
                if (undoList.Count == 0) undoList.Add(new List<UndoStep>());
                undoList[undoList.Count-1].Add( new UndoStep(heights2d, splats3d, heightsRect.offset.x, heightsRect.offset.z, splatsRect.offset.x, splatsRect.offset.z) );
            }

            //apply
            heights.matrix.WriteHeightmap(data, heights2d, (useFallof ? preset.brushFallof : -1));

            if (paintSplat) Matrix.AddSplatmaps(data,
                new Matrix[] {splats.matrix, sediments.matrix},
                new int[] {preset.foreground.num, preset.background.num},
                new float[] {preset.foreground.apply? preset.foreground.opacity:0, preset.background.apply? preset.background.opacity:0},
                brushFallof:(useFallof ? preset.brushFallof : -1),
                array:splats3d); //note that splat and sediments are additive
        }
Ejemplo n.º 22
0
 public static CoordRect Intersect(CoordRect c1, CoordRect c2)
 {
     c1.Clamp(c2.Min, c2.Max); return c1;
 }
Ejemplo n.º 23
0
 public Matrix(CoordRect rect)
 {
     this.rect = rect;
         array = new float[rect.size.x*rect.size.z];
 }
Ejemplo n.º 24
0
        static public void ErosionIteration(Matrix heights, Matrix erosion, Matrix sedimentSum, CoordRect area = new CoordRect(),
                                            float erosionDurability = 0.9f, float erosionAmount = 1f, float sedimentAmount = 0.5f, int erosionFluidityIterations = 3, float ruffle = 0.1f,
                                            Matrix torrents         = null, Matrix sediments    = null, int[] stepsArray = null, int[] heightsInt = null, int[] order = null)
        {
            if (area.isZero)
            {
                area = heights.rect;
            }
            int count = heights.count;
            int seed  = 12345;

            #region Creating order array

            int steps = 1000000;

            //creating int-type copy of heights
            if (heightsInt == null)
            {
                heightsInt = new int[count];
            }
            for (int i = 0; i < heights.count; i++)
            {
                heightsInt[i] = (int)(Mathf.Clamp01(heights.array[i]) * steps);
            }

            //order array
            if (order == null)
            {
                order = new int[count];
            }
            order = ArrayTools.Order(heightsInt, order: order, max: heights.count, stepsArray: stepsArray);

            //setting out-of-area order num to negative
            for (int j = 0; j < heights.count; j++)
            {
                int   pos   = order[j];
                Coord coord = heights.rect.CoordByNum(pos);
                if (!area.CheckInRangeAndBounds(coord))
                {
                    order[j] = -1;
                }
            }

            #endregion

            #region Creating torrents

            if (torrents == null)
            {
                torrents = new Matrix(heights.rect);
            }
            torrents.ChangeRect(heights.rect);
            torrents.Fill(1f);                             //casting initial rain

            for (int j = count - 1; j >= 0; j--)
            {
                //finding column ordered by height
                int pos = order[j];
                if (pos < 0)
                {
                    continue;
                }

                /*
                 * MooreCross height = new MooreCross(heights, pos); //moore
                 * MooreCross torrent = new MooreCross(torrents, pos); //moore
                 * if (torrent.c > 2000000000) torrent.c = 2000000000;
                 *
                 * //creating torrents
                 * MooreCross delta = new MooreCross(height); //moore
                 * delta.SubtractInverse(height.c);
                 * delta.ClampPositive();
                 *
                 * delta.Percent(); //every side now determines a percent - how many water should go to it
                 * delta.Multiply(torrent.c);
                 * torrent.Add(delta);
                 */

                //getting height values
                float[] m = heights.array; int i = pos; int sizeX = heights.rect.size.x;
                float   h = m[i]; float hx = m[i - 1]; float hX = m[i + 1]; float hz = m[i - sizeX]; float hZ = m[i + sizeX];
                float   hxz = m[i - 1 - sizeX]; float hXz = m[i + 1 - sizeX]; float hxZ = m[i - 1 + sizeX]; float hXZ = m[i + 1 + sizeX];

                //creating delta
                float d = h - h; float dx = h - hx; float dX = h - hX; float dz = h - hz; float dZ = h - hZ;
                float dxz = h - hxz; float dXz = h - hXz; float dxZ = h - hxZ; float dXZ = h - hXZ;

                //ignoring negative delta values
                d   = d > 0? d : 0; dx = dx > 0? dx : 0; dX = dX > 0? dX : 0; dz = dz > 0? dz : 0; dZ = dZ > 0? dZ : 0;
                dxz = dxz > 0? dxz : 0; dXz = dXz > 0? dXz : 0; dxZ = dxZ > 0? dxZ : 0; dXZ = dXZ > 0? dXZ : 0;

                //finding percents
                float p = 0, px = 0, pX = 0, pz = 0, pZ = 0, pxz = 0, pXz = 0, pxZ = 0, pXZ = 0;
                float s = d + dx + dX + dz + dZ + dxz + dXz + dxZ + dXZ;
                if (s > 0.00001f)
                {
                    p = d / s; px = dx / s; pX = dX / s; pz = dz / s; pZ = dZ / s; pxz = dxz / s; pXz = dXz / s; pxZ = dxZ / s; pXZ = dXZ / s;
                }

                //getting central torrent (and clamping it)
                float t = torrents.array[i];
                if (t > 2000000000)
                {
                    t = 2000000000;
                }

                //spreading central torrent according percents delta. And adding to torrents array
                m                 = torrents.array;
                m[i]             += t * p; m[i - 1] += t * px; m[i + 1] += t * pX; m[i - sizeX] += t * pz; m[i + sizeX] += t * pZ;
                m[i - 1 - sizeX] += t * pxz; m[i + 1 - sizeX] += t * pXz; m[i - 1 + sizeX] += t * pxZ; m[i + 1 + sizeX] += t * pXZ;
            }
            #endregion

            #region Erosion

            if (sediments == null)
            {
                sediments = new Matrix(heights.rect);
            }
            else
            {
                sediments.ChangeRect(heights.rect);
            }
            sediments.Clear();

            for (int j = count - 1; j >= 0; j--)
            {
                //finding column ordered by height
                int pos = order[j];
                if (pos < 0)
                {
                    continue;
                }

                /*
                 * Cross height = new Cross(heights, pos);
                 * Cross torrent = new Cross(torrents, pos);
                 * Cross sediment = new Cross(sediments, pos);
                 *
                 * //erosion
                 * float erodeLine = (height.c + height.min)/2f; //halfway between current and maximum height
                 *
                 * if (height.c > erodeLine) //raising soil if column is higher than eroded column
                 * {
                 *      float raised = height.c - erodeLine;
                 *      raised = Mathf.Min(raised, raised*(torrent.c-1) * (1-erosionDurability));  //could not raise more soil than height-minHeight. //torrents always have 1 or more
                 *      raised *= erosionAmount;
                 *
                 *      heights.array[pos] -= raised; //raising soil
                 *      height.c -= raised;
                 *      sediments.array[pos] += raised * sedimentAmount; //and saving raised to sediment
                 *      sediment.c += raised * sedimentAmount;
                 *
                 *      if (paintErosion != null) paintErosion.array[pos] += raised * mapsFactor; //and writing to ref
                 * }
                 */

                //getting height values
                float[] m = heights.array; int i = pos; int sizeX = heights.rect.size.x;
                float   h = m[i]; float hx = m[i - 1]; float hX = m[i + 1]; float hz = m[i - sizeX]; float hZ = m[i + sizeX];

                //height minimum
                float h_min = h;
                if (hx < h_min)
                {
                    h_min = hx;
                }
                if (hX < h_min)
                {
                    h_min = hX;
                }
                if (hz < h_min)
                {
                    h_min = hz;
                }
                if (hZ < h_min)
                {
                    h_min = hZ;
                }

                //erosion line
                float erodeLine = (h + h_min) / 2f;                               //halfway between current and maximum height
                if (h < erodeLine)
                {
                    continue;
                }

                //raising soil
                float raised    = h - erodeLine;
                float maxRaised = raised * (torrents.array[pos] - 1) * (1 - erosionDurability);
                if (raised > maxRaised)
                {
                    raised = maxRaised;
                }
                raised *= erosionAmount;

                //saving arrays
                heights.array[pos]   -= raised;
                sediments.array[pos] += raised * sedimentAmount;
                if (erosion != null)
                {
                    erosion.array[pos] += raised;                                                  //and writing to ref
                }
            }
            #endregion

            #region Settling sediment

            for (int l = 0; l < erosionFluidityIterations; l++)
            {
                for (int j = count - 1; j >= 0; j--)
                {
                    //finding column ordered by height
                    int pos = order[j];
                    if (pos < 0)
                    {
                        continue;
                    }

                    /*
                     * Cross height = new Cross(heights, pos);
                     * Cross sediment = new Cross(sediments, pos);
                     * float sedimentSum = sediment.c+sediment.px+sediment.nx+sediment.pz+sediment.nz;
                     * if (sedimentSum < 0.00001f) continue;
                     *
                     * //finding columns that sediment will spread to
                     * Cross spread = new Cross(1,1,1,1,1); //actually it'a s bool-cross
                     *
                     * //from top to bottom
                     * foreach (int i in height.Sorted())
                     * {
                     *      //float curMaxLevel = (height*spread).max;
                     *      float curMaxLevel = 0;
                     *      if (spread.c > 0.1f && height.c > curMaxLevel) curMaxLevel = height.c;
                     *      if (spread.px > 0.1f && height.px > curMaxLevel) curMaxLevel = height.px;
                     *      if (spread.nx > 0.1f && height.nx > curMaxLevel) curMaxLevel = height.nx;
                     *      if (spread.pz > 0.1f && height.pz > curMaxLevel) curMaxLevel = height.pz;
                     *      if (spread.nz > 0.1f && height.nz > curMaxLevel) curMaxLevel = height.nz;
                     *
                     *      //sum of lack of heights to current max level  less  then total sediment
                     *      float lackSum = 0; //... + Mathf.Max(curMaxLevel-height.px, 0) + ...
                     *      if (curMaxLevel-height.c > 0) lackSum += curMaxLevel-height.c;
                     *      if (curMaxLevel-height.px > 0) lackSum += curMaxLevel-height.px;
                     *      if (curMaxLevel-height.pz > 0) lackSum += curMaxLevel-height.pz;
                     *      if (curMaxLevel-height.nx > 0) lackSum += curMaxLevel-height.nx;
                     *      if (curMaxLevel-height.nz > 0) lackSum += curMaxLevel-height.nz;
                     *
                     *      if (lackSum < sedimentSum) break;
                     *      spread[i] = 0;  //I find your lack of sediment disturbing!
                     *
                     *      //if ((lackSum < sedimentSum)) spread = new Cross(1,1,1,1,1);
                     *      //else spread = new Cross(0,0,0,0,0);
                     *
                     * }
                     *
                     * //find sediment-filled level
                     * float columnsRemain = spread.c+spread.px+spread.nx+spread.pz+spread.nz; //aka spread.sum;
                     * float filledLevel = 0;
                     * if (columnsRemain > 0.00001f) filledLevel = // ((height*spread).sum + sediment.sum)/columnsRemain
                     *      ((height.c*spread.c)+(height.px*spread.px)+(height.nx*spread.nx)+(height.pz*spread.pz)+(height.nz*spread.nz) + sedimentSum)/columnsRemain;
                     *
                     * //transfering sediment
                     * sediment = new Cross(
                     *      filledLevel-height.c>0 ? (filledLevel-height.c)*spread.c : 0,
                     *      filledLevel-height.px>0 ? (filledLevel-height.px)*spread.px : 0,
                     *      filledLevel-height.nx>0 ? (filledLevel-height.nx)*spread.nx : 0,
                     *      filledLevel-height.pz>0 ? (filledLevel-height.pz)*spread.pz : 0,
                     *      filledLevel-height.nz>0 ? (filledLevel-height.nz)*spread.nz : 0);
                     *
                     * sediment.ToMatrix(sediments, pos);
                     */


                    //getting height values
                    float[] m = heights.array; int sizeX = heights.rect.size.x;
                    float   h = m[pos]; float hx = m[pos - 1]; float hX = m[pos + 1]; float hz = m[pos - sizeX]; float hZ = m[pos + sizeX];

                    //getting sediment values
                    m = sediments.array;
                    float s = m[pos]; float sx = m[pos - 1]; float sX = m[pos + 1]; float sz = m[pos - sizeX]; float sZ = m[pos + sizeX];

                    //sediment sum
                    float sum = s + sx + sX + sz + sZ;
                    if (sum < 0.00001f)
                    {
                        continue;
                    }

                    //pouring sum to all cells
                    float sedimentFifth = sum / 5;
                    s = sedimentFifth; sx = sedimentFifth; sX = sedimentFifth; sz = sedimentFifth; sZ = sedimentFifth;

                    //levelling
                    //for (int i=0; i<2; i++)
                    //{
                    //x line
                    float avg = (h + s + sx + hx) / 2;
                    if (h + s > hx + sx)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sx += transfer;
                    }
                    else
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; s += transfer;
                    }

                    avg = (hx + sx + sX + hX) / 2;
                    if (hx + sx > hX + sX)
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; sX += transfer;
                    }
                    else
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; sx += transfer;
                    }

                    avg = (h + s + sX + hX) / 2;
                    if (h + s > hX + sX)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sX += transfer;
                    }
                    else
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; s += transfer;
                    }

                    //z line
                    avg = (h + s + sz + hz) / 2;
                    if (h + s > hz + sz)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; s += transfer;
                    }

                    avg = (hZ + sZ + sz + hz) / 2;
                    if (hZ + sZ > hz + sz)
                    {
                        float transfer = sZ + hZ - avg; if (transfer > sZ)
                        {
                            transfer = sZ;
                        }
                        sZ -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; sZ += transfer;
                    }

                    avg = (h + s + sz + hz) / 2;
                    if (h + s > hz + sz)
                    {
                        float transfer = s + h - avg; if (transfer > s)
                        {
                            transfer = s;
                        }
                        s -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; s += transfer;
                    }

                    //side pairs
                    avg = (hx + sx + sz + hz) / 2;
                    if (hx + sx > hz + sz)
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; sx += transfer;
                    }

                    avg = (hX + sX + sZ + hZ) / 2;
                    if (hX + sX > hZ + sZ)
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; sZ += transfer;
                    }
                    else
                    {
                        float transfer = sZ + hZ - avg; if (transfer > sZ)
                        {
                            transfer = sZ;
                        }
                        sZ -= transfer; sX += transfer;
                    }

                    avg = (hx + sx + sZ + hZ) / 2;
                    if (hx + sx > hZ + sZ)
                    {
                        float transfer = sx + hx - avg; if (transfer > sx)
                        {
                            transfer = sx;
                        }
                        sx -= transfer; sZ += transfer;
                    }
                    else
                    {
                        float transfer = sZ + hZ - avg; if (transfer > sZ)
                        {
                            transfer = sZ;
                        }
                        sZ -= transfer; sx += transfer;
                    }

                    avg = (hX + sX + sz + hz) / 2;
                    if (hX + sX > hz + sz)
                    {
                        float transfer = sX + hX - avg; if (transfer > sX)
                        {
                            transfer = sX;
                        }
                        sX -= transfer; sz += transfer;
                    }
                    else
                    {
                        float transfer = sz + hz - avg; if (transfer > sz)
                        {
                            transfer = sz;
                        }
                        sz -= transfer; sX += transfer;
                    }
                    //}

                    //additionally levelling

                    /*int sNum = 0; //number of cells with sediment
                     * float total = 0; //total height + sediment level
                     * if (s>0.001f) { sNum++; total+=h+s; }
                     * if (sx>0.001f) { sNum++; total+=hx+sx; }  if (sX>0.001f) { sNum++; total+=hX+sX; }
                     * if (sz>0.001f) { sNum++; total+=hz+sz; }  if (sZ>0.001f) { sNum++; total+=hZ+sZ; }
                     *
                     * float totalAvg = total / sNum;
                     * if (s>0.001f) s=totalAvg-h;
                     * if (sx>0.001f) sx=totalAvg-hx;   if (sX>0.001f) sX=totalAvg-hX;
                     * if (sz>0.001f) sz=totalAvg-hz;  if (sZ>0.001f) sZ=totalAvg-hZ;*/

                    //to matrix
                    m      = sediments.array;
                    m[pos] = s; m[pos - 1] = sx; m[pos + 1] = sX; m[pos - sizeX] = sz; m[pos + sizeX] = sZ;

                    if (sedimentSum != null)
                    {
                        m       = sedimentSum.array;
                        m[pos] += s; m[pos - 1] += sx; m[pos + 1] += sX; m[pos - sizeX] += sz; m[pos + sizeX] += sZ;
                    }
                }
            }
            #endregion

            #region Writing sediments back to height, adding smooth and ruffle

            for (int j = count - 1; j >= 0; j--)
            {
                //writing heights
                heights.array[j] += sediments.array[j];

                seed = 214013 * seed + 2531011;
                float random = ((seed >> 16) & 0x7FFF) / 32768f;

                int pos = order[j];
                if (pos < 0)
                {
                    continue;
                }

                float[] m = heights.array; int sizeX = heights.rect.size.x;
                float   h = m[pos]; float hx = m[pos - 1]; float hX = m[pos + 1]; float hz = m[pos - sizeX]; float hZ = m[pos + sizeX];

                //smoothing sediments a bit
                float s = sediments.array[pos];
                if (s > 0.0001f)
                {
                    float smooth = s / 2f; if (smooth > 0.75f)
                    {
                        smooth = 0.75f;
                    }
                    heights.array[pos] = h * (1 - smooth) + (hx + hX + hz + hZ) / 4f * smooth;
                }

                else
                {
                    float maxHeight = hx; if (hX > maxHeight)
                    {
                        maxHeight = hX;
                    }
                    if (hz > maxHeight)
                    {
                        maxHeight = hz;
                    }
                    if (hZ > maxHeight)
                    {
                        maxHeight = hZ;
                    }
                    float minHeight = hx; if (hX < minHeight)
                    {
                        minHeight = hX;
                    }
                    if (hz < minHeight)
                    {
                        minHeight = hz;
                    }
                    if (hZ < minHeight)
                    {
                        minHeight = hZ;
                    }
                    float randomHeight = random * (maxHeight - minHeight) + minHeight;
                    heights.array[pos] = heights.array[pos] * (1 - ruffle) + randomHeight * ruffle;
                }
                //Cross height = new Cross(heights, pos);
                //float maxAround = Mathf.Max(heights.array[pos-1], heights.array[pos+1], heights.array[pos-heights.rect.size.x], heights.array[pos+heights.rect.size.x]);
                //heights.array[pos] = Mathf.Min(heights.array[pos], maxAround);

                //heights.array[pos] = Mathf.Min(height.c, height.maxAround);
                //heights.array[pos] = Mathf.Min(height.c, height.avgAround)*0.5f + height.c*0.5f;

                //float maxHeight = height.maxAround;
                //float minHeight = height.minAround;
                //float randomHeight = random*(maxHeight-minHeight) + minHeight;
                //heights.array[pos] = heights.array[pos]*(1-ruffle) + randomHeight*ruffle;
            }
            #endregion
        }                //erosion iteration
Ejemplo n.º 25
0
			public Matrix (Coord offset, Coord size)
			{
				this.rect = new CoordRect(offset, size);
				array = new float[rect.size.x*rect.size.z];
			}
Ejemplo n.º 26
0
			public Matrix (CoordRect rect)
			{
				this.rect = rect;
				array = new float[rect.size.x*rect.size.z];
			}
Ejemplo n.º 27
0
            public Stacker(CoordRect smallRect, CoordRect bigRect)
            {
                this.smallRect = smallRect; this.bigRect = bigRect;
                    isDownscaled = false;

                    //do not create additional matrices if rect sizes are the same
                    if (bigRect==smallRect)
                    {
                        upscaled = downscaled = new Matrix(bigRect);
                    }

                    else
                    {
                        downscaled = new Matrix(smallRect);
                        upscaled = new Matrix(bigRect);
                        difference = new Matrix(bigRect);
                        //once arrays created they should not be resized
                    }
            }
Ejemplo n.º 28
0
        public void ApplyBrush(Vector3 pos, float radius, bool useFallof = true)
        {
            //preparing height matrix
            float     heightPixelSizeX = terrains[0].terrainData.size.x / terrains[0].terrainData.heightmapResolution;
            float     heightPixelSizeZ = terrains[0].terrainData.size.z / terrains[0].terrainData.heightmapResolution;
            CoordRect heightRect       = pos.ToCoordRect(radius, heightPixelSizeX, heightPixelSizeZ);

            heightRect = heightRect.Approximate(preset.downscale);
            Matrix height = new Matrix(heightRect);

            //filling height matrix
            for (int t = 0; t < terrains.Length; t++)
            {
                GetHeight(height, terrains[t]);
            }
            Matrix sourceHeight = height.Copy();

            //downscaling
            if (preset.downscale > 1)
            {
                height = height.Downscale(preset.downscale);
            }

            //preparing splat matrices
            Matrix bedrockMatrix = null; Matrix sedimentMatrix = null;

            if ((preset.foreground.apply && terrains[0].terrainData.alphamapLayers > preset.foreground.num) ||
                (preset.background.apply && terrains[0].terrainData.alphamapLayers > preset.background.num))
            {
                bedrockMatrix = new Matrix(height.rect); sedimentMatrix = new Matrix(height.rect);
            }

            //brush
            if (preset.isNoise)
            {
                ApplyNoise(height, bedrockMatrix, sedimentMatrix);
            }
            if (preset.isErosion)
            {
                ApplyErosion(height, bedrockMatrix, sedimentMatrix);
            }

            //upscaling
            if (preset.downscale > 1)
            {
                height = height.Upscale(preset.downscale);
                if (bedrockMatrix != null)
                {
                    bedrockMatrix = bedrockMatrix.Upscale(preset.downscale);
                }
                if (sedimentMatrix != null)
                {
                    sedimentMatrix = sedimentMatrix.Upscale(preset.downscale);
                }
            }

            //making height additive
            if (!preset.preserveDetail || preset.downscale == 1)
            {
                height.Subtract(sourceHeight);
            }
            else
            {
                Matrix smoothHeight = sourceHeight.Downscale(preset.downscale);
                smoothHeight = smoothHeight.Upscale(preset.downscale);
                height.Subtract(smoothHeight);
            }

            //applying fallof
            if (useFallof)
            {
                Coord center = height.rect.Center; float rad = height.rect.size.x / 2f;
                Coord min = height.rect.Min; Coord max = height.rect.Max;
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float percent = (rad - Coord.Distance(new Coord(x, z), center)) / (rad - rad * preset.brushFallof);
                        if (percent < 0)
                        {
                            percent = 0;
                        }
                        if (percent > 1)
                        {
                            percent = 1;
                        }
                        percent = 3 * percent * percent - 2 * percent * percent * percent;

                        height[x, z] *= percent;
                        if (bedrockMatrix != null)
                        {
                            bedrockMatrix[x, z] *= percent;
                        }
                        if (sedimentMatrix != null)
                        {
                            sedimentMatrix[x, z] *= percent;
                        }
                    }
                }
            }

            //scaling splat matrices to match terrain splat resolution
            float     splatPixelSize = terrains[0].terrainData.size.x / terrains[0].terrainData.alphamapResolution;
            CoordRect splatRect      = pos.ToCoordRect(radius, splatPixelSize);

            if (bedrockMatrix != null)
            {
                bedrockMatrix = bedrockMatrix.Resize(splatRect);
            }
            if (sedimentMatrix != null)
            {
                sedimentMatrix = sedimentMatrix.Resize(splatRect);
            }

            //backing to terrain
            for (int t = 0; t < terrains.Length; t++)
            {
                AddHeight(height, terrains[t]);

                if (bedrockMatrix != null && preset.foreground.apply)
                {
                    AddSplat(bedrockMatrix, terrains[t], preset.foreground.num);
                }
                if (sedimentMatrix != null && preset.background.apply)
                {
                    AddSplat(sedimentMatrix, terrains[t], preset.background.num);
                }
            }
        }
Ejemplo n.º 29
0
        }                                                                                                                                  //inscribed parameter will shrink rect to make it lay inside original rect

        public void Round(CoordRect r, bool inscribed = false)
        {
            offset.Round(r.offset, ceil: inscribed); size.Round(r.size, ceil: !inscribed);
        }
Ejemplo n.º 30
0
        public void ToTexture(Texture2D texture=null, Color[] colors=null, float rangeMin=0, float rangeMax=1, bool resizeTexture=false)
        {
            //creating or resizing texture
                if (texture == null) texture = new Texture2D(rect.size.x, rect.size.z);
                if (resizeTexture) texture.Resize(rect.size.x, rect.size.z);

                //finding matrix-texture intersection
                Coord textureSize = new Coord(texture.width, texture.height);
                CoordRect textureRect = new CoordRect(new Coord(0,0), textureSize);
                CoordRect intersection = CoordRect.Intersect(textureRect, rect);

                //checking ref color array
                if (colors == null || colors.Length != intersection.size.x*intersection.size.z) colors = new Color[intersection.size.x*intersection.size.z];

                //filling texture
                Coord min = intersection.Min; Coord max = intersection.Max;
                for (int x=min.x; x<max.x; x++)
                    for (int z=min.z; z<max.z; z++)
                {
                    float val = this[x,z];

                    //adjusting value to range
                    val -= rangeMin;
                    val /= rangeMax-rangeMin;

                    //making color gradient
                    float byteVal = val * 256;
                    int flooredByteVal = (int)byteVal;
                    float remainder = byteVal - flooredByteVal;

                    float flooredVal = flooredByteVal/256f;
                    float ceiledVal = (flooredByteVal+1)/256f;

                    //saving to colors
                    int tx = x-min.x; int tz = z-min.z;
                    colors[tz*(max.x-min.x) + tx] = new Color(flooredVal, remainder>0.333f ? ceiledVal : flooredVal, remainder>0.666f ? ceiledVal : flooredVal);
                }

                texture.SetPixels(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z, colors);
                texture.Apply();
        }
Ejemplo n.º 31
0
 public static CoordRect Intersect(CoordRect c1, CoordRect c2)
 {
     c1.Clamp(c2.Min, c2.Max); return(c1);
 }
Ejemplo n.º 32
0
        public Matrix Resize(CoordRect newRect, float smoothness=1, Matrix result=null)
        {
            //calculating ratio
                int upscaleRatio = newRect.size.x / rect.size.x;
                int downscaleRatio = rect.size.x / newRect.size.x;

                //checking if rect could be rescaled
                if (upscaleRatio > 1 && !newRect.Divisible(upscaleRatio)) Debug.LogError("Matrix rect " + rect + " could not be upscaled to " + newRect + " with factor " + upscaleRatio);
                if (downscaleRatio > 1 && !rect.Divisible(downscaleRatio)) Debug.LogError("Matrix rect " + rect + " could not be downscaled to " + newRect + " with factor " + downscaleRatio);

                //scaling
                if (upscaleRatio > 1) result = Upscale(upscaleRatio, result:result);
                if (downscaleRatio > 1) result = Downscale(downscaleRatio, smoothness:smoothness, result:result);

                //returning clone if all ratios are 1
                if (upscaleRatio <= 1 && downscaleRatio <= 1) return Clone(result);
                else return result;
        }
Ejemplo n.º 33
0
 public void Round(CoordRect r, bool inscribed=false)
 {
     offset.Round(r.offset, ceil:inscribed); size.Round(r.size, ceil:!inscribed);
 }
Ejemplo n.º 34
0
 public void RemoveBorders(CoordRect centerRect)
 {
     RemoveBorders(
             Mathf.Max(0,centerRect.offset.x-rect.offset.x),
             Mathf.Max(0,centerRect.offset.z-rect.offset.z),
             Mathf.Max(0,rect.Max.x-centerRect.Max.x+1),
             Mathf.Max(0,rect.Max.z-centerRect.Max.z+1) );
 }
Ejemplo n.º 35
0
        public void ApplyBrush(Rect worldRect, bool useFallof = true, bool newUndo = false)
        {
            TerrainData data = terrain.terrainData;
            //if (data.heightmapResolution-1 > 512 || data.alphamapResolution > 512) return;

            //preparing useful values
            bool paintSplat = preset.paintSplat;

            if (data.alphamapLayers == 0)
            {
                paintSplat = false;
            }

            //finding minimum resolution
            int smallerRes    = Mathf.Min(data.heightmapResolution - 1, data.alphamapResolution);
            int largerRes     = Mathf.Max(data.heightmapResolution - 1, data.alphamapResolution);
            int downscaledRes = largerRes / preset.downscale;
            int minRes        = Mathf.Min(smallerRes, downscaledRes);

            //scale factors (relative to min res)
            int heightFactor     = (data.heightmapResolution - 1) / minRes;
            int splatFactor      = data.alphamapResolution / minRes;
            int downscaledFactor = downscaledRes / minRes;

            //creating rects
            CoordRect minRect        = new CoordRect(worldRect.x * minRes, worldRect.y * minRes, worldRect.width * minRes, worldRect.height * minRes);
            CoordRect heightsRect    = minRect * heightFactor;
            CoordRect splatsRect     = minRect * splatFactor;
            CoordRect downscaledRect = minRect * downscaledFactor;

            //checking stackers
            if (heights == null || heights.smallRect != downscaledRect || heights.bigRect != heightsRect)
            {
                heights = new Matrix.Stacker(downscaledRect, heightsRect);
            }

            if (splats == null || splats.smallRect != downscaledRect || splats.bigRect != splatsRect)
            {
                splats = new Matrix.Stacker(downscaledRect, splatsRect);
            }

            if (sediments == null || sediments.smallRect != downscaledRect || sediments.bigRect != splatsRect)
            {
                sediments = new Matrix.Stacker(downscaledRect, splatsRect);
            }

            heights.preserveDetail = preserveDetail; splats.preserveDetail = preserveDetail; sediments.preserveDetail = preserveDetail;

            //creating original arrays
            heights.matrix.ChangeRect(heightsRect);
            float[,] heights2d = heights.matrix.ReadHeighmap(data);

            splats.matrix.ChangeRect(splatsRect); sediments.matrix.ChangeRect(splatsRect);
            float[,,] splats3d = null;
            if (paintSplat)
            {
                splats3d = splats.matrix.ReadSplatmap(data, preset.foreground.num);
                sediments.matrix.ReadSplatmap(data, preset.background.num, splats3d);
            }

            //downscaling arrays
            heights.ToSmall();
            if (paintSplat)
            {
                splats.ToSmall(); sediments.ToSmall();
            }

            //generating
                        #if UNITY_EDITOR
            if (!preset.isErosion)
            {
                Matrix heightsMatrix = heights.matrix; Matrix splatsMatrix = splats.matrix; Matrix sedimentsMatrix = sediments.matrix;

                Coord min = heightsMatrix.rect.Min; Coord max = heightsMatrix.rect.Max;
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float noise = ErosionBrushPlugin.Noise.Fractal(x, z, preset.noise_size);
                        //noise = 1f*(x-min.x)/(max.x-min.x);
                        noise = (noise - (1 - preset.noise_uplift)) * preset.noise_amount;
                        heightsMatrix[x, z] += noise / data.size.y;

                        if (paintSplat)
                        {
                            float splatNoise = Mathf.Max(0, noise);
                            splatsMatrix[x, z] = Mathf.Sqrt(splatNoise) * 0.3f;

                            float sedimentNoise = Mathf.Max(0, -noise);
                            sedimentsMatrix[x, z] = Mathf.Sqrt(sedimentNoise) * 0.3f;
                        }

                        //test
                        //splatsMatrix[x,z] += 0.5f; //1f * (x-min.x) / (max.x-min.x);
                        //sediments.matrix[x,z] += 0.5f;// 1f * (z-min.z) / (max.z-min.z);
                    }
                }
            }
            else
            {
                ErosionBrushPlugin.Erosion.ErosionIteration(heights.matrix.array, paintSplat? splats.matrix.array:null, paintSplat? sediments.matrix.array:null,
                                                            heights.matrix.rect.size.x, heights.matrix.rect.size.z,
                                                            erosionDurability: preset.erosion_durability, erosionAmount: preset.erosion_amount, sedimentAmount: preset.sediment_amount, erosionFluidityIterations: preset.erosion_fluidityIterations);

                //blurring heights
                heights.matrix.Blur(intensity: preset.erosion_smooth);

                //increasing splat
                splats.matrix.Multiply(1.3f);
                sediments.matrix.Multiply(1.3f);
            }
                        #endif

            //upscaling arrays (+blur)
            heights.ToBig(); splats.ToBig(); sediments.ToBig();

            //record undo. Undo.RecordObject and SetDirty are done in editor
            if (recordUndo)
            {
                if (newUndo)
                {
                    if (undoList.Count > 10)
                    {
                        undoList.RemoveAt(0);
                    }
                    undoList.Add(new List <UndoStep>());
                }
                if (undoList.Count == 0)
                {
                    undoList.Add(new List <UndoStep>());
                }
                undoList[undoList.Count - 1].Add(new UndoStep(heights2d, splats3d, heightsRect.offset.x, heightsRect.offset.z, splatsRect.offset.x, splatsRect.offset.z));
            }

            //apply
            heights.matrix.WriteHeightmap(data, heights2d, (useFallof ? preset.brushFallof : -1));

            if (paintSplat)
            {
                Matrix.AddSplatmaps(data,
                                    new Matrix[] { splats.matrix, sediments.matrix },
                                    new int[] { preset.foreground.num, preset.background.num },
                                    new float[] { preset.foreground.apply?preset.foreground.opacity: 0, preset.background.apply? preset.background.opacity:0 },
                                    brushFallof: (useFallof ? preset.brushFallof : -1),
                                    array: splats3d); //note that splat and sediments are additive
            }
        }
Ejemplo n.º 36
0
			public Matrix () { array = new float[0]; rect = new CoordRect(0,0,0,0); count = 0; } //for serializer