⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 terrrender.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
   *zDiff = vec.z;

   return vec.len();
}

void TerrainRender::emitTerrChunk(SquareStackNode *n, F32 squareDistance, U32 lightMask, bool farClip, bool drawDetails, bool drawBumps)
{
   //if(n->pos.x || n->pos.y)
   //   return;
   GridChunk *gc = mCurrentBlock->findChunk(n->pos);
   EmitChunk *chunk = (EmitChunk *) FrameAllocator::alloc(sizeof(EmitChunk));
   chunk->x = n->pos.x + mBlockOffset.x + mTerrainOffset.x;
   chunk->y = n->pos.y + mBlockOffset.y + mTerrainOffset.y;
   chunk->gridX = n->pos.x;
   chunk->gridY = n->pos.y;
   chunk->lightMask = lightMask;

   chunk->next = mCurrentTexture->list;
   mCurrentTexture->list = chunk;

   if(mRenderingCommander)
      return;

   chunk->edge[0] = (ChunkEdge *) n->top;
   chunk->edge[1] = (ChunkEdge *) n->right;
   chunk->edge[2] = (ChunkEdge *) n->bottom;
   chunk->edge[3] = (ChunkEdge *) n->left;

   chunk->edge[0]->c2 = chunk;
   chunk->edge[1]->c1 = chunk;
   chunk->edge[2]->c1 = chunk;
   chunk->edge[3]->c2 = chunk;


   // holes only in the primary terrain block
   if (gc->emptyFlags && mBlockPos.x == 0 && mBlockPos.y == 0)
      chunk->emptyFlags = gc->emptyFlags;
   else
      chunk->emptyFlags = 0;

   S32 subDivLevel;
   F32 growFactor = 0;

   F32 minSubdivideDistance = 1000000;
   chunk->clip = farClip;

   chunk->renderDetails = drawDetails;
    chunk->renderBumps = drawBumps;

   if(squareDistance < 1)
      subDivLevel = -1;
   else
   {
      for(subDivLevel = 2; subDivLevel >= 0; subDivLevel--)
      {
         F32 subdivideDistance = fixedToFloat(gc->heightDeviance[subDivLevel]) / mPixelError;
         if(subdivideDistance > minSubdivideDistance)
            subdivideDistance = minSubdivideDistance;

         if(squareDistance >= subdivideDistance)
            break;
         F32 clampDistance = subdivideDistance * 0.75;
         if(squareDistance > clampDistance)
         {
            growFactor = (squareDistance - clampDistance) / (0.25 * subdivideDistance);
            subDivLevel--;
            break;
         }
         minSubdivideDistance = clampDistance;
      }
   }
   chunk->subDivLevel = subDivLevel;
   chunk->growFactor = growFactor;
}

void TerrainRender::processCurrentBlock(SceneState*, EdgeParent *topEdge, EdgeParent *rightEdge, EdgeParent *bottomEdge, EdgeParent *leftEdge)
{
   SquareStackNode stack[TerrainBlock::BlockShift*4];
   Point3F minPoint, maxPoint;

   stack[0].level = TerrainBlock::BlockShift;
   stack[0].clipFlags = ((1 << mNumClipPlanes) - 1) | FarSphereMask;  // test all the planes
   stack[0].pos.set(0,0);
   stack[0].top = topEdge;
   stack[0].right = rightEdge;
   stack[0].bottom = bottomEdge;
   stack[0].left = leftEdge;
   stack[0].lightMask = (1 << mDynamicLightCount) - 1; // test all the lights
   stack[0].texAllocated = false;

   Vector<SceneState::FogBand> *posFog = mSceneState->getPosFogBands();
   Vector<SceneState::FogBand> *negFog = mSceneState->getNegFogBands();
   bool clipAbove = posFog->size() > 0 && (*posFog)[0].isFog == false;
   bool clipBelow = negFog->size() > 0 && (*negFog)[0].isFog == false;
   bool clipOn = posFog->size() > 0 && (*posFog)[0].isFog == true;

   if(posFog->size() != 0 || negFog->size() != 0)
      stack[0].clipFlags |= FogPlaneBoxMask;

   S32 curStackSize = 1;
   F32 squareDistance;

   F32 worldToScreenScale   = dglProjectRadius(1,1);
   F32 zeroDetailDistance   = (mSquareSize * worldToScreenScale) / (1 << 6) - (mSquareSize >> 1);
    F32 zeroBumpDistance         = (mSquareSize * worldToScreenScale) / (1 << mCurrentBlock->mZeroBumpScale) - (mSquareSize >> 1);

   while(curStackSize)
   {
      SquareStackNode *n = stack + curStackSize - 1;
      // see if it's visible
      GridSquare *sq = mCurrentBlock->findSquare(n->level, n->pos);

      minPoint.set(mSquareSize * n->pos.x + mBlockPos.x,
                   mSquareSize * n->pos.y + mBlockPos.y,
                   fixedToFloat(sq->minHeight));
      maxPoint.set(minPoint.x + (mSquareSize << n->level),
                   minPoint.y + (mSquareSize << n->level),
                   fixedToFloat(sq->maxHeight));

      // holes only in the primary terrain block
      if ((sq->flags & GridSquare::Empty) && mBlockPos.x == 0 && mBlockPos.y == 0)
      {
         curStackSize--;
         continue;
      }

      F32 zDiff;
      squareDistance = getSquareDistance(minPoint, maxPoint, &zDiff);

      S32 nextClipFlags = 0;

      if(n->clipFlags)
      {
         if(n->clipFlags & FogPlaneBoxMask)
         {
            F32 camZ = mCamPos.z;
            bool boxBelow = camZ > maxPoint.z;
            bool boxAbove = camZ < minPoint.z;
            bool boxOn = !(boxAbove || boxBelow);
            if( clipOn ||
                (clipAbove && boxAbove && (maxPoint.z - camZ > (*posFog)[0].cap)) ||
                (clipBelow && boxBelow && (camZ - minPoint.z > (*negFog)[0].cap)) ||
                (boxOn && (( clipAbove && maxPoint.z - camZ > (*posFog)[0].cap ) ||
                           ( clipBelow && camZ - minPoint.z > (*negFog)[0].cap ))))
            {
               // Using the fxSunLight can cause the "sky" to extend down below the camera.
               // To avoid the sun showing through, the terrain must always be rendered.
               // If the fxSunLight is not being used, the following optimization can be
               // uncommented.
               #if 0
               if(boxBelow && !mSceneState->isBoxFogVisible(squareDistance, maxPoint.z, minPoint.z))
               {
                  // Totally fogged terrain tiles can be thrown out as long as they are
                  // below the camera. If they are ubove, the sky will show through the
                  // fog.
                  curStackSize--;
                  continue;
               }
               #endif
               nextClipFlags |= FogPlaneBoxMask;
            }
         }
         if(n->clipFlags & FarSphereMask)
         {
            if(squareDistance >= mFarDistance)
            {
               curStackSize--;
               continue;
            }

            S32 squareSz = mSquareSize << n->level;
            if(squareDistance + maxPoint.z - minPoint.z + squareSz + squareSz > mFarDistance)
               nextClipFlags |= FarSphereMask;
         }

         // zDelta for screen error height deviance.
         F32 zDelta = squareDistance * mPixelError;
         minPoint.z -= zDelta;
         maxPoint.z += zDelta;

         nextClipFlags |= TestSquareVisibility(minPoint, maxPoint, n->clipFlags, mSquareSize);
         if(nextClipFlags == -1)
         {
            //if(!n->texAllocated)
            //   textureRecurse(n);

            // trivially rejected, so pop it off the stack
            curStackSize--;
            continue;
         }
      }
      if(!n->texAllocated)
      {
         S32 squareSz = mSquareSize << n->level;
         // first check the level - if its 3 or less, we have to just make a bitmap:
         // level 3 == 8x8 square - 8x8 * 16x16 == 128x128
         if(n->level > 6)
            goto notexalloc;

         S32 mipLevel = TerrainTextureMipLevel;
         if(!mRenderingCommander)
         {
            if(n->level > mTextureMinSquareSize + 2)
            {
               // get the mip level of the square and see if we're in range
               if(squareDistance > 0.001)
               {
                  S32 size = S32(dglProjectRadius(squareDistance + (squareSz >> 1), squareSz));
                  mipLevel = getPower((S32)(size * 0.75));
                  if(mipLevel > TerrainTextureMipLevel) // too big for this square
                     goto notexalloc;
               }
               else
                  goto notexalloc;
            }
         }
         allocTerrTexture(n->pos, n->level, mipLevel, true, squareDistance);
         n->texAllocated = true;
         if(mRenderingCommander) // level == 6
         {
            emitTerrChunk(n, 0, 0, 0, 0, 0);
            curStackSize--;
            continue;
         }
      }
notexalloc:
      if(n->lightMask)
         n->lightMask = TestSquareLights(sq, n->level, n->pos, n->lightMask);

      if(n->level == 2)
      {
         AssertFatal(n->texAllocated, "Invalid texture index.");

         bool drawDetails = false;
         if (mEnableTerrainDetails && squareDistance < zeroDetailDistance)
            drawDetails = true;

             //END
            bool drawBumps = false;
// CW - stuff with bump maps
            if (mEnableTerrainEmbossBumps && squareDistance < zeroBumpDistance)
                drawBumps = true;
// CW - end bump map stuff
         emitTerrChunk(n, squareDistance, n->lightMask, nextClipFlags & FarSphereMask, drawDetails, drawBumps);
         curStackSize--;
         continue;
      }
      bool allocChunkEdges = (n->level == 3);

      Point2I pos = n->pos;

      ChunkScanEdge *top = (ChunkScanEdge *) n->top;
      ChunkScanEdge *right = (ChunkScanEdge *) n->right;
      ChunkScanEdge *bottom = (ChunkScanEdge *) n->bottom;
      ChunkScanEdge *left = (ChunkScanEdge *) n->left;

      // subdivide this square and throw it on the stack
      S32 squareOneSize = 1 << n->level;
      S32 squareHalfSize = squareOneSize >> 1;

      ChunkCornerPoint *midPoint = allocPoint(Point2I(pos.x + squareHalfSize, pos.y + squareHalfSize));
      S32 nextLevel = n->level - 1;

      subdivideChunkEdge(top, Point2I(pos.x + squareHalfSize, pos.y + squareOneSize), allocChunkEdges);
      subdivideChunkEdge(right, Point2I(pos.x + squareOneSize, pos.y + squareHalfSize), allocChunkEdges);
      subdivideChunkEdge(bottom, Point2I(pos.x + squareHalfSize, pos.y), allocChunkEdges);
      subdivideChunkEdge(left, Point2I(pos.x, pos.y + squareHalfSize), allocChunkEdges);

      // cross edges go top, right, bottom, left
      EdgeParent *crossEdges[4];
      allocRenderEdges(4, crossEdges, allocChunkEdges);
      crossEdges[0]->p1 = top->mp;
      crossEdges[0]->p2 = midPoint;
      crossEdges[1]->p1 = midPoint;
      crossEdges[1]->p2 = right->mp;
      crossEdges[2]->p1 = midPoint;
      crossEdges[2]->p2 = bottom->mp;
      crossEdges[3]->p1 = left->mp;
      crossEdges[3]->p2 = midPoint;

      n->level = nextLevel;
      n->clipFlags = nextClipFlags;

      for(S32 i = 1; i < 4; i++)
      {
         n[i].level = nextLevel;
         n[i].clipFlags = nextClipFlags;
         n[i].lightMask = n->lightMask;
         n[i].texAllocated = n->texAllocated;
      }
      // push in reverse order of processing.
      n[3].pos = pos;
      n[3].top = crossEdges[3];
      n[3].right = crossEdges[2];
      n[3].bottom = bottom->e1;
      n[3].left = left->e2;

      n[2].pos.set(pos.x + squareHalfSize, pos.y);
      n[2].top = crossEdges[1];
      n[2].right = right->e2;
      n[2].bottom = bottom->e2;
      n[2].left = crossEdges[2];

      n[1].pos.set(pos.x, pos.y + squareHalfSize);
      n[1].top = top->e1;
      n[1].right = crossEdges[0];
      n[1].bottom = crossEdges[3];
      n[1].left = left->e1;

      n[0].pos.set(pos.x + squareHalfSize, pos.y + squareHalfSize);
      n[0].top = top->e2;
      n[0].right = right->e1;
      n[0].bottom = crossEdges[1];
      n[0].left = crossEdges[0];

      curStackSize += 3;
   }
}





//---------------------------------------------------------------
//---------------------------------------------------------------
// Root block render function
//---------------------------------------------------------------
//---------------------------------------------------------------

void TerrainRender::fixEdge(ChunkEdge *edge, S32 x, S32 y, S32 dx, S32 dy)
{
   S32 minLevel, maxLevel;
   F32 growFactor;

   if(edge->c1)
   {
      minLevel = edge->c1->subDivLevel;
      maxLevel = edge->c1->subDivLevel;
      growFactor = edge->c1->growFactor;
      if(edge->c2)
      {
         if(edge->c2->subDivLevel < minLevel)
            minLevel = edge->c2->subDivLevel;
         else if(edge->c2->subDivLevel > maxLevel)
         {
            maxLevel = edge->c2->subDivLevel;
            growFactor = edge->c2->growFactor;
         }
         else if(edge->c2->growFactor > growFactor)
            growFactor = edge->c2->growFactor;
      }
   }
   else
   {
      minLevel = maxLevel = edge->c2->subDivLevel;
      growFactor = edge->c2->growFactor;
   }
   if(minLevel == 2)
   {
      edge->pointCount = 0;
      return;
   }

   // get the mid heights
   EdgePoint *pmid = &edge->pt[1];
   ChunkCornerPoint *p1 = edge->p1;
   ChunkCornerPoint *p2 = edge->p2;

   pmid->x = (p1->x + p2->x) * 0.5;
   pmid->y = (p1->y + p2->y) * 0.5;

   if(maxLevel == 2)
   {
      // pure interp
      pmid->z = (p1->z + p2->z) * 0.5;
      pmid->distance = (*pmid - mCamPos).len();
      pmid->fogRed = (p1->fogRed + p2->fogRed) * 0.5;
      pmid->fogGreen = (p1->fogGreen + p2->fogGreen) * 0.5;

      if(minLevel >= 0)
      {
         edge->pointCount = 1;
         return;
      }
   }
   else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -