Advertisement
JontePonte

quadtree draft

Nov 19th, 2024
7
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.08 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using Unity.VisualScripting;
  3. using UnityEngine;
  4. using Unity.Mathematics;
  5. using Unity.Collections;
  6. using Unity.Jobs;
  7. using Unity.Burst;
  8. using Particle = Simulation.Particle;
  9.  
  10. public struct Node
  11. {
  12. public Quad boundary;
  13. public float mass;
  14. public float2 centerOfMass;
  15. public int childIndex;
  16. public int next;
  17. }
  18. public struct Quad
  19. {
  20. //Bottom left of rectangle
  21. public Vector2 position;
  22. public float size;
  23.  
  24. public int FindNode(Vector2 pos)
  25. {
  26. bool wX = pos.x - position.x < size / 2;
  27. bool sY = pos.y - position.y < size / 2;
  28.  
  29. if (wX && !sY) return 0;
  30. if (!wX && !sY) return 1;
  31. if (wX && sY) return 2;
  32. if(!wX && sY) return 3;
  33.  
  34. return 0;
  35. }
  36. }
  37.  
  38. public class QuadTree
  39. {
  40. public NativeList<Node> nodes;
  41.  
  42. public QuadTree()
  43. {
  44. nodes = new(Allocator.Persistent);
  45. float halfScreenSize = Simulation.HalfScreenSize;
  46. Quad boundary = new() { position = new Vector2(-halfScreenSize, -halfScreenSize), size = halfScreenSize * 2 };
  47. nodes.Add(new Node
  48. {
  49. boundary = boundary,
  50. next = 0
  51. });
  52. }
  53.  
  54. ~QuadTree()
  55. {
  56. nodes.Dispose();
  57. }
  58.  
  59. public void DrawTree()
  60. {
  61. foreach (var node in nodes)
  62. {
  63. DrawSquare(node.boundary.position, node.boundary.size);
  64. }
  65. }
  66. static void DrawSquare(Vector2 position, float size)
  67. {
  68. Debug.DrawLine(position, new Vector2(position.x, position.y + size), Color.red);
  69. Debug.DrawLine(new Vector2(position.x, position.y + size), new Vector2(position.x + size, position.y + size), Color.red);
  70. Debug.DrawLine(new Vector2(position.x + size, position.y + size), new Vector2(position.x + size, position.y), Color.red);
  71. Debug.DrawLine(new Vector2(position.x + size, position.y), new Vector2(position.x, position.y), Color.red);
  72. }
  73.  
  74. public void Propagate()
  75. {
  76. int count = nodes.Length - 1;
  77. for (int i = count; i > 0; i--)
  78. {
  79. int child = nodes[i].childIndex;
  80. if(child == 0) continue;
  81.  
  82. Node node = nodes[i];
  83. Node nw = nodes[child];
  84. Node ne = nodes[child + 1];
  85. Node sw = nodes[child + 2];
  86. Node se = nodes[child + 3];
  87. node.centerOfMass = nw.centerOfMass * nw.mass
  88. + ne.centerOfMass * ne.mass
  89. + sw.centerOfMass * sw.mass
  90. + se.centerOfMass * se.mass;
  91. node.mass = nw.mass
  92. + ne.mass
  93. + sw.mass
  94. + se.mass;
  95. node.centerOfMass /= node.mass;
  96. nodes[i] = node;
  97.  
  98. }
  99. }
  100.  
  101. public void Insert(Particle particle)
  102. {
  103. int nodeIndex = 0;
  104. Node node = nodes[0];
  105. while (node.childIndex != 0)
  106. {
  107. int quad = node.boundary.FindNode(particle.position);
  108. nodeIndex = quad + node.childIndex;
  109. node = nodes[nodeIndex];
  110. }
  111.  
  112. if (node.mass == 0)
  113. {
  114. node.centerOfMass = particle.position;
  115. node.mass = particle.mass;
  116. nodes[nodeIndex] = node;
  117. return;
  118. }
  119.  
  120. if (Equals(node.centerOfMass, particle.position))
  121. {
  122. node.mass += particle.mass;
  123. nodes[nodeIndex] = node;
  124. return;
  125. }
  126.  
  127. Vector2 nodePos = node.centerOfMass;
  128. float nodeMass = node.mass;
  129. while (true)
  130. {
  131. Subdivide(nodeIndex);
  132. node = nodes[nodeIndex];
  133. int childIndex = node.childIndex;
  134. int q1 = node.boundary.FindNode(nodePos);
  135. int q2 = node.boundary.FindNode(particle.position);
  136.  
  137. if (q1 == q2)
  138. {
  139. nodeIndex = q1 + childIndex;
  140. }
  141. else
  142. {
  143. int n1 = q1 + childIndex;
  144. int n2 = q2 + childIndex;
  145.  
  146. nodes[n1] = new Node
  147. {
  148. centerOfMass = nodePos,
  149. mass = nodeMass,
  150. boundary = nodes[n1].boundary,
  151. next = nodes[n1].next
  152. };
  153. nodes[n2] = new Node
  154. {
  155. centerOfMass = particle.position,
  156. mass = particle.mass,
  157. boundary = nodes[n2].boundary,
  158. next = nodes[n2].next
  159. };
  160. return;
  161. }
  162. }
  163. }
  164.  
  165. void Subdivide(int parentIndex)
  166. {
  167. Node parent = nodes[parentIndex];
  168. parent.childIndex = nodes.Length;
  169. nodes[parentIndex] = parent;
  170. Vector2 parentPos = parent.boundary.position;
  171. Vector2 nwPosition = new(parentPos.x, parentPos.y + parent.boundary.size / 2);
  172. Vector2 nePosition = new(parentPos.x + parent.boundary.size / 2, parentPos.y + parent.boundary.size / 2);
  173. Vector2 swPosition = new(parentPos.x, parentPos.y);
  174. Vector2 sePosition = new(parentPos.x + parent.boundary.size / 2, parentPos.y);
  175.  
  176. Node nw = new()
  177. {
  178. boundary = new Quad { position = nwPosition, size = parent.boundary.size / 2 },
  179. next = parent.childIndex + 1
  180. };
  181. Node ne = new()
  182. {
  183. boundary = new Quad { position = nePosition, size = parent.boundary.size / 2 },
  184. next = parent.childIndex + 2
  185. };
  186. Node sw = new()
  187. {
  188. boundary = new Quad { position = swPosition, size = parent.boundary.size / 2 },
  189. next = parent.childIndex + 3
  190. };
  191. Node se = new()
  192. {
  193. boundary = new Quad { position = sePosition, size = parent.boundary.size / 2 },
  194. next = parent.next
  195. };
  196.  
  197. nodes.Add(nw);
  198. nodes.Add(ne);
  199. nodes.Add(sw);
  200. nodes.Add(se);
  201. }
  202. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement