private float[,] generateVoronoi(float[,] heightMap, Vector2 arraySize, GeneratorProgressDelegate generatorProgressDelegate) { int Tx = (int) arraySize.x; int Ty = (int) arraySize.y; // Create Voronoi set... ArrayList voronoiSet = new ArrayList(); int i; for (i = 0; i < voronoiCells; i++) { Peak newPeak = new Peak(); int xCoord = (int) Mathf.Floor(UnityEngine.Random.value * Tx); int yCoord = (int) Mathf.Floor(UnityEngine.Random.value * Ty); float pointHeight = UnityEngine.Random.value; if (UnityEngine.Random.value > voronoiFeatures) { pointHeight = 0.0f; } newPeak.peakPoint = new Vector2(xCoord, yCoord); newPeak.peakHeight = pointHeight; voronoiSet.Add(newPeak); } int Mx; int My; float highestScore = 0.0f; for (My = 0; My < Ty; My++) { for (Mx = 0; Mx < Tx; Mx++) { ArrayList peakDistances = new ArrayList(); for (i = 0; i < voronoiCells; i++) { Peak peakI = (Peak) voronoiSet[i]; Vector2 peakPoint = peakI.peakPoint; float distanceToPeak = Vector2.Distance(peakPoint, new Vector2(Mx, My)); PeakDistance newPeakDistance = new PeakDistance(); newPeakDistance.id = i; newPeakDistance.dist = distanceToPeak; peakDistances.Add(newPeakDistance); } peakDistances.Sort(); PeakDistance peakDistOne = (PeakDistance) peakDistances[0]; PeakDistance peakDistTwo = (PeakDistance) peakDistances[1]; int p1 = peakDistOne.id; float d1 = peakDistOne.dist; float d2 = peakDistTwo.dist; float scale = Mathf.Abs(d1 - d2) / ((Tx + Ty) / Mathf.Sqrt(voronoiCells)); Peak peakOne = (Peak) voronoiSet[p1]; float h1 = (float) peakOne.peakHeight; float hScore = h1 - Mathf.Abs(d1 / d2) * h1; float asRadians; switch (voronoiType) { case VoronoiType.Linear: // Nothing... break; case VoronoiType.Sine: asRadians = hScore * Mathf.PI - Mathf.PI / 2; hScore = 0.5f + Mathf.Sin(asRadians) / 2; break; case VoronoiType.Tangent: asRadians = hScore * Mathf.PI / 2; hScore = 0.5f + Mathf.Tan(asRadians) / 2; break; } hScore = (hScore * scale * voronoiScale) + (hScore * (1.0f - voronoiScale)); if (hScore < 0.0f) { hScore = 0.0f; } else if (hScore > 1.0f) { hScore = 1.0f; } heightMap[Mx, My] = hScore; if (hScore > highestScore) { highestScore = hScore; } } // Show progress... float completePoints = My * Ty; float totalPoints = Tx * Ty; float percentComplete = completePoints / totalPoints; generatorProgressDelegate("Voronoi Generator", "Generating height map. Please wait.", percentComplete); } // Normalise... for (My = 0; My < Ty; My++) { for (Mx = 0; Mx < Tx; Mx++) { float normalisedHeight = heightMap[Mx, My] * (1.0f / highestScore); heightMap[Mx, My] = normalisedHeight; } } return heightMap; }
// voronoiPresets.Add(new voronoiPresetData("Scattered Peaks", VoronoiType.Linear, 16, 8, 0.5f, 1.0f)); // voronoiPresets.Add(new voronoiPresetData("Rolling Hills", VoronoiType.Sine, 8, 8, 0.0f, 1.0f)); // voronoiPresets.Add(new voronoiPresetData("Jagged Mountains", VoronoiType.Linear, 32, 32, 0.5f, 1.0f)); private float[,] generateVoronoi(ref float[,] heightMap, Vector2 arraySize, bool regenFlag) { int Tx = (int)arraySize.x; int Ty = (int)arraySize.y; // Create Voronoi set... ArrayList voronoiSet = new ArrayList(); int i; int inc = 1; if (regenFlag) inc++; for (i = 0; i < voronoiCells; i += inc) { Peak newPeak = new Peak(); int xCoord = (int)Mathf.Floor(UnityEngine.Random.value * Tx); int yCoord = (int)Mathf.Floor(UnityEngine.Random.value * Ty); float pointHeight = UnityEngine.Random.value; if (UnityEngine.Random.value > voronoiFeatures) { pointHeight = 0.0f; } newPeak.peakPoint = new Vector2(xCoord, yCoord); newPeak.peakHeight = pointHeight; voronoiSet.Add(newPeak); } int Mx; int My; float highestScore = 0.0f; for (My = 0; My < Ty; My += inc) { for (Mx = 0; Mx < Tx; Mx += inc) { ArrayList peakDistances = new ArrayList(); try { for (i = 0; i < voronoiCells; i += inc) { Peak peakI = (Peak)voronoiSet[i]; Vector2 peakPoint = peakI.peakPoint; float distanceToPeak = Vector2.Distance(peakPoint, new Vector2(Mx, My)); PeakDistance newPeakDistance = new PeakDistance(); newPeakDistance.id = i; newPeakDistance.dist = distanceToPeak; peakDistances.Add(newPeakDistance); } } catch (Exception) { } peakDistances.Sort(); PeakDistance peakDistOne = (PeakDistance)peakDistances[0]; PeakDistance peakDistTwo = (PeakDistance)peakDistances[1]; int p1 = peakDistOne.id; float d1 = peakDistOne.dist; float d2 = peakDistTwo.dist; float scale = Mathf.Abs(d1 - d2) / ((Tx + Ty) / Mathf.Sqrt(voronoiCells)); Peak peakOne = (Peak)voronoiSet[p1]; float h1 = (float)peakOne.peakHeight; float hScore = h1 - Mathf.Abs(d1 / d2) * h1; float asRadians; switch (voronoiType) { case VoronoiType.Linear: // Nothing... break; case VoronoiType.Sine: asRadians = hScore * Mathf.PI - Mathf.PI / 2; hScore = 0.5f + Mathf.Sin(asRadians) / 2; break; case VoronoiType.Tangent: asRadians = hScore * Mathf.PI / 2; hScore = 0.5f + Mathf.Tan(asRadians) / 2; break; } hScore = (hScore * scale * voronoiScale) + (hScore * (1.0f - voronoiScale)); if (hScore < 0.0f) { hScore = 0.0f; } else if (hScore > 1.0f) { hScore = 1.0f; } heightMap[Mx, My] += hScore; if (hScore > highestScore) { highestScore = hScore; } heightMap[Mx, My] = hScore + heightMap[Mx, My] < 1? heightMap[Mx, My] : 1; heightMap[Mx, My] *= mHeight; } } // Normalise... //for (My = 0; My < Ty; My++) //{ // for (Mx = 0; Mx < Tx; Mx++) // { // float normalisedHeight = heightMap[Mx, My] * (1.0f / highestScore); // heightMap[Mx, My] = normalisedHeight; // } //} return heightMap; }