Advertisement
Guest User

Untitled

a guest
Feb 20th, 2019
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.60 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Threading.Tasks;
  5. using UnityEngine;
  6.  
  7. public class HexagonalGrid : List<GridTile>
  8. {
  9. public int GridSize { get; private set; }
  10. public int TileCount { get; private set; }
  11.  
  12. public WorldGenerator World { get; private set; }
  13.  
  14. public HexagonalGrid(WorldGenerator Generator, float[,] HeightMap, float[,] TemperatureMap, float[,] HumidityMap, float cullRange)
  15. {
  16. this.GridSize = Generator.MapSize;
  17. this.TileCount = Generator.TileCount;
  18. this.World = Generator;
  19.  
  20. // GENERATE GRID TILES
  21. Clear();
  22.  
  23. int maxX = Mathf.FloorToInt(TileCount * 0.7f);
  24. for (int x = 0; x < maxX; x++)
  25. {
  26. for (int y = 0; y < TileCount * 2 + 2; y++)
  27. {
  28. if (y % 2 != 0)
  29. {
  30. if (x == maxX - 1) continue;
  31. }
  32.  
  33. GridTile tile = new GridTile(this, new Point(x, y), HeightMap, TemperatureMap, HumidityMap, cullRange);
  34. Add(tile);
  35. }
  36. }
  37. }
  38.  
  39. public GridTile GetTile(Vector2Int Point)
  40. {
  41. GridTile result = null;
  42.  
  43. object locker = new object();
  44. Parallel.ForEach(this, (tile, state) => {
  45. if (tile.IsContaining(Point))
  46. {
  47. lock (locker) { result = tile; }
  48. state.Stop();
  49. }
  50. });
  51.  
  52. return result;
  53. }
  54.  
  55. public GridTile GetCullingTile(Vector2Int Pixel)
  56. {
  57. GridTile result = null;
  58.  
  59. object locker = new object();
  60. Parallel.ForEach(this, (tile, state) => {
  61. if(tile.IsCullContaining(Pixel))
  62. {
  63. lock (locker) { result = tile; }
  64. state.Stop();
  65. }
  66. });
  67.  
  68. return result;
  69. }
  70.  
  71. private GridTile selectedTile;
  72.  
  73. public void SelectTile(GridTile Tile)
  74. {
  75. if (selectedTile != null) selectedTile.GridLineObject.GetComponent<LineRenderer>().widthMultiplier = World.GridWidthMultiplier;
  76.  
  77. Tile.GridLineObject.GetComponent<LineRenderer>().widthMultiplier = 1f;
  78. selectedTile = Tile;
  79. }
  80. }
  81.  
  82. public class GridTile
  83. {
  84. public Point Position { get; private set; }
  85. public Vector2 Center { get; private set; }
  86.  
  87. public Vector3[] Points { get; private set; }
  88.  
  89. public Point[] FillingPixels { get; private set; }
  90. public Point[] CulledPixels { get; private set; }
  91.  
  92. public GameObject GridLineObject;
  93.  
  94. public List<GameObject> CulledDetail = new List<GameObject>();
  95.  
  96. public float Height { get; private set; }
  97. public float Temperature { get; private set; }
  98. public float Humidity { get; private set; }
  99.  
  100. public int BiomeIndex { get; private set; }
  101. public int HeightIndex { get; private set; }
  102.  
  103. private HexagonalGrid grid;
  104. private float hexSize;
  105.  
  106. public GridTile(HexagonalGrid Parent, Point Position, float[,] HeightMap, float[,] TemperatureMap, float[,] HumidityMap, float cullRange)
  107. {
  108. grid = Parent;
  109. this.Position = Position;
  110.  
  111. // CALCULATE POSITION AND SIZE
  112. float tileSize = (float)grid.GridSize / grid.TileCount;
  113. hexSize = tileSize / 2f;
  114.  
  115. float height = Mathf.Sqrt(3) * hexSize;
  116.  
  117. float centerX = 0;
  118. float centerY = 0;
  119.  
  120. if(Position.Y == 0 || Position.Y % 2 == 0)
  121. {
  122. centerX = (tileSize * Position.X) + (hexSize * Position.X) + hexSize;
  123. centerY = (height / 2 * Position.Y) + hexSize;
  124. }
  125. else
  126. {
  127. centerX = (tileSize * Position.X) + (hexSize * Position.X) + tileSize + (hexSize / 2);
  128. centerY = (height / 2 * Position.Y) + hexSize;
  129. }
  130.  
  131. Center = new Vector2(centerX, centerY);
  132.  
  133. Points = generatePoints(hexSize, HeightMap);
  134. FillingPixels = generateFillingPixels(Points);
  135.  
  136. if(cullRange != 0f)
  137. {
  138. float culledHexA = hexSize * cullRange;
  139. Vector3[] culledPoints = generatePoints(culledHexA, HeightMap);
  140. CulledPixels = generateFillingPixels(culledPoints);
  141. }
  142.  
  143. // ASSIGN HEIGHT, HUMIDITY, TEMPERATURE, BIOME
  144. float avrHeight = 0;
  145. float avrTemp = 0;
  146. float avrHum = 0;
  147.  
  148. foreach(Point point in FillingPixels)
  149. {
  150. if (point.X < 0 || point.Y < 0 || point.X >= HeightMap.GetLength(0) || point.Y >= HeightMap.GetLength(1)) continue;
  151.  
  152. avrHeight += HeightMap[point.X, point.Y];
  153. avrTemp += TemperatureMap[point.X, point.Y];
  154. avrHum += HumidityMap[point.X, point.Y];
  155. }
  156.  
  157. Height = avrHeight / FillingPixels.GetLength(0);
  158. Temperature = avrTemp / FillingPixels.GetLength(0);
  159. Humidity = avrHum / FillingPixels.GetLength(0);
  160.  
  161. BiomeIndex = BiomeData.GetBiomeIndex(grid.World.Biomes, Height, Temperature, Humidity);
  162. HeightIndex = HeightInfo.GetHeightIndex(grid.World.Heights, Height);
  163. }
  164.  
  165. private Vector3[] generatePoints(float Size, float[,] heightMap)
  166. {
  167. Vector3[] result = new Vector3[6];
  168. //PointHeights = new float[6];
  169.  
  170. float lastHeight = 0;
  171. for(int i = 0; i < 6; i++)
  172. {
  173. Vector2 point = Utils.HexCorner(Center, Size, i);
  174. float height = lastHeight;
  175.  
  176. //Points[i] = Utils.HexCorner(Center, Size, i);
  177. //float height = 0;
  178.  
  179. if (point.x > 0 && point.y > 0 && point.x < heightMap.GetLength(0) && point.y < heightMap.GetLength(1))
  180. {
  181. height = heightMap[(int)point.x, (int)point.y];
  182. }
  183.  
  184. result[i] = new Vector3(point.x, height, point.y);
  185. lastHeight = height;
  186. //PointHeights[i] = height;
  187. }
  188.  
  189. return result;
  190. }
  191.  
  192. private Point[] generateFillingPixels(Vector3[] points)
  193. {
  194. List<Point> pixels = new List<Point>();
  195.  
  196. // GENERATE SIDE PIXEL POSITIONS
  197. for (int i = 0; i < 6; i++)
  198. {
  199. int pointB = i == 5 ? 0 : i + 1;
  200.  
  201. Point p1 = new Point(Mathf.RoundToInt(points[i].x), Mathf.RoundToInt(points[i].z));
  202. Point p2 = new Point(Mathf.RoundToInt(points[pointB].x), Mathf.RoundToInt(points[pointB].z));
  203.  
  204. pixels.AddRange(Utils.GetLinePixels(p1, p2).ToArray());
  205. }
  206.  
  207. // FILL HEX
  208. List<Point> samplePoints = new List<Point>();
  209. samplePoints.Add(new Point(Mathf.RoundToInt(Center.x), Mathf.RoundToInt(Center.y)));
  210.  
  211. while (samplePoints.Count > 0)
  212. {
  213. Point[] curSamplePoints = samplePoints.ToArray();
  214.  
  215. samplePoints.Clear();
  216.  
  217. foreach (Point sPoint in curSamplePoints)
  218. {
  219. for (int x = -1; x < 2; x++)
  220. {
  221. for (int y = -1; y < 2; y++)
  222. {
  223. if (x == 0 && y == 0) continue; // Ignored point
  224. if (x == -1 && y == -1) continue; // Ignored point
  225. if (x == 1 && y == 1) continue; // Ignored point
  226. if (x == 1 && y == -1) continue; // Ignored point
  227. if (x == -1 && y == 1) continue; // Ignored point
  228.  
  229. Point curPoint = new Point(sPoint.X + x, sPoint.Y + y);
  230.  
  231. if (curPoint.X < 0 || curPoint.Y < 0 || curPoint.X >= grid.GridSize || curPoint.Y >= grid.GridSize) continue; // Outside Bounds
  232.  
  233. if (!pixels.Exists(pixel => pixel.X == curPoint.X && pixel.Y == curPoint.Y))
  234. {
  235. pixels.Add(curPoint);
  236. samplePoints.Add(curPoint);
  237. }
  238. }
  239. }
  240. }
  241. }
  242.  
  243. return pixels.ToArray();
  244. }
  245.  
  246. public bool IsContaining(Vector2Int Point)
  247. {
  248. foreach (Point p in FillingPixels)
  249. {
  250. if (p.X == Point.x && p.Y == Point.y) return true;
  251. }
  252.  
  253. return false;
  254. }
  255.  
  256. public bool IsCullContaining(Vector2Int Point)
  257. {
  258. foreach(Point p in CulledPixels)
  259. {
  260. if (p.X == Point.x && p.Y == Point.y) return true;
  261. }
  262.  
  263. return false;
  264. }
  265. }
  266.  
  267. public static class Utils
  268. {
  269. public static Vector2 HexCorner(Vector2 center, float size, int i)
  270. {
  271. float angle_deg = 60 * i - 0;
  272. float angle_rad = Mathf.PI / 180 * angle_deg;
  273.  
  274. return new Vector2(center.x + size * Mathf.Cos(angle_rad), center.y + size * Mathf.Sin(angle_rad));
  275. }
  276.  
  277. public static List<Point> GetLinePixels(Point a, Point b)
  278. {
  279. List<Point> result = new List<Point>();
  280.  
  281. int w = b.X - a.X;
  282. int h = b.Y - a.Y;
  283. int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
  284. if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1;
  285. if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1;
  286. if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1;
  287. int longest = Mathf.Abs(w);
  288. int shortest = Mathf.Abs(h);
  289. if (!(longest > shortest))
  290. {
  291. longest = Mathf.Abs(h);
  292. shortest = Mathf.Abs(w);
  293. if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1;
  294. dx2 = 0;
  295. }
  296. int numerator = longest >> 1;
  297. for (int i = 0; i <= longest; i++)
  298. {
  299. result.Add(a);
  300. //putpixel(x, y, color);
  301. numerator += shortest;
  302. if (!(numerator < longest))
  303. {
  304. numerator -= longest;
  305. a.X += dx1;
  306. a.Y += dy1;
  307. }
  308. else
  309. {
  310. a.X += dx2;
  311. a.Y += dy2;
  312. }
  313. }
  314.  
  315. return result;
  316. }
  317.  
  318. //public static List<Point> GetLinePixels(Point a, Point b)
  319. //{
  320. // List<Point> result = new List<Point>();
  321.  
  322. // //Point a = new Point(Mathf.RoundToInt(PointA.x), Mathf.RoundToInt(PointA.y));
  323. // //Point b = new Point(Mathf.RoundToInt(PointB.x), Mathf.RoundToInt(PointB.y));
  324.  
  325. // int dx = Mathf.Abs(b.X - a.X), sx = a.X < b.X ? 1 : -1;
  326. // int dy = Mathf.Abs(b.Y - a.Y), sy = a.Y < b.Y ? 1 : -1;
  327. // int err = (dx > dy ? dx : -dy) / 2, e2;
  328. // for (; ; )
  329. // {
  330. // result.Add(new Point(a.X, a.Y));
  331.  
  332. // if (a.X == b.Y && a.X == b.Y) break;
  333. // e2 = err;
  334. // if (e2 > -dx) { err -= dy; a.X += sx; }
  335. // if (e2 < dy) { err += dx; a.Y += sy; }
  336. // }
  337.  
  338. // return result;
  339. //}
  340. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement