WorldQuery.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  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. mCheckPoint(false),
  37. mCheckAABB(false),
  38. mCheckOOBB(false),
  39. mCheckCircle(false)
  40. {
  41. // Set debug associations.
  42. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
  43. {
  44. VECTOR_SET_ASSOCIATION( mLayeredQueryResults[n] );
  45. }
  46. VECTOR_SET_ASSOCIATION( mQueryResults );
  47. // Clear the query.
  48. clearQuery();
  49. }
  50. //-----------------------------------------------------------------------------
  51. S32 WorldQuery::add( SceneObject* pSceneObject )
  52. {
  53. // Debug Profiling.
  54. PROFILE_SCOPE(WorldQuery_Add);
  55. return CreateProxy( pSceneObject->getAABB(), static_cast<PhysicsProxy*>(pSceneObject) );
  56. }
  57. //-----------------------------------------------------------------------------
  58. void WorldQuery::remove( SceneObject* pSceneObject )
  59. {
  60. // Debug Profiling.
  61. PROFILE_SCOPE(WorldQuery_Remove);
  62. DestroyProxy( pSceneObject->getWorldProxy() );
  63. }
  64. //-----------------------------------------------------------------------------
  65. bool WorldQuery::update( SceneObject* pSceneObject, const b2AABB& aabb, const b2Vec2& displacement )
  66. {
  67. // Debug Profiling.
  68. PROFILE_SCOPE(WorldQuery_Update);
  69. return MoveProxy( pSceneObject->getWorldProxy(), aabb, displacement );
  70. }
  71. //-----------------------------------------------------------------------------
  72. void WorldQuery::addAlwaysInScope( SceneObject* pSceneObject )
  73. {
  74. // Debug Profiling.
  75. PROFILE_SCOPE(WorldQuery_AddAlwaysInScope);
  76. // Sanity!
  77. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  78. {
  79. AssertFatal( (*itr) != pSceneObject, "Object attempted to be in Always-in-Scope more than once." );
  80. }
  81. // Add to always-in-scope.
  82. mAlwaysInScopeSet.push_back( pSceneObject );
  83. // Set always in scope.
  84. pSceneObject->mAlwaysInScope = true;
  85. }
  86. //-----------------------------------------------------------------------------
  87. void WorldQuery::removeAlwaysInScope( SceneObject* pSceneObject )
  88. {
  89. // Debug Profiling.
  90. PROFILE_SCOPE(WorldQuery_RemoveAlwaysInScope);
  91. // Remove from always-in-scope.
  92. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  93. {
  94. // Skip if not object.
  95. if ( (*itr) != pSceneObject )
  96. continue;
  97. mAlwaysInScopeSet.erase_fast( itr );
  98. // Reset always in scope.
  99. pSceneObject->mAlwaysInScope = false;
  100. return;
  101. }
  102. AssertFatal( false, "Object attempted to be removed from Always-in-Scope but wasn't present." );
  103. }
  104. //-----------------------------------------------------------------------------
  105. U32 WorldQuery::collisionQueryAABB( const b2AABB& aabb )
  106. {
  107. // Debug Profiling.
  108. PROFILE_SCOPE(WorldQuery_collisionQueryAABB);
  109. mMasterQueryKey++;
  110. // Flag as not a ray-cast query result.
  111. mIsRaycastQueryResult = false;
  112. // Query.
  113. b2Vec2 verts[4];
  114. verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
  115. verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
  116. verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
  117. verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
  118. mComparePolygonShape.Set( verts, 4 );
  119. mCompareTransform.SetIdentity();
  120. mCheckAABB = true;
  121. mpScene->getWorld()->QueryAABB( this, aabb );
  122. mCheckAABB = false;
  123. // Inject always-in-scope.
  124. injectAlwaysInScope();
  125. return getQueryResultsCount();
  126. }
  127. //-----------------------------------------------------------------------------
  128. U32 WorldQuery::collisionQueryRay( const Vector2& point1, const Vector2& point2 )
  129. {
  130. // Debug Profiling.
  131. PROFILE_SCOPE(WorldQuery_CollisionQueryRay);
  132. mMasterQueryKey++;
  133. // Flag as a ray-cast query result.
  134. mIsRaycastQueryResult = true;
  135. // Query.
  136. mpScene->getWorld()->RayCast( this, point1, point2 );
  137. // Inject always-in-scope.
  138. injectAlwaysInScope();
  139. return getQueryResultsCount();
  140. }
  141. //-----------------------------------------------------------------------------
  142. U32 WorldQuery::collisionQueryPoint( const Vector2& point )
  143. {
  144. // Debug Profiling.
  145. PROFILE_SCOPE(WorldQuery_CollisionQueryPoint);
  146. mMasterQueryKey++;
  147. // Flag as not a ray-cast query result.
  148. mIsRaycastQueryResult = false;
  149. // Query.
  150. b2AABB aabb;
  151. aabb.lowerBound = point;
  152. aabb.upperBound = point;
  153. mCheckPoint = true;
  154. mComparePoint = point;
  155. mpScene->getWorld()->QueryAABB( this, aabb );
  156. mCheckPoint = false;
  157. // Inject always-in-scope.
  158. injectAlwaysInScope();
  159. return getQueryResultsCount();
  160. }
  161. //-----------------------------------------------------------------------------
  162. U32 WorldQuery::collisionQueryCircle( const Vector2& centroid, const F32 radius )
  163. {
  164. // Debug Profiling.
  165. PROFILE_SCOPE(WorldQuery_CollisionQueryCircle);
  166. mMasterQueryKey++;
  167. // Flag as not a ray-cast query result.
  168. mIsRaycastQueryResult = false;
  169. // Query.
  170. b2AABB aabb;
  171. mCompareTransform.SetIdentity();
  172. mCompareCircleShape.m_p = centroid;
  173. mCompareCircleShape.m_radius = radius;
  174. mCompareCircleShape.ComputeAABB( &aabb, mCompareTransform, 0 );
  175. mCheckCircle = true;
  176. mpScene->getWorld()->QueryAABB( this, aabb );
  177. mCheckCircle = false;
  178. // Inject always-in-scope.
  179. injectAlwaysInScope();
  180. return getQueryResultsCount();
  181. }
  182. //-----------------------------------------------------------------------------
  183. U32 WorldQuery::aabbQueryAABB( const b2AABB& aabb )
  184. {
  185. // Debug Profiling.
  186. PROFILE_SCOPE(WorldQuery_aabbQueryAABB);
  187. mMasterQueryKey++;
  188. // Flag as not a ray-cast query result.
  189. mIsRaycastQueryResult = false;
  190. // Query.
  191. Query( this, aabb );
  192. // Inject always-in-scope.
  193. injectAlwaysInScope();
  194. return getQueryResultsCount();
  195. }
  196. //-----------------------------------------------------------------------------
  197. U32 WorldQuery::aabbQueryRay( const Vector2& point1, const Vector2& point2 )
  198. {
  199. // Debug Profiling.
  200. PROFILE_SCOPE(WorldQuery_AABBQueryRay);
  201. mMasterQueryKey++;
  202. // Flag as a ray-cast query result.
  203. mIsRaycastQueryResult = true;
  204. // Query.
  205. mCompareRay.p1 = point1;
  206. mCompareRay.p2 = point2;
  207. mCompareRay.maxFraction = 1.0f;
  208. mCompareTransform.SetIdentity();
  209. RayCast( this, mCompareRay );
  210. // Inject always-in-scope.
  211. injectAlwaysInScope();
  212. return getQueryResultsCount();
  213. }
  214. //-----------------------------------------------------------------------------
  215. U32 WorldQuery::aabbQueryPoint( const Vector2& point )
  216. {
  217. // Debug Profiling.
  218. PROFILE_SCOPE(WorldQuery_AABBQueryPoint);
  219. mMasterQueryKey++;
  220. // Flag as not a ray-cast query result.
  221. mIsRaycastQueryResult = false;
  222. // Query.
  223. b2AABB aabb;
  224. aabb.lowerBound = point;
  225. aabb.upperBound = point;
  226. Query( this, aabb );
  227. // Inject always-in-scope.
  228. injectAlwaysInScope();
  229. return getQueryResultsCount();
  230. }
  231. //-----------------------------------------------------------------------------
  232. U32 WorldQuery::aabbQueryCircle( const Vector2& centroid, const F32 radius )
  233. {
  234. // Debug Profiling.
  235. PROFILE_SCOPE(WorldQuery_AABBQueryCircle);
  236. mMasterQueryKey++;
  237. // Flag as not a ray-cast query result.
  238. mIsRaycastQueryResult = false;
  239. // Query.
  240. b2AABB aabb;
  241. mCompareTransform.SetIdentity();
  242. mCompareCircleShape.m_p = centroid;
  243. mCompareCircleShape.m_radius = radius;
  244. mCompareCircleShape.ComputeAABB( &aabb, mCompareTransform, 0 );
  245. mCheckCircle = true;
  246. Query( this, aabb );
  247. mCheckCircle = false;
  248. // Inject always-in-scope.
  249. injectAlwaysInScope();
  250. return getQueryResultsCount();
  251. }
  252. //-----------------------------------------------------------------------------
  253. U32 WorldQuery::oobbQueryAABB( const b2AABB& aabb )
  254. {
  255. // Debug Profiling.
  256. PROFILE_SCOPE(WorldQuery_aabbQueryAABB);
  257. mMasterQueryKey++;
  258. // Flag as not a ray-cast query result.
  259. mIsRaycastQueryResult = false;
  260. // Query.
  261. b2Vec2 verts[4];
  262. verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
  263. verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
  264. verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
  265. verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
  266. mComparePolygonShape.Set( verts, 4 );
  267. mCompareTransform.SetIdentity();
  268. mCheckOOBB = true;
  269. mCheckAABB = true;
  270. Query( this, aabb );
  271. mCheckAABB = false;
  272. mCheckOOBB = false;
  273. // Inject always-in-scope.
  274. injectAlwaysInScope();
  275. return getQueryResultsCount();
  276. }
  277. //-----------------------------------------------------------------------------
  278. U32 WorldQuery::oobbQueryRay( const Vector2& point1, const Vector2& point2 )
  279. {
  280. // Debug Profiling.
  281. PROFILE_SCOPE(WorldQuery_AABBQueryRay);
  282. mMasterQueryKey++;
  283. // Flag as a ray-cast query result.
  284. mIsRaycastQueryResult = true;
  285. // Query.
  286. mCompareRay.p1 = point1;
  287. mCompareRay.p2 = point2;
  288. mCompareRay.maxFraction = 1.0f;
  289. mCompareTransform.SetIdentity();
  290. mCheckOOBB = true;
  291. RayCast( this, mCompareRay );
  292. mCheckOOBB = false;
  293. // Inject always-in-scope.
  294. injectAlwaysInScope();
  295. return getQueryResultsCount();
  296. }
  297. //-----------------------------------------------------------------------------
  298. U32 WorldQuery::oobbQueryPoint( const Vector2& point )
  299. {
  300. // Debug Profiling.
  301. PROFILE_SCOPE(WorldQuery_AABBQueryPoint);
  302. mMasterQueryKey++;
  303. // Flag as not a ray-cast query result.
  304. mIsRaycastQueryResult = false;
  305. // Query.
  306. b2AABB aabb;
  307. aabb.lowerBound = point;
  308. aabb.upperBound = point;
  309. mComparePoint = point;
  310. mCompareTransform.SetIdentity();
  311. mCheckOOBB = true;
  312. mCheckPoint = true;
  313. Query( this, aabb );
  314. mCheckPoint = false;
  315. mCheckOOBB = false;
  316. // Inject always-in-scope.
  317. injectAlwaysInScope();
  318. return getQueryResultsCount();
  319. }
  320. //-----------------------------------------------------------------------------
  321. U32 WorldQuery::oobbQueryCircle( const Vector2& centroid, const F32 radius )
  322. {
  323. // Debug Profiling.
  324. PROFILE_SCOPE(WorldQuery_OOBBQueryCircle);
  325. mMasterQueryKey++;
  326. // Flag as not a ray-cast query result.
  327. mIsRaycastQueryResult = false;
  328. // Query.
  329. b2AABB aabb;
  330. mCompareTransform.SetIdentity();
  331. mCompareCircleShape.m_p = centroid;
  332. mCompareCircleShape.m_radius = radius;
  333. mCompareCircleShape.ComputeAABB( &aabb, mCompareTransform, 0 );
  334. mCheckOOBB = true;
  335. mCheckCircle = true;
  336. Query( this, aabb );
  337. mCheckCircle = false;
  338. mCheckOOBB = false;
  339. // Inject always-in-scope.
  340. injectAlwaysInScope();
  341. return getQueryResultsCount();
  342. }
  343. //-----------------------------------------------------------------------------
  344. U32 WorldQuery::anyQueryAABB( const b2AABB& aabb )
  345. {
  346. // Debug Profiling.
  347. PROFILE_SCOPE(WorldQuery_anyQueryAABBAABB);
  348. // Query.
  349. oobbQueryAABB( aabb );
  350. mMasterQueryKey--;
  351. collisionQueryAABB( aabb );
  352. // Inject always-in-scope.
  353. injectAlwaysInScope();
  354. return getQueryResultsCount();
  355. }
  356. U32 WorldQuery::anyQueryArea(const Vector2& lower, const Vector2& upper)
  357. {
  358. b2AABB aabb;
  359. aabb.lowerBound.Set(getMin(lower.x, lower.x), getMin(lower.x, upper.x));
  360. aabb.upperBound.Set(getMax(lower.x, upper.x), getMax(lower.x, upper.x));
  361. return anyQueryAABB(aabb);
  362. }
  363. //-----------------------------------------------------------------------------
  364. U32 WorldQuery::anyQueryRay( const Vector2& point1, const Vector2& point2 )
  365. {
  366. // Debug Profiling.
  367. PROFILE_SCOPE(WorldQuery_AnyQueryRay);
  368. // Query.
  369. oobbQueryRay( point1, point2 );
  370. mMasterQueryKey--;
  371. collisionQueryRay( point1, point2 );
  372. // Inject always-in-scope.
  373. injectAlwaysInScope();
  374. return getQueryResultsCount();
  375. }
  376. //-----------------------------------------------------------------------------
  377. U32 WorldQuery::anyQueryPoint( const Vector2& point )
  378. {
  379. // Debug Profiling.
  380. PROFILE_SCOPE(WorldQuery_AnyQueryPoint);
  381. // Query.
  382. oobbQueryPoint( point );
  383. mMasterQueryKey--;
  384. collisionQueryPoint( point );
  385. // Inject always-in-scope.
  386. injectAlwaysInScope();
  387. return getQueryResultsCount();
  388. }
  389. //-----------------------------------------------------------------------------
  390. U32 WorldQuery::anyQueryCircle( const Vector2& centroid, const F32 radius )
  391. {
  392. // Debug Profiling.
  393. PROFILE_SCOPE(WorldQuery_AnyQueryCircle);
  394. // Query.
  395. oobbQueryCircle( centroid, radius );
  396. mMasterQueryKey--;
  397. collisionQueryCircle( centroid, radius );
  398. // Inject always-in-scope.
  399. injectAlwaysInScope();
  400. return getQueryResultsCount();
  401. }
  402. //-----------------------------------------------------------------------------
  403. void WorldQuery::clearQuery( void )
  404. {
  405. // Debug Profiling.
  406. PROFILE_SCOPE(WorldQuery_ClearQuery);
  407. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
  408. {
  409. mLayeredQueryResults[n].clear();
  410. }
  411. mQueryResults.clear();
  412. }
  413. //-----------------------------------------------------------------------------
  414. typeWorldQueryResultVector& WorldQuery::getLayeredQueryResults( const U32 layer )
  415. {
  416. // Sanity!
  417. AssertFatal( layer < MAX_LAYERS_SUPPORTED, "WorldQuery::getResults() - Layer out of range." );
  418. return mLayeredQueryResults[ layer ];
  419. }
  420. //-----------------------------------------------------------------------------
  421. void WorldQuery::sortRaycastQueryResult( void )
  422. {
  423. // Debug Profiling.
  424. PROFILE_SCOPE(WorldQuery_SortRayCastQueryResult);
  425. // Ignore if not a ray-cast query result or there are not results to sort.
  426. if ( !getIsRaycastQueryResult() || getQueryResultsCount() == 0 )
  427. return;
  428. // Sort query results.
  429. dQsort( mQueryResults.address(), mQueryResults.size(), sizeof(WorldQueryResult), rayCastFractionSort );
  430. for ( U32 layer = 0; layer < MAX_LAYERS_SUPPORTED; ++layer )
  431. {
  432. // Fetch layer query results.
  433. typeWorldQueryResultVector& layerQueryResults = mLayeredQueryResults[layer];
  434. // Skip if nothing in the layer query results.
  435. if ( layerQueryResults.size() == 0 )
  436. continue;
  437. // Sort query results.
  438. dQsort( layerQueryResults.address(), layerQueryResults.size(), sizeof(WorldQueryResult), rayCastFractionSort );
  439. }
  440. }
  441. //-----------------------------------------------------------------------------
  442. bool WorldQuery::ReportFixture( b2Fixture* fixture )
  443. {
  444. // Debug Profiling.
  445. PROFILE_SCOPE(WorldQuery_ReportFixture);
  446. // If not the correct proxy then ignore.
  447. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(fixture->GetBody()->GetUserData());
  448. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  449. return true;
  450. // Fetch scene object.
  451. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  452. // Ignore if already tagged with the world query key.
  453. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  454. return true;
  455. // Enabled filter.
  456. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  457. return true;
  458. // Visible filter.
  459. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  460. return true;
  461. // Picking allowed filter.
  462. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  463. return true;
  464. // Check collision point.
  465. if ( mCheckPoint && !fixture->TestPoint( mComparePoint ) )
  466. return true;
  467. // Check collision AABB.
  468. if ( mCheckAABB )
  469. if ( !b2TestOverlap( &mComparePolygonShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) )
  470. return true;
  471. // Check collision circle.
  472. if ( mCheckCircle )
  473. if ( !b2TestOverlap( &mCompareCircleShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) )
  474. return true;
  475. // Fetch layer and group masks.
  476. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  477. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  478. // Compare masks and report.
  479. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  480. {
  481. WorldQueryResult queryResult( pSceneObject );
  482. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  483. mQueryResults.push_back( queryResult );
  484. // Tag with world query key.
  485. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  486. }
  487. return true;
  488. }
  489. //-----------------------------------------------------------------------------
  490. F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, F32 fraction )
  491. {
  492. // Debug Profiling.
  493. PROFILE_SCOPE(WorldQuery_ReportFixtureRay);
  494. // If not the correct proxy then ignore.
  495. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(fixture->GetBody()->GetUserData());
  496. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  497. return 1.0f;
  498. // Fetch scene object.
  499. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  500. // Ignore if already tagged with the world query key.
  501. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  502. return 1.0f;
  503. // Enabled filter.
  504. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  505. return 1.0f;
  506. // Visible filter.
  507. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  508. return 1.0f;
  509. // Picking allowed filter.
  510. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  511. return 1.0f;
  512. // Fetch layer and group masks.
  513. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  514. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  515. // Fetch collision shape index.
  516. const S32 shapeIndex = pSceneObject->getCollisionShapeIndex( fixture );
  517. // Sanity!
  518. AssertFatal( shapeIndex >= 0, "WorldQuery::ReportFixture() - Cannot find shape index reported on physics proxy of a fixture." );
  519. // Compare masks and report.
  520. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  521. {
  522. WorldQueryResult queryResult( pSceneObject, point, normal, fraction, (U32)shapeIndex );
  523. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  524. mQueryResults.push_back( queryResult );
  525. // Tag with world query key.
  526. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  527. }
  528. return 1.0f;
  529. }
  530. //-----------------------------------------------------------------------------
  531. bool WorldQuery::QueryCallback( S32 proxyId )
  532. {
  533. // Debug Profiling.
  534. PROFILE_SCOPE(WorldQuery_QueryCallback);
  535. // If not the correct proxy then ignore.
  536. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(GetUserData( proxyId ));
  537. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  538. return true;
  539. // Fetch scene object.
  540. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  541. // Ignore if already tagged with the world query key.
  542. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  543. return true;
  544. // Enabled filter.
  545. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  546. return true;
  547. // Visible filter. If an object has a size x or y value of zero then they are treated here as invisible.
  548. if (mQueryFilter.mVisibleFilter && (!pSceneObject->getVisible() || pSceneObject->getSize().isXZero() || pSceneObject->getSize().isYZero()))
  549. return true;
  550. // Picking allowed filter.
  551. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  552. return true;
  553. // Check OOBB.
  554. if ( mCheckOOBB )
  555. {
  556. // Fetch the shapes render OOBB.
  557. b2PolygonShape oobb;
  558. oobb.Set( pSceneObject->getRenderOOBB(), 4);
  559. // Check point.
  560. if ( mCheckPoint )
  561. {
  562. if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) )
  563. return true;
  564. }
  565. // Check AABB.
  566. else if ( mCheckAABB )
  567. {
  568. if ( !b2TestOverlap( &mComparePolygonShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
  569. return true;
  570. }
  571. // Check circle.
  572. else if ( mCheckCircle )
  573. {
  574. if ( !b2TestOverlap( &mCompareCircleShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
  575. return true;
  576. }
  577. }
  578. // Check circle.
  579. else if ( mCheckCircle )
  580. {
  581. // Fetch the shapes AABB.
  582. b2AABB aabb = pSceneObject->getAABB();
  583. b2Vec2 verts[4];
  584. verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
  585. verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
  586. verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
  587. verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
  588. b2PolygonShape shapeAABB;
  589. shapeAABB.Set( verts, 4);
  590. if ( !b2TestOverlap( &mCompareCircleShape, 0, &shapeAABB, 0, mCompareTransform, mCompareTransform ) )
  591. return true;
  592. }
  593. // Fetch layer and group masks.
  594. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  595. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  596. // Compare masks and report.
  597. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  598. {
  599. WorldQueryResult queryResult( pSceneObject );
  600. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  601. mQueryResults.push_back( queryResult );
  602. // Tag with world query key.
  603. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  604. }
  605. return true;
  606. }
  607. //-----------------------------------------------------------------------------
  608. F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId )
  609. {
  610. // Debug Profiling.
  611. PROFILE_SCOPE(WorldQuery_RayCastCallback);
  612. // If not the correct proxy then ignore.
  613. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(GetUserData( proxyId ));
  614. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  615. return 1.0f;
  616. // Fetch scene object.
  617. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  618. // Ignore if already tagged with the world query key.
  619. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  620. return 1.0f;
  621. // Enabled filter.
  622. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  623. return 1.0f;
  624. // Visible filter.
  625. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  626. return 1.0f;
  627. // Picking allowed filter.
  628. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  629. return 1.0f;
  630. // Check OOBB.
  631. if ( mCheckOOBB )
  632. {
  633. // Fetch the shapes render OOBB.
  634. b2PolygonShape oobb;
  635. oobb.Set( pSceneObject->getRenderOOBB(), 4);
  636. b2RayCastOutput rayOutput;
  637. if ( !oobb.RayCast( &rayOutput, mCompareRay, mCompareTransform, 0 ) )
  638. return true;
  639. }
  640. // Fetch layer and group masks.
  641. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  642. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  643. // Compare masks and report.
  644. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  645. {
  646. WorldQueryResult queryResult( pSceneObject );
  647. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  648. mQueryResults.push_back( queryResult );
  649. // Tag with world query key.
  650. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  651. }
  652. return 1.0f;
  653. }
  654. //-----------------------------------------------------------------------------
  655. void WorldQuery::injectAlwaysInScope( void )
  656. {
  657. // Debug Profiling.
  658. PROFILE_SCOPE(WorldQuery_InjectAlwaysInScope);
  659. // Finish if filtering always-in-scope.
  660. if ( mQueryFilter.mAlwaysInScopeFilter )
  661. return;
  662. // Iterate always-in-scope.
  663. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  664. {
  665. // Fetch scene object.
  666. SceneObject* pSceneObject = (*itr);
  667. // Ignore if already tagged with the world query key.
  668. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  669. continue;
  670. // Enabled filter.
  671. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  672. continue;
  673. // Visible filter.
  674. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  675. continue;
  676. // Picking allowed filter.
  677. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  678. continue;
  679. // Fetch layer and group masks.
  680. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  681. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  682. // Compare masks and report.
  683. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  684. {
  685. WorldQueryResult queryResult( pSceneObject );
  686. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  687. mQueryResults.push_back( queryResult );
  688. // Tag with world query key.
  689. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  690. }
  691. }
  692. }
  693. //-----------------------------------------------------------------------------
  694. S32 QSORT_CALLBACK WorldQuery::rayCastFractionSort(const void* a, const void* b)
  695. {
  696. // Debug Profiling.
  697. PROFILE_SCOPE(WorldQuery_RayCastFractionSort);
  698. // Fetch scene objects.
  699. WorldQueryResult* pQueryResultA = (WorldQueryResult*)a;
  700. WorldQueryResult* pQueryResultB = (WorldQueryResult*)b;
  701. // Fetch fractions.
  702. const F32 queryFractionA = pQueryResultA->mFraction;
  703. const F32 queryFractionB = pQueryResultB->mFraction;
  704. if ( queryFractionA < queryFractionB )
  705. return -1;
  706. if ( queryFractionA > queryFractionB )
  707. return 1;
  708. return 0;
  709. }