WorldQuery.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "2d/scene/WorldQuery.h"
  23. #ifndef _SCENE_H_
  24. #include "Scene.h"
  25. #endif
  26. #ifndef _SCENE_OBJECT_H_
  27. #include "2d/sceneobject/SceneObject.h"
  28. #endif
  29. // Debug Profiling.
  30. #include "debug/profiler.h"
  31. //-----------------------------------------------------------------------------
  32. WorldQuery::WorldQuery( Scene* pScene ) :
  33. mpScene(pScene),
  34. mIsRaycastQueryResult(false),
  35. mMasterQueryKey(0),
  36. mCheckFixturePoint(false),
  37. mFixturePoint(0.0f, 0.0f)
  38. {
  39. // Set debug associations.
  40. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
  41. {
  42. VECTOR_SET_ASSOCIATION( mLayeredQueryResults[n] );
  43. }
  44. VECTOR_SET_ASSOCIATION( mQueryResults );
  45. // Clear the query.
  46. clearQuery();
  47. }
  48. //-----------------------------------------------------------------------------
  49. S32 WorldQuery::add( SceneObject* pSceneObject )
  50. {
  51. // Debug Profiling.
  52. PROFILE_SCOPE(WorldQuery_Add);
  53. return CreateProxy( pSceneObject->getAABB(), static_cast<PhysicsProxy*>(pSceneObject) );
  54. }
  55. //-----------------------------------------------------------------------------
  56. void WorldQuery::remove( SceneObject* pSceneObject )
  57. {
  58. // Debug Profiling.
  59. PROFILE_SCOPE(WorldQuery_Remove);
  60. DestroyProxy( pSceneObject->getWorldProxy() );
  61. }
  62. //-----------------------------------------------------------------------------
  63. bool WorldQuery::update( SceneObject* pSceneObject, const b2AABB& aabb, const b2Vec2& displacement )
  64. {
  65. // Debug Profiling.
  66. PROFILE_SCOPE(WorldQuery_Update);
  67. return MoveProxy( pSceneObject->getWorldProxy(), aabb, displacement );
  68. }
  69. //-----------------------------------------------------------------------------
  70. void WorldQuery::addAlwaysInScope( SceneObject* pSceneObject )
  71. {
  72. // Debug Profiling.
  73. PROFILE_SCOPE(WorldQuery_AddAlwaysInScope);
  74. // Sanity!
  75. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  76. {
  77. AssertFatal( (*itr) != pSceneObject, "Object attempted to be in Always-in-Scope more than once." );
  78. }
  79. // Add to always-in-scope.
  80. mAlwaysInScopeSet.push_back( pSceneObject );
  81. // Set always in scope.
  82. pSceneObject->mAlwaysInScope = true;
  83. }
  84. //-----------------------------------------------------------------------------
  85. void WorldQuery::removeAlwaysInScope( SceneObject* pSceneObject )
  86. {
  87. // Debug Profiling.
  88. PROFILE_SCOPE(WorldQuery_RemoveAlwaysInScope);
  89. // Remove from always-in-scope.
  90. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  91. {
  92. // Skip if not object.
  93. if ( (*itr) != pSceneObject )
  94. continue;
  95. mAlwaysInScopeSet.erase_fast( itr );
  96. // Reset always in scope.
  97. pSceneObject->mAlwaysInScope = false;
  98. return;
  99. }
  100. AssertFatal( false, "Object attempted to be removed from Always-in-Scope but wasn't present." );
  101. }
  102. //-----------------------------------------------------------------------------
  103. U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb )
  104. {
  105. // Debug Profiling.
  106. PROFILE_SCOPE(WorldQuery_FixtureQueryArea);
  107. mMasterQueryKey++;
  108. // Flag as not a ray-cast query result.
  109. mIsRaycastQueryResult = false;
  110. // Query.
  111. mpScene->getWorld()->QueryAABB( this, aabb );
  112. // Inject always-in-scope.
  113. injectAlwaysInScope();
  114. return getQueryResultsCount();
  115. }
  116. //-----------------------------------------------------------------------------
  117. U32 WorldQuery::fixtureQueryRay( const Vector2& point1, const Vector2& point2 )
  118. {
  119. // Debug Profiling.
  120. PROFILE_SCOPE(WorldQuery_FixtureQueryRay);
  121. mMasterQueryKey++;
  122. // Flag as a ray-cast query result.
  123. mIsRaycastQueryResult = true;
  124. // Query.
  125. mpScene->getWorld()->RayCast( this, point1, point2 );
  126. // Inject always-in-scope.
  127. injectAlwaysInScope();
  128. return getQueryResultsCount();
  129. }
  130. //-----------------------------------------------------------------------------
  131. U32 WorldQuery::fixtureQueryPoint( const Vector2& point )
  132. {
  133. // Debug Profiling.
  134. PROFILE_SCOPE(WorldQuery_FixtureQueryPoint);
  135. mMasterQueryKey++;
  136. // Flag as not a ray-cast query result.
  137. mIsRaycastQueryResult = false;
  138. // Query.
  139. b2AABB aabb;
  140. aabb.lowerBound = point;
  141. aabb.upperBound = point;
  142. mCheckFixturePoint = true;
  143. mFixturePoint = point;
  144. mpScene->getWorld()->QueryAABB( this, aabb );
  145. mCheckFixturePoint = false;
  146. // Inject always-in-scope.
  147. injectAlwaysInScope();
  148. return getQueryResultsCount();
  149. }
  150. //-----------------------------------------------------------------------------
  151. U32 WorldQuery::renderQueryArea( const b2AABB& aabb )
  152. {
  153. // Debug Profiling.
  154. PROFILE_SCOPE(WorldQuery_RenderQueryArea);
  155. mMasterQueryKey++;
  156. // Flag as not a ray-cast query result.
  157. mIsRaycastQueryResult = false;
  158. // Query.
  159. Query( this, aabb );
  160. // Inject always-in-scope.
  161. injectAlwaysInScope();
  162. return getQueryResultsCount();
  163. }
  164. //-----------------------------------------------------------------------------
  165. U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 )
  166. {
  167. // Debug Profiling.
  168. PROFILE_SCOPE(WorldQuery_RenderQueryRay);
  169. mMasterQueryKey++;
  170. // Flag as a ray-cast query result.
  171. mIsRaycastQueryResult = true;
  172. // Query.
  173. b2RayCastInput rayInput;
  174. rayInput.p1 = point1;
  175. rayInput.p2 = point2;
  176. rayInput.maxFraction = 1.0f;
  177. RayCast( this, rayInput );
  178. // Inject always-in-scope.
  179. injectAlwaysInScope();
  180. return getQueryResultsCount();
  181. }
  182. //-----------------------------------------------------------------------------
  183. U32 WorldQuery::renderQueryPoint( const Vector2& point )
  184. {
  185. // Debug Profiling.
  186. PROFILE_SCOPE(WorldQuery_RenderQueryPoint);
  187. mMasterQueryKey++;
  188. // Flag as not a ray-cast query result.
  189. mIsRaycastQueryResult = false;
  190. // Query.
  191. b2RayCastInput rayInput;
  192. rayInput.p1 = point;
  193. rayInput.p2 = b2Vec2( point.x + b2_linearSlop, point.y + b2_linearSlop );
  194. rayInput.maxFraction = 1.0f;
  195. RayCast( this, rayInput );
  196. // Inject always-in-scope.
  197. injectAlwaysInScope();
  198. return getQueryResultsCount();
  199. }
  200. //-----------------------------------------------------------------------------
  201. U32 WorldQuery::anyQueryArea( const b2AABB& aabb )
  202. {
  203. // Debug Profiling.
  204. PROFILE_SCOPE(WorldQuery_AnyQueryAreaAABB);
  205. // Query.
  206. renderQueryArea( aabb );
  207. mMasterQueryKey--;
  208. fixtureQueryArea( aabb );
  209. // Inject always-in-scope.
  210. injectAlwaysInScope();
  211. return getQueryResultsCount();
  212. }
  213. //-----------------------------------------------------------------------------
  214. U32 WorldQuery::anyQueryArea( const Vector2& lowerBound, const Vector2& upperBound )
  215. {
  216. // Debug Profiling.
  217. PROFILE_SCOPE(WorldQuery_AnyQueryAreaBounds);
  218. // Calculate AABB.
  219. b2AABB aabb;
  220. aabb.lowerBound.Set( getMin( lowerBound.x, upperBound.x ), getMin( lowerBound.x, upperBound.x ) );
  221. aabb.upperBound.Set( getMax( lowerBound.x, upperBound.x ), getMax( lowerBound.x, upperBound.x ) );
  222. // Query.
  223. return anyQueryArea( aabb );
  224. }
  225. //-----------------------------------------------------------------------------
  226. U32 WorldQuery::anyQueryRay( const Vector2& point1, const Vector2& point2 )
  227. {
  228. // Debug Profiling.
  229. PROFILE_SCOPE(WorldQuery_AnyQueryRay);
  230. // Query.
  231. renderQueryRay( point1, point2 );
  232. mMasterQueryKey--;
  233. fixtureQueryRay( point1, point2 );
  234. // Inject always-in-scope.
  235. injectAlwaysInScope();
  236. return getQueryResultsCount();
  237. }
  238. //-----------------------------------------------------------------------------
  239. U32 WorldQuery::anyQueryPoint( const Vector2& point )
  240. {
  241. // Debug Profiling.
  242. PROFILE_SCOPE(WorldQuery_AnyQueryPoint);
  243. // Query.
  244. renderQueryPoint( point );
  245. mMasterQueryKey--;
  246. fixtureQueryPoint( point );
  247. // Inject always-in-scope.
  248. injectAlwaysInScope();
  249. return getQueryResultsCount();
  250. }
  251. //-----------------------------------------------------------------------------
  252. void WorldQuery::clearQuery( void )
  253. {
  254. // Debug Profiling.
  255. PROFILE_SCOPE(WorldQuery_ClearQuery);
  256. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
  257. {
  258. mLayeredQueryResults[n].clear();
  259. }
  260. mQueryResults.clear();
  261. }
  262. //-----------------------------------------------------------------------------
  263. typeWorldQueryResultVector& WorldQuery::getLayeredQueryResults( const U32 layer )
  264. {
  265. // Sanity!
  266. AssertFatal( layer < MAX_LAYERS_SUPPORTED, "WorldQuery::getResults() - Layer out of range." );
  267. return mLayeredQueryResults[ layer ];
  268. }
  269. //-----------------------------------------------------------------------------
  270. void WorldQuery::sortRaycastQueryResult( void )
  271. {
  272. // Debug Profiling.
  273. PROFILE_SCOPE(WorldQuery_SortRayCastQueryResult);
  274. // Ignore if not a ray-cast query result or there are not results to sort.
  275. if ( !getIsRaycastQueryResult() || getQueryResultsCount() == 0 )
  276. return;
  277. // Sort query results.
  278. dQsort( mQueryResults.address(), mQueryResults.size(), sizeof(WorldQueryResult), rayCastFractionSort );
  279. for ( U32 layer = 0; layer < MAX_LAYERS_SUPPORTED; ++layer )
  280. {
  281. // Fetch layer query results.
  282. typeWorldQueryResultVector& layerQueryResults = mLayeredQueryResults[layer];
  283. // Skip if nothing in the layer query results.
  284. if ( layerQueryResults.size() == 0 )
  285. continue;
  286. // Sort query results.
  287. dQsort( layerQueryResults.address(), layerQueryResults.size(), sizeof(WorldQueryResult), rayCastFractionSort );
  288. }
  289. }
  290. //-----------------------------------------------------------------------------
  291. bool WorldQuery::ReportFixture( b2Fixture* fixture )
  292. {
  293. // Debug Profiling.
  294. PROFILE_SCOPE(WorldQuery_ReportFixture);
  295. // If not the correct proxy then ignore.
  296. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(fixture->GetBody()->GetUserData());
  297. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  298. return true;
  299. // Fetch scene object.
  300. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  301. // Ignore if already tagged with the world query key.
  302. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  303. return true;
  304. // Enabled filter.
  305. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  306. return true;
  307. // Visible filter.
  308. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  309. return true;
  310. // Picking allowed filter.
  311. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  312. return true;
  313. // Check fixture point.
  314. if ( mCheckFixturePoint && !fixture->TestPoint( mFixturePoint ) )
  315. return true;
  316. // Tag with world query key.
  317. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  318. // Fetch layer and group masks.
  319. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  320. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  321. // Compare masks and report.
  322. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  323. {
  324. WorldQueryResult queryResult( pSceneObject );
  325. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  326. mQueryResults.push_back( queryResult );
  327. }
  328. return true;
  329. }
  330. //-----------------------------------------------------------------------------
  331. F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, F32 fraction )
  332. {
  333. // Debug Profiling.
  334. PROFILE_SCOPE(WorldQuery_ReportFixtureRay);
  335. // If not the correct proxy then ignore.
  336. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(fixture->GetBody()->GetUserData());
  337. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  338. return 1.0f;
  339. // Fetch scene object.
  340. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  341. // Ignore if already tagged with the world query key.
  342. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  343. return 1.0f;
  344. // Enabled filter.
  345. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  346. return 1.0f;
  347. // Visible filter.
  348. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  349. return 1.0f;
  350. // Picking allowed filter.
  351. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  352. return 1.0f;
  353. // Tag with world query key.
  354. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  355. // Fetch layer and group masks.
  356. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  357. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  358. // Fetch collision shape index.
  359. const S32 shapeIndex = pSceneObject->getCollisionShapeIndex( fixture );
  360. // Sanity!
  361. AssertFatal( shapeIndex >= 0, "2dWorldQuery::ReportFixture() - Cannot find shape index reported on physics proxy of a fixture." );
  362. // Compare masks and report.
  363. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  364. {
  365. WorldQueryResult queryResult( pSceneObject, point, normal, fraction, (U32)shapeIndex );
  366. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  367. mQueryResults.push_back( queryResult );
  368. }
  369. return 1.0f;
  370. }
  371. //-----------------------------------------------------------------------------
  372. bool WorldQuery::QueryCallback( S32 proxyId )
  373. {
  374. // Debug Profiling.
  375. PROFILE_SCOPE(WorldQuery_QueryCallback);
  376. // If not the correct proxy then ignore.
  377. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(GetUserData( proxyId ));
  378. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  379. return true;
  380. // Fetch scene object.
  381. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  382. // Ignore if already tagged with the world query key.
  383. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  384. return true;
  385. // Enabled filter.
  386. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  387. return true;
  388. // Visible filter.
  389. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  390. return true;
  391. // Picking allowed filter.
  392. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  393. return true;
  394. // Tag with world query key.
  395. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  396. // Fetch layer and group masks.
  397. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  398. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  399. // Compare masks and report.
  400. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  401. {
  402. WorldQueryResult queryResult( pSceneObject );
  403. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  404. mQueryResults.push_back( queryResult );
  405. }
  406. return true;
  407. }
  408. //-----------------------------------------------------------------------------
  409. F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId )
  410. {
  411. // Debug Profiling.
  412. PROFILE_SCOPE(WorldQuery_RayCastCallback);
  413. // If not the correct proxy then ignore.
  414. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(GetUserData( proxyId ));
  415. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  416. return 1.0f;
  417. // Fetch scene object.
  418. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  419. // Ignore if already tagged with the world query key.
  420. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  421. return 1.0f;
  422. // Enabled filter.
  423. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  424. return 1.0f;
  425. // Visible filter.
  426. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  427. return 1.0f;
  428. // Picking allowed filter.
  429. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  430. return 1.0f;
  431. // Tag with world query key.
  432. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  433. // Fetch layer and group masks.
  434. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  435. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  436. // Compare masks and report.
  437. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  438. {
  439. WorldQueryResult queryResult( pSceneObject );
  440. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  441. mQueryResults.push_back( queryResult );
  442. }
  443. return 1.0f;
  444. }
  445. //-----------------------------------------------------------------------------
  446. void WorldQuery::injectAlwaysInScope( void )
  447. {
  448. // Debug Profiling.
  449. PROFILE_SCOPE(WorldQuery_InjectAlwaysInScope);
  450. // Finish if filtering always-in-scope.
  451. if ( mQueryFilter.mAlwaysInScopeFilter )
  452. return;
  453. // Iterate always-in-scope.
  454. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  455. {
  456. // Fetch scene object.
  457. SceneObject* pSceneObject = (*itr);
  458. // Ignore if already tagged with the world query key.
  459. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  460. continue;
  461. // Tag with world query key.
  462. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  463. // Enabled filter.
  464. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  465. continue;
  466. // Visible filter.
  467. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  468. continue;
  469. // Picking allowed filter.
  470. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  471. continue;
  472. // Fetch layer and group masks.
  473. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  474. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  475. // Compare masks and report.
  476. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  477. {
  478. WorldQueryResult queryResult( pSceneObject );
  479. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  480. mQueryResults.push_back( queryResult );
  481. }
  482. }
  483. }
  484. //-----------------------------------------------------------------------------
  485. S32 QSORT_CALLBACK WorldQuery::rayCastFractionSort(const void* a, const void* b)
  486. {
  487. // Debug Profiling.
  488. PROFILE_SCOPE(WorldQuery_RayCastFractionSort);
  489. // Fetch scene objects.
  490. WorldQueryResult* pQueryResultA = (WorldQueryResult*)a;
  491. WorldQueryResult* pQueryResultB = (WorldQueryResult*)b;
  492. // Fetch fractions.
  493. const F32 queryFractionA = pQueryResultA->mFraction;
  494. const F32 queryFractionB = pQueryResultB->mFraction;
  495. if ( queryFractionA < queryFractionB )
  496. return -1;
  497. if ( queryFractionA > queryFractionB )
  498. return 1;
  499. return 0;
  500. }