Browse Source

- Finished the WorldQuery. This is a breaking change! The old "Size" option for the Scene picking methods no longer exists. Now you have "Any", "AABB", "OOBB" & "Collision". The old "Size" option is analogous to "AABB".
- CompositeSprite pick methods now pick the OOBB.
- Updated the PickingToy to demonstrate the new changes.

MelvMay-GG 12 years ago
parent
commit
1d0030a

+ 1 - 1
engine/source/2d/core/SpriteBatch.cc

@@ -109,7 +109,7 @@ void SpriteBatch::prepareRender( SceneRenderObject* pSceneRenderObject, const Sc
         SpriteBatchQuery* pSpriteBatchQuery = getSpriteBatchQuery( true );
 
         // Perform query.
-        pSpriteBatchQuery->renderQueryArea( localAABB );
+        pSpriteBatchQuery->queryArea( localAABB, false );
 
         // Debug Profiling.
         PROFILE_END(); // SpriteBatch_PrepareRenderQuery

+ 2 - 0
engine/source/2d/core/SpriteBatchItem.h

@@ -291,6 +291,8 @@ public:
 
     virtual void copyTo( SpriteBatchItem* pSpriteBatchItem ) const;
 
+    inline const Vector2* getRenderOOBB( void ) const { return mRenderOOBB; }
+
     void prepareRender( SceneRenderRequest* pSceneRenderRequest, const U32 batchTransformId );
     void render( BatchRender* pBatchRenderer, const SceneRenderRequest* pSceneRenderRequest, const U32 batchTransformId );
 

+ 61 - 21
engine/source/2d/core/SpriteBatchQuery.cc

@@ -39,8 +39,8 @@ SpriteBatchQuery::SpriteBatchQuery( SpriteBatch* pSpriteBatch ) :
         mpSpriteBatch(pSpriteBatch),
         mIsRaycastQueryResult(false),
         mMasterQueryKey(0),
-        mCheckFixturePoint(false),
-        mFixturePoint(0.0f, 0.0f)
+        mCheckPoint(false),
+        mComparePoint(0.0f, 0.0f)
 {
     // Set debug associations.
     VECTOR_SET_ASSOCIATION( mQueryResults );
@@ -81,10 +81,10 @@ bool SpriteBatchQuery::update( SpriteBatchItem* pSpriteBatchItem, const b2AABB&
 
 //-----------------------------------------------------------------------------
 
-U32 SpriteBatchQuery::renderQueryArea( const b2AABB& aabb )
+U32 SpriteBatchQuery::queryArea( const b2AABB& aabb, const bool targetOOBB )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(SpriteBatchQuery_RenderQueryArea);
+    PROFILE_SCOPE(SpriteBatchQuery_QueryArea);
 
     mMasterQueryKey++;
 
@@ -92,17 +92,26 @@ U32 SpriteBatchQuery::renderQueryArea( const b2AABB& aabb )
     mIsRaycastQueryResult = false;
 
     // Query.
+    b2Vec2 verts[4];
+    verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
+    verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
+    verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
+    verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
+    mCompareShape.Set( verts, 4 );
+    mCompareTransform.SetIdentity();
+    mCheckOOBB = targetOOBB;
     Query( this, aabb );
+    mCheckOOBB = false;
 
     return getQueryResultsCount();
 }
 
 //-----------------------------------------------------------------------------
 
-U32 SpriteBatchQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 )
+U32 SpriteBatchQuery::queryRay( const Vector2& point1, const Vector2& point2, const bool targetOOBB )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(SpriteBatchQuery_RenderQueryRay);
+    PROFILE_SCOPE(SpriteBatchQuery_QueryRay);
 
     mMasterQueryKey++;
 
@@ -110,23 +119,23 @@ U32 SpriteBatchQuery::renderQueryRay( const Vector2& point1, const Vector2& poin
     mIsRaycastQueryResult = true;
 
     // Query.
-    b2RayCastInput rayInput;
-    rayInput.p1 = point1;
-    rayInput.p2 = point2;
-
-    rayInput.maxFraction = 1.0f;
-
-    RayCast( this, rayInput );
+    mCompareRay.p1 = point1;
+    mCompareRay.p2 = point2;
+    mCompareRay.maxFraction = 1.0f;
+    mCompareTransform.SetIdentity();
+    mCheckOOBB = targetOOBB;
+    RayCast( this, mCompareRay );
+    mCheckOOBB = false;
 
     return getQueryResultsCount();
 }
 
 //-----------------------------------------------------------------------------
 
-U32 SpriteBatchQuery::renderQueryPoint( const Vector2& point )
+U32 SpriteBatchQuery::queryPoint( const Vector2& point, const bool targetOOBB )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(SpriteBatchQuery_RenderQueryPoint);
+    PROFILE_SCOPE(SpriteBatchQuery_QueryPoint);
 
     mMasterQueryKey++;
 
@@ -134,12 +143,13 @@ U32 SpriteBatchQuery::renderQueryPoint( const Vector2& point )
     mIsRaycastQueryResult = false;
 
     // Query.
-    b2RayCastInput rayInput;
-    rayInput.p1 = point;
-    rayInput.p2 = b2Vec2( point.x + b2_linearSlop, point.y + b2_linearSlop );
-    rayInput.maxFraction = 1.0f;
-
-    RayCast( this, rayInput );
+    b2AABB aabb;
+    aabb.lowerBound = point;
+    aabb.upperBound = point;
+    mCompareTransform.SetIdentity();
+    mCheckOOBB = targetOOBB;
+    Query( this, aabb );
+    mCheckOOBB = false;
 
     return getQueryResultsCount();
 }
@@ -180,6 +190,25 @@ bool SpriteBatchQuery::QueryCallback( S32 proxyId )
     if ( pSpriteBatchItem->getSpriteBatchQueryKey() == mMasterQueryKey )
         return true;
 
+    // Check OOBB.
+    if ( mCheckOOBB )
+    {
+            // Fetch the shapes render OOBB.
+        b2PolygonShape oobb;
+        oobb.Set( pSpriteBatchItem->getRenderOOBB(), 4);
+
+        if ( mCheckPoint )
+        {
+            if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) )
+                return true;
+        }
+        else
+        {
+            if ( !b2TestOverlap( &mCompareShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
+                return true;
+        }
+    }
+
     // Tag with world query key.
     pSpriteBatchItem->setSpriteBatchQueryKey( mMasterQueryKey );
 
@@ -203,6 +232,17 @@ F32 SpriteBatchQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId
     if ( pSpriteBatchItem->getSpriteBatchQueryKey() == mMasterQueryKey )
         return 1.0f;
 
+    // Check OOBB.
+    if ( mCheckOOBB )
+    {
+        // Fetch the shapes render OOBB.
+        b2PolygonShape oobb;
+        oobb.Set( pSpriteBatchItem->getRenderOOBB(), 4);
+        b2RayCastOutput rayOutput;
+        if ( !oobb.RayCast( &rayOutput, mCompareRay, mCompareTransform, 0 ) )
+            return true;
+    }
+
     // Tag with world query key.
     pSpriteBatchItem->setSpriteBatchQueryKey( mMasterQueryKey );
 

+ 10 - 6
engine/source/2d/core/SpriteBatchQuery.h

@@ -48,10 +48,10 @@ public:
     void            remove( SpriteBatchItem* pSpriteBatchItem );
     bool            update( SpriteBatchItem* pSpriteBatchItem, const b2AABB& aabb, const b2Vec2& displacement );
 
-    //// Render queries.
-    U32             renderQueryArea( const b2AABB& aabb );
-    U32             renderQueryRay( const Vector2& point1, const Vector2& point2 );
-    U32             renderQueryPoint( const Vector2& point );
+    //// Spatial queries.
+    U32             queryArea( const b2AABB& aabb, const bool targetOOBB );
+    U32             queryRay( const Vector2& point1, const Vector2& point2, const bool targetOOBB );
+    U32             queryPoint( const Vector2& point, const bool targetOOBB );
  
     /// Results.
     void            clearQuery( void );
@@ -74,8 +74,12 @@ private:
 
 private:
     SpriteBatch*                mpSpriteBatch;
-    bool                        mCheckFixturePoint;
-    b2Vec2                      mFixturePoint;
+    b2PolygonShape              mCompareShape;
+    b2RayCastInput              mCompareRay;
+    b2Vec2                      mComparePoint;
+    b2Transform                 mCompareTransform;
+    bool                        mCheckOOBB;
+    bool                        mCheckPoint;
     typeSpriteBatchQueryResultVector mQueryResults;
     bool                        mIsRaycastQueryResult;
     typeSceneObjectVector       mAlwaysInScopeSet;

+ 3 - 2
engine/source/2d/scene/Scene.cc

@@ -991,7 +991,7 @@ void Scene::sceneRender( const SceneRenderState* pSceneRenderState )
     mpWorldQuery->setQueryFilter( queryFilter );
 
     // Query render AABB.
-    mpWorldQuery->renderQueryArea( cameraAABB );
+    mpWorldQuery->aabbQueryArea( cameraAABB );
 
     // Debug Profiling.
     PROFILE_END();  //Scene_RenderSceneVisibleQuery
@@ -5312,7 +5312,8 @@ b2JointType Scene::getJointTypeEnum(const char* label)
 static EnumTable::Enums pickModeLookup[] =
                 {
                 { Scene::PICK_ANY,          "Any" },
-                { Scene::PICK_SIZE,         "Size" },
+                { Scene::PICK_AABB,         "AABB" },
+                { Scene::PICK_OOBB,         "OOBB" },
                 { Scene::PICK_COLLISION,    "Collision" },
                 };
 

+ 2 - 1
engine/source/2d/scene/Scene.h

@@ -198,7 +198,8 @@ public:
         PICK_INVALID,
         ///---
         PICK_ANY,
-        PICK_SIZE,
+        PICK_AABB,
+        PICK_OOBB,
         PICK_COLLISION,
     };
 

+ 123 - 110
engine/source/2d/scene/Scene_ScriptBinding.h

@@ -2307,7 +2307,7 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou
               "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n"
               "@param sceneGroupMask Optional scene group mask.  (-1) or empty string selects all groups.\n"
               "@param sceneLayerMask Optional scene layer mask.  (-1) or empty string selects all layers.\n"
-              "@param pickMode Optional mode 'any', 'size' or 'collision' (default is 'size').\n"
+              "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'oobb').\n"
               "@return Returns list of object IDs.")
 {
     // Upper left and lower right bound.
@@ -2370,7 +2370,7 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou
     }
 
     // Calculate pick mode.
-    Scene::PickMode pickMode = Scene::PICK_SIZE;
+    Scene::PickMode pickMode = Scene::PICK_OOBB;
     if ( (U32)argc > (firstArg + 2))
     {
         pickMode = Scene::getPickModeEnum(argv[firstArg + 2]);
@@ -2378,7 +2378,7 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou
     if ( pickMode == Scene::PICK_INVALID )
     {
         Con::warnf("Scene::pickArea() - Invalid pick mode of %s", argv[firstArg + 2]);
-        pickMode = Scene::PICK_SIZE;
+        pickMode = Scene::PICK_OOBB;
     }
 
 
@@ -2401,13 +2401,17 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou
     {
         pWorldQuery->anyQueryArea( aabb );    
     }
-    else if ( pickMode == Scene::PICK_SIZE )
+    else if ( pickMode == Scene::PICK_AABB )
     {
-        pWorldQuery->renderQueryArea( aabb );    
+        pWorldQuery->aabbQueryArea( aabb );    
+    }
+    else if ( pickMode == Scene::PICK_OOBB )
+    {
+        pWorldQuery->oobbQueryArea( aabb );    
     }
     else if ( pickMode == Scene::PICK_COLLISION )
     {
-        pWorldQuery->fixtureQueryArea( aabb );    
+        pWorldQuery->collisionQueryArea( aabb );    
     }
     else
     {
@@ -2462,7 +2466,7 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup
               "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n"
               "@param sceneGroupMask Optional scene group mask.  (-1) or empty string selects all groups.\n"
               "@param sceneLayerMask Optional scene layer mask.  (-1) or empty string selects all layers.\n"
-              "@param pickMode Optional mode 'any', 'size' or 'collision' (default is 'size').\n"
+              "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'oobb').\n"
               "@return Returns list of object IDs.")
 {
     // Upper left and lower right bound.
@@ -2525,7 +2529,7 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup
     }
 
     // Calculate pick mode.
-    Scene::PickMode pickMode = Scene::PICK_SIZE;
+    Scene::PickMode pickMode = Scene::PICK_OOBB;
     if ( (U32)argc > (firstArg + 2))
     {
         pickMode = Scene::getPickModeEnum(argv[firstArg + 2]);
@@ -2533,7 +2537,7 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup
     if ( pickMode == Scene::PICK_INVALID )
     {
         Con::warnf("Scene::pickRay() - Invalid pick mode of %s", argv[firstArg + 2]);
-        pickMode = Scene::PICK_SIZE;
+        pickMode = Scene::PICK_OOBB;
     }
 
 
@@ -2549,13 +2553,17 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup
     {
         pWorldQuery->anyQueryRay( v1, v2 );    
     }
-    else if ( pickMode == Scene::PICK_SIZE )
+    else if ( pickMode == Scene::PICK_AABB )
+    {
+        pWorldQuery->aabbQueryRay( v1, v2 );    
+    }
+    else if ( pickMode == Scene::PICK_OOBB )
     {
-        pWorldQuery->renderQueryRay( v1, v2 );    
+        pWorldQuery->oobbQueryRay( v1, v2 );    
     }
     else if ( pickMode == Scene::PICK_COLLISION )
     {
-        pWorldQuery->fixtureQueryRay( v1, v2 );    
+        pWorldQuery->collisionQueryRay( v1, v2 );    
     }
     else
     {
@@ -2611,55 +2619,40 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup
 
 //-----------------------------------------------------------------------------
 
-ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [sceneGroupMask], [sceneLayerMask] ) Picks objects with collision shapes intersecting the specified ray with optional group/layer masks.\n"
-                "Unlike other pick methods, this returns the complete detail for each object encountered, returning the collision point, normal and fraction of the ray intersection.\n"
-                "@param startx/y The coordinates of the start point as either (\"x y\") or (x,y)\n"
-                "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n"
-                "@param sceneGroupMask Optional scene group mask.  (-1) or empty string selects all groups.\n"
-                "@param sceneLayerMask Optional scene layer mask.  (-1) or empty string selects all layers.\n"
-                "@return Returns a list of objects in blocks of detail items where each block represents a single object and its collision detail in the format:"
-                "<ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> etc.\n")
+ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified point with optional group/layer masks.\n"
+              "@param x/y The coordinate of the point as either (\"x y\") or (x,y)\n"
+              "@param sceneGroupMask Optional scene group mask.  (-1) or empty string selects all groups.\n"
+              "@param sceneLayerMask Optional scene layer mask.  (-1) or empty string selects all layers.\n"
+              "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'ooabb').\n"
+              "@return Returns list of object IDs.")
 {
-    // Upper left and lower right bound.
-    Vector2 v1, v2;
+    // The point.
+    Vector2 point;
 
     // The index of the first optional parameter.
     U32 firstArg;
 
-    // Grab the number of elements in the first two parameters.
-    U32 elementCount1 = Utility::mGetStringElementCount(argv[2]);
-    U32 elementCount2 = 1;
-    if (argc > 3)
-        elementCount2 = Utility::mGetStringElementCount(argv[3]);
+    // Grab the number of elements in the first parameter.
+    U32 elementCount = Utility::mGetStringElementCount(argv[2]);
 
-    // ("x1 y1 x2 y2")
-    if ((elementCount1 == 4) && (argc < 9))
+    // ("x y")
+    if ((elementCount == 2) && (argc < 8))
     {
-        v1 = Utility::mGetStringElementVector(argv[2]);
-        v2 = Utility::mGetStringElementVector(argv[2], 2);
+        point = Utility::mGetStringElementVector(argv[2]);
         firstArg = 3;
     }
    
-    // ("x1 y1", "x2 y2")
-    else if ((elementCount1 == 2) && (elementCount2 == 2) && (argc > 3) && (argc < 9))
+    // (x, y)
+    else if ((elementCount == 1) && (argc > 3))
     {
-        v1 = Utility::mGetStringElementVector(argv[2]);
-        v2 = Utility::mGetStringElementVector(argv[3]);
+        point = Vector2(dAtof(argv[2]), dAtof(argv[3]));
         firstArg = 4;
     }
    
-    // (x1, y1, x2, y2)
-    else if (argc > 5)
-    {
-        v1 = Vector2(dAtof(argv[2]), dAtof(argv[3]));
-        v2 = Vector2(dAtof(argv[4]), dAtof(argv[5]));
-        firstArg = 6;
-    }
-   
     // Invalid
     else
     {
-        Con::warnf("Scene::pickRayCollision() - Invalid number of parameters!");
+        Con::warnf("Scene::pickPoint() - Invalid number of parameters!");
         return NULL;
     }
 
@@ -2679,6 +2672,19 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s
             sceneLayerMask = dAtoi(argv[firstArg + 1]);
     }
 
+    // Calculate pick mode.
+    Scene::PickMode pickMode = Scene::PICK_OOBB;
+    if ( (U32)argc > (firstArg + 2 ))
+    {
+        pickMode = Scene::getPickModeEnum(argv[firstArg + 2]);
+    }
+    if ( pickMode == Scene::PICK_INVALID )
+    {
+        Con::warnf("Scene::pickPoint() - Invalid pick mode of %s", argv[firstArg + 2]);
+        pickMode = Scene::PICK_OOBB;
+    }
+
+
     // Fetch world query and clear results.
     WorldQuery* pWorldQuery = object->getWorldQuery( true );
 
@@ -2687,10 +2693,26 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s
     pWorldQuery->setQueryFilter( queryFilter );
 
     // Perform query.
-    pWorldQuery->fixtureQueryRay( v1, v2 );    
-
-    // Sanity!
-    AssertFatal( pWorldQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." );
+    if ( pickMode == Scene::PICK_ANY )
+    {
+        pWorldQuery->anyQueryPoint( point );    
+    }
+    else if ( pickMode == Scene::PICK_AABB )
+    {
+        pWorldQuery->aabbQueryPoint( point );    
+    }
+    else if ( pickMode == Scene::PICK_OOBB )
+    {
+        pWorldQuery->oobbQueryPoint( point );    
+    }
+    else if ( pickMode == Scene::PICK_COLLISION )
+    {
+        pWorldQuery->collisionQueryPoint( point );    
+    }
+    else
+    {
+        AssertFatal( false, "Unsupported pick mode." );
+    }
 
     // Fetch result count.
     const U32 resultCount = pWorldQuery->getQueryResultsCount();
@@ -2699,9 +2721,6 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s
     if ( resultCount == 0 )
         return NULL;
 
-    // Sort ray-cast result.
-    pWorldQuery->sortRaycastQueryResult();
-
     // Fetch results.
     typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults();
 
@@ -2717,21 +2736,14 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s
     // Add Picked Objects to List.
     for ( U32 n = 0; n < resultCount; n++ )
     {
-        // Fetch query result.
-        const WorldQueryResult& queryResult = queryResults[n];
-
-        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d %g %g %g %g %g %d ",
-            queryResult.mpSceneObject->getId(),
-            queryResult.mPoint.x, queryResult.mPoint.y,
-            queryResult.mNormal.x, queryResult.mNormal.y,
-            queryResult.mFraction,
-            queryResult.mShapeIndex );
+        // Output Object ID.
+        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d ", queryResults[n].mpSceneObject->getId() );
 
         // Finish early if we run out of buffer space.
         if ( bufferCount >= maxBufferSize )
         {
             // Warn.
-            Con::warnf("Scene::pickRayCollision() - Too many items picked to return to scripts!");
+            Con::warnf("Scene::pickPoint() - Too many items picked to return to scripts!");
             break;
         }
     }
@@ -2743,42 +2755,58 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s
     return pBuffer;
 }
 
+
 //-----------------------------------------------------------------------------
 
-ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified point with optional group/layer masks.\n"
-              "@param x/y The coordinate of the point as either (\"x y\") or (x,y)\n"
-              "@param sceneGroupMask Optional scene group mask.  (-1) or empty string selects all groups.\n"
-              "@param sceneLayerMask Optional scene layer mask.  (-1) or empty string selects all layers.\n"
-              "@param pickMode Optional mode 'any', 'size' or 'collision' (default is 'size').\n"
-              "@return Returns list of object IDs.")
+ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [sceneGroupMask], [sceneLayerMask] ) Picks objects with collision shapes intersecting the specified ray with optional group/layer masks.\n"
+                "Unlike other pick methods, this returns the complete detail for each object encountered, returning the collision point, normal and fraction of the ray intersection.\n"
+                "@param startx/y The coordinates of the start point as either (\"x y\") or (x,y)\n"
+                "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n"
+                "@param sceneGroupMask Optional scene group mask.  (-1) or empty string selects all groups.\n"
+                "@param sceneLayerMask Optional scene layer mask.  (-1) or empty string selects all layers.\n"
+                "@return Returns a list of objects in blocks of detail items where each block represents a single object and its collision detail in the format:"
+                "<ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> etc.\n")
 {
-    // The point.
-    Vector2 point;
+    // Upper left and lower right bound.
+    Vector2 v1, v2;
 
     // The index of the first optional parameter.
     U32 firstArg;
 
-    // Grab the number of elements in the first parameter.
-    U32 elementCount = Utility::mGetStringElementCount(argv[2]);
+    // Grab the number of elements in the first two parameters.
+    U32 elementCount1 = Utility::mGetStringElementCount(argv[2]);
+    U32 elementCount2 = 1;
+    if (argc > 3)
+        elementCount2 = Utility::mGetStringElementCount(argv[3]);
 
-    // ("x y")
-    if ((elementCount == 2) && (argc < 8))
+    // ("x1 y1 x2 y2")
+    if ((elementCount1 == 4) && (argc < 9))
     {
-        point = Utility::mGetStringElementVector(argv[2]);
+        v1 = Utility::mGetStringElementVector(argv[2]);
+        v2 = Utility::mGetStringElementVector(argv[2], 2);
         firstArg = 3;
     }
    
-    // (x, y)
-    else if ((elementCount == 1) && (argc > 3))
+    // ("x1 y1", "x2 y2")
+    else if ((elementCount1 == 2) && (elementCount2 == 2) && (argc > 3) && (argc < 9))
     {
-        point = Vector2(dAtof(argv[2]), dAtof(argv[3]));
+        v1 = Utility::mGetStringElementVector(argv[2]);
+        v2 = Utility::mGetStringElementVector(argv[3]);
         firstArg = 4;
     }
    
+    // (x1, y1, x2, y2)
+    else if (argc > 5)
+    {
+        v1 = Vector2(dAtof(argv[2]), dAtof(argv[3]));
+        v2 = Vector2(dAtof(argv[4]), dAtof(argv[5]));
+        firstArg = 6;
+    }
+   
     // Invalid
     else
     {
-        Con::warnf("Scene::pickPoint() - Invalid number of parameters!");
+        Con::warnf("Scene::pickRayCollision() - Invalid number of parameters!");
         return NULL;
     }
 
@@ -2798,19 +2826,6 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s
             sceneLayerMask = dAtoi(argv[firstArg + 1]);
     }
 
-    // Calculate pick mode.
-    Scene::PickMode pickMode = Scene::PICK_SIZE;
-    if ( (U32)argc > (firstArg + 2 ))
-    {
-        pickMode = Scene::getPickModeEnum(argv[firstArg + 2]);
-    }
-    if ( pickMode == Scene::PICK_INVALID )
-    {
-        Con::warnf("Scene::pickPoint() - Invalid pick mode of %s", argv[firstArg + 2]);
-        pickMode = Scene::PICK_SIZE;
-    }
-
-
     // Fetch world query and clear results.
     WorldQuery* pWorldQuery = object->getWorldQuery( true );
 
@@ -2819,22 +2834,10 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s
     pWorldQuery->setQueryFilter( queryFilter );
 
     // Perform query.
-    if ( pickMode == Scene::PICK_ANY )
-    {
-        pWorldQuery->anyQueryPoint( point );    
-    }
-    else if ( pickMode == Scene::PICK_SIZE )
-    {
-        pWorldQuery->renderQueryPoint( point );    
-    }
-    else if ( pickMode == Scene::PICK_COLLISION )
-    {
-        pWorldQuery->fixtureQueryPoint( point );    
-    }
-    else
-    {
-        AssertFatal( false, "Unsupported pick mode." );
-    }
+    pWorldQuery->collisionQueryRay( v1, v2 );    
+
+    // Sanity!
+    AssertFatal( pWorldQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." );
 
     // Fetch result count.
     const U32 resultCount = pWorldQuery->getQueryResultsCount();
@@ -2843,6 +2846,9 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s
     if ( resultCount == 0 )
         return NULL;
 
+    // Sort ray-cast result.
+    pWorldQuery->sortRaycastQueryResult();
+
     // Fetch results.
     typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults();
 
@@ -2858,14 +2864,21 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s
     // Add Picked Objects to List.
     for ( U32 n = 0; n < resultCount; n++ )
     {
-        // Output Object ID.
-        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d ", queryResults[n].mpSceneObject->getId() );
+        // Fetch query result.
+        const WorldQueryResult& queryResult = queryResults[n];
+
+        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d %g %g %g %g %g %d ",
+            queryResult.mpSceneObject->getId(),
+            queryResult.mPoint.x, queryResult.mPoint.y,
+            queryResult.mNormal.x, queryResult.mNormal.y,
+            queryResult.mFraction,
+            queryResult.mShapeIndex );
 
         // Finish early if we run out of buffer space.
         if ( bufferCount >= maxBufferSize )
         {
             // Warn.
-            Con::warnf("Scene::pickPoint() - Too many items picked to return to scripts!");
+            Con::warnf("Scene::pickRayCollision() - Too many items picked to return to scripts!");
             break;
         }
     }

+ 175 - 56
engine/source/2d/scene/WorldQuery.cc

@@ -39,9 +39,9 @@ WorldQuery::WorldQuery( Scene* pScene ) :
         mpScene(pScene),
         mIsRaycastQueryResult(false),
         mMasterQueryKey(0),
-        mCheckFixturePoint(false),
-        mCheckFixtureArea(false),
-        mFixturePoint(0.0f, 0.0f)
+        mCheckPoint(false),
+        mCheckArea(false),
+        mCheckOOBB(false)
 {
     // Set debug associations.
     for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
@@ -131,10 +131,10 @@ void WorldQuery::removeAlwaysInScope( SceneObject* pSceneObject )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb )
+U32 WorldQuery::collisionQueryArea( const b2AABB& aabb )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_FixtureQueryArea);
+    PROFILE_SCOPE(WorldQuery_CollisionQueryArea);
 
     mMasterQueryKey++;
 
@@ -142,16 +142,16 @@ U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb )
     mIsRaycastQueryResult = false;
 
     // Query.
-    mCheckFixtureArea = true;
     b2Vec2 verts[4];
     verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
     verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
     verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
     verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
-    mFixtureAreaShape.Set( verts, 4);
-    mFixtureAreaTransform.SetIdentity();
+    mCompareShape.Set( verts, 4 );
+    mCompareTransform.SetIdentity();
+    mCheckArea = true;
     mpScene->getWorld()->QueryAABB( this, aabb );
-    mCheckFixtureArea = false;
+    mCheckArea = false;
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -161,10 +161,10 @@ U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::fixtureQueryRay( const Vector2& point1, const Vector2& point2 )
+U32 WorldQuery::collisionQueryRay( const Vector2& point1, const Vector2& point2 )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_FixtureQueryRay);
+    PROFILE_SCOPE(WorldQuery_CollisionQueryRay);
 
     mMasterQueryKey++;
 
@@ -182,10 +182,10 @@ U32 WorldQuery::fixtureQueryRay( const Vector2& point1, const Vector2& point2 )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::fixtureQueryPoint( const Vector2& point )
+U32 WorldQuery::collisionQueryPoint( const Vector2& point )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_FixtureQueryPoint);
+    PROFILE_SCOPE(WorldQuery_CollisionQueryPoint);
 
     mMasterQueryKey++;
 
@@ -196,10 +196,10 @@ U32 WorldQuery::fixtureQueryPoint( const Vector2& point )
     b2AABB aabb;
     aabb.lowerBound = point;
     aabb.upperBound = point;
-    mCheckFixturePoint = true;
-    mFixturePoint = point;
+    mCheckPoint = true;
+    mComparePoint = point;
     mpScene->getWorld()->QueryAABB( this, aabb );
-    mCheckFixturePoint = false;
+    mCheckPoint = false;
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -209,10 +209,10 @@ U32 WorldQuery::fixtureQueryPoint( const Vector2& point )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::renderQueryArea( const b2AABB& aabb )
+U32 WorldQuery::aabbQueryArea( const b2AABB& aabb )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_RenderQueryArea);
+    PROFILE_SCOPE(WorldQuery_AABBQueryArea);
 
     mMasterQueryKey++;
 
@@ -230,10 +230,10 @@ U32 WorldQuery::renderQueryArea( const b2AABB& aabb )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 )
+U32 WorldQuery::aabbQueryRay( const Vector2& point1, const Vector2& point2 )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_RenderQueryRay);
+    PROFILE_SCOPE(WorldQuery_AABBQueryRay);
 
     mMasterQueryKey++;
 
@@ -241,13 +241,35 @@ U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 )
     mIsRaycastQueryResult = true;
 
     // Query.
-    b2RayCastInput rayInput;
-    rayInput.p1 = point1;
-    rayInput.p2 = point2;
+    mCompareRay.p1 = point1;
+    mCompareRay.p2 = point2;
+    mCompareRay.maxFraction = 1.0f;
+    mCompareTransform.SetIdentity();
+    RayCast( this, mCompareRay );
 
-    rayInput.maxFraction = 1.0f;
+    // Inject always-in-scope.
+    injectAlwaysInScope();
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+U32 WorldQuery::aabbQueryPoint( const Vector2& point )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(WorldQuery_AABBQueryPoint);
+
+    mMasterQueryKey++;
 
-    RayCast( this, rayInput );
+    // Flag as not a ray-cast query result.
+    mIsRaycastQueryResult = false;
+
+    // Query.
+    b2AABB aabb;
+    aabb.lowerBound = point;
+    aabb.upperBound = point;
+    Query( this, aabb );
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -257,10 +279,10 @@ U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::renderQueryPoint( const Vector2& point )
+U32 WorldQuery::oobbQueryArea( const b2AABB& aabb )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_RenderQueryPoint);
+    PROFILE_SCOPE(WorldQuery_AABBQueryArea);
 
     mMasterQueryKey++;
 
@@ -268,12 +290,73 @@ U32 WorldQuery::renderQueryPoint( const Vector2& point )
     mIsRaycastQueryResult = false;
 
     // Query.
-    b2RayCastInput rayInput;
-    rayInput.p1 = point;
-    rayInput.p2 = b2Vec2( point.x + b2_linearSlop, point.y + b2_linearSlop );
-    rayInput.maxFraction = 1.0f;
+    b2Vec2 verts[4];
+    verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y );
+    verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y );
+    verts[2].Set( aabb.upperBound.x, aabb.upperBound.y );
+    verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y );
+    mCompareShape.Set( verts, 4 );
+    mCompareTransform.SetIdentity();
+    mCheckOOBB = true;
+    Query( this, aabb );
+    mCheckOOBB = false;
+
+    // Inject always-in-scope.
+    injectAlwaysInScope();
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+U32 WorldQuery::oobbQueryRay( const Vector2& point1, const Vector2& point2 )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(WorldQuery_AABBQueryRay);
+
+    mMasterQueryKey++;
+
+    // Flag as a ray-cast query result.
+    mIsRaycastQueryResult = true;
 
-    RayCast( this, rayInput );
+    // Query.
+    mCompareRay.p1 = point1;
+    mCompareRay.p2 = point2;
+    mCompareRay.maxFraction = 1.0f;
+    mCompareTransform.SetIdentity();
+    mCheckOOBB = true;
+    RayCast( this, mCompareRay );
+    mCheckOOBB = false;
+
+    // Inject always-in-scope.
+    injectAlwaysInScope();
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+U32 WorldQuery::oobbQueryPoint( const Vector2& point )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(WorldQuery_AABBQueryPoint);
+
+    mMasterQueryKey++;
+
+    // Flag as not a ray-cast query result.
+    mIsRaycastQueryResult = false;
+
+    // Query.
+    b2AABB aabb;
+    aabb.lowerBound = point;
+    aabb.upperBound = point;
+    mComparePoint = point;
+    mCompareTransform.SetIdentity();
+    mCheckOOBB = true;
+    mCheckPoint = true;
+    Query( this, aabb );
+    mCheckPoint = false;
+    mCheckOOBB = false;
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -289,9 +372,11 @@ U32 WorldQuery::anyQueryArea( const b2AABB& aabb )
     PROFILE_SCOPE(WorldQuery_AnyQueryAreaAABB);
 
     // Query.
-    renderQueryArea( aabb );
+    aabbQueryArea( aabb );
+    mMasterQueryKey--;
+    oobbQueryArea( aabb );
     mMasterQueryKey--;
-    fixtureQueryArea( aabb );
+    collisionQueryArea( aabb );
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -323,9 +408,11 @@ U32 WorldQuery::anyQueryRay( const Vector2& point1, const Vector2& point2 )
     PROFILE_SCOPE(WorldQuery_AnyQueryRay);
 
     // Query.
-    renderQueryRay( point1, point2 );
+    aabbQueryRay( point1, point2 );
     mMasterQueryKey--;
-    fixtureQueryRay( point1, point2 );
+    oobbQueryRay( point1, point2 );
+    mMasterQueryKey--;
+    collisionQueryRay( point1, point2 );
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -341,9 +428,11 @@ U32 WorldQuery::anyQueryPoint( const Vector2& point )
     PROFILE_SCOPE(WorldQuery_AnyQueryPoint);
 
     // Query.
-    renderQueryPoint( point );
+    aabbQueryPoint( point );
+    mMasterQueryKey--;
+    oobbQueryPoint( point );
     mMasterQueryKey--;
-    fixtureQueryPoint( point );
+    collisionQueryPoint( point );
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -435,18 +524,15 @@ bool WorldQuery::ReportFixture( b2Fixture* fixture )
     if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
         return true;
 
-    // Check fixture point.
-    if ( mCheckFixturePoint && !fixture->TestPoint( mFixturePoint ) )
+    // Check collision point.
+    if ( mCheckPoint && !fixture->TestPoint( mComparePoint ) )
         return true;
 
-    // Check fixture area.
-    if ( mCheckFixtureArea )
-        if ( !b2TestOverlap( &mFixtureAreaShape, 0, fixture->GetShape(), 0, mFixtureAreaTransform, fixture->GetBody()->GetTransform() ) )
+    // Check collision area.
+    if ( mCheckArea )
+        if ( !b2TestOverlap( &mCompareShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) )
         return true;
 
-    // Tag with world query key.
-    pSceneObject->setWorldQueryKey( mMasterQueryKey );
-
     // Fetch layer and group masks.
     const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
     const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
@@ -457,6 +543,9 @@ bool WorldQuery::ReportFixture( b2Fixture* fixture )
         WorldQueryResult queryResult( pSceneObject );
         mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
         mQueryResults.push_back( queryResult );
+
+        // Tag with world query key.
+        pSceneObject->setWorldQueryKey( mMasterQueryKey );
     }
 
     return true;
@@ -493,9 +582,6 @@ F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2
     if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
         return 1.0f;
 
-    // Tag with world query key.
-    pSceneObject->setWorldQueryKey( mMasterQueryKey );
-
     // Fetch layer and group masks.
     const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
     const U32 sceneGroupMask = pSceneObject->getSceneGroupMask();
@@ -512,6 +598,9 @@ F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2
         WorldQueryResult queryResult( pSceneObject, point, normal, fraction, (U32)shapeIndex );
         mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
         mQueryResults.push_back( queryResult );
+
+        // Tag with world query key.
+        pSceneObject->setWorldQueryKey( mMasterQueryKey );
     }
 
     return 1.0f;
@@ -548,8 +637,24 @@ bool WorldQuery::QueryCallback( S32 proxyId )
     if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
         return true;
 
-    // Tag with world query key.
-    pSceneObject->setWorldQueryKey( mMasterQueryKey );
+    // Check OOBB.
+    if ( mCheckOOBB )
+    {
+            // Fetch the shapes render OOBB.
+        b2PolygonShape oobb;
+        oobb.Set( pSceneObject->getRenderOOBB(), 4);
+
+        if ( mCheckPoint )
+        {
+            if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) )
+                return true;
+        }
+        else
+        {
+            if ( !b2TestOverlap( &mCompareShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
+                return true;
+        }
+    }
 
     // Fetch layer and group masks.
     const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
@@ -561,6 +666,9 @@ bool WorldQuery::QueryCallback( S32 proxyId )
         WorldQueryResult queryResult( pSceneObject );
         mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
         mQueryResults.push_back( queryResult );
+
+        // Tag with world query key.
+        pSceneObject->setWorldQueryKey( mMasterQueryKey );
     }
 
     return true;
@@ -597,8 +705,16 @@ F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId )
     if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() )
         return 1.0f;
 
-    // Tag with world query key.
-    pSceneObject->setWorldQueryKey( mMasterQueryKey );
+    // Check OOBB.
+    if ( mCheckOOBB )
+    {
+        // Fetch the shapes render OOBB.
+        b2PolygonShape oobb;
+        oobb.Set( pSceneObject->getRenderOOBB(), 4);
+        b2RayCastOutput rayOutput;
+        if ( !oobb.RayCast( &rayOutput, mCompareRay, mCompareTransform, 0 ) )
+            return true;
+    }
 
     // Fetch layer and group masks.
     const U32 sceneLayerMask = pSceneObject->getSceneLayerMask();
@@ -610,6 +726,9 @@ F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId )
         WorldQueryResult queryResult( pSceneObject );
         mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
         mQueryResults.push_back( queryResult );
+
+        // Tag with world query key.
+        pSceneObject->setWorldQueryKey( mMasterQueryKey );
     }
 
     return 1.0f;
@@ -636,9 +755,6 @@ void WorldQuery::injectAlwaysInScope( void )
         if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey )
             continue;
 
-        // Tag with world query key.
-        pSceneObject->setWorldQueryKey( mMasterQueryKey );
-
         // Enabled filter.
         if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() )
             continue;
@@ -661,6 +777,9 @@ void WorldQuery::injectAlwaysInScope( void )
             WorldQueryResult queryResult( pSceneObject );
             mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult );
             mQueryResults.push_back( queryResult );
+
+            // Tag with world query key.
+            pSceneObject->setWorldQueryKey( mMasterQueryKey );
         }
     }
 }

+ 23 - 16
engine/source/2d/scene/WorldQuery.h

@@ -56,17 +56,22 @@ public:
     void            addAlwaysInScope( SceneObject* pSceneObject );
     void            removeAlwaysInScope( SceneObject* pSceneObject );
 
-    //// World fixture queries.
-    U32             fixtureQueryArea( const b2AABB& aabb );
-    U32             fixtureQueryRay( const Vector2& point1, const Vector2& point2 );
-    U32             fixtureQueryPoint( const Vector2& point );
-
-    //// Render queries.
-    U32             renderQueryArea( const b2AABB& aabb );
-    U32             renderQueryRay( const Vector2& point1, const Vector2& point2 );
-    U32             renderQueryPoint( const Vector2& point );
-
-    /// World fixture & render queries.
+    /// World collision-shape queries.
+    U32             collisionQueryArea( const b2AABB& aabb );
+    U32             collisionQueryRay( const Vector2& point1, const Vector2& point2 );
+    U32             collisionQueryPoint( const Vector2& point );
+
+    /// AABB queries.
+    U32             aabbQueryArea( const b2AABB& aabb );
+    U32             aabbQueryRay( const Vector2& point1, const Vector2& point2 );
+    U32             aabbQueryPoint( const Vector2& point );
+
+    /// OOBB queries.
+    U32             oobbQueryArea( const b2AABB& aabb );
+    U32             oobbQueryRay( const Vector2& point1, const Vector2& point2 );
+    U32             oobbQueryPoint( const Vector2& point );
+
+    /// Any queries.
     U32             anyQueryArea( const b2AABB& aabb );
     U32             anyQueryArea( const Vector2& lowerBound, const Vector2& upperBound );
     U32             anyQueryRay( const Vector2& point1, const Vector2& point2 );
@@ -96,11 +101,13 @@ private:
 private:
     Scene*                      mpScene;
     WorldQueryFilter            mQueryFilter;
-    b2PolygonShape              mFixtureAreaShape;
-    b2Transform                 mFixtureAreaTransform;
-    bool                        mCheckFixturePoint;
-    bool                        mCheckFixtureArea;
-    b2Vec2                      mFixturePoint;
+    b2PolygonShape              mCompareShape;
+    b2RayCastInput              mCompareRay;
+    b2Vec2                      mComparePoint;
+    b2Transform                 mCompareTransform;
+    bool                        mCheckPoint;
+    bool                        mCheckArea;
+    bool                        mCheckOOBB;
     typeWorldQueryResultVector  mLayeredQueryResults[MAX_LAYERS_SUPPORTED];
     typeWorldQueryResultVector  mQueryResults;
     bool                        mIsRaycastQueryResult;

+ 3 - 3
engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h

@@ -904,7 +904,7 @@ ConsoleMethod(CompositeSprite, pickPoint, const char*, 3, 4,    "(x / y ) Picks
     point = b2MulT( renderTransform, point );
 
     // Perform query.
-    pSpriteBatchQuery->renderQueryPoint( point );
+    pSpriteBatchQuery->queryPoint( point, true );
 
     // Fetch result count.
     const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount();
@@ -1028,7 +1028,7 @@ ConsoleMethod(CompositeSprite, pickArea, const char*, 4, 6, "(startx/y, endx/y )
     CoreMath::mRotateAABB( aabb, -renderTransform.q.GetAngle(), aabb );
 
     // Perform query.
-    pSpriteBatchQuery->renderQueryArea( aabb );
+    pSpriteBatchQuery->queryArea( aabb, true );
 
     // Fetch result count.
     const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount();
@@ -1142,7 +1142,7 @@ ConsoleMethod(CompositeSprite, pickRay, const char*, 4, 6,  "(startx/y, endx/y)
     v2 = b2MulT( renderTransform, v2 );
 
     // Perform query.
-    pSpriteBatchQuery->renderQueryRay( v1, v2 );
+    pSpriteBatchQuery->queryRay( v1, v2, true );
 
     // Sanity!
     AssertFatal( pSpriteBatchQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." );

+ 6 - 5
modules/PickingToy/1/main.cs

@@ -23,14 +23,14 @@
 function PickingToy::create( %this )
 {
     // Configure the toy.
-    PickingToy.PickType = Area;
+    PickingToy.PickType = Point;
     PickingToy.PickMode = Any;
-    PickingToy.NotPickedAlpha = 0.25;
-    PickingToy.PickAreaSize = 4;
+    PickingToy.NotPickedAlpha = 0.2;
+    PickingToy.PickAreaSize = 10;
 
     // Add the configuration options.
-    addSelectionOption( "Any,Size,Collision", "Pick Mode", 3, "setPickMode", false, "Selects the picking mode." );
-    addSelectionOption( "Area,Point", "Pick Type", 2, "setPickType", true, "Selects the picking type." );
+    addSelectionOption( "Any,AABB,OOBB,Collision", "Pick Mode", 4, "setPickMode", false, "Selects the picking mode." );
+    addSelectionOption( "Point,Area", "Pick Type", 2, "setPickType", true, "Selects the picking type." );
 
     // Force-on debug options.
     setAABBOption( true );
@@ -82,6 +82,7 @@ function PickingToy::createBackground( %this )
     %object.SceneLayer = 31;
     %object.Image = "ToyAssets:highlightBackground";
     %object.BlendColor = SlateGray;
+    %object.PickingAllowed = false;
 }
 
 //-----------------------------------------------------------------------------