static public 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);
			}
Beispiel #2
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;
			}
Beispiel #3
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;
			}
Beispiel #4
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;
			}
Beispiel #5
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
					}
				}
Beispiel #6
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);
			}
Beispiel #7
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);
			}
Beispiel #8
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();
			}
Beispiel #9
0
        public void ApplyBrush(Rect worldRect, bool useFallof = true, bool newUndo = false)
        {
            TerrainData data = terrain.terrainData;

            //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 (!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 = 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);
            }

            //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
            }
        }
Beispiel #10
0
		public void Round (int val, bool inscribed=false) { offset.Round(val, ceil:inscribed); size.Round(val, ceil:!inscribed); } //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); }
Beispiel #11
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) ); 
			}
Beispiel #12
0
			static public 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);
			}
Beispiel #13
0
        public void ApplyBrush(Rect worldRect, bool useFallof=true, bool newUndo=false)
        {
            TerrainData data = terrain.terrainData;

            //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 (!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 = 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);
            }

            //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
        }
Beispiel #14
0
			public void ChangeRect (CoordRect newRect) //will re-create array only if it is needed
			{
				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];
				}
			}
Beispiel #15
0
			public Matrix (Coord offset, Coord size)
			{
				this.rect = new CoordRect(offset, size);
				array = new float[rect.size.x*rect.size.z];
			}
Beispiel #16
0
			public Matrix (CoordRect rect)
			{
				this.rect = rect;
				array = new float[rect.size.x*rect.size.z];
			}
Beispiel #17
0
		public static CoordRect Intersect (CoordRect c1, CoordRect c2) { c1.Clamp(c2.Min, c2.Max); return c1; }
Beispiel #18
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];
         }
 }