Example #1
0
void TerrCell::updateGrid( const RectI &gridRect, bool opacityOnly )
{
   PROFILE_SCOPE( TerrCell_UpdateGrid );

   // If we have a VB... then update it.
   if ( mVertexBuffer.isValid() && !opacityOnly )            
      _updateVertexBuffer();

   // Update our PB, if any
   _updatePrimitiveBuffer();

   // If we don't have children... then we're
   // a leaf at the bottom of the cell quadtree
   // and we should just update our bounds.
   if ( !mChildren[0] )
   {
      if ( !opacityOnly )
         _updateBounds(); 

      _updateMaterials();
      return;
   }

   // Otherwise, we must call updateGrid on our children
   // and then update our bounds/materials AFTER to contain them.

   mMaterials = 0;

   for ( U32 i = 0; i < 4; i++ )
   {
      TerrCell *cell = mChildren[i];

      // The overlap test doesn't hit shared edges
      // so grow it a bit when we create it.
      const RectI cellRect( cell->mPoint.x - 1,
                            cell->mPoint.y - 1,
                            cell->mSize + 2, 
                            cell->mSize + 2 );

      // We do an overlap and containment test as it 
      // properly handles zero sized rects.
      if (  cellRect.contains( gridRect ) ||
            cellRect.overlaps( gridRect ) )
         cell->updateGrid( gridRect, opacityOnly );

      // Update the bounds from our children.
      if ( !opacityOnly )
      {
         if ( i == 0 )
            mBounds = mChildren[i]->getBounds();
         else
            mBounds.intersect( mChildren[i]->getBounds() );

         mRadius = mBounds.len() * 0.5f;
      }

      // Update the material flags.
      mMaterials |= mChildren[i]->getMaterials();
   }

   if ( mMaterial )
      mMaterial->init( mTerrain, mMaterials );
}
Example #2
0
void TerrainBlock::_renderBlock( SceneRenderState *state )
{
   PROFILE_SCOPE( TerrainBlock_RenderBlock );

   // Prevent rendering shadows if feature is disabled
   if ( !mCastShadows && state->isShadowPass() ) 
      return;
	  
   MatrixF worldViewXfm = state->getWorldViewMatrix();
   worldViewXfm.mul( getRenderTransform() );

   MatrixF worldViewProjXfm = state->getProjectionMatrix();
   worldViewProjXfm.mul( worldViewXfm );

   const MatrixF &objectXfm = getRenderWorldTransform();

   Point3F objCamPos = state->getDiffuseCameraPosition();
   objectXfm.mulP( objCamPos );

   // Get the shadow material.
   if ( !mDefaultMatInst )
      mDefaultMatInst = TerrainCellMaterial::getShadowMat();

   // Make sure we have a base material.
   if ( !mBaseMaterial )
   {
      mBaseMaterial = new TerrainCellMaterial();
      mBaseMaterial->init( this, 0, false, false, true );
   }

   // Did the detail layers change?
   if ( mDetailsDirty )
   {   
      _updateMaterials();
      mDetailsDirty = false;
   }

   // If the layer texture has been cleared or is 
   // dirty then update it.
   if ( mLayerTex.isNull() || mLayerTexDirty )
      _updateLayerTexture();

   // If the layer texture is dirty or we lost the base
   // texture then regenerate it.
   if ( mLayerTexDirty || mBaseTex.isNull() )
   {
      _updateBaseTexture( false );
      mLayerTexDirty = false;
   }   

   static Vector<TerrCell*> renderCells;
   renderCells.clear();

   mCell->cullCells( state,
                     objCamPos,
                     &renderCells );

   RenderPassManager *renderPass = state->getRenderPass();

   MatrixF *riObjectToWorldXfm = renderPass->allocUniqueXform( getRenderTransform() );

   const bool isColorDrawPass = state->isDiffusePass() || state->isReflectPass();

   // This is here for shadows mostly... it allows the
   // proper shadow material to be generated.
   BaseMatInstance *defaultMatInst = state->getOverrideMaterial( mDefaultMatInst );

   // Only pass and use the light manager if this is not a shadow pass.
   LightManager *lm = NULL;
   if ( isColorDrawPass )
      lm = LIGHTMGR;

   for ( U32 i=0; i < renderCells.size(); i++ )
   {
      TerrCell *cell = renderCells[i];

      // Ok this cell is fit to render.
      TerrainRenderInst *inst = renderPass->allocInst<TerrainRenderInst>();

      // Setup lights for this cell.
      if ( lm )
      {
         SphereF bounds = cell->getSphereBounds();
         getRenderTransform().mulP( bounds.center );

         LightQuery query;
         query.init( bounds );
		   query.getLights( inst->lights, 8 );
      }

      GFXVertexBufferHandleBase vertBuff;
      GFXPrimitiveBufferHandle  primBuff;

      cell->getRenderPrimitive( &inst->prim, &vertBuff, &primBuff );

      inst->mat = defaultMatInst;
      inst->vertBuff = vertBuff.getPointer();

      if ( primBuff.isValid() )
      {
         // Use the cell's custom primitive buffer
         inst->primBuff = primBuff.getPointer();
      }
      else
      {
         // Use the standard primitive buffer for this cell
         inst->primBuff = mPrimBuffer.getPointer();
      }

      inst->objectToWorldXfm = riObjectToWorldXfm;

      // If we're not drawing to the shadow map then we need
      // to include the normal rendering materials. 
      if ( isColorDrawPass )
      {         
         const SphereF &bounds = cell->getSphereBounds();         

         F32 sqDist = ( bounds.center - objCamPos ).lenSquared();         

         F32 radiusSq = mSquared( ( mMaxDetailDistance + bounds.radius ) * smDetailScale );

         // If this cell is near enough to get detail textures then
         // use the full detail mapping material.  Else we use the
         // simple base only material.
         if ( !state->isReflectPass() && sqDist < radiusSq )
            inst->cellMat = cell->getMaterial();
         else if ( state->isReflectPass() )
            inst->cellMat = mBaseMaterial->getReflectMat();
         else
            inst->cellMat = mBaseMaterial;
      }

      inst->defaultKey = (U32)cell->getMaterials();

      // Submit it for rendering.
      renderPass->addInst( inst );
   }

   // Trigger the debug rendering.
   if (  state->isDiffusePass() && 
         !renderCells.empty() && 
         smDebugRender )
   {      
      // Store the render cells for later.
      mDebugCells = renderCells;

      ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
      ri->renderDelegate.bind( this, &TerrainBlock::_renderDebug );
      ri->type = RenderPassManager::RIT_Editor;
      state->getRenderPass()->addInst( ri );
   }
}
Example #3
0
void TerrCell::_init( TerrainBlock *terrain,               
                      const Point2I &point,
                      U32 size,
                      U32 level )
{
   PROFILE_SCOPE( TerrCell_Init );

   mTerrain = terrain;
   mPoint = point;
   mSize = size;
   mLevel = level;

   // Generate a VB (and maybe a PB) for this cell, unless we are the Root cell.
   if ( level > 0 )
   {
      _updateVertexBuffer();
      _updatePrimitiveBuffer();
   }
      
   if ( mSize <= smMinCellSize )
   {
      // Update our bounds and materials... the 
      // parent will use it to update itself.
      _updateBounds();
      _updateMaterials();
      return;
   }

   // Create our children and update our 
   // bounds and materials from them.

   const U32 childSize = mSize / 2;
   const U32 childLevel = mLevel + 1;

   mChildren[0] = new TerrCell;
   mChildren[0]->_init( mTerrain,               
                        Point2I( mPoint.x, mPoint.y ),
                        childSize,
                        childLevel );
   mBounds = mChildren[0]->getBounds();
   mMaterials = mChildren[0]->getMaterials();

   mChildren[1] = new TerrCell;
   mChildren[1]->_init( mTerrain,               
                        Point2I( mPoint.x + childSize, mPoint.y ),
                        childSize,
                        childLevel );
   mBounds.intersect( mChildren[1]->getBounds() );
   mMaterials |= mChildren[1]->getMaterials();

   mChildren[2] = new TerrCell;
   mChildren[2]->_init( mTerrain,               
                        Point2I( mPoint.x, mPoint.y + childSize ),
                        childSize,
                        childLevel );
   mBounds.intersect( mChildren[2]->getBounds() );
   mMaterials |= mChildren[2]->getMaterials();

   mChildren[3] = new TerrCell;
   mChildren[3]->_init( mTerrain,               
                        Point2I( mPoint.x + childSize, mPoint.y + childSize ),
                        childSize, 
                        childLevel );
   mBounds.intersect( mChildren[3]->getBounds() );
   mMaterials |= mChildren[3]->getMaterials();

   mRadius = mBounds.len() * 0.5f;

   _updateOBB();
}