static Stack<U16Vec2> RiverStack; //Стек для постройки реки #endregion Fields #region Methods public static void CreateChunk(ref Chunk map, GlobalTerrainSettings settings, HeighmapNeighboring hmNbHeight, float landscapeRoughness, HeighmapNeighboring hmNbForest, float forestRoughness, float forestDensity) { float?[,] buf = new float?[map.Height, map.Width]; WorldGenerator.CreateHeightmap(ref buf, landscapeRoughness, hmNbHeight); for (ushort y = 0; y < map.Height; ++y) for (ushort x = 0; x < map.Width; ++x) { map.HeightMatrix[y, x] = Mathf.Clamp(buf[y, x].Value, 0, Mathf.Abs(buf[y, x].Value)); buf[y, x] = null; } WorldGenerator.CreateHeightmap(ref buf, forestRoughness, hmNbForest); for (ushort y = 0; y < map.Height; ++y) for (ushort x = 0; x < map.Width; ++x) { buf[y, x] = buf[y, x].Value * forestDensity; map.ForestMatrix[y, x] = Mathf.Clamp(buf[y, x].Value, 0, Mathf.Abs(buf[y, x].Value)); } map.Rivers = WorldGenerator.CreateRivers(map.HeightMatrix, ref map.TerrainMatrix, settings.RiversParam); map.Clusters = WorldGenerator.CreateClusters(ref map, settings.ClustersParam); map.Roads = WorldGenerator.CreateRoads(map.HeightMatrix, ref map.TerrainMatrix, map.Clusters, settings.RoadsParam); WorldGenerator.CreateTerrainmap(ref map.TerrainMatrix, map.HeightMatrix, settings); }
public static void CreateHeightmap(ref float?[,] matrix, float roughness, HeighmapNeighboring hmNb) { ushort height = (ushort)matrix.GetLength(0); ushort width = (ushort)matrix.GetLength(1); //-- Assert //TODO C# 6.0 System.Diagnostics.Debug.Assert((hmNb.Left == null || hmNb.Left.Length == height) && (hmNb.Right == null || hmNb.Right.Length == height)); System.Diagnostics.Debug.Assert((hmNb.Top == null || hmNb.Top.Length == width) && (hmNb.Bottom == null || hmNb.Bottom.Length == width)); //-- //Задаём начальные значения по углам //TODO C# 6.0 if (!matrix[0, 0].HasValue) matrix[0, 0] = ((hmNb.Left == null ? (hmNb.Bottom == null ? Random.Range(-roughness, roughness) : hmNb.Bottom[0]) : hmNb.Left[0]) + (hmNb.Bottom == null ? (hmNb.Left == null ? Random.Range(-roughness, roughness) : hmNb.Left[0]) : hmNb.Bottom[0])) * 0.5f; if (!matrix[0, width - 1].HasValue) matrix[0, width - 1] = ((hmNb.Bottom == null ? (hmNb.Right == null ? Random.Range(-roughness, roughness) : hmNb.Right[0]) : hmNb.Bottom[width - 1]) + (hmNb.Right == null ? (hmNb.Bottom == null ? Random.Range(-roughness, roughness) : hmNb.Bottom[width - 1]) : hmNb.Right[0])) * 0.5f; if (!matrix[height - 1, 0].HasValue) matrix[height - 1, 0] = ((hmNb.Top == null ? (hmNb.Left == null ? Random.Range(-roughness, roughness) : hmNb.Left[height - 1]) : hmNb.Top[0]) + (hmNb.Left == null ? (hmNb.Top == null ? Random.Range(-roughness, roughness) : hmNb.Top[0]) : hmNb.Left[height - 1])) * 0.5f; if (!matrix[height - 1, width - 1].HasValue) matrix[height - 1, width - 1] = ((hmNb.Right == null ? (hmNb.Top == null ? Random.Range(-roughness, roughness) : hmNb.Top[width - 1]) : hmNb.Right[height - 1]) + (hmNb.Top == null ? (hmNb.Right == null ? Random.Range(-roughness, roughness) : hmNb.Right[height - 1]) : hmNb.Top[width - 1])) * 0.5f; float randRangeCoef = roughness / (height + width); if (hmNb.Left != null) for (ushort i = 1; i < height - 1; ++i) matrix[i, 0] = hmNb.Left[i] + Random.Range(-randRangeCoef, randRangeCoef); if (hmNb.Right != null) for (ushort i = 1; i < height - 1; ++i) matrix[i, width - 1] = hmNb.Right[i] + Random.Range(-randRangeCoef, randRangeCoef); if (hmNb.Bottom != null) for (ushort i = 1; i < width - 1; ++i) matrix[0, i] = hmNb.Bottom[i] + Random.Range(-randRangeCoef, randRangeCoef); if (hmNb.Top != null) for (ushort i = 1; i < width - 1; ++i) matrix[height - 1, i] = hmNb.Top[i] + Random.Range(-randRangeCoef, randRangeCoef); ushort len = (ushort)Mathf.Max(Mathf.NextPowerOfTwo(height), Mathf.NextPowerOfTwo(width)); ushort[] yOffsets = new ushort[len + 2];//////////////////////////////temp ushort[] xOffsets = new ushort[len + 2];/////////////////////////////////temp yOffsets[0] = (ushort)(height - 1); xOffsets[0] = (ushort)(width - 1); ushort[] yOffsetsBuf = new ushort[len + 2]; ushort[] xOffsetsBuf = new ushort[len + 2]; ushort count = 1; while (count != len) { System.Array.Copy(yOffsets, yOffsetsBuf, len + 2);//////////////////////////////temp +2 System.Array.Copy(xOffsets, xOffsetsBuf, len + 2);//////////////////////////////temp +2 for (ushort i = 0; i < count; ++i) { ushort q = (ushort)(yOffsetsBuf[i] + 1 >> 1); byte nr = (byte)((yOffsetsBuf[i] + 1) & 1 ^ 1); yOffsets[i << 1] = q; yOffsets[(i << 1) + 1] = (ushort)(q - nr); q = (ushort)(xOffsetsBuf[i] + 1 >> 1); nr = (byte)((xOffsetsBuf[i] + 1) & 1 ^ 1); xOffsets[i << 1] = q; xOffsets[(i << 1) + 1] = (ushort)(q - nr); } count <<= 1; //Центры for (ushort y = 0, yPoint = yOffsets[0]; y < count; y += 2) { for (ushort x = 0, xPoint = xOffsets[0]; x < count; x += 2) { if (!matrix[yPoint, xPoint].HasValue) { float randRange = (yOffsets[y] + yOffsets[y + 1] + xOffsets[x] + xOffsets[x + 1]) * randRangeCoef; matrix[yPoint, xPoint] = (matrix[yPoint - yOffsets[y], xPoint - xOffsets[x]] + matrix[yPoint + yOffsets[y + 1], xPoint - xOffsets[x]] + matrix[yPoint - yOffsets[y], xPoint + xOffsets[x + 1]] + matrix[yPoint + yOffsets[y + 1], xPoint + xOffsets[x + 1]]) * 0.25f + Random.Range(-randRange, randRange); } xPoint += (ushort)(xOffsets[x + 1] + xOffsets[x + 2]); } yPoint += (ushort)(yOffsets[y + 1] + yOffsets[y + 2]); } //Вертикальные границы for (ushort y = 0, yPoint = yOffsets[0]; y < count; y += 2) { if (!matrix[yPoint, 0].HasValue) { float randRange = (yOffsets[y] + yOffsets[y + 1] + xOffsets[0]) * randRangeCoef; matrix[yPoint, 0] = (matrix[yPoint - yOffsets[y], 0] + matrix[yPoint + yOffsets[y + 1], 0] + matrix[yPoint, xOffsets[0]]) * 0.33333f + Random.Range(-randRange, randRange); } if (!matrix[yPoint, width - 1].HasValue) { float randRange = (yOffsets[y] + yOffsets[y + 1] + xOffsets[count - 1]) * randRangeCoef; matrix[yPoint, width - 1] = (matrix[yPoint - yOffsets[y], width - 1] + matrix[yPoint + yOffsets[y + 1], width - 1] + matrix[yPoint, width - 1 - xOffsets[count - 1]]) * 0.33333f + Random.Range(-randRange, randRange); } yPoint += (ushort)(yOffsets[y + 1] + yOffsets[y + 2]); } //Горизонтальные границы for (ushort x = 0, xPoint = xOffsets[0]; x < count; x += 2) { if (!matrix[0, xPoint].HasValue) { float randRange = (xOffsets[x] + xOffsets[x + 1] + yOffsets[0]) * randRangeCoef; matrix[0, xPoint] = (matrix[0, xPoint - xOffsets[x]] + matrix[0, xPoint + xOffsets[x + 1]] + matrix[yOffsets[0], xPoint]) * 0.33333f + Random.Range(-randRange, randRange); } if (!matrix[height - 1, xPoint].HasValue) { float randRange = (xOffsets[x] + xOffsets[x + 1] + yOffsets[count - 1]) * randRangeCoef; matrix[height - 1, xPoint] = (matrix[height - 1, xPoint - xOffsets[x]] + matrix[height - 1, xPoint + xOffsets[x + 1]] + matrix[height - 1 - yOffsets[count - 1], xPoint]) * 0.33333f + Random.Range(-randRange, randRange); } xPoint += (ushort)(xOffsets[x + 1] + xOffsets[x + 2]); } //Первый столбец for (ushort y = 0, yPoint = yOffsets[0]; y < count - 2; y += 2) { if (!matrix[yPoint + yOffsets[y + 1], xOffsets[0]].HasValue) { float randRange = (yOffsets[y + 1] + yOffsets[y + 2] + xOffsets[0] + xOffsets[1]) * randRangeCoef; matrix[yPoint + yOffsets[y + 1], xOffsets[0]] = (matrix[yPoint, xOffsets[0]] + matrix[yPoint + yOffsets[y + 1] + yOffsets[y + 2], xOffsets[0]] + matrix[yPoint + yOffsets[y + 1], 0] + matrix[yPoint + yOffsets[y + 1], xOffsets[0] + xOffsets[1]]) * 0.25f + Random.Range(-randRange, randRange); } yPoint += (ushort)(yOffsets[y + 1] + yOffsets[y + 2]); } //Первая строка for (ushort x = 0, xPoint = xOffsets[0]; x < count - 2; x += 2) { if (!matrix[yOffsets[0], xPoint + xOffsets[x + 1]].HasValue) { float randRange = (xOffsets[x + 1] + xOffsets[x + 2] + yOffsets[0] + yOffsets[1]) * randRangeCoef; matrix[yOffsets[0], xPoint + xOffsets[x + 1]] = (matrix[yOffsets[0], xPoint] + matrix[yOffsets[0], xPoint + xOffsets[x + 1] + xOffsets[x + 2]] + matrix[0, xPoint + xOffsets[x + 1]] + matrix[yOffsets[0] + yOffsets[1], xPoint + xOffsets[x + 1]]) * 0.25f + Random.Range(-randRange, randRange); } xPoint += (ushort)(xOffsets[x + 1] + xOffsets[x + 2]); } //Остальное for (ushort y = 1, yPoint = (ushort)(yOffsets[0] + yOffsets[1]); y < count - 2; y += 2)// -1 ? { for (ushort x = 1, xPoint = (ushort)(xOffsets[0] + xOffsets[1]); x < count - 2; x += 2)// -1 ? { if (!matrix[yPoint + yOffsets[y + 1], xPoint].HasValue) { float randRange = (yOffsets[y + 1] + yOffsets[y + 2] + xOffsets[x] + xOffsets[x + 1]) * randRangeCoef; matrix[yPoint + yOffsets[y + 1], xPoint] = (matrix[yPoint + yOffsets[y + 1], xPoint - xOffsets[x]] + matrix[yPoint, xPoint] + matrix[yPoint + yOffsets[y + 1], xPoint + xOffsets[x + 1]] + matrix[yPoint + yOffsets[y + 1] + yOffsets[y + 2], xPoint]) * 0.25f + Random.Range(-randRange, randRange); } if (!matrix[yPoint, xPoint + xOffsets[x + 1]].HasValue) { float randRange = (yOffsets[y] + yOffsets[y + 1] + xOffsets[x + 1] + xOffsets[x + 2]) * randRangeCoef; matrix[yPoint, xPoint + xOffsets[x + 1]] = (matrix[yPoint - yOffsets[y], xPoint + xOffsets[x + 1]] + matrix[yPoint, xPoint] + matrix[yPoint, xPoint + xOffsets[x + 1] + xOffsets[x + 2]] + matrix[yPoint + yOffsets[y + 1], xPoint + xOffsets[x + 1]]) * 0.25f + Random.Range(-randRange, randRange); } xPoint += (ushort)(xOffsets[x + 1] + xOffsets[x + 2]); } yPoint += (ushort)(yOffsets[y + 1] + yOffsets[y + 2]); } } }
//TODO Временно public static void CreateLocalMap(ref LocalMap map, LocalTerrainSettings settings, HeighmapNeighboring hmNb, float landscapeRoughness, float forest) { float?[,] buf = new float?[map.Height, map.Width]; WorldGenerator.CreateHeightmap(ref buf, landscapeRoughness, hmNb); float[,] buf2 = new float[map.Height, map.Width]; for (ushort y = 0; y < map.Height; ++y) for (ushort x = 0; x < map.Width; ++x) { buf2[y, x] = buf[y, x].Value; buf[y, x] = null; } WorldGenerator.CreateTerrainmap(ref map.TerrainMatrix, buf2, settings); WorldGenerator.CreateVegetation(ref map, settings, forest); }