//public static TerrainOutputImage getVectorFieldImage(Vector[][] vectorField) //{ // int width = CELL_SIZE * vectorField.Length; // int height = CELL_SIZE * vectorField[0].Length; // Pen linePen = new Pen(Color.Black, 1); // Pen directionPen = new Pen(Color.Red, 1); // Bitmap bitmap = new Bitmap(width, height); // Graphics g = Graphics.FromImage(bitmap); // g.SmoothingMode = SmoothingMode.HighQuality; // g.Clear(Color.White); // for(int x = 0; x < vectorField.Length; x++) // { // for (int y = 0; y < vectorField[x].Length; y++) // { // drawVector(x * CELL_SIZE + CELL_SIZE/2, y * CELL_SIZE + CELL_SIZE/2, vectorField[x][y], g, linePen, directionPen); // } // } // TerrainOutputImage vectorFieldOutputImage = new TerrainOutputImage(); // vectorFieldOutputImage.Title = "Vector field"; // vectorFieldOutputImage.Key = "vectorField"; // vectorFieldOutputImage.ImageData = new int[bitmap.Width][]; // for (int i = 0; i < bitmap.Width; i++) // { // vectorFieldOutputImage.ImageData[i] = new int[bitmap.Height]; // for (int j = 0; j < bitmap.Height; j++) // { // Color color = bitmap.GetPixel(i, j); // vectorFieldOutputImage.ImageData[i][j] = (color.R << 24) | (color.G << 16) | (color.B << 8) | 0xff; // } // } // return vectorFieldOutputImage; //} //private static void drawVector(int posX, int posY, Vector vector, Graphics g, Pen linePen, Pen directionPen) //{ // float amplification = (CELL_SIZE/2)-1; // GraphicsState state = g.Save(); // g.TranslateTransform(posX, posY); // g.DrawLine(directionPen, 0, 0, vector.Vx * amplification, vector.Vy * amplification); // g.DrawLine(linePen, 0, 0, vector.Vx * -amplification, vector.Vy * -amplification); // g.Restore(state); //} private static void getLowestNeighbour(float?[][] heightMap, int x, int y, out int finalX, out int finalY) { float?currentHeight = 9999; int nX; int nY; finalX = x; finalY = y; float?neighbourHeight = TerrainHelpers.getLeft(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getLeftLeftTop(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getTopLeft(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getTopTopLeft(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getTop(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getTopTopRight(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getTopRight(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getRightRightTop(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getRight(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getRightRightBottom(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getBottomRight(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getBottomBottomRight(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getBottom(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getBottomBottomLeft(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getBottomLeft(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } neighbourHeight = TerrainHelpers.getLeftLeftBottom(heightMap, x, y, out nX, out nY); if (neighbourHeight != null && neighbourHeight < currentHeight) { currentHeight = neighbourHeight; finalX = nX; finalY = nY; } }
public static void startWork(List <TerrainInput> terrainInputs, List <TerrainOutput> terrainOutputs, HeightmapWorkflowData heightmapWorkflowData) { int size = 513; Dictionary <string, TerrainInput> inputMap = new Dictionary <string, TerrainInput>(); Dictionary <string, FormField> formFieldsMap = new Dictionary <string, FormField>(); createInputMap(terrainInputs, inputMap, formFieldsMap); System.Console.Out.WriteLine("Starting"); switch (((FormFieldOptions)formFieldsMap["parameters_gridSize"]).Value) { case 0: size = 65; break; case 1: size = 129; break; case 2: size = 257; break; case 3: size = 513; break; case 4: size = 1025; break; } Random random; if (targetSamples > 0) { random = new Random(); if (curSample == 0) { meanHeight = new List <float>(); meanVariance = new List <float>(); } } else { random = new Random(((FormFieldInteger)formFieldsMap["parameters_seed"]).Value); } //Random random = new Random(((FormFieldInteger)formFieldsMap["parameters_seed"]).Value); float heightFactor = (float)((FormFieldInteger)formFieldsMap["parameters_maxHeight"]).Value / (float)((FormFieldInteger)formFieldsMap["parameters_cellSize"]).Value; float?[][] heightMap = new float?[size][]; for (int x = 0; x < heightMap.Length; x++) { heightMap[x] = new float?[size]; for (int y = 0; y < heightMap.Length; y++) { heightMap[x][y] = null; } } System.Console.Out.WriteLine("Data created"); TerrainOutputImage terrainOutputRidges = new TerrainOutputImage(); terrainOutputRidges.Title = "Ridges"; terrainOutputRidges.Key = "ridges"; List <List <GeoPoint> > ridges = new List <List <GeoPoint> >(); if (((FormFieldCheck)formFieldsMap["parameters_useRidgeSketch"]).Value) { int[][] resizedPixels = Helpers.Instance.ResizePixels(((TerrainInputSketch)inputMap["ridgeSketch"]).Value, ((TerrainInputSketch)inputMap["ridgeSketch"]).Width, ((TerrainInputSketch)inputMap["ridgeSketch"]).Height, size, size); terrainOutputRidges.ImageData = resizedPixels; for (int x = 0; x < heightMap.Length; x++) { for (int y = 0; y < heightMap.Length; y++) { float height = (float)(((resizedPixels[x][y] & 0xff000000) >> 24) / 256.0); if (height != 0) { heightMap[x][y] = height; } } } } else { int ridgeParticles = ((FormFieldInteger)formFieldsMap["parameters_ridgeParticles"]).Value; RidgeHelpers.createRidges(heightMap, ridges, random, ridgeParticles); terrainOutputRidges.ImageData = new int[heightMap.Length][]; for (int x = 0; x < heightMap.Length; x++) { terrainOutputRidges.ImageData[x] = new int[heightMap.Length]; for (int y = 0; y < heightMap[x].Length; y++) { byte color = 0; if (heightMap[x][y] != null) { color = (byte)(heightMap[x][y] * 256); } terrainOutputRidges.ImageData[x][y] = (color << 24) | (color << 16) | (color << 8) | 0xff; } } } GeoPoint[][] gaussGeoPoints = TerrainHelpers.calculateDistanceToRidges(heightMap); TerrainOutputImage gaussTerrainOutputHeightMap = new TerrainOutputImage(); gaussTerrainOutputHeightMap.Title = "Gauss Height map"; gaussTerrainOutputHeightMap.Key = "gaussHeightMap"; gaussTerrainOutputHeightMap.ImageData = new int[gaussGeoPoints.Length][]; for (int x = 0; x < gaussGeoPoints.Length; x++) { gaussTerrainOutputHeightMap.ImageData[x] = new int[gaussGeoPoints.Length]; for (int y = 0; y < gaussGeoPoints[x].Length; y++) { byte color = (byte)(gaussGeoPoints[x][y].Height * 256); gaussTerrainOutputHeightMap.ImageData[x][y] = (color << 24) | (color << 16) | (color << 8) | 0xff; } } float?[][] gaussHeightMap = new float?[gaussGeoPoints.Length][]; for (int x = 0; x < gaussGeoPoints.Length; x++) { gaussHeightMap[x] = new float?[gaussGeoPoints.Length]; for (int y = 0; y < gaussGeoPoints[x].Length; y++) { gaussHeightMap[x][y] = gaussGeoPoints[x][y].Height; } } int[][] roughnessSketch = Helpers.Instance.ResizePixels(((TerrainInputSketch)inputMap["roughnessSketch"]).Value, ((TerrainInputSketch)inputMap["roughnessSketch"]).Width, ((TerrainInputSketch)inputMap["roughnessSketch"]).Height, size, size); float[][] roughness = new float[size][]; int veryLowColor = ColorToInt(stringToColor("#0000ffff")); int lowColor = ColorToInt(stringToColor("#00ffffff")); int highColor = ColorToInt(stringToColor("#ffff00ff")); int veryHighColor = ColorToInt(stringToColor("#ff0000ff")); for (int x = 0; x < size; x++) { roughness[x] = new float[size]; for (int y = 0; y < size; y++) { if (roughnessSketch[x][y] == veryLowColor) { roughness[x][y] = 0.5f; } else if (roughnessSketch[x][y] == lowColor) { roughness[x][y] = 0.75f; } else if (roughnessSketch[x][y] == highColor) { roughness[x][y] = 1.25f; } else if (roughnessSketch[x][y] == veryHighColor) { roughness[x][y] = 1.5f; } else { roughness[x][y] = 1f; } } } TerrainOutputImage terrainOutputRoughness = new TerrainOutputImage(); terrainOutputRoughness.Title = "Roughness"; terrainOutputRoughness.Key = "roughness"; terrainOutputRoughness.ImageData = roughnessSketch; //List<GeoPoint> riverPoints = RiverHelpers.traceRivers(gaussHeightMap, ridges, 8, random); /*foreach(GeoPoint geoPoint in riverPoints) * { * heightMap[geoPoint.X][geoPoint.Y] = geoPoint.Height; * }*/ List <GeoPoint> riverPoints = new List <GeoPoint>(); System.Console.Out.WriteLine("Ridges created"); TerrainHelpers.generateTerrain(heightMap, random, roughness, riverPoints, gaussHeightMap); System.Console.Out.WriteLine("Terrain created"); int termalErosionPass = ((FormFieldInteger)formFieldsMap["parameters_thermalErosionPass"]).Value; if (termalErosionPass != 0) { ErosionHelpers.applyThermalErosion(heightMap, termalErosionPass); System.Console.Out.WriteLine("ThermalErosion applied"); } int hydraulicErosionPass = ((FormFieldInteger)formFieldsMap["parameters_hydraulicErosionPass"]).Value; if (hydraulicErosionPass != 0) { HydraulicErosionCell[][] hydraulicErosionCells = ErosionHelpers.applyHydraulicErosion(heightMap, hydraulicErosionPass); System.Console.Out.WriteLine("HydraulicErosion applied"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("###Pass " + hydraulicErosionPass + "######"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); System.Console.Out.WriteLine("########################"); } System.Console.Out.WriteLine("##From terrain changed!!!"); String meanHeightStr = "Mean samples: "; String meanVarianceStr = "Mean variance: "; Boolean doContinue = true; if (targetSamples > 0) { //meanHeight = new List<float>(); //meanVariance = new List<float>(); int count = 0; double sum = 0; double diffSum = 0; for (int x = 0; x < heightMap.Length; x++) { for (int y = 0; y < heightMap[x].Length; y++) { count++; sum += heightMap[x][y].Value; diffSum += Math.Abs(getAdjacentCellsMean(heightMap, x, y).Value - heightMap[x][y].Value); } } float mean = (float)(sum / count); float diffMean = (float)(diffSum / count); meanHeight.Add(mean); meanVariance.Add(diffMean); foreach (float meanValue in meanHeight) { meanHeightStr += "#" + meanValue; } foreach (float varianceValue in meanVariance) { meanVarianceStr += "#" + varianceValue; } System.Console.Out.WriteLine(meanHeightStr); System.Console.Out.WriteLine(meanVarianceStr); curSample++; if (curSample < targetSamples) { terrainOutputs.Clear(); System.Console.Out.WriteLine("Starting sample:" + curSample); doContinue = false; startWork(terrainInputs, terrainOutputs, heightmapWorkflowData); } else { System.Console.Out.WriteLine("All samples done"); } } if (!doContinue) { return; } TerrainOutputMesh terrainOutputMesh = new TerrainOutputMesh(); terrainOutputMesh.Title = "Height map mesh"; terrainOutputMesh.Key = "heightMap"; terrainOutputMesh.CameraPosition = new float[] { 0, size / 4, 0 }; terrainOutputMesh.CameraRotation = new float[] { 22.5f, 45, 0 }; exportHeightMap(heightMap, terrainOutputMesh, heightFactor); TerrainOutputImage terrainOutputHeightMap = new TerrainOutputImage(); terrainOutputHeightMap.Title = "Height map bmp"; terrainOutputHeightMap.Key = "heightMapBmp"; GeoPoint[][] heightMapGeoPoints = new GeoPoint[heightMap.Length][]; terrainOutputHeightMap.ImageData = new int[heightMap.Length][]; heightmapWorkflowData.HeightmapCells = new float[heightMap.Length][]; float maxHeight = 0; float minHeight = 1; for (int x = 0; x < heightMap.Length; x++) { heightMapGeoPoints[x] = new GeoPoint[heightMap[x].Length]; terrainOutputHeightMap.ImageData[x] = new int[heightMap.Length]; heightmapWorkflowData.HeightmapCells[x] = new float[heightMap.Length]; for (int y = 0; y < heightMap[x].Length; y++) { GeoPoint geoPoint = new GeoPoint(); geoPoint.Height = (float)heightMap[x][y]; geoPoint.X = x; geoPoint.Y = y; heightMapGeoPoints[x][y] = geoPoint; byte color = (byte)(heightMap[x][y] * 256); terrainOutputHeightMap.ImageData[x][y] = (color << 24) | (color << 16) | (color << 8) | 0xff; heightmapWorkflowData.HeightmapCells[x][y] = (float)heightMap[x][y]; if (maxHeight < (float)heightMap[x][y]) { maxHeight = (float)heightMap[x][y]; } if (minHeight > (float)heightMap[x][y]) { minHeight = (float)heightMap[x][y]; } } } heightmapWorkflowData.MaxHeight = maxHeight * (float)((FormFieldInteger)formFieldsMap["parameters_maxHeight"]).Value; heightmapWorkflowData.MinHeight = minHeight * (float)((FormFieldInteger)formFieldsMap["parameters_maxHeight"]).Value; heightmapWorkflowData.CellSize = (float)((FormFieldInteger)formFieldsMap["parameters_cellSize"]).Value; foreach (GeoPoint geoPoint in riverPoints) { byte color = (byte)(geoPoint.Height * 256); terrainOutputHeightMap.ImageData[geoPoint.X][geoPoint.Y] = (0x00 << 24) | (0x00 << 16) | (color << 8) | 0xff; } int chunk = 0; TerrainOutputMesh splittedMesh = new TerrainOutputMesh(); splittedMesh.Title = "Terrain"; splittedMesh.Key = "terrainHeightMap"; List <float[]> grassLand = new List <float[]>(); MeshGeneratorHelpers.FillHeightMapMesh(splittedMesh, heightMapGeoPoints, heightmapWorkflowData.CellSize, heightmapWorkflowData.MinHeight, heightmapWorkflowData.MaxHeight, grassLand); /*splittedMesh.VertexData.Add(new List<float[]>()); * splittedMesh.FacesData.Add(new List<int[]>()); * splittedMesh.MaterialColor.Add("#ffffffff"); * splittedMesh.MaterialTexture.Add("HeightMapMaterials\\transitionTexture.png"); * splittedMesh.TexureCoordData.Add(new List<float[]>()); * exportTransitionHeightMap(heightMapGeoPoints, splittedMesh, chunk, heightFactor);*/ terrainOutputs.Add(splittedMesh); //terrainOutputs.Add(terrainOutputMesh); terrainOutputs.Add(terrainOutputHeightMap); terrainOutputs.Add(gaussTerrainOutputHeightMap); terrainOutputs.Add(terrainOutputRidges); //terrainOutputs.Add(terrainOutputObject); //terrainOutputs.Add(terrainOutputRoughness); //terrainOutputs.Add(terrainOutputSplitted); //Vector[][] waterVelocityField = RiverHelpers.getVelocityField(gaussHeightMap); //terrainOutputs.Add(RiverHelpers.getVectorFieldImage(waterVelocityField)); }
private static Vector getCellVector(float?[][] heightMap, int x, int y) { float currentVx = 0; float currentVy = 0; int nX; int nY; List <Vector> vectors = new List <Vector>(); float?currentValue = TerrainHelpers.getTopLeft(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentValue = (float)Math.Cos(Math.PI / 4) * currentValue; currentVx = -(float)currentValue; currentVy = -(float)currentValue; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getLeft(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentVx = -(float)currentValue; currentVy = 0; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getBottomLeft(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentValue = (float)Math.Cos(Math.PI / 4) * currentValue; currentVx = -(float)currentValue; currentVy = (float)currentValue; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getTop(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentVx = 0; currentVy = -(float)currentValue; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getBottom(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentVx = 0; currentVy = (float)currentValue; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getTopRight(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentValue = (float)Math.Cos(Math.PI / 4) * currentValue; currentVx = (float)currentValue; currentVy = -(float)currentValue; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getRight(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentVx = (float)currentValue; currentVy = 0; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getBottomRight(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; currentValue = (float)Math.Cos(Math.PI / 4) * currentValue; currentVx = (float)currentValue; currentVy = (float)currentValue; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getTopTopLeft(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = -smaller; currentVy = -larger; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getLeftLeftTop(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = -larger; currentVy = -smaller; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getTopTopRight(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = smaller; currentVy = -larger; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getRightRightTop(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = larger; currentVy = -smaller; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getRightRightBottom(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = larger; currentVy = smaller; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getBottomBottomRight(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = smaller; currentVy = larger; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getBottomBottomLeft(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = -smaller; currentVy = larger; vectors.Add(new Vector(currentVx, currentVy)); } currentValue = TerrainHelpers.getLeftLeftBottom(heightMap, x, y, out nX, out nY); if (currentValue != null && currentValue < heightMap[x][y]) { currentValue = heightMap[x][y] - currentValue; float larger = (float)(Math.Cos(Math.Atan(0.5)) * currentValue); float smaller = (float)(Math.Sin(Math.Atan(0.5)) * currentValue); currentVx = -larger; currentVy = smaller; vectors.Add(new Vector(currentVx, currentVy)); } Vector finalVector = new Vector(0, 0); foreach (Vector vector in vectors) { finalVector.Vx += vector.Vx; finalVector.Vy += vector.Vy; } finalVector.normalize(); return(finalVector); }