@@ -80,25 +80,25 @@ sample scenes to your Assets folder to open them.
80
80
81
81
### Insertion
82
82
The objects can be of any unmanaged type, when inserting, an AABB must be provided:
83
-
84
- // Insert a bunch of triangles
85
- for (int i = 0; i < tris.Length; i++)
86
- {
87
- var triangle = tris[i];
88
- octree.Insert(triangle, triangle.GetAABB());
89
- }
90
-
83
+ ``` cs
84
+ // Insert a bunch of triangles
85
+ for (int i = 0 ; i < tris .Length ; i ++ )
86
+ {
87
+ var triangle = tris [i ];
88
+ octree .Insert (triangle , triangle .GetAABB ());
89
+ }
90
+ ```
91
91
Often times however, it's more efficient to insert Id's that map to something outside of
92
92
the tree (like DOTS entities).
93
93
94
94
If you know your objects are points, you can insert them faster by using:
95
-
96
- // Insert entities that are 'points'
97
- for (int i = 0; i < entities.Length; i++)
98
- {
99
- octree.InsertPoint(entities[i], positions[i]);
100
- }
101
-
95
+ ``` cs
96
+ // Insert entities that are 'points'
97
+ for (int i = 0 ; i < entities .Length ; i ++ )
98
+ {
99
+ octree .InsertPoint (entities [i ], positions [i ]);
100
+ }
101
+ ```
102
102
Note that objects inserted as points only support range and nearest neighbour queries.
103
103
104
104
### Queries
@@ -112,19 +112,20 @@ This turned out to be the most efficent and easiest to implement while keeping t
112
112
113
113
A raycast query for example, requires you to implement IOctreeRayIntersecter which
114
114
acts as a delegate to determine if a ray intersects with an object that's in the tree.
115
-
116
- public static bool RaycastAABB<T>(this NativeOctree<T> octree, Ray ray, out OctreeRaycastHit<T> hit) where T : unmanaged
117
- {
118
- return octree.Raycast<RayAABBIntersecter<T>>(ray, out hit);
119
- }
120
-
121
- struct RayAABBIntersecter<T> : IOctreeRayIntersecter<T>
122
- {
123
- public bool IntersectRay(in PrecomputedRay ray, T obj, AABB objBounds, out float distance)
124
- {
125
- return objBounds.IntersectsRay(ray, out distance);
126
- }
127
- }
115
+ ``` cs
116
+ public static bool RaycastAABB <T >(this NativeOctree < T > octree , Ray ray , out OctreeRaycastHit <T > hit ) where T : unmanaged
117
+ {
118
+ return octree .Raycast <RayAABBIntersecter <T >>(ray , out hit );
119
+ }
120
+
121
+ struct RayAABBIntersecter <T > : IOctreeRayIntersecter <T >
122
+ {
123
+ public bool IntersectRay (in PrecomputedRay ray , T obj , AABB objBounds , out float distance )
124
+ {
125
+ return objBounds .IntersectsRay (ray , out distance );
126
+ }
127
+ }
128
+ ```
128
129
129
130
The example above just tests the ray against the object's bounds. (See NativeOctreeExtensions) But you could go a step further
130
131
and test it against a triangle, a collider and so forth. Note that the tree itself
@@ -133,66 +134,66 @@ if the ray doesn't exit with the object's bounds since those checks are cheap.
133
134
134
135
### Nearest Neighbour
135
136
NativeTrees support nearest neighbour queries. You should implement IOctreeNearestVisitor and IOctreeDistanceProvider.
136
-
137
- struct AABBDistanceSquaredProvider<T> : IOctreeDistanceProvider<T>
138
- {
139
- // Just return the distance squared to our bounds
140
- public float DistanceSquared(float3 point, T obj, AABB bounds) => bounds.DistanceSquared(point);
141
- }
142
-
143
- struct OctreeNearestAABBVisitor<T> : IOctreeNearestVisitor<T>
144
- {
145
- public T nearest;
146
- public bool found;
137
+ ``` cs
138
+ struct AABBDistanceSquaredProvider <T > : IOctreeDistanceProvider <T >
139
+ {
140
+ // Just return the distance squared to our bounds
141
+ public float DistanceSquared (float3 point , T obj , AABB bounds ) => bounds .DistanceSquared (point );
142
+ }
143
+
144
+ struct OctreeNearestAABBVisitor <T > : IOctreeNearestVisitor <T >
145
+ {
146
+ public T nearest ;
147
+ public bool found ;
147
148
148
- public bool OnVist(T obj)
149
- {
150
- this.found = true;
151
- this.nearest = obj;
149
+ public bool OnVist (T obj )
150
+ {
151
+ this .found = true ;
152
+ this .nearest = obj ;
152
153
153
- return false; // immediately stop iterating at first hit
154
- // if we want the 2nd or 3rd neighbour, we could iterate on and keep track of the count!
155
- }
156
- }
157
-
154
+ return false ; // immediately stop iterating at first hit
155
+ // if we want the 2nd or 3rd neighbour, we could iterate on and keep track of the count!
156
+ }
157
+ }
158
+ ```
158
159
The extensions classes show an example of these implementation. But only for AABB's.
159
160
If you need more detail on your distance, you can implement your type specific behaviour using these interfaces.
160
161
161
162
To get the nearest neighbour:
162
-
163
- var visitor = new OctreeNearestAABBVisitor<Entity>();
164
- octree.Nearest(point, maxDistance, ref visitor, default(AABBDistanceSquaredProvider<Entity>));
165
- Entity nearestEntity = visitor.nearest;
166
-
163
+ ``` cs
164
+ var visitor = new OctreeNearestAABBVisitor <Entity >();
165
+ octree .Nearest (point , maxDistance , ref visitor , default (AABBDistanceSquaredProvider <Entity >));
166
+ Entity nearestEntity = visitor .nearest ;
167
+ ```
167
168
### Range
168
169
169
170
Here's an example that adds unique objects that overlap with a range to a hashset:
170
-
171
- public static void RangeAABBUnique<T>(this NativeOctree<T> octree, AABB range, NativeParallelHashSet<T> results)
172
- where T : unmanaged, IEquatable<T>
173
- {
174
- var vistor = new RangeAABBUniqueVisitor<T>()
175
- {
176
- results = results
177
- };
171
+ ``` cs
172
+ public static void RangeAABBUnique <T >(this NativeOctree < T > octree , AABB range , NativeParallelHashSet < T > results )
173
+ where T : unmanaged , IEquatable < T >
174
+ {
175
+ var vistor = new RangeAABBUniqueVisitor <T >()
176
+ {
177
+ results = results
178
+ };
178
179
179
- octree.Range(range, ref vistor);
180
- }
180
+ octree .Range (range , ref vistor );
181
+ }
181
182
182
- struct RangeAABBUniqueVisitor<T> : IOctreeRangeVisitor<T> where T : unmanaged, IEquatable<T>
183
- {
184
- public NativeParallelHashSet<T> results;
183
+ struct RangeAABBUniqueVisitor <T > : IOctreeRangeVisitor <T > where T : unmanaged , IEquatable <T >
184
+ {
185
+ public NativeParallelHashSet <T > results ;
185
186
186
- public bool OnVisit(T obj, AABB objBounds, AABB queryRange)
187
- {
188
- // check if our object's AABB overlaps with the query AABB
189
- if (objBounds.Overlaps(queryRange))
190
- results.Add(obj);
191
-
192
- return true; // always keep iterating, we want to catch all objects
193
- }
194
- }
195
-
187
+ public bool OnVisit (T obj , AABB objBounds , AABB queryRange )
188
+ {
189
+ // check if our object's AABB overlaps with the query AABB
190
+ if (objBounds .Overlaps (queryRange ))
191
+ results .Add (obj );
192
+
193
+ return true ; // always keep iterating, we want to catch all objects
194
+ }
195
+ }
196
+ ```
196
197
It's important to note that the query itself iterates all of the objects that are in nodes that overlap with
197
198
the input range. An extra check should be performed to test if the object overlaps.
198
199
Also, if the objects aren't points, it's possible for them to be visited multiple times as they reside in more than one node.
0 commit comments