WorldQuery.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  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. //-----------------------------------------------------------------------------
  357. U32 WorldQuery::anyQueryRay( const Vector2& point1, const Vector2& point2 )
  358. {
  359. // Debug Profiling.
  360. PROFILE_SCOPE(WorldQuery_AnyQueryRay);
  361. // Query.
  362. oobbQueryRay( point1, point2 );
  363. mMasterQueryKey--;
  364. collisionQueryRay( point1, point2 );
  365. // Inject always-in-scope.
  366. injectAlwaysInScope();
  367. return getQueryResultsCount();
  368. }
  369. //-----------------------------------------------------------------------------
  370. U32 WorldQuery::anyQueryPoint( const Vector2& point )
  371. {
  372. // Debug Profiling.
  373. PROFILE_SCOPE(WorldQuery_AnyQueryPoint);
  374. // Query.
  375. oobbQueryPoint( point );
  376. mMasterQueryKey--;
  377. collisionQueryPoint( point );
  378. // Inject always-in-scope.
  379. injectAlwaysInScope();
  380. return getQueryResultsCount();
  381. }
  382. //-----------------------------------------------------------------------------
  383. U32 WorldQuery::anyQueryCircle( const Vector2& centroid, const F32 radius )
  384. {
  385. // Debug Profiling.
  386. PROFILE_SCOPE(WorldQuery_AnyQueryCircle);
  387. // Query.
  388. oobbQueryCircle( centroid, radius );
  389. mMasterQueryKey--;
  390. collisionQueryCircle( centroid, radius );
  391. // Inject always-in-scope.
  392. injectAlwaysInScope();
  393. return getQueryResultsCount();
  394. }
  395. //-----------------------------------------------------------------------------
  396. void WorldQuery::clearQuery( void )
  397. {
  398. // Debug Profiling.
  399. PROFILE_SCOPE(WorldQuery_ClearQuery);
  400. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
  401. {
  402. mLayeredQueryResults[n].clear();
  403. }
  404. mQueryResults.clear();
  405. }
  406. //-----------------------------------------------------------------------------
  407. typeWorldQueryResultVector& WorldQuery::getLayeredQueryResults( const U32 layer )
  408. {
  409. // Sanity!
  410. AssertFatal( layer < MAX_LAYERS_SUPPORTED, "WorldQuery::getResults() - Layer out of range." );
  411. return mLayeredQueryResults[ layer ];
  412. }
  413. //-----------------------------------------------------------------------------
  414. void WorldQuery::sortRaycastQueryResult( void )
  415. {
  416. // Debug Profiling.
  417. PROFILE_SCOPE(WorldQuery_SortRayCastQueryResult);
  418. // Ignore if not a ray-cast query result or there are not results to sort.
  419. if ( !getIsRaycastQueryResult() || getQueryResultsCount() == 0 )
  420. return;
  421. // Sort query results.
  422. dQsort( mQueryResults.address(), mQueryResults.size(), sizeof(WorldQueryResult), rayCastFractionSort );
  423. for ( U32 layer = 0; layer < MAX_LAYERS_SUPPORTED; ++layer )
  424. {
  425. // Fetch layer query results.
  426. typeWorldQueryResultVector& layerQueryResults = mLayeredQueryResults[layer];
  427. // Skip if nothing in the layer query results.
  428. if ( layerQueryResults.size() == 0 )
  429. continue;
  430. // Sort query results.
  431. dQsort( layerQueryResults.address(), layerQueryResults.size(), sizeof(WorldQueryResult), rayCastFractionSort );
  432. }
  433. }
  434. //-----------------------------------------------------------------------------
  435. bool WorldQuery::ReportFixture( b2Fixture* fixture )
  436. {
  437. // Debug Profiling.
  438. PROFILE_SCOPE(WorldQuery_ReportFixture);
  439. // If not the correct proxy then ignore.
  440. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(fixture->GetBody()->GetUserData());
  441. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  442. return true;
  443. // Fetch scene object.
  444. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  445. // Ignore if already tagged with the world query key.
  446. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  447. return true;
  448. // Enabled filter.
  449. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  450. return true;
  451. // Visible filter.
  452. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  453. return true;
  454. // Picking allowed filter.
  455. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  456. return true;
  457. // Check collision point.
  458. if ( mCheckPoint && !fixture->TestPoint( mComparePoint ) )
  459. return true;
  460. // Check collision AABB.
  461. if ( mCheckAABB )
  462. if ( !b2TestOverlap( &mComparePolygonShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) )
  463. return true;
  464. // Check collision circle.
  465. if ( mCheckCircle )
  466. if ( !b2TestOverlap( &mCompareCircleShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) )
  467. return true;
  468. // Fetch layer and group masks.
  469. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  470. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  471. // Compare masks and report.
  472. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  473. {
  474. WorldQueryResult queryResult( pSceneObject );
  475. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  476. mQueryResults.push_back( queryResult );
  477. // Tag with world query key.
  478. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  479. }
  480. return true;
  481. }
  482. //-----------------------------------------------------------------------------
  483. F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, F32 fraction )
  484. {
  485. // Debug Profiling.
  486. PROFILE_SCOPE(WorldQuery_ReportFixtureRay);
  487. // If not the correct proxy then ignore.
  488. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(fixture->GetBody()->GetUserData());
  489. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  490. return 1.0f;
  491. // Fetch scene object.
  492. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  493. // Ignore if already tagged with the world query key.
  494. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  495. return 1.0f;
  496. // Enabled filter.
  497. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  498. return 1.0f;
  499. // Visible filter.
  500. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  501. return 1.0f;
  502. // Picking allowed filter.
  503. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  504. return 1.0f;
  505. // Fetch layer and group masks.
  506. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  507. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  508. // Fetch collision shape index.
  509. const S32 shapeIndex = pSceneObject->getCollisionShapeIndex( fixture );
  510. // Sanity!
  511. AssertFatal( shapeIndex >= 0, "WorldQuery::ReportFixture() - Cannot find shape index reported on physics proxy of a fixture." );
  512. // Compare masks and report.
  513. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  514. {
  515. WorldQueryResult queryResult( pSceneObject, point, normal, fraction, (U32)shapeIndex );
  516. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  517. mQueryResults.push_back( queryResult );
  518. // Tag with world query key.
  519. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  520. }
  521. return 1.0f;
  522. }
  523. //-----------------------------------------------------------------------------
  524. bool WorldQuery::QueryCallback( S32 proxyId )
  525. {
  526. // Debug Profiling.
  527. PROFILE_SCOPE(WorldQuery_QueryCallback);
  528. // If not the correct proxy then ignore.
  529. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(GetUserData( proxyId ));
  530. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  531. return true;
  532. // Fetch scene object.
  533. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  534. // Ignore if already tagged with the world query key.
  535. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  536. return true;
  537. // Enabled filter.
  538. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  539. return true;
  540. // Visible filter.
  541. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  542. return true;
  543. // Picking allowed filter.
  544. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  545. return true;
  546. // Check OOBB.
  547. if ( mCheckOOBB )
  548. {
  549. // Fetch the shapes render OOBB.
  550. b2PolygonShape oobb;
  551. oobb.Set( pSceneObject->getRenderOOBB(), 4);
  552. // Check point.
  553. if ( mCheckPoint )
  554. {
  555. if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) )
  556. return true;
  557. }
  558. // Check AABB.
  559. else if ( mCheckAABB )
  560. {
  561. if ( !b2TestOverlap( &mComparePolygonShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
  562. return true;
  563. }
  564. // Check circle.
  565. else if ( mCheckCircle )
  566. {
  567. if ( !b2TestOverlap( &mCompareCircleShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
  568. return true;
  569. }
  570. }
  571. // Check circle.
  572. else if ( mCheckCircle )
  573. {
  574. // Fetch the shapes AABB.
  575. b2AABB aabb = pSceneObject->getAABB();
  576. b2Vec2 verts[4];
  577. verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
  578. verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
  579. verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
  580. verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
  581. b2PolygonShape shapeAABB;
  582. shapeAABB.Set( verts, 4);
  583. if ( !b2TestOverlap( &mCompareCircleShape, 0, &shapeAABB, 0, mCompareTransform, mCompareTransform ) )
  584. return true;
  585. }
  586. // Fetch layer and group masks.
  587. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  588. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  589. // Compare masks and report.
  590. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  591. {
  592. WorldQueryResult queryResult( pSceneObject );
  593. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  594. mQueryResults.push_back( queryResult );
  595. // Tag with world query key.
  596. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  597. }
  598. return true;
  599. }
  600. //-----------------------------------------------------------------------------
  601. F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId )
  602. {
  603. // Debug Profiling.
  604. PROFILE_SCOPE(WorldQuery_RayCastCallback);
  605. // If not the correct proxy then ignore.
  606. PhysicsProxy* pPhysicsProxy = static_cast<PhysicsProxy*>(GetUserData( proxyId ));
  607. if ( pPhysicsProxy->getPhysicsProxyType() != PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT )
  608. return 1.0f;
  609. // Fetch scene object.
  610. SceneObject* pSceneObject = static_cast<SceneObject*>(pPhysicsProxy);
  611. // Ignore if already tagged with the world query key.
  612. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  613. return 1.0f;
  614. // Enabled filter.
  615. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  616. return 1.0f;
  617. // Visible filter.
  618. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  619. return 1.0f;
  620. // Picking allowed filter.
  621. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  622. return 1.0f;
  623. // Check OOBB.
  624. if ( mCheckOOBB )
  625. {
  626. // Fetch the shapes render OOBB.
  627. b2PolygonShape oobb;
  628. oobb.Set( pSceneObject->getRenderOOBB(), 4);
  629. b2RayCastOutput rayOutput;
  630. if ( !oobb.RayCast( &rayOutput, mCompareRay, mCompareTransform, 0 ) )
  631. return true;
  632. }
  633. // Fetch layer and group masks.
  634. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  635. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  636. // Compare masks and report.
  637. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  638. {
  639. WorldQueryResult queryResult( pSceneObject );
  640. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  641. mQueryResults.push_back( queryResult );
  642. // Tag with world query key.
  643. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  644. }
  645. return 1.0f;
  646. }
  647. //-----------------------------------------------------------------------------
  648. void WorldQuery::injectAlwaysInScope( void )
  649. {
  650. // Debug Profiling.
  651. PROFILE_SCOPE(WorldQuery_InjectAlwaysInScope);
  652. // Finish if filtering always-in-scope.
  653. if ( mQueryFilter.mAlwaysInScopeFilter )
  654. return;
  655. // Iterate always-in-scope.
  656. for( typeSceneObjectVector::iterator itr = mAlwaysInScopeSet.begin(); itr != mAlwaysInScopeSet.end(); ++itr )
  657. {
  658. // Fetch scene object.
  659. SceneObject* pSceneObject = (*itr);
  660. // Ignore if already tagged with the world query key.
  661. if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
  662. continue;
  663. // Enabled filter.
  664. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
  665. continue;
  666. // Visible filter.
  667. if ( mQueryFilter.mVisibleFilter && !pSceneObject->getVisible() )
  668. continue;
  669. // Picking allowed filter.
  670. if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
  671. continue;
  672. // Fetch layer and group masks.
  673. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
  674. const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
  675. // Compare masks and report.
  676. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 )
  677. {
  678. WorldQueryResult queryResult( pSceneObject );
  679. mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
  680. mQueryResults.push_back( queryResult );
  681. // Tag with world query key.
  682. pSceneObject->setWorldQueryKey( mMasterQueryKey );
  683. }
  684. }
  685. }
  686. //-----------------------------------------------------------------------------
  687. S32 QSORT_CALLBACK WorldQuery::rayCastFractionSort(const void* a, const void* b)
  688. {
  689. // Debug Profiling.
  690. PROFILE_SCOPE(WorldQuery_RayCastFractionSort);
  691. // Fetch scene objects.
  692. WorldQueryResult* pQueryResultA = (WorldQueryResult*)a;
  693. WorldQueryResult* pQueryResultB = (WorldQueryResult*)b;
  694. // Fetch fractions.
  695. const F32 queryFractionA = pQueryResultA->mFraction;
  696. const F32 queryFractionB = pQueryResultB->mFraction;
  697. if ( queryFractionA < queryFractionB )
  698. return -1;
  699. if ( queryFractionA > queryFractionB )
  700. return 1;
  701. return 0;
  702. }