| 1 | /* | 
|---|
| 2 | ----------------------------------------------------------------------------- | 
|---|
| 3 | This source file is part of OGRE | 
|---|
| 4 |     (Object-oriented Graphics Rendering Engine) | 
|---|
| 5 | For the latest info, see http://www.ogre3d.org/ | 
|---|
| 6 |  | 
|---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd | 
|---|
| 8 | Also see acknowledgements in Readme.html | 
|---|
| 9 |  | 
|---|
| 10 | This program is free software; you can redistribute it and/or modify it under | 
|---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software | 
|---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later | 
|---|
| 13 | version. | 
|---|
| 14 |  | 
|---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | 
|---|
| 18 |  | 
|---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with | 
|---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 
|---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to | 
|---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. | 
|---|
| 23 |  | 
|---|
| 24 | You may alternatively use this source under the terms of a specific version of | 
|---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from | 
|---|
| 26 | Torus Knot Software Ltd. | 
|---|
| 27 | ----------------------------------------------------------------------------- | 
|---|
| 28 | */ | 
|---|
| 29 | #include "OgreStableHeaders.h" | 
|---|
| 30 | #include "OgreSceneQuery.h" | 
|---|
| 31 | #include "OgreException.h" | 
|---|
| 32 | #include "OgreSceneManager.h" | 
|---|
| 33 |  | 
|---|
| 34 | namespace Ogre { | 
|---|
| 35 |  | 
|---|
| 36 |     //----------------------------------------------------------------------- | 
|---|
| 37 |     SceneQuery::SceneQuery(SceneManager* mgr) | 
|---|
| 38 |         : mParentSceneMgr(mgr), mQueryMask(0xFFFFFFFF),  | 
|---|
| 39 |                 mWorldFragmentType(SceneQuery::WFT_NONE) | 
|---|
| 40 |     { | 
|---|
| 41 |                 // default type mask to everything except lights & fx (previous behaviour) | 
|---|
| 42 |                 mQueryTypeMask = (0xFFFFFFFF & ~SceneManager::FX_TYPE_MASK)  | 
|---|
| 43 |                         & ~SceneManager::LIGHT_TYPE_MASK; | 
|---|
| 44 |  | 
|---|
| 45 |     } | 
|---|
| 46 |     //----------------------------------------------------------------------- | 
|---|
| 47 |     SceneQuery::~SceneQuery() | 
|---|
| 48 |     { | 
|---|
| 49 |     } | 
|---|
| 50 |     //----------------------------------------------------------------------- | 
|---|
| 51 |     void SceneQuery::setQueryMask(uint32 mask) | 
|---|
| 52 |     { | 
|---|
| 53 |         mQueryMask = mask; | 
|---|
| 54 |     } | 
|---|
| 55 |     //----------------------------------------------------------------------- | 
|---|
| 56 |     uint32 SceneQuery::getQueryMask(void) const | 
|---|
| 57 |     { | 
|---|
| 58 |         return mQueryMask; | 
|---|
| 59 |     } | 
|---|
| 60 |         //----------------------------------------------------------------------- | 
|---|
| 61 |         void SceneQuery::setQueryTypeMask(uint32 mask) | 
|---|
| 62 |         { | 
|---|
| 63 |                 mQueryTypeMask = mask; | 
|---|
| 64 |         } | 
|---|
| 65 |         //----------------------------------------------------------------------- | 
|---|
| 66 |         uint32 SceneQuery::getQueryTypeMask(void) const | 
|---|
| 67 |         { | 
|---|
| 68 |                 return mQueryTypeMask; | 
|---|
| 69 |         } | 
|---|
| 70 |     //----------------------------------------------------------------------- | 
|---|
| 71 |     void SceneQuery::setWorldFragmentType(enum SceneQuery::WorldFragmentType wft) | 
|---|
| 72 |     { | 
|---|
| 73 |         // Check supported | 
|---|
| 74 |         if (mSupportedWorldFragments.find(wft) == mSupportedWorldFragments.end()) | 
|---|
| 75 |         { | 
|---|
| 76 |             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "This world fragment type is not supported.", | 
|---|
| 77 |                 "SceneQuery::setWorldFragmentType"); | 
|---|
| 78 |         } | 
|---|
| 79 |         mWorldFragmentType = wft; | 
|---|
| 80 |     } | 
|---|
| 81 |     //----------------------------------------------------------------------- | 
|---|
| 82 |     SceneQuery::WorldFragmentType  | 
|---|
| 83 |     SceneQuery::getWorldFragmentType(void) const | 
|---|
| 84 |     { | 
|---|
| 85 |         return mWorldFragmentType; | 
|---|
| 86 |     } | 
|---|
| 87 |     //----------------------------------------------------------------------- | 
|---|
| 88 |     RegionSceneQuery::RegionSceneQuery(SceneManager* mgr) | 
|---|
| 89 |         :SceneQuery(mgr), mLastResult(NULL) | 
|---|
| 90 |     { | 
|---|
| 91 |     } | 
|---|
| 92 |     //----------------------------------------------------------------------- | 
|---|
| 93 |     RegionSceneQuery::~RegionSceneQuery() | 
|---|
| 94 |     { | 
|---|
| 95 |         clearResults(); | 
|---|
| 96 |     } | 
|---|
| 97 |     //----------------------------------------------------------------------- | 
|---|
| 98 |     SceneQueryResult& RegionSceneQuery::getLastResults(void) const | 
|---|
| 99 |     { | 
|---|
| 100 |         assert(mLastResult); | 
|---|
| 101 |         return *mLastResult; | 
|---|
| 102 |     } | 
|---|
| 103 |     //----------------------------------------------------------------------- | 
|---|
| 104 |     void RegionSceneQuery::clearResults(void) | 
|---|
| 105 |     { | 
|---|
| 106 |         if (mLastResult) | 
|---|
| 107 |         { | 
|---|
| 108 |             delete mLastResult; | 
|---|
| 109 |         } | 
|---|
| 110 |         mLastResult = NULL; | 
|---|
| 111 |     } | 
|---|
| 112 |         //--------------------------------------------------------------------- | 
|---|
| 113 |     SceneQueryResult& | 
|---|
| 114 |     RegionSceneQuery::execute(void) | 
|---|
| 115 |     { | 
|---|
| 116 |         clearResults(); | 
|---|
| 117 |         mLastResult = new SceneQueryResult(); | 
|---|
| 118 |         // Call callback version with self as listener | 
|---|
| 119 |         execute(this); | 
|---|
| 120 |         return *mLastResult; | 
|---|
| 121 |     } | 
|---|
| 122 |         //--------------------------------------------------------------------- | 
|---|
| 123 |     bool RegionSceneQuery:: | 
|---|
| 124 |         queryResult(MovableObject* obj) | 
|---|
| 125 |     { | 
|---|
| 126 |         // Add to internal list | 
|---|
| 127 |         mLastResult->movables.push_back(obj); | 
|---|
| 128 |         // Continue | 
|---|
| 129 |         return true; | 
|---|
| 130 |     } | 
|---|
| 131 |         //--------------------------------------------------------------------- | 
|---|
| 132 |     bool RegionSceneQuery::queryResult(SceneQuery::WorldFragment* fragment) | 
|---|
| 133 |     { | 
|---|
| 134 |         // Add to internal list | 
|---|
| 135 |         mLastResult->worldFragments.push_back(fragment); | 
|---|
| 136 |         // Continue | 
|---|
| 137 |         return true; | 
|---|
| 138 |     } | 
|---|
| 139 |     //----------------------------------------------------------------------- | 
|---|
| 140 |     AxisAlignedBoxSceneQuery::AxisAlignedBoxSceneQuery(SceneManager* mgr) | 
|---|
| 141 |         : RegionSceneQuery(mgr) | 
|---|
| 142 |     { | 
|---|
| 143 |     } | 
|---|
| 144 |     //----------------------------------------------------------------------- | 
|---|
| 145 |     AxisAlignedBoxSceneQuery::~AxisAlignedBoxSceneQuery() | 
|---|
| 146 |     { | 
|---|
| 147 |     } | 
|---|
| 148 |     //----------------------------------------------------------------------- | 
|---|
| 149 |     void AxisAlignedBoxSceneQuery::setBox(const AxisAlignedBox& box) | 
|---|
| 150 |     { | 
|---|
| 151 |         mAABB = box; | 
|---|
| 152 |     } | 
|---|
| 153 |     //----------------------------------------------------------------------- | 
|---|
| 154 |     const AxisAlignedBox& AxisAlignedBoxSceneQuery::getBox(void) const | 
|---|
| 155 |     { | 
|---|
| 156 |         return mAABB; | 
|---|
| 157 |     } | 
|---|
| 158 |     //----------------------------------------------------------------------- | 
|---|
| 159 |     SphereSceneQuery::SphereSceneQuery(SceneManager* mgr) | 
|---|
| 160 |         : RegionSceneQuery(mgr) | 
|---|
| 161 |     { | 
|---|
| 162 |     } | 
|---|
| 163 |     //----------------------------------------------------------------------- | 
|---|
| 164 |     SphereSceneQuery::~SphereSceneQuery() | 
|---|
| 165 |     { | 
|---|
| 166 |     } | 
|---|
| 167 |     //----------------------------------------------------------------------- | 
|---|
| 168 |     void SphereSceneQuery::setSphere(const Sphere& sphere) | 
|---|
| 169 |     { | 
|---|
| 170 |         mSphere = sphere; | 
|---|
| 171 |     } | 
|---|
| 172 |     //----------------------------------------------------------------------- | 
|---|
| 173 |     const Sphere& SphereSceneQuery::getSphere() const | 
|---|
| 174 |     { | 
|---|
| 175 |         return mSphere; | 
|---|
| 176 |     } | 
|---|
| 177 |  | 
|---|
| 178 |     //----------------------------------------------------------------------- | 
|---|
| 179 |     PlaneBoundedVolumeListSceneQuery::PlaneBoundedVolumeListSceneQuery(SceneManager* mgr) | 
|---|
| 180 |         : RegionSceneQuery(mgr) | 
|---|
| 181 |     { | 
|---|
| 182 |     } | 
|---|
| 183 |     //----------------------------------------------------------------------- | 
|---|
| 184 |     PlaneBoundedVolumeListSceneQuery::~PlaneBoundedVolumeListSceneQuery() | 
|---|
| 185 |     { | 
|---|
| 186 |     } | 
|---|
| 187 |     //----------------------------------------------------------------------- | 
|---|
| 188 |     void PlaneBoundedVolumeListSceneQuery::setVolumes(const PlaneBoundedVolumeList& volumes) | 
|---|
| 189 |     { | 
|---|
| 190 |         mVolumes = volumes; | 
|---|
| 191 |     } | 
|---|
| 192 |     //----------------------------------------------------------------------- | 
|---|
| 193 |     const PlaneBoundedVolumeList& PlaneBoundedVolumeListSceneQuery::getVolumes() const | 
|---|
| 194 |     { | 
|---|
| 195 |         return mVolumes; | 
|---|
| 196 |     } | 
|---|
| 197 |  | 
|---|
| 198 |     //----------------------------------------------------------------------- | 
|---|
| 199 |     RaySceneQuery::RaySceneQuery(SceneManager* mgr) : SceneQuery(mgr) | 
|---|
| 200 |     { | 
|---|
| 201 |         mSortByDistance = false; | 
|---|
| 202 |         mMaxResults = 0; | 
|---|
| 203 |     } | 
|---|
| 204 |     //----------------------------------------------------------------------- | 
|---|
| 205 |     RaySceneQuery::~RaySceneQuery() | 
|---|
| 206 |     { | 
|---|
| 207 |     } | 
|---|
| 208 |     //----------------------------------------------------------------------- | 
|---|
| 209 |     void RaySceneQuery::setRay(const Ray& ray) | 
|---|
| 210 |     { | 
|---|
| 211 |         mRay = ray; | 
|---|
| 212 |     } | 
|---|
| 213 |     //----------------------------------------------------------------------- | 
|---|
| 214 |     const Ray& RaySceneQuery::getRay(void) const | 
|---|
| 215 |     { | 
|---|
| 216 |         return mRay; | 
|---|
| 217 |     } | 
|---|
| 218 |     //----------------------------------------------------------------------- | 
|---|
| 219 |     void RaySceneQuery::setSortByDistance(bool sort, ushort maxresults) | 
|---|
| 220 |     { | 
|---|
| 221 |         mSortByDistance = sort; | 
|---|
| 222 |         mMaxResults = maxresults; | 
|---|
| 223 |     } | 
|---|
| 224 |     //----------------------------------------------------------------------- | 
|---|
| 225 |     bool RaySceneQuery::getSortByDistance(void) const | 
|---|
| 226 |     { | 
|---|
| 227 |         return mSortByDistance; | 
|---|
| 228 |     } | 
|---|
| 229 |     //----------------------------------------------------------------------- | 
|---|
| 230 |     ushort RaySceneQuery::getMaxResults(void) const | 
|---|
| 231 |     { | 
|---|
| 232 |         return mMaxResults; | 
|---|
| 233 |     } | 
|---|
| 234 |     //----------------------------------------------------------------------- | 
|---|
| 235 |     RaySceneQueryResult& RaySceneQuery::execute(void) | 
|---|
| 236 |     { | 
|---|
| 237 |         // Clear without freeing the vector buffer | 
|---|
| 238 |         mResult.clear(); | 
|---|
| 239 |          | 
|---|
| 240 |         // Call callback version with self as listener | 
|---|
| 241 |         this->execute(this); | 
|---|
| 242 |  | 
|---|
| 243 |         if (mSortByDistance) | 
|---|
| 244 |         { | 
|---|
| 245 |             if (mMaxResults != 0 && mMaxResults < mResult.size()) | 
|---|
| 246 |             { | 
|---|
| 247 |                 // Partially sort the N smallest elements, discard others | 
|---|
| 248 |                 std::partial_sort(mResult.begin(), mResult.begin()+mMaxResults, mResult.end()); | 
|---|
| 249 |                 mResult.resize(mMaxResults); | 
|---|
| 250 |             } | 
|---|
| 251 |             else | 
|---|
| 252 |             { | 
|---|
| 253 |                 // Sort entire result array | 
|---|
| 254 |                 std::sort(mResult.begin(), mResult.end()); | 
|---|
| 255 |             } | 
|---|
| 256 |         } | 
|---|
| 257 |  | 
|---|
| 258 |         return mResult; | 
|---|
| 259 |     } | 
|---|
| 260 |     //----------------------------------------------------------------------- | 
|---|
| 261 |     RaySceneQueryResult& RaySceneQuery::getLastResults(void) | 
|---|
| 262 |     { | 
|---|
| 263 |         return mResult; | 
|---|
| 264 |     } | 
|---|
| 265 |     //----------------------------------------------------------------------- | 
|---|
| 266 |     void RaySceneQuery::clearResults(void) | 
|---|
| 267 |     { | 
|---|
| 268 |         // C++ idiom to free vector buffer: swap with empty vector | 
|---|
| 269 |         RaySceneQueryResult().swap(mResult); | 
|---|
| 270 |     } | 
|---|
| 271 |     //----------------------------------------------------------------------- | 
|---|
| 272 |     bool RaySceneQuery::queryResult(MovableObject* obj, Real distance) | 
|---|
| 273 |     { | 
|---|
| 274 |         // Add to internal list | 
|---|
| 275 |         RaySceneQueryResultEntry dets; | 
|---|
| 276 |         dets.distance = distance; | 
|---|
| 277 |         dets.movable = obj; | 
|---|
| 278 |         dets.worldFragment = NULL; | 
|---|
| 279 |         mResult.push_back(dets); | 
|---|
| 280 |         // Continue | 
|---|
| 281 |         return true; | 
|---|
| 282 |     } | 
|---|
| 283 |     //----------------------------------------------------------------------- | 
|---|
| 284 |     bool RaySceneQuery::queryResult(SceneQuery::WorldFragment* fragment, Real distance) | 
|---|
| 285 |     { | 
|---|
| 286 |         // Add to internal list | 
|---|
| 287 |         RaySceneQueryResultEntry dets; | 
|---|
| 288 |         dets.distance = distance; | 
|---|
| 289 |         dets.movable = NULL; | 
|---|
| 290 |         dets.worldFragment = fragment; | 
|---|
| 291 |         mResult.push_back(dets); | 
|---|
| 292 |         // Continue | 
|---|
| 293 |         return true; | 
|---|
| 294 |     } | 
|---|
| 295 |     //----------------------------------------------------------------------- | 
|---|
| 296 |     /* | 
|---|
| 297 |     PyramidSceneQuery::PyramidSceneQuery(SceneManager* mgr) : RegionSceneQuery(mgr) | 
|---|
| 298 |     { | 
|---|
| 299 |     } | 
|---|
| 300 |     //----------------------------------------------------------------------- | 
|---|
| 301 |     PyramidSceneQuery::~PyramidSceneQuery() | 
|---|
| 302 |     { | 
|---|
| 303 |     } | 
|---|
| 304 |     */ | 
|---|
| 305 |     //----------------------------------------------------------------------- | 
|---|
| 306 |     IntersectionSceneQuery::IntersectionSceneQuery(SceneManager* mgr) | 
|---|
| 307 |     : SceneQuery(mgr), mLastResult(NULL) | 
|---|
| 308 |     { | 
|---|
| 309 |     } | 
|---|
| 310 |     //----------------------------------------------------------------------- | 
|---|
| 311 |     IntersectionSceneQuery::~IntersectionSceneQuery() | 
|---|
| 312 |     { | 
|---|
| 313 |         clearResults(); | 
|---|
| 314 |     } | 
|---|
| 315 |     //----------------------------------------------------------------------- | 
|---|
| 316 |     IntersectionSceneQueryResult& IntersectionSceneQuery::getLastResults(void) const | 
|---|
| 317 |     { | 
|---|
| 318 |         assert(mLastResult); | 
|---|
| 319 |         return *mLastResult; | 
|---|
| 320 |     } | 
|---|
| 321 |     //----------------------------------------------------------------------- | 
|---|
| 322 |     void IntersectionSceneQuery::clearResults(void) | 
|---|
| 323 |     { | 
|---|
| 324 |         if (mLastResult) | 
|---|
| 325 |         { | 
|---|
| 326 |             delete mLastResult; | 
|---|
| 327 |         } | 
|---|
| 328 |         mLastResult = NULL; | 
|---|
| 329 |     } | 
|---|
| 330 |         //--------------------------------------------------------------------- | 
|---|
| 331 |     IntersectionSceneQueryResult& | 
|---|
| 332 |     IntersectionSceneQuery::execute(void) | 
|---|
| 333 |     { | 
|---|
| 334 |         clearResults(); | 
|---|
| 335 |         mLastResult = new IntersectionSceneQueryResult(); | 
|---|
| 336 |         // Call callback version with self as listener | 
|---|
| 337 |         execute(this); | 
|---|
| 338 |         return *mLastResult; | 
|---|
| 339 |     } | 
|---|
| 340 |         //--------------------------------------------------------------------- | 
|---|
| 341 |     bool IntersectionSceneQuery:: | 
|---|
| 342 |         queryResult(MovableObject* first, MovableObject* second) | 
|---|
| 343 |     { | 
|---|
| 344 |         // Add to internal list | 
|---|
| 345 |         mLastResult->movables2movables.push_back( | 
|---|
| 346 |             SceneQueryMovableObjectPair(first, second) | 
|---|
| 347 |             ); | 
|---|
| 348 |         // Continue | 
|---|
| 349 |         return true; | 
|---|
| 350 |     } | 
|---|
| 351 |         //--------------------------------------------------------------------- | 
|---|
| 352 |     bool IntersectionSceneQuery:: | 
|---|
| 353 |         queryResult(MovableObject* movable, SceneQuery::WorldFragment* fragment) | 
|---|
| 354 |     { | 
|---|
| 355 |         // Add to internal list | 
|---|
| 356 |         mLastResult->movables2world.push_back( | 
|---|
| 357 |             SceneQueryMovableObjectWorldFragmentPair(movable, fragment) | 
|---|
| 358 |             ); | 
|---|
| 359 |         // Continue | 
|---|
| 360 |         return true; | 
|---|
| 361 |     } | 
|---|
| 362 |  | 
|---|
| 363 |  | 
|---|
| 364 |  | 
|---|
| 365 |  | 
|---|
| 366 | } | 
|---|
| 367 |      | 
|---|
| 368 |  | 
|---|
| 369 |  | 
|---|
| 370 |  | 
|---|