source: OniSplit/Akira/QuadtreeNode.cs@ 1138

Last change on this file since 1138 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 3.6 KB
Line 
1using System;
2using System.Collections.Generic;
3
4namespace Oni.Akira
5{
6 internal class QuadtreeNode
7 {
8 public const int ChildCount = 4;
9 private QuadtreeNode[] nodes = new QuadtreeNode[ChildCount];
10 private OctreeNode[] leafs = new OctreeNode[ChildCount];
11 private readonly Vector3 center;
12 private readonly float size;
13 private readonly OctreeNode.Face face;
14 private int index;
15
16 public enum Axis
17 {
18 U = 0,
19 V = 1
20 }
21
22 public struct ChildPosition
23 {
24 private readonly int index;
25
26 public ChildPosition(int index)
27 {
28 this.index = index;
29 }
30
31 public int Index => index;
32
33 public int U => this[Axis.U];
34 public int V => this[Axis.V];
35
36 public int this[Axis axis] => ((index >> (int)axis) & 1);
37
38 public static IEnumerable<ChildPosition> All
39 {
40 get
41 {
42 for (int i = 0; i < 4; i++)
43 yield return new ChildPosition(i);
44 }
45 }
46 }
47
48 public QuadtreeNode(Vector3 center, float size, OctreeNode.Face face)
49 {
50 this.center = center;
51 this.size = size;
52 this.face = face;
53 }
54
55 public QuadtreeNode[] Nodes => nodes;
56 public OctreeNode[] Leafs => leafs;
57
58 public void Build(OctreeNode adjacentNode)
59 {
60 float childSize = size * 0.5f;
61
62 foreach (var position in ChildPosition.All)
63 {
64 var childCenter = GetChildNodeCenter(position);
65 var adjacentCenter = OctreeNode.MovePoint(childCenter, face, childSize * 0.5f);
66 var childAdjacentNode = adjacentNode.FindLargestOrEqual(adjacentCenter, childSize);
67
68 if (childAdjacentNode.IsLeaf)
69 {
70 leafs[position.Index] = childAdjacentNode;
71 }
72 else
73 {
74 var child = new QuadtreeNode(childCenter, childSize, face);
75 child.Build(childAdjacentNode);
76 nodes[position.Index] = child;
77 }
78 }
79 }
80
81 private Vector3 GetChildNodeCenter(ChildPosition position)
82 {
83 float offset = size * 0.25f;
84
85 float u = (position.U == 0) ? -offset : offset;
86 float v = (position.V == 0) ? -offset : offset;
87
88 var result = center;
89
90 if (face.Axis == OctreeNode.Axis.X)
91 {
92 result.Y += u;
93 result.Z += v;
94 }
95 else if (face.Axis == OctreeNode.Axis.Y)
96 {
97 result.X += u;
98 result.Z += v;
99 }
100 else
101 {
102 result.X += u;
103 result.Y += v;
104 }
105
106 return result;
107 }
108
109 public int Index => index;
110
111 public List<QuadtreeNode> GetDfsList()
112 {
113 var list = new List<QuadtreeNode>();
114
115 DfsTraversal(node => {
116 node.index = list.Count;
117 list.Add(node);
118 });
119
120 return list;
121 }
122
123 private void DfsTraversal(Action<QuadtreeNode> action)
124 {
125 action(this);
126
127 foreach (var node in nodes)
128 {
129 if (node != null)
130 node.DfsTraversal(action);
131 }
132 }
133 }
134}
Note: See TracBrowser for help on using the repository browser.