diff options
Diffstat (limited to 'linden/indra/llmath/lloctree.h')
-rw-r--r-- | linden/indra/llmath/lloctree.h | 94 |
1 files changed, 59 insertions, 35 deletions
diff --git a/linden/indra/llmath/lloctree.h b/linden/indra/llmath/lloctree.h index 6e068cd..22f298c 100644 --- a/linden/indra/llmath/lloctree.h +++ b/linden/indra/llmath/lloctree.h | |||
@@ -40,6 +40,11 @@ | |||
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #define LL_OCTREE_PARANOIA_CHECK 0 | 42 | #define LL_OCTREE_PARANOIA_CHECK 0 |
43 | #if LL_DARWIN | ||
44 | #define LL_OCTREE_MAX_CAPACITY 32 | ||
45 | #else | ||
46 | #define LL_OCTREE_MAX_CAPACITY 256 | ||
47 | #endif | ||
43 | 48 | ||
44 | template <class T> class LLOctreeState; | 49 | template <class T> class LLOctreeState; |
45 | template <class T> class LLOctreeNode; | 50 | template <class T> class LLOctreeNode; |
@@ -107,7 +112,8 @@ public: | |||
107 | virtual void removeByAddress(T* data) { getOctState()->removeByAddress(data); } | 112 | virtual void removeByAddress(T* data) { getOctState()->removeByAddress(data); } |
108 | virtual bool hasLeafState() const { return getOctState()->isLeaf(); } | 113 | virtual bool hasLeafState() const { return getOctState()->isLeaf(); } |
109 | virtual void destroy() { getOctState()->destroy(); } | 114 | virtual void destroy() { getOctState()->destroy(); } |
110 | virtual oct_node* getNodeAt(T* data) { return getOctState()->getNodeAt(data); } | 115 | virtual oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } |
116 | virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); } | ||
111 | virtual U8 getOctant() const { return mOctant; } | 117 | virtual U8 getOctant() const { return mOctant; } |
112 | virtual void setOctant(U8 octant) { mOctant = octant; } | 118 | virtual void setOctant(U8 octant) { mOctant = octant; } |
113 | virtual const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; } | 119 | virtual const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; } |
@@ -136,9 +142,14 @@ public: | |||
136 | return ret; | 142 | return ret; |
137 | } | 143 | } |
138 | 144 | ||
145 | virtual bool isInside(const LLVector3d& pos, const F64& rad) const | ||
146 | { | ||
147 | return rad <= mSize.mdV[0]*2.0 && isInside(pos); | ||
148 | } | ||
149 | |||
139 | virtual bool isInside(T* data) const | 150 | virtual bool isInside(T* data) const |
140 | { | 151 | { |
141 | return data->getBinRadius() <= mSize.mdV[0]*2.0 && isInside(data->getPositionGroup()); | 152 | return isInside(data->getPositionGroup(), data->getBinRadius()); |
142 | } | 153 | } |
143 | 154 | ||
144 | virtual bool isInside(const LLVector3d& pos) const | 155 | virtual bool isInside(const LLVector3d& pos) const |
@@ -174,6 +185,11 @@ public: | |||
174 | 185 | ||
175 | bool contains(T* xform) | 186 | bool contains(T* xform) |
176 | { | 187 | { |
188 | return contains(xform->getBinRadius()); | ||
189 | } | ||
190 | |||
191 | bool contains(F64 radius) | ||
192 | { | ||
177 | if (mParent == NULL) | 193 | if (mParent == NULL) |
178 | { //root node contains nothing | 194 | { //root node contains nothing |
179 | return false; | 195 | return false; |
@@ -181,7 +197,6 @@ public: | |||
181 | 197 | ||
182 | F64 size = mSize.mdV[0]; | 198 | F64 size = mSize.mdV[0]; |
183 | F64 p_size = size * 2.0; | 199 | F64 p_size = size * 2.0; |
184 | F64 radius = xform->getBinRadius(); | ||
185 | 200 | ||
186 | return (radius <= 0.001 && size <= 0.001) || | 201 | return (radius <= 0.001 && size <= 0.001) || |
187 | (radius <= p_size && radius > size); | 202 | (radius <= p_size && radius > size); |
@@ -189,17 +204,10 @@ public: | |||
189 | 204 | ||
190 | static void pushCenter(LLVector3d ¢er, LLVector3d &size, T* data) | 205 | static void pushCenter(LLVector3d ¢er, LLVector3d &size, T* data) |
191 | { | 206 | { |
192 | LLVector3 pos(data->getPositionGroup()); | 207 | LLVector3d pos(data->getPositionGroup()); |
193 | F64 p[] = | ||
194 | { | ||
195 | (F64) pos.mV[0], | ||
196 | (F64) pos.mV[1], | ||
197 | (F64) pos.mV[2] | ||
198 | }; | ||
199 | |||
200 | for (U32 i = 0; i < 3; i++) | 208 | for (U32 i = 0; i < 3; i++) |
201 | { | 209 | { |
202 | if (p[i] > center.mdV[i]) | 210 | if (pos.mdV[i] > center.mdV[i]) |
203 | { | 211 | { |
204 | center.mdV[i] += size.mdV[i]; | 212 | center.mdV[i] += size.mdV[i]; |
205 | } | 213 | } |
@@ -273,11 +281,15 @@ public: | |||
273 | oct_node* getOctNode() { return (oct_node*) BaseType::getNode(); } | 281 | oct_node* getOctNode() { return (oct_node*) BaseType::getNode(); } |
274 | 282 | ||
275 | virtual oct_node* getNodeAt(T* data) | 283 | virtual oct_node* getNodeAt(T* data) |
284 | { | ||
285 | return getNodeAt(data->getPositionGroup(), data->getBinRadius()); | ||
286 | } | ||
287 | |||
288 | virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) | ||
276 | { | 289 | { |
277 | const LLVector3d& pos = data->getPositionGroup(); | ||
278 | LLOctreeNode<T>* node = getOctNode(); | 290 | LLOctreeNode<T>* node = getOctNode(); |
279 | 291 | ||
280 | if (node->isInside(data)) | 292 | if (node->isInside(pos, rad)) |
281 | { | 293 | { |
282 | //do a quick search by octant | 294 | //do a quick search by octant |
283 | U8 octant = node->getOctant(pos.mdV); | 295 | U8 octant = node->getOctant(pos.mdV); |
@@ -287,7 +299,7 @@ public: | |||
287 | //at the appropriate octant or is smaller than the object. | 299 | //at the appropriate octant or is smaller than the object. |
288 | //by definition, that node is the smallest node that contains | 300 | //by definition, that node is the smallest node that contains |
289 | // the data | 301 | // the data |
290 | while (keep_going && node->getSize().mdV[0] >= data->getBinRadius()) | 302 | while (keep_going && node->getSize().mdV[0] >= rad) |
291 | { | 303 | { |
292 | keep_going = FALSE; | 304 | keep_going = FALSE; |
293 | for (U32 i = 0; i < node->getChildCount() && !keep_going; i++) | 305 | for (U32 i = 0; i < node->getChildCount() && !keep_going; i++) |
@@ -301,9 +313,9 @@ public: | |||
301 | } | 313 | } |
302 | } | 314 | } |
303 | } | 315 | } |
304 | else if (!node->contains(data) && node->getParent()) | 316 | else if (!node->contains(rad) && node->getParent()) |
305 | { //if we got here, data does not exist in this node | 317 | { //if we got here, data does not exist in this node |
306 | return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(data); | 318 | return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(pos, rad); |
307 | } | 319 | } |
308 | 320 | ||
309 | return node; | 321 | return node; |
@@ -317,22 +329,15 @@ public: | |||
317 | return false; | 329 | return false; |
318 | } | 330 | } |
319 | LLOctreeNode<T>* node = getOctNode(); | 331 | LLOctreeNode<T>* node = getOctNode(); |
332 | LLOctreeNode<T>* parent = node->getOctParent(); | ||
320 | 333 | ||
321 | if (data->getBinRadius() <= node->getSize().mdV[0]) | 334 | //is it here? |
322 | { | 335 | if (node->isInside(data->getPositionGroup())) |
323 | oct_node* dest = getNodeAt(data); | ||
324 | |||
325 | if (dest != node) | ||
326 | { | ||
327 | dest->insert(data); | ||
328 | return false; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | //no kid found, is it even here? | ||
333 | if (node->isInside(data)) | ||
334 | { | 336 | { |
335 | if (node->contains(data)) | 337 | if (getElementCount() < LL_OCTREE_MAX_CAPACITY && |
338 | (node->contains(data->getBinRadius()) || | ||
339 | (data->getBinRadius() > node->getSize().mdV[0] && | ||
340 | parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY))) | ||
336 | { //it belongs here | 341 | { //it belongs here |
337 | if (data == NULL) | 342 | if (data == NULL) |
338 | { | 343 | { |
@@ -353,7 +358,19 @@ public: | |||
353 | return true; | 358 | return true; |
354 | } | 359 | } |
355 | else | 360 | else |
356 | { | 361 | { |
362 | //find a child to give it to | ||
363 | oct_node* child = NULL; | ||
364 | for (U32 i = 0; i < getChildCount(); i++) | ||
365 | { | ||
366 | child = getChild(i); | ||
367 | if (child->isInside(data->getPositionGroup())) | ||
368 | { | ||
369 | child->insert(data); | ||
370 | return false; | ||
371 | } | ||
372 | } | ||
373 | |||
357 | //it's here, but no kids are in the right place, make a new kid | 374 | //it's here, but no kids are in the right place, make a new kid |
358 | LLVector3d center(node->getCenter()); | 375 | LLVector3d center(node->getCenter()); |
359 | LLVector3d size(node->getSize()*0.5); | 376 | LLVector3d size(node->getSize()*0.5); |
@@ -385,7 +402,7 @@ public: | |||
385 | 402 | ||
386 | //make the new kid | 403 | //make the new kid |
387 | LLOctreeState<T>* newstate = new LLOctreeState<T>(); | 404 | LLOctreeState<T>* newstate = new LLOctreeState<T>(); |
388 | oct_node* child = new LLOctreeNode<T>(center, size, newstate, node); | 405 | child = new LLOctreeNode<T>(center, size, newstate, node); |
389 | addChild(child); | 406 | addChild(child); |
390 | 407 | ||
391 | child->insert(data); | 408 | child->insert(data); |
@@ -393,8 +410,15 @@ public: | |||
393 | } | 410 | } |
394 | else | 411 | else |
395 | { | 412 | { |
396 | //it's not in here, give it to the parent | 413 | //it's not in here, give it to the root |
397 | node->getOctParent()->insert(data); | 414 | LLOctreeNode<T>* parent = node->getOctParent(); |
415 | while (parent) | ||
416 | { | ||
417 | node = parent; | ||
418 | parent = node->getOctParent(); | ||
419 | } | ||
420 | |||
421 | node->insert(data); | ||
398 | } | 422 | } |
399 | 423 | ||
400 | return false; | 424 | return false; |