/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright 2000-2005 The OGRE Team Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. You may alternatively use this source under the terms of a specific version of the OGRE Unrestricted License provided you have obtained such a license from Torus Knot Software Ltd. ----------------------------------------------------------------------------- */ /*************************************************************************** OgreOctreeSceneQuery.cpp - description ------------------- begin : Tues July 20, 2004 copyright : (C) 2004by Jon Anderson email : janders@users.sf.net ***************************************************************************/ #include #include #include #include namespace Ogre { //--------------------------------------------------------------------- OctreeIntersectionSceneQuery::OctreeIntersectionSceneQuery(SceneManager* creator) : DefaultIntersectionSceneQuery(creator) { } //--------------------------------------------------------------------- OctreeIntersectionSceneQuery::~OctreeIntersectionSceneQuery() {} //--------------------------------------------------------------------- void OctreeIntersectionSceneQuery::execute(IntersectionSceneQueryListener* listener) { typedef std::pair MovablePair; typedef std::set < std::pair > MovableSet; MovableSet set; // Iterate over all movable types Root::MovableObjectFactoryIterator factIt = Root::getSingleton().getMovableObjectFactoryIterator(); while(factIt.hasMoreElements()) { SceneManager::MovableObjectIterator it = mParentSceneMgr->getMovableObjectIterator( factIt.getNext()->getType()); while( it.hasMoreElements() ) { MovableObject * e = it.getNext(); std::list < SceneNode * > list; //find the nodes that intersect the AAB static_cast( mParentSceneMgr ) -> findNodesIn( e->getWorldBoundingBox(), list, 0 ); //grab all moveables from the node that intersect... std::list < SceneNode * >::iterator nit = list.begin(); while( nit != list.end() ) { SceneNode::ObjectIterator oit = (*nit) -> getAttachedObjectIterator(); while( oit.hasMoreElements() ) { MovableObject * m = oit.getNext(); if( m != e && set.find( MovablePair(e,m)) == set.end() && set.find( MovablePair(m,e)) == set.end() && (m->getQueryFlags() & mQueryMask) && (m->getTypeFlags() & mQueryTypeMask) && m->isInScene() && e->getWorldBoundingBox().intersects( m->getWorldBoundingBox() ) ) { listener -> queryResult( e, m ); // deal with attached objects, since they are not directly attached to nodes if (m->getMovableType() == "Entity") { Entity* e2 = static_cast(m); Entity::ChildObjectListIterator childIt = e2->getAttachedObjectIterator(); while(childIt.hasMoreElements()) { MovableObject* c = childIt.getNext(); if (c->getQueryFlags() & mQueryMask && e->getWorldBoundingBox().intersects( c->getWorldBoundingBox() )) { listener->queryResult(e, c); } } } } set.insert( MovablePair(e,m) ); } ++nit; } } } } /** Creates a custom Octree AAB query */ OctreeAxisAlignedBoxSceneQuery::OctreeAxisAlignedBoxSceneQuery(SceneManager* creator) : DefaultAxisAlignedBoxSceneQuery(creator) { } /** Deletes the custom Octree query */ OctreeAxisAlignedBoxSceneQuery::~OctreeAxisAlignedBoxSceneQuery() {} /** Finds any entities that intersect the AAB for the query. */ void OctreeAxisAlignedBoxSceneQuery::execute(SceneQueryListener* listener) { std::list < SceneNode * > list; //find the nodes that intersect the AAB static_cast( mParentSceneMgr ) -> findNodesIn( mAABB, list, 0 ); //grab all moveables from the node that intersect... std::list < SceneNode * >::iterator it = list.begin(); while( it != list.end() ) { SceneNode::ObjectIterator oit = (*it) -> getAttachedObjectIterator(); while( oit.hasMoreElements() ) { MovableObject * m = oit.getNext(); if( (m->getQueryFlags() & mQueryMask) && (m->getTypeFlags() & mQueryTypeMask) && m->isInScene() && mAABB.intersects( m->getWorldBoundingBox() ) ) { listener -> queryResult( m ); // deal with attached objects, since they are not directly attached to nodes if (m->getMovableType() == "Entity") { Entity* e = static_cast(m); Entity::ChildObjectListIterator childIt = e->getAttachedObjectIterator(); while(childIt.hasMoreElements()) { MovableObject* c = childIt.getNext(); if (c->getQueryFlags() & mQueryMask) { listener->queryResult(c); } } } } } ++it; } } //--------------------------------------------------------------------- OctreeRaySceneQuery:: OctreeRaySceneQuery(SceneManager* creator) : DefaultRaySceneQuery(creator) { } //--------------------------------------------------------------------- OctreeRaySceneQuery::~OctreeRaySceneQuery() {} //--------------------------------------------------------------------- void OctreeRaySceneQuery::execute(RaySceneQueryListener* listener) { std::list < SceneNode * > list; //find the nodes that intersect the AAB static_cast( mParentSceneMgr ) -> findNodesIn( mRay, list, 0 ); //grab all moveables from the node that intersect... std::list < SceneNode * >::iterator it = list.begin(); while( it != list.end() ) { SceneNode::ObjectIterator oit = (*it) -> getAttachedObjectIterator(); while( oit.hasMoreElements() ) { MovableObject * m = oit.getNext(); if( (m->getQueryFlags() & mQueryMask) && (m->getTypeFlags() & mQueryTypeMask) && m->isInScene() ) { std::pair result = mRay.intersects(m->getWorldBoundingBox()); if( result.first ) { listener -> queryResult( m, result.second ); // deal with attached objects, since they are not directly attached to nodes if (m->getMovableType() == "Entity") { Entity* e = static_cast(m); Entity::ChildObjectListIterator childIt = e->getAttachedObjectIterator(); while(childIt.hasMoreElements()) { MovableObject* c = childIt.getNext(); if (c->getQueryFlags() & mQueryMask) { result = mRay.intersects(c->getWorldBoundingBox()); if (result.first) { listener->queryResult(c, result.second); } } } } } } } ++it; } } //--------------------------------------------------------------------- OctreeSphereSceneQuery:: OctreeSphereSceneQuery(SceneManager* creator) : DefaultSphereSceneQuery(creator) { } //--------------------------------------------------------------------- OctreeSphereSceneQuery::~OctreeSphereSceneQuery() {} //--------------------------------------------------------------------- void OctreeSphereSceneQuery::execute(SceneQueryListener* listener) { std::list < SceneNode * > list; //find the nodes that intersect the AAB static_cast( mParentSceneMgr ) -> findNodesIn( mSphere, list, 0 ); //grab all moveables from the node that intersect... std::list < SceneNode * >::iterator it = list.begin(); while( it != list.end() ) { SceneNode::ObjectIterator oit = (*it) -> getAttachedObjectIterator(); while( oit.hasMoreElements() ) { MovableObject * m = oit.getNext(); if( (m->getQueryFlags() & mQueryMask) && (m->getTypeFlags() & mQueryTypeMask) && m->isInScene() && mSphere.intersects( m->getWorldBoundingBox() ) ) { listener -> queryResult( m ); // deal with attached objects, since they are not directly attached to nodes if (m->getMovableType() == "Entity") { Entity* e = static_cast(m); Entity::ChildObjectListIterator childIt = e->getAttachedObjectIterator(); while(childIt.hasMoreElements()) { MovableObject* c = childIt.getNext(); if (c->getQueryFlags() & mQueryMask && mSphere.intersects( c->getWorldBoundingBox())) { listener->queryResult(c); } } } } } ++it; } } //--------------------------------------------------------------------- OctreePlaneBoundedVolumeListSceneQuery:: OctreePlaneBoundedVolumeListSceneQuery(SceneManager* creator) : DefaultPlaneBoundedVolumeListSceneQuery(creator) { } //--------------------------------------------------------------------- OctreePlaneBoundedVolumeListSceneQuery::~OctreePlaneBoundedVolumeListSceneQuery() {} //--------------------------------------------------------------------- void OctreePlaneBoundedVolumeListSceneQuery::execute(SceneQueryListener* listener) { std::set checkedSceneNodes; PlaneBoundedVolumeList::iterator pi, piend; piend = mVolumes.end(); for (pi = mVolumes.begin(); pi != piend; ++pi) { std::list < SceneNode * > list; //find the nodes that intersect the AAB static_cast( mParentSceneMgr ) -> findNodesIn( *pi, list, 0 ); //grab all moveables from the node that intersect... std::list < SceneNode * >::iterator it, itend; itend = list.end(); for (it = list.begin(); it != itend; ++it) { // avoid double-check same scene node if (!checkedSceneNodes.insert(*it).second) continue; SceneNode::ObjectIterator oit = (*it) -> getAttachedObjectIterator(); while( oit.hasMoreElements() ) { MovableObject * m = oit.getNext(); if( (m->getQueryFlags() & mQueryMask) && (m->getTypeFlags() & mQueryTypeMask) && m->isInScene() && (*pi).intersects( m->getWorldBoundingBox() ) ) { listener -> queryResult( m ); // deal with attached objects, since they are not directly attached to nodes if (m->getMovableType() == "Entity") { Entity* e = static_cast(m); Entity::ChildObjectListIterator childIt = e->getAttachedObjectIterator(); while(childIt.hasMoreElements()) { MovableObject* c = childIt.getNext(); if (c->getQueryFlags() & mQueryMask && (*pi).intersects( c->getWorldBoundingBox())) { listener->queryResult(c); } } } } } } }//for } }