void SceneManager::_renderScene( SceneRenderState* state, U32 objectMask, SceneZoneSpace* baseObject, U32 baseZone )
{
   AssertFatal( this == gClientSceneGraph, "SceneManager::_buildSceneGraph - Only the client scenegraph can support this call!" );

   PROFILE_SCOPE( SceneGraph_batchRenderImages );

   // In the editor, override the type mask for diffuse passes.

   if( gEditingMission && state->isDiffusePass() )
      objectMask = EDITOR_RENDER_TYPEMASK;

   // Update the zoning state and traverse zones.

   if( getZoneManager() )
   {
      // Update.

      getZoneManager()->updateZoningState();

      // If zone culling isn't disabled, traverse the
      // zones now.

      if( !state->getCullingState().disableZoneCulling() )
      {
         // Find the start zone if we haven't already.

         if( !baseObject )
         {
            getZoneManager()->findZone( state->getCameraPosition(), baseObject, baseZone );
            AssertFatal( baseObject != NULL, "SceneManager::_renderScene - findZone() did not return an object" );
         }

         // Traverse zones starting in base object.

         SceneTraversalState traversalState( &state->getCullingState() );
         PROFILE_START( Scene_traverseZones );
         baseObject->traverseZones( &traversalState, baseZone );
         PROFILE_END();

         // Set the scene render box to the area we have traversed.

         state->setRenderArea( traversalState.getTraversedArea() );
      }
   }

   // Set the query box for the container query.  Never
   // make it larger than the frustum's AABB.  In the editor,
   // always query the full frustum as that gives objects
   // the opportunity to render editor visualizations even if
   // they are otherwise not in view.

   if( !state->getFrustum().getBounds().isOverlapped( state->getRenderArea() ) )
   {
      // This handles fringe cases like flying backwards into a zone where you
      // end up pretty much standing on a zone border and looking directly into
      // its "walls".  In that case the traversal area will be behind the frustum
      // (remember that the camera isn't where visibility starts, it's the near
      // distance).

      return;
   }

   Box3F queryBox = state->getFrustum().getBounds();
   if( !gEditingMission )
   {
      queryBox.minExtents.setMax( state->getRenderArea().minExtents );
      queryBox.maxExtents.setMin( state->getRenderArea().maxExtents );
   }

   PROFILE_START( Scene_cullObjects );

   //TODO: We should split the codepaths here based on whether the outdoor zone has visible space.
   //    If it has, we should use the container query-based path.
   //    If it hasn't, we should fill the object list directly from the zone lists which will usually
   //       include way fewer objects.
   
   // Gather all objects that intersect the scene render box.

   mBatchQueryList.clear();
   getContainer()->findObjectList( queryBox, objectMask, &mBatchQueryList );

   // Cull the list.

   U32 numRenderObjects = state->getCullingState().cullObjects(
      mBatchQueryList.address(),
      mBatchQueryList.size(),
      !state->isDiffusePass() ? SceneCullingState::CullEditorOverrides : 0 // Keep forced editor stuff out of non-diffuse passes.
   );

   //HACK: If the control object is a Player and it is not in the render list, force
   // it into it.  This really should be solved by collision bounds being separate from
   // object bounds; only because the Player class is using bounds not encompassing
   // the actual player object is it that we have this problem in the first place.
   // Note that we are forcing the player object into ALL passes here but such
   // is the power of proliferation of things done wrong.

   GameConnection* connection = GameConnection::getConnectionToServer();
   if( connection )
   {
      Player* player = dynamic_cast< Player* >( connection->getControlObject() );
      if( player )
      {
         mBatchQueryList.setSize( numRenderObjects );
         if( !mBatchQueryList.contains( player ) )
         {
            mBatchQueryList.push_back( player );
            numRenderObjects ++;
         }
      }
   }

   PROFILE_END();

   // Render the remaining objects.

   PROFILE_START( Scene_renderObjects );
   state->renderObjects( mBatchQueryList.address(), numRenderObjects );
   PROFILE_END();

   // Render bounding boxes, if enabled.

   if( smRenderBoundingBoxes && state->isDiffusePass() )
   {
      GFXDEBUGEVENT_SCOPE( Scene_renderBoundingBoxes, ColorI::WHITE );

      GameBase* cameraObject = 0;
      if( connection )
         cameraObject = connection->getCameraObject();

      GFXStateBlockDesc desc;
      desc.setFillModeWireframe();
      desc.setZReadWrite( true, false );

      for( U32 i = 0; i < numRenderObjects; ++ i )
      {
         SceneObject* object = mBatchQueryList[ i ];

         // Skip global bounds object.
         if( object->isGlobalBounds() )
            continue;

         // Skip camera object as we're viewing the scene from it.
         if( object == cameraObject )
            continue;

         const Box3F& worldBox = object->getWorldBox();
         GFX->getDrawUtil()->drawObjectBox(
            desc,
            Point3F( worldBox.len_x(), worldBox.len_y(), worldBox.len_z() ),
            worldBox.getCenter(),
            MatrixF::Identity,
            ColorI::WHITE
         );
      }
   }
}
Exemplo n.º 2
0
void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mat )
{   
   GFXDrawUtil *drawer = GFX->getDrawUtil();

   GFX->setTexture( 0, NULL );

   // Render world box.
   if ( false )
   {
      Box3F wbox( mWorldBox );
      //if ( getServerObject() )      
      //   Box3F wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox;      
      GFXStateBlockDesc desc;
      desc.setCullMode( GFXCullNone );
      desc.setFillModeWireframe();
      drawer->drawCube( desc, wbox, ColorI::RED );
   }


   const Vector< Point3F > &pointList = mGeometry.points;
	const Vector< ConvexShape::Face > &faceList = mGeometry.faces;

   // Render Edges.
   if ( false )
   {
      GFXTransformSaver saver;
      //GFXFrustumSaver fsaver;

      MatrixF xfm( getRenderTransform() );
      xfm.scale( getScale() );
      GFX->multWorld( xfm );

      GFXStateBlockDesc desc;
      desc.setZReadWrite( true, false );
      desc.setBlend( true );
      GFX->setStateBlockByDesc( desc );

      //MathUtils::getZBiasProjectionMatrix( 0.01f, state->getFrustum(), )

      const Point3F &camFvec = state->getCameraTransform().getForwardVector();



      for ( S32 i = 0; i < faceList.size(); i++ )
      {         
         const ConvexShape::Face &face = faceList[i];
         
         const Vector< ConvexShape::Edge > &edgeList = face.edges;

         const Vector< U32 > &facePntList = face.points;

         PrimBuild::begin( GFXLineList, edgeList.size() * 2 );
         
         PrimBuild::color( ColorI::WHITE * 0.8f );

         for ( S32 j = 0; j < edgeList.size(); j++ )         
         {
            PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] - camFvec * 0.001f );
            PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] - camFvec * 0.001f );
         }
         
         PrimBuild::end();
      }
   }

   ColorI faceColorsx[4] = 
   {
      ColorI( 255, 0, 0 ),
      ColorI( 0, 255, 0 ),
      ColorI( 0, 0, 255 ),
      ColorI( 255, 0, 255 )
   };

   MatrixF objToWorld( mObjToWorld );
   objToWorld.scale( mObjScale );

   // Render faces centers/colors.
   if ( false )
   {
      GFXStateBlockDesc desc;
      desc.setCullMode( GFXCullNone );
      
      Point3F size( 0.1f );

      for ( S32 i = 0; i < faceList.size(); i++ )
      {
         ColorI color = faceColorsx[ i % 4 ];
         S32 div = ( i / 4 ) * 4;
         if ( div > 0 )
            color /= div;
         color.alpha = 255;
         
         Point3F pnt;
         objToWorld.mulP( faceList[i].centroid, &pnt );
         drawer->drawCube( desc, size, pnt, color, NULL );
      }
   }

   // Render winding order.
   if ( false )
   {
      GFXStateBlockDesc desc;
      desc.setCullMode( GFXCullNone );
      desc.setZReadWrite( true, false );
      GFX->setStateBlockByDesc( desc );  

      U32 pointCount = 0;
      for ( S32 i = 0; i < faceList.size(); i++ )      
         pointCount += faceList[i].winding.size();      

      PrimBuild::begin( GFXLineList, pointCount * 2 );
      
      for ( S32 i = 0; i < faceList.size(); i++ )
      {
         for ( S32 j = 0; j < faceList[i].winding.size(); j++ )
         {
            Point3F p0 = pointList[ faceList[i].points[ faceList[i].winding[j] ] ];
            Point3F p1 = p0 + mSurfaces[ faceList[i].id ].getUpVector() * 0.75f * ( Point3F::One / mObjScale );

            objToWorld.mulP( p0 );
            objToWorld.mulP( p1 );

            ColorI color = faceColorsx[ j % 4 ];
            S32 div = ( j / 4 ) * 4;
            if ( div > 0 )
               color /= div;
            color.alpha = 255;
            
            PrimBuild::color( color );
            PrimBuild::vertex3fv( p0 );            
            PrimBuild::color( color );
            PrimBuild::vertex3fv( p1 );                        
         }
      }

      PrimBuild::end();
   }

   // Render Points.
   if ( false )
   {      
      /*
      GFXTransformSaver saver;

      MatrixF xfm( getRenderTransform() );
      xfm.scale( getScale() );
      GFX->multWorld( xfm );

      GFXStateBlockDesc desc;
      Point3F size( 0.05f );
      */
   }

   // Render surface transforms.
   if ( false )
   {
      GFXStateBlockDesc desc;
      desc.setBlend( false );
      desc.setZReadWrite( true, true );

      Point3F scale(mNormalLength);

      for ( S32 i = 0; i < mSurfaces.size(); i++ )
      {
         MatrixF objToWorld( mObjToWorld );
         objToWorld.scale( mObjScale );

         MatrixF renderMat;
         renderMat.mul( objToWorld, mSurfaces[i] );

         renderMat.setPosition( renderMat.getPosition() + renderMat.getUpVector() * 0.001f );
              
         drawer->drawTransform( desc, renderMat, &scale, NULL );
      }
   }
}