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

📄 ettile.cpp

📁 etm2.2是基于Ogre引擎开发的地形库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }


    void Tile::getRenderOperation(RenderOperation& op)
    {
      op.useIndexes = true;
      op.operationType = RenderOperation::OT_TRIANGLE_LIST;
      op.vertexData = mTerrain;
      op.indexData = getIndexData();
    }

    void Tile::_updateRenderQueue(RenderQueue* queue)
    {
      mLightListDirty = true;
      queue->addRenderable(this, mRenderQueueID);
    }


    void Tile::_updateCustomGpuParameter(const GpuProgramParameters::AutoConstantEntry& constEntry,
      GpuProgramParameters* params) const
    {
      if (constEntry.data == MORPH_CUSTOM_PARAM_ID)
      {
        params->_writeRawConstant(constEntry.physicalIndex, mLODMorphFactor);
      }
      else
      {
        Renderable::_updateCustomGpuParameter(constEntry, params);
      }
    }


    Vector3 Tile::getVector(size_t x, size_t z) const
    {
      float posX = mInfo.getOffset().x + (mStartX + x)*mInfo.getScaling().x;
      float posZ = mInfo.getOffset().z + (mStartZ + z)*mInfo.getScaling().z;
      return Vector3(posX, mInfo.getHeightAt(posX, posZ), posZ);
    }

    void Tile::calculateMinLevelDist2()
    {
      Real C = mOpt.factorC;

      // LOD 0 has no distance
      mLODChangeMinDistSqr[0] = 0.0f;


      for (unsigned int level = 1; level < mOpt.maxMipMapLevel; ++level)
      {
        mLODChangeMinDistSqr[level] = 0.0f;

        size_t step = 1 << level;
        size_t higherstep = step >> 1;

        float* pDeltas = 0;
        // for LOD morphing, lock the according delta buffer now
        if (mOpt.useLODMorph)
        {
          // indexed at LOD-1, because there are only maxLOD-1 transitions between LODs...
          emptyBuffer(mDeltaBuffers[level-1]);
          pDeltas = static_cast<float*>(mDeltaBuffers[level-1]->lock(HardwareBuffer::HBL_NORMAL));
        }

        // for every vertex that is not used in the current LOD we calculate its interpolated
        // height and compare against its actual height. the largest difference of a vertex
        // is then used to determine the minimal distance for this LOD.
        for (size_t j = 0; j < mOpt.tileSize - step; j += step)
        {
          for (size_t i = 0; i < mOpt.tileSize - step; i += step)
          {
            Vector3 v1 = getVector(i, j);
            Vector3 v2 = getVector(i+step, j);
            Vector3 v3 = getVector(i, j+step);
            Vector3 v4 = getVector(i+step, j+step);
            Plane t1 (v1, v3, v2);
            Plane t2 (v2, v3, v4);

            size_t zubound = (j == (mOpt.tileSize - step) ? step : step - 1);
            for (size_t z = 0; z <= zubound; ++z)
            {
              size_t xubound = (i == (mOpt.tileSize - step) ? step : step - 1);
              for (size_t x = 0; x < xubound; ++x)
              {
                size_t fulldetailx = i + x;
                size_t fulldetailz = j + z;
                if (fulldetailx % step == 0 && fulldetailz % step == 0)
                {
                  continue;
                }

                Real zpct = Real(z) / Real(step);
                Real xpct = Real(x) / Real(step);

                Vector3 actualPos = getVector(fulldetailx, fulldetailz);
                Real interp_h;
                if (xpct + zpct <= 1.0f)
                {
                  interp_h = (
                    -(t1.normal.x * actualPos.x)
                    - t1.normal.z * actualPos.z
                    - t1.d) / t1.normal.y;
                }
                else
                {
                  interp_h = (
                    -(t2.normal.x * actualPos.x)
                    - t2.normal.z * actualPos.z
                    - t2.d) / t2.normal.y;
                }

                Real actual_h = getVector(fulldetailx, fulldetailz).y;
                Real delta = fabs(interp_h - actual_h);

                Real D2 = delta * delta * C * C;

                if (mLODChangeMinDistSqr[level] < D2)
                  mLODChangeMinDistSqr[level] = D2;

                // for LOD morphing, store the difference in the delta buffer
                if (mOpt.useLODMorph &&
                  fulldetailx != 0 && fulldetailx != (mOpt.tileSize-1) &&
                  fulldetailz != 0 && fulldetailz != (mOpt.tileSize-1))
                {
                  pDeltas[fulldetailx + (fulldetailz * mOpt.tileSize)] = interp_h - actual_h;
                }
              }
            }
          }
        }

        // unlock delta buffers
        if (mOpt.useLODMorph)
          mDeltaBuffers[level-1]->unlock();
      }


      // post validate
      for (unsigned int i = 1; i < mOpt.maxMipMapLevel; ++i)
      {
        // ensure level distances are increasing
        if (mLODChangeMinDistSqr[i] < mLODChangeMinDistSqr[i-1])
          mLODChangeMinDistSqr[i] = mLODChangeMinDistSqr[i-1];

      }
    }


    void Tile::_notifyCurrentCamera(Camera* cam)
    {
      MovableObject::_notifyCurrentCamera(cam);

      Vector3 cpos = cam->getDerivedPosition();
      const AxisAlignedBox& aabb = getWorldBoundingBox(true);
      Vector3 diff(0, 0, 0);
      diff.makeFloor(cpos - aabb.getMinimum());
      diff.makeCeil(cpos - aabb.getMaximum());

      // find the LOD to use for this tile
      Real L = diff.squaredLength();
      mLOD = mOpt.maxMipMapLevel-1;
      for (unsigned int i = 1; i < mOpt.maxMipMapLevel; ++i)
      {
        if (mLODChangeMinDistSqr[i] > L)
        {
          mLOD = i - 1;
          break;
        }
      }

      if (mOpt.useLODMorph)
      {
        // find the next LOD after the current one
        unsigned int nextLevel = mLOD + 1;
        for (unsigned int i = nextLevel; i < mOpt.maxMipMapLevel; ++i)
        {
          if (mLODChangeMinDistSqr[i] > mLODChangeMinDistSqr[mLOD])
          {
            nextLevel = i;
            break;
          }
        }

        // determine the LOD morph factor between the two LODs
        if (nextLevel == mOpt.maxMipMapLevel)
        {
          mLODMorphFactor = 0;
        }
        else
        {
          Real range = mLODChangeMinDistSqr[nextLevel] - mLODChangeMinDistSqr[mLOD];
          Real percent = (L - mLODChangeMinDistSqr[mLOD]) / range;
          Real rescale = 1.0f / (1.0f - mOpt.lodMorphStart);
          mLODMorphFactor = std::max((percent - mOpt.lodMorphStart), Real(0));
        }

        if (mLastNextLevel != nextLevel)
        {
          if (nextLevel != mOpt.maxMipMapLevel)
          {
            mTerrain->vertexBufferBinding->setBinding(DELTA_BINDING, mDeltaBuffers[nextLevel-1]);
          }
          else
          {
            // bind dummy
            mTerrain->vertexBufferBinding->setBinding(DELTA_BINDING, mDeltaBuffers[0]);
          }
        }
        mLastNextLevel = nextLevel;
      }
    }


    unsigned int Tile::getLOD() const
    {
      return mLOD;
    }


    void Tile::updateTerrain(size_t startx, size_t startz, size_t endx, size_t endz)
    {
      // determine the area of this tile that needs to be updated
      size_t fromX = std::max(mStartX, startx);
      size_t fromZ = std::max(mStartZ, startz);
      size_t toX = std::min(endx, mStartX+mOpt.tileSize-1);
      size_t toZ = std::min(endz, mStartZ+mOpt.tileSize-1);

      const VertexElement* posElem = mTerrain->vertexDeclaration->findElementBySemantic(VES_POSITION);
      unsigned char* pBase = static_cast<unsigned char*>(mMainBuffer->lock(HardwareBuffer::HBL_NORMAL));

      // update all necessary vertices
      for (size_t j = fromZ; j <= toZ; ++j)
      {
        for (size_t i = fromX; i <= toX; ++i)
        {
          size_t tX = i - mStartX;
          size_t tZ = j - mStartZ;
          unsigned char* pBasePos = pBase + (tZ*mOpt.tileSize + tX) * mMainBuffer->getVertexSize();

          Real height = mInfo.getOffset().y + mInfo.at(i, j) * mInfo.getScaling().y;
          float* pPos;
          posElem->baseVertexPointerToElement(pBasePos, &pPos);
          pPos[1] = height;
        }
      }

      mMainBuffer->unlock();

      // update the extents of this terrain tile
      size_t ex = mStartX + mOpt.tileSize;
      size_t ez = mStartZ + mOpt.tileSize;
      // find min and max heights
      Real minHeight = mInfo.getOffset().y + mInfo.getScaling().y, maxHeight = mInfo.getOffset().y;
      for (size_t j = mStartZ; j < ez; ++j)
      {
        for (size_t i = mStartX; i < ex; ++i)
        {
          Real height = mInfo.getOffset().y + mInfo.at(i, j)*mInfo.getScaling().y;
          if (height < minHeight)
            minHeight = height;
          if (height > maxHeight)
            maxHeight = height;
        }
      }
      mBounds.setMinimumY(minHeight);
      mBounds.setMaximumY(maxHeight);

      mCenter = mBounds.getCenter();

      mBoundingRadius = (mBounds.getMaximum() - mCenter).length();

      // recalculate the distances at which to switch LOD
      calculateMinLevelDist2();

      // recalculate vertex normals, if necessary
      if (mOpt.vertexNormals)
        calculateVertexNormals();
    }


  }
}

⌨️ 快捷键说明

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