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