TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node Class Reference

#include <KDTree.h>

Public Member Functions

 Node ()
 
 Node (const Node &other)
 
 Node (const Array< Handle * > &pt)
 
 ~Node ()
 
bool isLeaf () const
 
void getHandles (Array< Handle * > &handleArray) const
 
void verifyNode (const Vector3 &lo, const Vector3 &hi)
 
NodefindDeepestContainingNode (const AABox &bounds)
 
void getIntersectingMembers (const AABox &box, const Sphere &sphere, Array< T * > &members, bool useSphere) const
 
void assignSplitBounds (const AABox &myBounds)
 
bool intersects (const Ray &ray, float distance) const
 
template<typename RayCallback >
void intersectRay (const Ray &ray, RayCallback &intersectCallback, float &distance, bool intersectCallbackIsFast) const
 

Static Public Member Functions

static void serializeStructure (const Node *n, BinaryOutput &bo)
 
static NodedeserializeStructure (BinaryInput &bi)
 

Public Attributes

AABox splitBounds
 
Vector3::Axis splitAxis
 
float splitLocation
 
Nodechild [2]
 
Array< Handle * > valueArray
 
Array< AABoxboundsArray
 

Constructor & Destructor Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::Node ( )
inline

Creates node with NULL children

372  {
374  splitLocation = 0;
375  splitBounds = AABox(-Vector3::inf(), Vector3::inf());
376  for (int i = 0; i < 2; ++i) {
377  child[i] = NULL;
378  }
379  }
Node * child[2]
Definition: KDTree.h:351
Definition: Vector3.h:122
arena_t NULL
Definition: jemalloc_internal.h:624
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340
AABox splitBounds
Definition: KDTree.h:335
static const Vector3 & inf()
Definition: Vector3.cpp:124

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::Node ( const Node other)
inline

Doesn't clone children.

384  : valueArray(other.valueArray), boundsArray(other.boundsArray) {
385  splitAxis = other.splitAxis;
386  splitLocation = other.splitLocation;
387  splitBounds = other.splitBounds;
388  for (int i = 0; i < 2; ++i) {
389  child[i] = NULL;
390  }
391  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
arena_t NULL
Definition: jemalloc_internal.h:624
Array< AABox > boundsArray
Definition: KDTree.h:369
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340
AABox splitBounds
Definition: KDTree.h:335
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::Node ( const Array< Handle * > &  pt)
inline

Copies the specified subarray of pt into point, NULLs the children. Assumes a second pass will set splitBounds.

395  : valueArray(pt) {
397  splitLocation = 0;
398  for (int i = 0; i < 2; ++i) {
399  child[i] = NULL;
400  }
401 
402  boundsArray.resize(valueArray.size());
403  for (int i = 0; i < valueArray.size(); ++i) {
404  boundsArray[i] = valueArray[i]->bounds;
405  }
406  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
Definition: Vector3.h:122
arena_t NULL
Definition: jemalloc_internal.h:624
Array< AABox > boundsArray
Definition: KDTree.h:369
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340

+ Here is the call graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::~Node ( )
inline

Deletes the children (but not the values)

409  {
410  for (int i = 0; i < 2; ++i) {
411  delete child[i];
412  }
413  }
Node * child[2]
Definition: KDTree.h:351

Member Function Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::assignSplitBounds ( const AABox myBounds)
inline

Recurse through the tree, assigning splitBounds fields.

566  {
567  splitBounds = myBounds;
568 
569  AABox childBounds[2];
570  myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]);
571 
572 # if defined(G3D_DEBUG) && defined(VERIFY_TREE)
573  // Verify the split
574  for (int v = 0; v < boundsArray.size(); ++v) {
575  const AABox& bounds = boundsArray[v];
576  debugAssert(myBounds.contains(bounds));
577  }
578 # endif
579 
580  for (int c = 0; c < 2; ++c) {
581  if (child[c]) {
582  child[c]->assignSplitBounds(childBounds[c]);
583  }
584  }
585  }
Node * child[2]
Definition: KDTree.h:351
void assignSplitBounds(const AABox &myBounds)
Definition: KDTree.h:566
Array< AABox > boundsArray
Definition: KDTree.h:369
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340
#define debugAssert(exp)
Definition: debugAssert.h:160
AABox splitBounds
Definition: KDTree.h:335
void split(const Vector3::Axis &axis, float location, AABox &low, AABox &high) const
Definition: AABox.cpp:112

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
static Node* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::deserializeStructure ( BinaryInput bi)
inlinestatic

Clears the member table

495  {
496  if (bi.readUInt8() == 0) {
497  return NULL;
498  } else {
499  Node* n = new Node();
500  n->splitBounds.deserialize(bi);
501  deserialize(n->splitAxis, bi);
502  n->splitLocation = bi.readFloat32();
503  for (int c = 0; c < 2; ++c) {
504  n->child[c] = deserializeStructure(bi);
505  }
506  return n;
507  }
508  }
arena_t NULL
Definition: jemalloc_internal.h:624
void deserialize(std::string &s, BinaryInput &b)
Definition: serialize.h:16
static Node * deserializeStructure(BinaryInput &bi)
Definition: KDTree.h:495
Node()
Definition: KDTree.h:372

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::findDeepestContainingNode ( const AABox bounds)
inline

Returns the deepest node that completely contains bounds.

511  {
512 
513  // See which side of the splitting plane the bounds are on
514  if (bounds.high()[splitAxis] < splitLocation) {
515  // Bounds are on the low side. Recurse into the child
516  // if it exists.
517  if (child[0] != NULL) {
518  return child[0]->findDeepestContainingNode(bounds);
519  }
520  } else if (bounds.low()[splitAxis] > splitLocation) {
521  // Bounds are on the high side, recurse into the child
522  // if it exists.
523  if (child[1] != NULL) {
524  return child[1]->findDeepestContainingNode(bounds);
525  }
526  }
527 
528  // There was no containing child, so this node is the
529  // deepest containing node.
530  return this;
531  }
Node * child[2]
Definition: KDTree.h:351
Node * findDeepestContainingNode(const AABox &bounds)
Definition: KDTree.h:511
arena_t NULL
Definition: jemalloc_internal.h:624
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::getHandles ( Array< Handle * > &  handleArray) const
inline

Recursively appends all handles and children's handles to the array.

425  {
426  handleArray.append(valueArray);
427  for (int i = 0; i < 2; ++i) {
428  if (child[i] != NULL) {
429  child[i]->getHandles(handleArray);
430  }
431  }
432  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
arena_t NULL
Definition: jemalloc_internal.h:624
void getHandles(Array< Handle * > &handleArray) const
Definition: KDTree.h:425

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::getIntersectingMembers ( const AABox box,
const Sphere sphere,
Array< T * > &  members,
bool  useSphere 
) const
inline

Appends all members that intersect the box. If useSphere is true, members that pass the box test face a second test against the sphere.

541  {
542 
543  // Test all values at this node
544  for (int v = 0; v < boundsArray.size(); ++v) {
545  const AABox& bounds = boundsArray[v];
546  if (bounds.intersects(box) &&
547  (! useSphere || bounds.intersects(sphere))) {
548  members.append(& (valueArray[v]->value));
549  }
550  }
551 
552  // If the left child overlaps the box, recurse into it
553  if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) {
554  child[0]->getIntersectingMembers(box, sphere, members, useSphere);
555  }
556 
557  // If the right child overlaps the box, recurse into it
558  if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) {
559  child[1]->getIntersectingMembers(box, sphere, members, useSphere);
560  }
561  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
void getIntersectingMembers(const AABox &box, const Sphere &sphere, Array< T * > &members, bool useSphere) const
Definition: KDTree.h:537
arena_t NULL
Definition: jemalloc_internal.h:624
Array< AABox > boundsArray
Definition: KDTree.h:369
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
template<typename RayCallback >
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::intersectRay ( const Ray ray,
RayCallback &  intersectCallback,
float &  distance,
bool  intersectCallbackIsFast 
) const
inline
607  {
608 
609  if (! intersects(ray, distance)) {
610  // The ray doesn't hit this node, so it can't hit the children of the node.
611  return;
612  }
613 
614  // Test for intersection against every object at this node.
615  for (int v = 0; v < valueArray.size(); ++v) {
616  bool canHitThisObject = true;
617 
618  if (! intersectCallbackIsFast) {
619  // See if
620  Vector3 location;
621  const AABox& bounds = boundsArray[v];
622  bool alreadyInsideBounds = false;
623  bool rayWillHitBounds =
625  ray.origin(), ray.direction(), bounds, location, alreadyInsideBounds);
626 
627  canHitThisObject = (alreadyInsideBounds ||
628  (rayWillHitBounds && ((location - ray.origin()).squaredLength() < square(distance))));
629  }
630 
631  if (canHitThisObject) {
632  // It is possible that this ray hits this object. Look for the intersection using the
633  // callback.
634  const T& value = valueArray[v]->value;
635  intersectCallback(ray, value, distance);
636  }
637  }
638 
639  // There are three cases to consider next:
640  //
641  // 1. the ray can start on one side of the splitting plane and never enter the other,
642  // 2. the ray can start on one side and enter the other, and
643  // 3. the ray can travel exactly down the splitting plane
644 
645  enum {NONE = -1};
646  int firstChild = NONE;
647  int secondChild = NONE;
648 
649  if (ray.origin()[splitAxis] < splitLocation) {
650 
651  // The ray starts on the small side
652  firstChild = 0;
653 
654  if (ray.direction()[splitAxis] > 0) {
655  // The ray will eventually reach the other side
656  secondChild = 1;
657  }
658 
659  } else if (ray.origin()[splitAxis] > splitLocation) {
660 
661  // The ray starts on the large side
662  firstChild = 1;
663 
664  if (ray.direction()[splitAxis] < 0) {
665  secondChild = 0;
666  }
667  } else {
668  // The ray starts on the splitting plane
669  if (ray.direction()[splitAxis] < 0) {
670  // ...and goes to the small side
671  firstChild = 0;
672  } else if (ray.direction()[splitAxis] > 0) {
673  // ...and goes to the large side
674  firstChild = 1;
675  }
676  }
677 
678  // Test on the side closer to the ray origin.
679  if ((firstChild != NONE) && child[firstChild]) {
680  child[firstChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast);
681  }
682 
683  if (ray.direction()[splitAxis] != 0) {
684  // See if there was an intersection before hitting the splitting plane.
685  // If so, there is no need to look on the far side and recursion terminates.
686  float distanceToSplittingPlane = (splitLocation - ray.origin()[splitAxis]) / ray.direction()[splitAxis];
687  if (distanceToSplittingPlane > distance) {
688  // We aren't going to hit anything else before hitting the splitting plane,
689  // so don't bother looking on the far side of the splitting plane at the other
690  // child.
691  return;
692  }
693  }
694 
695  // Test on the side farther from the ray origin.
696  if ((secondChild != NONE) && child[secondChild]) {
697  child[secondChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast);
698  }
699 
700  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
Array< AABox > boundsArray
Definition: KDTree.h:369
double distance(double x, double y)
Definition: g3dmath.h:731
Vector3::Axis splitAxis
Definition: KDTree.h:337
bool intersects(const Ray &ray, float distance) const
Definition: KDTree.h:588
void intersectRay(const Ray &ray, RayCallback &intersectCallback, float &distance, bool intersectCallbackIsFast) const
Definition: KDTree.h:603
float splitLocation
Definition: KDTree.h:340
static bool collisionLocationForMovingPointFixedAABox(const Vector3 &point, const Vector3 &velocity, const class AABox &box, Vector3 &outLocation, bool &inside=ignoreBool, Vector3 &normal=ignore)
Definition: CollisionDetection.cpp:1226
double square(double fValue)
Definition: g3dmath.h:698
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
bool G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::intersects ( const Ray ray,
float  distance 
) const
inline

Returns true if the ray intersects this node

588  {
589  // See if the ray will ever hit this node or its children
590  Vector3 location;
591  bool alreadyInsideBounds = false;
592  bool rayWillHitBounds =
594  ray.origin(), ray.direction(), splitBounds, location, alreadyInsideBounds);
595 
596  bool canHitThisNode = (alreadyInsideBounds ||
597  (rayWillHitBounds && ((location - ray.origin()).squaredLength() < square(distance))));
598 
599  return canHitThisNode;
600  }
double distance(double x, double y)
Definition: g3dmath.h:731
static bool collisionLocationForMovingPointFixedAABox(const Vector3 &point, const Vector3 &velocity, const class AABox &box, Vector3 &outLocation, bool &inside=ignoreBool, Vector3 &normal=ignore)
Definition: CollisionDetection.cpp:1226
double square(double fValue)
Definition: g3dmath.h:698
AABox splitBounds
Definition: KDTree.h:335

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
bool G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::isLeaf ( ) const
inline

Returns true if this node is a leaf (no children)

416  {
417  return (child[0] == NULL) && (child[1] == NULL);
418  }
Node * child[2]
Definition: KDTree.h:351
arena_t NULL
Definition: jemalloc_internal.h:624
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
static void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::serializeStructure ( const Node n,
BinaryOutput bo 
)
inlinestatic

Stores the locations of the splitting planes (the structure but not the content) so that the tree can be quickly rebuilt from a previous configuration without calling balance.

480  {
481  if (n == NULL) {
482  bo.writeUInt8(0);
483  } else {
484  bo.writeUInt8(1);
485  n->splitBounds.serialize(bo);
486  serialize(n->splitAxis, bo);
487  bo.writeFloat32(n->splitLocation);
488  for (int c = 0; c < 2; ++c) {
489  serializeStructure(n->child[c], bo);
490  }
491  }
492  }
arena_t NULL
Definition: jemalloc_internal.h:624
void serialize(const std::string &s, BinaryOutput &b)
Definition: serialize.h:12
static void serializeStructure(const Node *n, BinaryOutput &bo)
Definition: KDTree.h:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
void G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::verifyNode ( const Vector3 lo,
const Vector3 hi 
)
inline
434  {
435  // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
436  // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
437 
438  debugAssertM(lo == splitBounds.low(),
439  format("lo = %s, splitBounds.lo = %s",
440  lo.toString().c_str(), splitBounds.low().toString().c_str()));
441  debugAssert(hi == splitBounds.high());
442 
443  for (int i = 0; i < valueArray.length(); ++i) {
444  const AABox& b = valueArray[i]->bounds;
445  debugAssert(b == boundsArray[i]);
446  (void)b;
447 
448  for(int axis = 0; axis < 3; ++axis) {
449  debugAssert(b.low()[axis] <= b.high()[axis]);
450  debugAssert(b.low()[axis] >= lo[axis]);
451  debugAssert(b.high()[axis] <= hi[axis]);
452  }
453  }
454 
455  if (child[0] || child[1]) {
458  }
459 
460  Vector3 newLo = lo;
461  newLo[splitAxis] = splitLocation;
462  Vector3 newHi = hi;
463  newHi[splitAxis] = splitLocation;
464 
465  if (child[0] != NULL) {
466  child[0]->verifyNode(lo, newHi);
467  }
468 
469  if (child[1] != NULL) {
470  child[1]->verifyNode(newLo, hi);
471  }
472  }
Array< Handle * > valueArray
Definition: KDTree.h:361
Node * child[2]
Definition: KDTree.h:351
arena_t NULL
Definition: jemalloc_internal.h:624
const Point3 & low() const
Definition: AABox.h:136
Array< AABox > boundsArray
Definition: KDTree.h:369
void verifyNode(const Vector3 &lo, const Vector3 &hi)
Definition: KDTree.h:434
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
Vector3::Axis splitAxis
Definition: KDTree.h:337
float splitLocation
Definition: KDTree.h:340
#define debugAssert(exp)
Definition: debugAssert.h:160
std::string __cdecl format(const char *fmt...) G3D_CHECK_PRINTF_ARGS
AABox splitBounds
Definition: KDTree.h:335
const Point3 & high() const
Definition: AABox.h:141
std::string toString() const
Definition: Vector3.cpp:386

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Member Data Documentation

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Array<AABox> G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::boundsArray

For each object in the value array, a copy of its bounds. Packing these into an array at the node level instead putting them in the valueArray improves cache coherence, which is about a 3x performance increase when performing intersection computations.

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Node* G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::child[2]

child[0] contains all values strictly smaller than splitLocation along splitAxis.

child[1] contains all values strictly larger.

Both may be NULL if there are not enough values to bother recursing.

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Vector3::Axis G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::splitAxis
template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
AABox G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::splitBounds

Spatial bounds on all values at this node and its children, based purely on the parent's splitting planes. May be infinite.

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
float G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::splitLocation

Location along the specified axis

template<class T , class BoundsFunc = BoundsTrait<T>, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T>>
Array<Handle*> G3D::KDTree< T, BoundsFunc, HashFunc, EqualsFunc >::Node::valueArray

Array of values at this node (i.e., values straddling the split plane + all values if this is a leaf node).

This is an array of pointers because that minimizes data movement during tree building, which accounts for about 15% of the time cost of tree building.


The documentation for this class was generated from the following file: