Advertisement
JontePonte

QuadTree draft

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