/*************************************************************************** OctTree.cpp - description ------------------- begin : Sun Mar 19 2000 copyright : (C) 2000 by Henrik Enqvist email : henqvist@excite.com ***************************************************************************/ #include #include "Private.h" #include "OctTree.h" #include "Group.h" #include "CollisionBounds.h" /* QuadTrees ignore Y axis */ OctTree::OctTree(int depth, float size, float x, float y, float z) { // m_fR = (float)(rand())/RAND_MAX; // m_fG = (float)(rand())/RAND_MAX; // m_fB = (float)(rand())/RAND_MAX; EmAssert(depth > 0, "Depth must be larger than 0"); EM_COUT("OctTree() size"<< size <<" pos "<< x <<" "<< y <<" "<< z << endl, 0); m_vtx.x = x; m_vtx.y = y; m_vtx.z = z; m_fSize = size; if (depth > 1) { #if EM_USE_QUADTREE m_vOctTree.reserve(4); #else m_vOctTree.reserve(8); #endif } this->split(depth-1); } OctTree::~OctTree() { } void OctTree::split(int depth) { if (depth < 1) return; EM_COUT("OctTree::split() "<< depth << endl, 0); // TODO: Speed things up by allocating all octtrees as an array // at the top octtree instead of allocating them one by one for (int a=-1; a<2; a+=2) { for (int b=-1; b<2; b+=2) { #if EM_USE_QUADTREE OctTree* ot = new OctTree(depth, m_fSize*0.5, m_vtx.x + a*m_fSize*0.5, 0, m_vtx.z + b*m_fSize*0.5); m_vOctTree.push_back(ot); #else for (int c=-1; c<2; c+=2) { OctTree* ot = new OctTree(depth, m_fSize*0.5, m_vtx.x + a*m_fSize*0.5, m_vtx.y + b*m_fSize*0.5, m_vtx.z + c*m_fSize*0.5); m_vOctTree.push_back(ot); } #endif } } } void OctTree::clear() { m_vGroup.clear(); vector::iterator iter = m_vOctTree.begin(); vector::iterator end = m_vOctTree.end(); for (; iter != end; iter++) { (*iter)->clear(); } } bool OctTree::insertGroup(Group * g) { EmAssert(g != NULL, "OctTree::insertGroup() group NULL"); EmAssert(g->p_CollisionBounds, "OctTree::insertGroup() collisionbounds NULL"); if (this->surround(g->p_CollisionBounds)) { // try to add the group to a child, exit if it was added vector::iterator iter = m_vOctTree.begin(); vector::iterator end = m_vOctTree.end(); for ( ; iter != end; iter++) { if ((*iter)->insertGroup(g)) { return true; } } // none of the children surrounded the group, insert it here m_vGroup.push_back(g); EM_COUT("OctTree() size " << m_vGroup.size(), 0); return true; } return false; } bool OctTree::surround(CollisionBounds * cb) { EmAssert(cb != NULL, "OctTree::surround() collisionbounds NULL"); // observe factor , loose octtrees if over 1. #define FACTOR 1.5f #if EM_USE_QUADTREE if ((cb->m_vtxTrans.x + cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) && (cb->m_vtxTrans.x - cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) && (cb->m_vtxTrans.z + cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) && (cb->m_vtxTrans.z - cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) { return true; } #else if ((cb->m_vtxTrans.x + cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) && (cb->m_vtxTrans.x - cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) && (cb->m_vtxTrans.y + cb->m_fRadius) < (m_vtx.y + m_fSize*FACTOR) && (cb->m_vtxTrans.y - cb->m_fRadius) > (m_vtx.y - m_fSize*FACTOR) && (cb->m_vtxTrans.z + cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) && (cb->m_vtxTrans.z - cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) { return true; } #endif return false; } bool OctTree::collide(CollisionBounds * cb) { EmAssert(cb != NULL, "OctTree::surround() collisionbounds NULL"); // observe factor , loose octtrees if over 1. #if EM_USE_QUADTREE if ((cb->m_vtxTrans.x - cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) && (cb->m_vtxTrans.x + cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) && (cb->m_vtxTrans.z - cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) && (cb->m_vtxTrans.z + cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) { return true; } #else if ((cb->m_vtxTrans.x - cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) && (cb->m_vtxTrans.x + cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) && (cb->m_vtxTrans.y - cb->m_fRadius) < (m_vtx.y + m_fSize*FACTOR) && (cb->m_vtxTrans.y + cb->m_fRadius) > (m_vtx.y - m_fSize*FACTOR) && (cb->m_vtxTrans.z - cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) && (cb->m_vtxTrans.z + cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) { return true; } #endif #undef FACTOR return false; } void OctTree::printTree(int depth) { for (int a=0; a::iterator iter = m_vOctTree.begin(); vector::iterator end = m_vOctTree.end(); for (; iter != end; iter++) { (*iter)->printTree(depth+1); } }