Browse Source

- Changed the contact filter so that the contact rules is now such that a contact occurs if either A is configured to contact B OR B is configured to contact A. Previously both conditions (AND) were required which caused undue configuration.
- The contact rule above now also determines if an object gets a direct callback i.e. "onCollision()" and "onCollisionEnd()". To receive a callback you still need to have "CollisionCallback" set to true but if it is then the object only gets it if its configuration could cause a contact. This means that if, for instance, A was configured to collide with B but not B with A then A would get a callback but not B. Again, A would only get a callback if it had turned-on the collision-callback flag. Also note that if a contact is made then the "onSceneCollision()" and "onEndSceneCollision()" is always called.
- Updated the existing toys to take advantage of this improvement.

MelvMay-GG 12 years ago
parent
commit
6db2661

+ 11 - 6
engine/source/2d/scene/ContactFilter.cc

@@ -48,10 +48,15 @@ bool ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
     if ( pSceneObjectA->mCollisionSuppress || pSceneObjectB->mCollisionSuppress )
         return false;
 
-    // Check group/layer masks.
-    return
-        (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 &&
-        (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 &&
-        (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 &&
-        (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0;
+    // Check collision rule A -> B.
+    if ( (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 &&
+         (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 )
+         return true;
+
+    // Check collision rule B -> A.
+    if ( (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 &&
+         (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0 )
+         return true;
+
+    return false;
 }

+ 41 - 53
engine/source/2d/scene/Scene.cc

@@ -557,12 +557,8 @@ void Scene::dispatchBeginContactCallbacks( void )
         if ( pSceneObjectA->isBeingDeleted() || pSceneObjectB->isBeingDeleted() )
             continue;
 
-        // Fetch collision callback status.
-        const bool sceneObjectACallback = pSceneObjectA->getCollisionCallback();
-        const bool sceneObjectBCallback = pSceneObjectB->getCollisionCallback();
-
         // Skip if both objects don't have collision callback active.
-        if ( !sceneObjectACallback && !sceneObjectBCallback )
+        if ( !pSceneObjectA->getCollisionCallback() && !pSceneObjectB->getCollisionCallback() )
             continue;
 
         // Fetch normal and contact points.
@@ -621,29 +617,26 @@ void Scene::dispatchBeginContactCallbacks( void )
                 shapeIndexA, shapeIndexB );
 		}
 
-        // Do both objects have collision callback active?
-        if ( sceneObjectACallback && sceneObjectBCallback )
+        // Does the scene handle the collision callback?
+        Namespace* pNamespace = getNamespace();
+        if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneCollision" ) ) != NULL )
         {
-            // Yes, so does the scene handle the collision callback?
-            Namespace* pNamespace = getNamespace();
-            if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneCollision" ) ) != NULL )
-            {
-                // Yes, so perform script callback on the Scene.
-                Con::executef( this, 4, "onSceneCollision",
-                    pSceneObjectABuffer,
-                    pSceneObjectBBuffer,
-                    pMiscInfoBuffer );
-            }
-            else
-            {
-                // No, so call it on its behaviors.
-                const char* args[5] = { "onSceneCollision", this->getIdString(), pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer };
-                callOnBehaviors( 5, args );
-            }
+            // Yes, so perform script callback on the Scene.
+            Con::executef( this, 4, "onSceneCollision",
+                pSceneObjectABuffer,
+                pSceneObjectBBuffer,
+                pMiscInfoBuffer );
+        }
+        else
+        {
+            // No, so call it on its behaviors.
+            const char* args[5] = { "onSceneCollision", this->getIdString(), pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer };
+            callOnBehaviors( 5, args );
         }
 
-        // Does object A have collision callback active?
-        if ( sceneObjectACallback )
+        // Is object A allowed to collide with object B?
+        if (    (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 &&
+                (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 )
         {
             // Yes, so does it handle the collision callback?
             if ( pSceneObjectA->isMethod("onCollision") )            
@@ -661,8 +654,9 @@ void Scene::dispatchBeginContactCallbacks( void )
             }
         }
 
-        // Does object B have collision callback active?
-        if ( sceneObjectBCallback )
+        // Is object B allowed to collide with object A?
+        if (    (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 &&
+                (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0 )
         {
             // Yes, so does it handle the collision callback?
             if ( pSceneObjectB->isMethod("onCollision") )            
@@ -713,12 +707,8 @@ void Scene::dispatchEndContactCallbacks( void )
         if ( pSceneObjectA->isBeingDeleted() || pSceneObjectB->isBeingDeleted() )
             continue;
 
-        // Fetch collision callback status.
-        const bool sceneObjectACallback = pSceneObjectA->getCollisionCallback();
-        const bool sceneObjectBCallback = pSceneObjectB->getCollisionCallback();
-
         // Skip if both objects don't have collision callback active.
-        if ( !sceneObjectACallback && !sceneObjectBCallback )
+        if ( !pSceneObjectA->getCollisionCallback() && !pSceneObjectB->getCollisionCallback() )
             continue;
 
         // Fetch shape index.
@@ -739,29 +729,26 @@ void Scene::dispatchEndContactCallbacks( void )
         char* pMiscInfoBuffer = Con::getArgBuffer(32);
         dSprintf(pMiscInfoBuffer, 32, "%d %d", shapeIndexA, shapeIndexB );
 
-        // Do both objects have collision callback active?
-        if ( sceneObjectACallback && sceneObjectBCallback )
+        // Does the scene handle the collision callback?
+        Namespace* pNamespace = getNamespace();
+        if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneEndCollision" ) ) != NULL )
         {
             // Yes, so does the scene handle the collision callback?
-            Namespace* pNamespace = getNamespace();
-            if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneEndCollision" ) ) != NULL )
-            {
-                // Yes, so does the scene handle the collision callback?
-                Con::executef( this, 4, "onSceneEndCollision",
-                    pSceneObjectABuffer,
-                    pSceneObjectBBuffer,
-                    pMiscInfoBuffer );
-            }
-            else
-            {
-                // No, so call it on its behaviors.
-                const char* args[5] = { "onSceneEndCollision", this->getIdString(), pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer };
-                callOnBehaviors( 5, args );
-            }
+            Con::executef( this, 4, "onSceneEndCollision",
+                pSceneObjectABuffer,
+                pSceneObjectBBuffer,
+                pMiscInfoBuffer );
+        }
+        else
+        {
+            // No, so call it on its behaviors.
+            const char* args[5] = { "onSceneEndCollision", this->getIdString(), pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer };
+            callOnBehaviors( 5, args );
         }
 
-        // Does object A have collision callback active?
-        if ( sceneObjectACallback )
+        // Is object A allowed to collide with object B?
+        if (    (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 &&
+                (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 )
         {
             // Yes, so does it handle the collision callback?
             if ( pSceneObjectA->isMethod("onEndCollision") )            
@@ -779,8 +766,9 @@ void Scene::dispatchEndContactCallbacks( void )
             }
         }
 
-        // Does object B have collision callback active?
-        if ( sceneObjectBCallback )
+        // Is object B allowed to collide with object A?
+        if (    (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 &&
+                (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0 )
         {
             // Yes, so does it handle the collision callback?
             if ( pSceneObjectB->isMethod("onEndCollision") )            

+ 1 - 2
modules/AquariumToy/1/main.cs

@@ -95,10 +95,9 @@ function AquariumToy::spawnFish(%this)
         CollisionCallback = true;
     };
 
+    %fish.setCollisionGroups( none );
     %fish.createPolygonBoxCollisionShape( 15, 15);
-    %fish.setCollisionGroups( 15 );
     %fish.setDefaultDensity( 1 );
-    %fish.setDefaultFriction( 1.0 );
     SandboxScene.add( %fish );
 
     %this.currentFish++;

+ 1 - 1
modules/RestitutionToy/1/main.cs

@@ -112,7 +112,7 @@ function RestitutionToy::createGround( %this )
     %ground.setSize(RestitutionToy.GroundWidth, 6);
     %ground.setRepeatX(RestitutionToy.GroundWidth / 60);   
     %ground.setSceneGroup( 1 );
-    %ground.setCollisionGroups( 2 );
+    %ground.setCollisionGroups( none );
     %ground.createEdgeCollisionShape(RestitutionToy.GroundWidth/-2, 3, RestitutionToy.GroundWidth/2, 3);
     SandboxScene.add(%ground);  
     

+ 13 - 12
modules/TruckToy/1/main.cs

@@ -35,6 +35,7 @@ function TruckToy::create( %this )
     TruckToy.BackdropDomain = 31;
     TruckToy.BackgroundDomain = 25;
     TruckToy.TruckDomain = 20;
+    TruckToy.GroundDomain = 18;
     TruckToy.ObstacleDomain = 15;
     TruckToy.ProjectileDomain = 16;
     TruckToy.ForegroundDomain = 10;    
@@ -226,9 +227,9 @@ function TruckToy::createFloor(%this)
     %obj.setPosition( 0, TruckToy.FloorLevel - (%obj.getSizeY()/2) );
     %obj.setRepeatX( TruckToy.WorldWidth / 12 );   
     %obj.setSceneLayer( TruckToy.ObstacleDomain );
-    %obj.setSceneGroup( TruckToy.ObstacleDomain );
+    %obj.setSceneGroup( TruckToy.GroundDomain );
     %obj.setDefaultFriction( TruckToy.ObstacleFriction );
-    %obj.setCollisionGroups( TruckToy.ObstacleDomain SPC TruckToy.ProjectileDomain );
+    %obj.setCollisionGroups( none );
     %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, 1.5, TruckToy.WorldWidth/2, 1.5 );
     %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, 3, TruckToy.WorldWidth/-2, 50 );
     %obj.createEdgeCollisionShape( TruckToy.WorldWidth/2, 3, TruckToy.WorldWidth/2, 50 );
@@ -345,7 +346,7 @@ function TruckToy::createBridge( %this, %posX, %posY, %linkCount )
       }
       else
       {      
-         %obj.setCollisionGroups( TruckToy.ObstacleDomain );   
+         %obj.setCollisionGroups( none );
          %obj.setDefaultDensity( 1 );
          %obj.setDefaultFriction( TruckToy.ObstacleFriction );
          %obj.createPolygonBoxCollisionShape( %linkWidth, %linkHeight );
@@ -406,7 +407,7 @@ function TruckToy::createChain( %this, %posX, %posY, %linkCount )
         
         %obj.setSceneLayer( TruckToy.BackgroundDomain-1 );
         %obj.setSceneGroup( TruckToy.ObstacleDomain );
-        %obj.setCollisionGroups( TruckToy.ObstacleDomain );
+        %obj.setCollisionGroups( none );
         %obj.setDefaultDensity( 1 );
         %obj.setDefaultFriction( 0.2 );
         %obj.createPolygonBoxCollisionShape( %linkWidth, %linkHeight );
@@ -521,7 +522,7 @@ function TruckToy::createBrick( %this, %brickNumber, %posX, %posY, %static )
     %obj.setSize( 1, 0.5 );
     %obj.setSceneLayer( TruckToy.ObstacleDomain );
     %obj.setSceneGroup( TruckToy.ObstacleDomain );
-    %obj.setCollisionGroups( TruckToy.ObstacleDomain );
+    %obj.setCollisionGroups( none );
     %obj.setDefaultFriction( TruckToy.ObstacleFriction );
     %obj.createPolygonBoxCollisionShape( 1, 0.5 );
     %obj.setAwake( false );
@@ -568,7 +569,7 @@ function TruckToy::createPlank( %this, %plankNumber, %posX, %posY, %angle, %stat
     %obj.setSceneLayer( TruckToy.ObstacleDomain );
     %obj.setSceneGroup( TruckToy.ObstacleDomain );
     %obj.setDefaultFriction( TruckToy.ObstacleFriction );
-    %obj.setCollisionGroups( TruckToy.ObstacleDomain );
+    %obj.setCollisionGroups( none );
     %obj.setAwake( false );
     %obj.setDefaultFriction( 1.0 );
 
@@ -607,7 +608,7 @@ function TruckToy::createWreckedCar( %this, %carNumber, %posX, %posY, %angle, %s
     %obj.setSize( 4, 1.5 );   
     %obj.setSceneLayer( TruckToy.ObstacleDomain );
     %obj.setSceneGroup( TruckToy.ObstacleDomain );
-    %obj.setCollisionGroups( TruckToy.ObstacleDomain );
+    %obj.setCollisionGroups( none );
     %obj.setAwake( false );
     %obj.setDefaultFriction( TruckToy.ObstacleFriction );
 
@@ -660,7 +661,7 @@ function TruckToy::createProjectile(%this)
     %projectile.Size = getRandom(0.5, 2);
     %projectile.Lifetime = 2.5;
     %projectile.createCircleCollisionShape( 0.2 ); 
-    %projectile.setCollisionGroups( TruckToy.ObstacleDomain );
+    %projectile.setCollisionGroups( TruckToy.GroundDomain );
     %projectile.CollisionCallback = true;
     SandboxScene.add( %projectile ); 
 }
@@ -708,8 +709,8 @@ function TruckToy::createTruck( %this, %posX, %posY )
     TruckToy.TruckBody.setImage( "TruckToy:truckBody" );
     TruckToy.TruckBody.setSize( 5, 2.5 );
     TruckToy.TruckBody.setSceneLayer( TruckToy.TruckDomain );
-    TruckToy.TruckBody.setSceneGroup( TruckToy.ObstacleDomain );
-    TruckToy.TruckBody.setCollisionGroups( TruckToy.ObstacleDomain SPC TruckToy.ObstacleDomain-1 );
+    TruckToy.TruckBody.setSceneGroup( TruckToy.ObstacleDomain);
+    TruckToy.TruckBody.setCollisionGroups( TruckToy.ObstacleDomain, TruckToy.ObstacleDomain-1, TruckToy.GroundDomain );
     TruckToy.TruckBody.createPolygonCollisionShape( "-2 0.2 -2 -0.5 0 -.95 2 -0.5 2 0.0 0 0.7 -1.5 0.7" ); 
     //TruckToy.TruckBody.setDebugOn( 5 );
     SandboxScene.add( TruckToy.TruckBody );
@@ -732,7 +733,7 @@ function TruckToy::createTruck( %this, %posX, %posY )
     %tireRear.setSize( 1.7, 1.7 );
     %tireRear.setSceneLayer( TruckToy.TruckDomain-1 );
     %tireRear.setSceneGroup( TruckToy.ObstacleDomain );
-    %tireRear.setCollisionGroups( TruckToy.ObstacleDomain );
+    %tireRear.setCollisionGroups( TruckToy.ObstacleDomain, TruckToy.GroundDomain );
     %tireRear.setDefaultFriction( TruckToy.WheelFriction );
     %tireRear.setDefaultDensity( TruckToy.RearWheelDensity );
     %tireRear.createCircleCollisionShape( 0.8 ); 
@@ -746,7 +747,7 @@ function TruckToy::createTruck( %this, %posX, %posY )
     %tireFront.setSize( 1.7, 1.7 );
     %tireFront.setSceneLayer( TruckToy.TruckDomain-1 );
     %tireFront.setSceneGroup( TruckToy.ObstacleDomain );
-    %tireFront.setCollisionGroups( TruckToy.ObstacleDomain );
+    %tireFront.setCollisionGroups( TruckToy.ObstacleDomain, TruckToy.GroundDomain );
     %tireFront.setDefaultFriction( TruckToy.WheelFriction );
     %tireFront.setDefaultDensity( TruckToy.FrontWheelDensity );
     %tireFront.createCircleCollisionShape( 0.8 );