From 0e0154e10ed22aa60779dad379a053e289791fc8 Mon Sep 17 00:00:00 2001 From: Xevion Date: Wed, 6 May 2020 00:23:59 -0500 Subject: [PATCH] improved bridson's algorithm attempt --- .../Assets/PointGeneration.cs | 52 ++++++++++++++++++- procedural-placement/Assets/PointRendering.cs | 7 ++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/procedural-placement/Assets/PointGeneration.cs b/procedural-placement/Assets/PointGeneration.cs index 544e26c..1519ffd 100644 --- a/procedural-placement/Assets/PointGeneration.cs +++ b/procedural-placement/Assets/PointGeneration.cs @@ -34,7 +34,7 @@ public static class PointGeneration { float angle = Random.value * Mathf.PI * 2; // Random radian angle Vector2 dir = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)); Vector2 candidate = spawnCenter + dir * Random.Range(radius, radius * 2); - + if (poisson_valid(candidate, regionSize, cellSize, points, grid, radius)) { points.Add(candidate); spawnPoints.Add(candidate); @@ -55,7 +55,7 @@ public static class PointGeneration { private static bool IsValidPoint(Vector2 point, Vector2 region) { return point.x >= 0 && point.y >= 0 && point.x < region.x && point.y < region.y; } - + private static bool poisson_valid(Vector2 candidate, Vector2 regionSize, float cellSize, List points, int[,] grid, float radius) { // Check that the point is valid @@ -83,4 +83,52 @@ public static class PointGeneration { return true; } + + public static List improved_poisson_sampling(int numPoints, Vector2 regionSize, float radius, + int attempts = 30) { + float cellSize = radius / Mathf.Sqrt(2); + + // A grid for + int[,] grid = new int[Mathf.CeilToInt(regionSize.x / cellSize), Mathf.CeilToInt(regionSize.y / cellSize)]; + List points = new List(); + List spawnPoints = new List(); + + spawnPoints.Add(regionSize / 2); + while (spawnPoints.Count > 0) { + int spawnIndex = Random.Range(0, spawnPoints.Count); + Vector2 spawnCenter = spawnPoints[spawnIndex]; + bool candidateAccepted = false; + + float seed = Random.value; + float epsilon = 0.000001f; + + for (int i = 0; i < attempts; i++) { + // float angle = Random.value * Mathf.PI * 2; // Random radian angle + // Vector2 dir = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)); + // Vector2 candidate = spawnCenter + dir * Random.Range(radius, radius * 2); + float theta = 2 * Mathf.PI * (seed + i / attempts); + float r = (radius * 2) + epsilon; + Vector2 dir = new Vector2(Mathf.Sin(theta), Mathf.Cos(theta)); + Vector2 candidate = spawnCenter + r * dir; + // Vector2 candidate = new Vector2( + // spawnCenter.x + r * Mathf.Sin(theta), + // spawnCenter.y + r * Mathf.Cos(theta) + // ); + + if (poisson_valid(candidate, regionSize, cellSize, points, grid, radius)) { + points.Add(candidate); + spawnPoints.Add(candidate); + grid[(int) (candidate.x / cellSize), (int) (candidate.y / cellSize)] = points.Count; + candidateAccepted = true; + break; + } + } + + if (!candidateAccepted) { + spawnPoints.RemoveAt(spawnIndex); + } + } + + return points; + } } \ No newline at end of file diff --git a/procedural-placement/Assets/PointRendering.cs b/procedural-placement/Assets/PointRendering.cs index 6e22d91..9076a42 100644 --- a/procedural-placement/Assets/PointRendering.cs +++ b/procedural-placement/Assets/PointRendering.cs @@ -7,7 +7,8 @@ using UnityEngine.Serialization; public enum SamplingTypes { Random, - Poisson + Poisson, + Improved_Poisson }; public class PointRendering : MonoBehaviour { @@ -53,6 +54,10 @@ public class PointRendering : MonoBehaviour { _points = PointGeneration.poisson_sampling(numPoints, regionSize, radius, retryAttempts); numPoints = _points.Count; break; + case SamplingTypes.Improved_Poisson: + _points = PointGeneration.improved_poisson_sampling(numPoints, regionSize, radius, retryAttempts); + numPoints = _points.Count; + break; default: throw new ArgumentOutOfRangeException(); }