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

📄 terrdata.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
         for(n = 0; n < TerrainBlock::BlockSize * TerrainBlock::BlockSize; n++)
            if(mMaterialAlphaMap[k][n])
               break;
         if(n == TerrainBlock::BlockSize * TerrainBlock::BlockSize)
            mMaterialFileName[k] = 0;
      }
      writeFile.writeString(mMaterialFileName[k]);
   }
   for(k=0; k < TerrainBlock::MaterialGroups; k++) {
      if(mMaterialFileName[k] && mMaterialFileName[k][0]) {
         AssertFatal(mMaterialAlphaMap[k] != NULL, "Error, must have a material map here!");
         writeFile.write(TerrainBlock::BlockSize * TerrainBlock::BlockSize, mMaterialAlphaMap[k]);
      }
   }
   if(mTextureScript)
   {
      U32 len = dStrlen(mTextureScript);
      writeFile.write(len);
      writeFile.write(len, mTextureScript);
   }
   else
      writeFile.write(U32(0));

   if(mHeightfieldScript)
   {
      U32 len = dStrlen(mHeightfieldScript);
      writeFile.write(len);
      writeFile.write(len, mHeightfieldScript);
   }
   else
      writeFile.write(U32(0));

   return (writeFile.getStatus() == FileStream::Ok);
}

//--------------------------------------

void TerrainFile::heightDevLine(U32 p1x, U32 p1y, U32 p2x, U32 p2y, U32 pmx, U32 pmy, U16 *devPtr)
{
   S32 h1 = getHeight(p1x, p1y);
   S32 h2 = getHeight(p2x, p2y);
   S32 hm = getHeight(pmx, pmy);
   S32 dev = ((h2 + h1) >> 1) - hm;
   if(dev < 0)
      dev = -dev;
   if(dev > *devPtr)
      *devPtr = dev;
}

void TerrainFile::buildChunkDeviance(S32 x, S32 y)
{
   GridChunk &gc = *(mChunkMap + x + (y << TerrainBlock::ChunkShift));
   gc.emptyFlags = 0;
   U32 sx = x << TerrainBlock::ChunkDownShift;
   U32 sy = y << TerrainBlock::ChunkDownShift;

   gc.heightDeviance[0] = 0;

   heightDevLine(sx, sy, sx + 2, sy, sx + 1, sy, &gc.heightDeviance[0]);
   heightDevLine(sx + 2, sy, sx + 4, sy, sx + 3, sy, &gc.heightDeviance[0]);

   heightDevLine(sx, sy + 2, sx + 2, sy + 2, sx + 1, sy + 2, &gc.heightDeviance[0]);
   heightDevLine(sx + 2, sy + 2, sx + 4, sy + 2, sx + 3, sy + 2, &gc.heightDeviance[0]);

   heightDevLine(sx, sy + 4, sx + 2, sy + 4, sx + 1, sy + 4, &gc.heightDeviance[0]);
   heightDevLine(sx + 2, sy + 4, sx + 4, sy + 4, sx + 3, sy + 4, &gc.heightDeviance[0]);

   heightDevLine(sx, sy, sx, sy + 2, sx, sy + 1, &gc.heightDeviance[0]);
   heightDevLine(sx + 2, sy, sx + 2, sy + 2, sx + 2, sy + 1, &gc.heightDeviance[0]);
   heightDevLine(sx + 4, sy, sx + 4, sy + 2, sx + 4, sy + 1, &gc.heightDeviance[0]);

   heightDevLine(sx, sy + 2, sx, sy + 4, sx, sy + 3, &gc.heightDeviance[0]);
   heightDevLine(sx + 2, sy + 2, sx + 2, sy + 4, sx + 2, sy + 3, &gc.heightDeviance[0]);
   heightDevLine(sx + 4, sy + 2, sx + 4, sy + 4, sx + 4, sy + 3, &gc.heightDeviance[0]);

   gc.heightDeviance[1] = gc.heightDeviance[0];

   heightDevLine(sx, sy, sx + 2, sy + 2, sx + 1, sy + 1, &gc.heightDeviance[1]);
   heightDevLine(sx + 2, sy, sx, sy + 2, sx + 1, sy + 1, &gc.heightDeviance[1]);

   heightDevLine(sx + 2, sy, sx + 4, sy + 2, sx + 3, sy + 1, &gc.heightDeviance[1]);
   heightDevLine(sx + 2, sy + 2, sx + 4, sy, sx + 3, sy + 1, &gc.heightDeviance[1]);

   heightDevLine(sx, sy + 2, sx + 2, sy + 4, sx + 1, sy + 3, &gc.heightDeviance[1]);
   heightDevLine(sx + 2, sy + 4, sx, sy + 2, sx + 1, sy + 3, &gc.heightDeviance[1]);

   heightDevLine(sx + 2, sy + 2, sx + 4, sy + 4, sx + 3, sy + 3, &gc.heightDeviance[1]);
   heightDevLine(sx + 2, sy + 4, sx + 4, sy + 2, sx + 3, sy + 3, &gc.heightDeviance[1]);

   gc.heightDeviance[2] = gc.heightDeviance[1];

   heightDevLine(sx, sy, sx + 4, sy, sx + 2, sy, &gc.heightDeviance[2]);
   heightDevLine(sx, sy + 4, sx + 4, sy + 4, sx + 2, sy + 4, &gc.heightDeviance[2]);
   heightDevLine(sx, sy, sx, sy + 4, sx, sy + 2, &gc.heightDeviance[2]);
   heightDevLine(sx + 4, sy, sx + 4, sy + 4, sx + 4, sy + 2, &gc.heightDeviance[2]);

   for(U32 j = 0; j < 4; j++)
   {
      for(U32 i = 0; i < 4; i++)
      {
         TerrainBlock::Material *mat = getMaterial(sx + i, sy + j);
         if(mat->flags & TerrainBlock::Material::Empty)
            gc.emptyFlags |= (1 << (j * 4 + i));
      }
   }
}

void TerrainFile::buildGridMap()
{
   S32 y;
   for(y = 0; y < TerrainBlock::ChunkSquareWidth; y++)
      for(U32 x = 0; x < TerrainBlock::ChunkSquareWidth; x++)
         buildChunkDeviance(x, y);

   GridSquare * gs = mGridMapBase;
   S32 i;
   for(i = TerrainBlock::BlockShift; i >= 0; i--)
   {
      mGridMap[i] = gs;
      gs += 1 << (2 * (TerrainBlock::BlockShift - i));
   }
   for(i = TerrainBlock::BlockShift; i >= 0; i--)
   {
      S32 squareCount = 1 << (TerrainBlock::BlockShift - i);
      S32 squareSize = (TerrainBlock::BlockSize) / squareCount;

      for(S32 squareX = 0; squareX < squareCount; squareX++)
      {
         for(S32 squareY = 0; squareY < squareCount; squareY++)
         {
            U16 min = 0xFFFF;
            U16 max = 0;
            U16 mindev45 = 0;
            U16 mindev135 = 0;

            Point3F p1, p2, p3, p4;

            // determine max error for both possible splits.
            PlaneF pl1, pl2, pl3, pl4;

            p1.set(0, 0, getHeight(squareX * squareSize, squareY * squareSize));
            p2.set(0, squareSize, getHeight(squareX * squareSize, squareY * squareSize + squareSize));
            p3.set(squareSize, squareSize, getHeight(squareX * squareSize + squareSize, squareY * squareSize + squareSize));
            p4.set(squareSize, 0, getHeight(squareX * squareSize + squareSize, squareY * squareSize));

            // pl1, pl2 = split45, pl3, pl4 = split135
            pl1.set(p1, p2, p3);
            pl2.set(p1, p3, p4);
            pl3.set(p1, p2, p4);
            pl4.set(p2, p3, p4);
            bool parentSplit45 = false;
            GridSquare *parent = NULL;
            if(i < TerrainBlock::BlockShift)
            {
               parent = findSquare(i+1, Point2I(squareX * squareSize, squareY * squareSize));
               parentSplit45 = parent->flags & GridSquare::Split45;
            }
            bool empty = true;
            bool hasEmpty = false;

            for(S32 sizeX = 0; sizeX <= squareSize; sizeX++)
            {
               for(S32 sizeY = 0; sizeY <= squareSize; sizeY++)
               {
                  S32 x = squareX * squareSize + sizeX;
                  S32 y = squareY * squareSize + sizeY;

                  if(sizeX != squareSize && sizeY != squareSize)
                  {
                     TerrainBlock::Material *mat = getMaterial(x, y);
                     if(!(mat->flags & TerrainBlock::Material::Empty))
                        empty = false;
                     else
                        hasEmpty = true;
                  }
                  U16 ht = getHeight(x, y);

                  if(ht < min)
                     min = ht;
                  if(ht > max)
                     max = ht;
                  Point3F pt(sizeX, sizeY, ht);
                  U16 dev;

                  if(sizeX < sizeY)
                     dev = calcDev(pl1, pt);
                  else if(sizeX > sizeY)
                     dev = calcDev(pl2, pt);
                  else
                     dev = Umax(calcDev(pl1, pt), calcDev(pl2, pt));

                  if(dev > mindev45)
                     mindev45 = dev;

                  if(sizeX + sizeY < squareSize)
                     dev = calcDev(pl3, pt);
                  else if(sizeX + sizeY > squareSize)
                     dev = calcDev(pl4, pt);
                  else
                     dev = Umax(calcDev(pl3, pt), calcDev(pl4, pt));

                  if(dev > mindev135)
                     mindev135 = dev;
               }
            }
            GridSquare *sq = findSquare(i, Point2I(squareX * squareSize, squareY * squareSize));
            sq->minHeight = min;
            sq->maxHeight = max;

            sq->flags = empty ? GridSquare::Empty : 0;
            if(hasEmpty)
               sq->flags |= GridSquare::HasEmpty;

            bool shouldSplit45 = ((squareX ^ squareY) & 1) == 0;
            bool split45;

            //split45 = shouldSplit45;
            if(i == 0)
               split45 = shouldSplit45;
            else if(i < 4 && shouldSplit45 == parentSplit45)
               split45 = shouldSplit45;
            else
               split45 = mindev45 < mindev135;

            //split45 = shouldSplit45;
            if(split45)
            {
               sq->flags |= GridSquare::Split45;
               sq->heightDeviance = mindev45;
            }
            else
               sq->heightDeviance = mindev135;
            if(parent)
               if(parent->heightDeviance < sq->heightDeviance)
                  parent->heightDeviance = sq->heightDeviance;
         }
      }
   }
   for (y = 0; y < TerrainBlock::BlockSize; y++)
   {
      for (S32 x=0; x < TerrainBlock::BlockSize; x++)
      {
         GridSquare *sq = findSquare(0, Point2I(x, y));
         S32 xpl = (x + 1) & TerrainBlock::BlockMask;
         S32 ypl = (y + 1) & TerrainBlock::BlockMask;
         for(U32 i = 0; i < TerrainBlock::MaterialGroups; i++)
         {
            if (mMaterialAlphaMap[i] != NULL) {
               U32 mapVal = (mMaterialAlphaMap[i][(y << TerrainBlock::BlockShift) + x]     +
                             mMaterialAlphaMap[i][(ypl << TerrainBlock::BlockShift) + x]   +
                             mMaterialAlphaMap[i][(ypl << TerrainBlock::BlockShift) + xpl] +
                             mMaterialAlphaMap[i][(y << TerrainBlock::BlockShift) + xpl]);
               if(mapVal)
                  sq->flags |= (GridSquare::MaterialStart << i);
            }
         }
      }
   }
   for (y = 0; y < TerrainBlock::BlockSize; y += 2)
   {
      for (S32 x=0; x < TerrainBlock::BlockSize; x += 2)
      {
         GridSquare *sq = findSquare(1, Point2I(x, y));
         GridSquare *s1 = findSquare(0, Point2I(x, y));
         GridSquare *s2 = findSquare(0, Point2I(x+1, y));
         GridSquare *s3 = findSquare(0, Point2I(x, y+1));
         GridSquare *s4 = findSquare(0, Point2I(x+1, y+1));
         sq->flags |= (s1->flags | s2->flags | s3->flags | s4->flags) & ~(GridSquare::MaterialStart -1);
      }
   }
   GridSquare *s = findSquare(1, Point2I(0, 0));
   U16 *dflags = mFlagMap;
   U16 *eflags = mFlagMap + TerrainBlock::FlagMapWidth * TerrainBlock::FlagMapWidth;

   for(;dflags != eflags;s++,dflags++)
      *dflags = s->flags;

}

//--------------------------------------
ResourceInstance *constructTerrainFile(Stream &stream)
{
   U8 version;
   stream.read(&version);
   if (version > TerrainFile::FILE_VERSION)
      return NULL;

   if (version != TerrainFile::FILE_VERSION) {
      Con::errorf(" ****************************************************");
      Con::errorf(" ****************************************************");
      Con::errorf(" ****************************************************");
      Con::errorf(" PLEASE RESAVE THE TERRAIN FILE FOR THIS MISSION!  THANKS!");
      Con::errorf(" ****************************************************");
      Con::errorf(" ****************************************************");
      Con::errorf(" ****************************************************");
   }

   TerrainFile* ret = new TerrainFile;
   // read the HeightField
   for (S32 i=0; i < (TerrainBlock::BlockSize * TerrainBlock::BlockSize); i++)
      stream.read(&ret->mHeightMap[i]);

   // read the material group map and flags...
   dMemset(ret->mMaterialMap, 0, sizeof(ret->mMaterialMap));
   TerrainBlock::Material * materialMap = (TerrainBlock::Material*)ret->mMaterialMap;

   AssertFatal(!(TerrainBlock::Material::PersistMask & TerrainFile::MATERIAL_GROUP_MASK),
               "Doh! We have flag clobberage...");

   for (S32 j=0; j < (TerrainBlock::BlockSize * TerrainBlock::BlockSize); j++)
   {
      U8 val;
      stream.read(&val);

      //
      ret->mBaseMaterialMap[j] = val & TerrainFile::MATERIAL_GROUP_MASK;
      materialMap[j].flags = val & TerrainBlock::Material::PersistMask;
   }

   // read the MaterialList Info
   S32 k, maxMaterials = TerrainBlock::MaterialGroups;
   for(k=0; k < maxMaterials;)
   {
      ret->mMaterialFileName[k] = stream.readSTString(true);
      if(ret->mMaterialFileName[k] && ret->mMaterialFileName[k][0])
         k++;
      else
         maxMaterials--;
   }
   for(;k < TerrainBlock::MaterialGroups; k++)
      ret->mMaterialFileName[k] = NULL;


   if(version == 1)
   {
      for(S32 j = 0; j < (TerrainBlock::BlockSize * TerrainBlock::BlockSize); j++) {
         if (ret->mMaterialAlphaMap[ret->mBaseMaterialMap[j]] == NULL) {
            ret->mMaterialAlphaMap[ret->mBaseMaterialMap[j]] = new U8[TerrainBlock::BlockSize * TerrainBlock::BlockSize];
            dMemset(ret->mMaterialAlphaMap[ret->mBaseMaterialMap[j]], 0, TerrainBlock::BlockSize * TerrainBlock::BlockSize);
         }

         ret->mMaterialAlphaMap[ret->mBaseMaterialMap[j]][j] = 255;
      }
   }
   else
   {
      for(S32 k=0; k < TerrainBlock::MaterialGroups; k++) {
         if(ret->mMaterialFileName[k] && ret->mMaterialFileName[k][0]) {
            AssertFatal(ret->mMaterialAlphaMap[k] == NULL, "Bad assumption.  There should be no alpha map at this point...");
            ret->mMaterialAlphaMap[k] = new U8[TerrainBlock::BlockSize * TerrainBlock::BlockSize];
            stream.read(TerrainBlock::BlockSize * TerrainBlock::BlockSize, ret->mMaterialAlphaMap[k]);
         }
      }
   }
   if(version >= 3)
   {
      U32 len;
      stream.read(&len);
      ret->mTextureScript = (char *) dMalloc(len + 1);
      stream.read(len, ret->mTextureScript);
      ret->mTextureScript[len] = 0;

      stream.read(&len);
      ret->mHeightfieldScript = (char *) dMalloc(len + 1);
      stream.read(len, ret->mHeightfieldScript);
      ret->mHeightfieldScript[len] = 0;
   }
   else
   {
      ret->mTextureScript = 0;
      ret->mHeightfieldScript = 0;
   }

   ret->buildGridMap();
   return ret;
}

void TerrainBlock::setBaseMaterial(U32 /*x*/, U32 /*y*/, U8 /*matGroup*/)
{

}

S32 TerrainBlock::getTerrainMapIndex(Point3F& pt)
{
   U8 alphas[MaterialGroups];
   int mapIndex;

   const MatrixF & mat = getTransform();
   Point3F origin;
   mat.getColumn(3, &origin);
   F32 squareSize = (F32) getSquareSize();
   F32 halfSquareSize = squareSize / 2;
   float x = (pt.x - origin.x + halfSquareSize) / squareSize;
   float y = (pt.y - origin.y + halfSquareSize) / squareSize;
   getMaterialAlpha(Point2I(x,y), alphas);
   MaterialPropertyMap* matMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
   if (matMap != NULL)
   {
      U8 maxAlpha = alphas[0];
      U8 maxAlpha2;
      int indexTexture = 0;
      for (int i=1; i<MaterialGroups; i++)
      {
         maxAlpha2 = getMax(alphas[i],maxAlpha);
         if (maxAlpha2 != maxAlpha)
         {
            indexTexture = i;
            maxAlpha = maxAlpha2;
         }
      }
      mapIndex = mMPMIndex[indexTexture];
   }
   return mapIndex;
}

⌨️ 快捷键说明

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