void Octree::Query_Frustum(std::vector<OctreeOccupant*> &result, const Frustum &frustum) const { // Query outside root elements - add them if they are visible for(std::unordered_set<OctreeOccupant*>::iterator it = m_outsideRoot.begin(); it != m_outsideRoot.end(); it++) { OctreeOccupant* pOc = *it; if(!frustum.Test_AABB_Outside(pOc->m_aabb)) { // Visible, add to list result.push_back(pOc); } } std::list<OctreeNode*> open; open.push_back(m_pRootNode.get()); while(!open.empty()) { // Depth-first (results in less memory usage), remove objects from open list OctreeNode* pCurrent = open.back(); open.pop_back(); switch(frustum.Test_AABB(pCurrent->m_region)) { case Frustum::inside: // Add all of this nodes occupants and those below, since all must be visibile pCurrent->GetAllOccupantsBelow(result); break; case Frustum::intersect: // Add occupants if they are visible for(std::unordered_set<OctreeOccupant*>::iterator it = pCurrent->m_pOccupants.begin(); it != pCurrent->m_pOccupants.end(); it++) { OctreeOccupant* pOc = *it; if(!frustum.Test_AABB_Outside(pOc->m_aabb)) { // Visible, add to list result.push_back(pOc); } } // Add children to open list if(pCurrent->m_hasChildren) { for(int x = 0; x < 2; x++) for(int y = 0; y < 2; y++) for(int z = 0; z < 2; z++) { if((*pCurrent->m_children)[x][y][z].GetNumOccupantsBelow() != 0) open.push_back(&(*pCurrent->m_children)[x][y][z]); } } break; // Outside case is ignored } } }