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

📄 tsshapeinstance.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
         else if (numUsedTE+3<=numTE)
         {
            emapMethod = ENVIRONMENT_MAP_MULTI_3;
            emapTE = numUsedTE;
            numUsedTE += 3;
         }
         else if (mAllowTwoPassEnvironmentMap)
            emapMethod = ENVIRONMENT_MAP_TWO_PASS;
         else
            emapMethod = NO_ENVIRONMENT_MAP;
      }
      else
         emapMethod = NO_ENVIRONMENT_MAP;

      // detail map...
      if (wantDMap)
      {
         if (smRenderData.detailMapAlpha>0.99f && numTE>=numUsedTE+1)
         {
            dmapMethod = DETAIL_MAP_MULTI_1;
            dmapTE = numUsedTE;
            numUsedTE++;
         }
         else if (smRenderData.detailMapAlpha<=0.9f && numTE>=numUsedTE+2)
         {
            dmapMethod = DETAIL_MAP_MULTI_2;
            dmapTE = 0;     // detail texture goes in first unit...
            baseTE++;       // so we bump this back one...
            emapTE++;       // this one gets bumped back 2...
            numUsedTE += 2; // end up using two additional units..
         }
         else
            dmapMethod = mAllowTwoPassDetailMap ? DETAIL_MAP_TWO_PASS : NO_DETAIL_MAP;
      }
      else
         dmapMethod = NO_DETAIL_MAP;

      // fog...
      if (wantFog)
      {
         // DMMUNDO!
         if (numTE>=numUsedTE+1 && emapMethod!=ENVIRONMENT_MAP_TWO_PASS)
         {
            fogMethod = smRenderData.fogMapHandle ? FOG_MULTI_1_TEXGEN : FOG_MULTI_1;
            fogTE = numUsedTE;
            numUsedTE++;
         }
         else
            fogMethod = smRenderData.fogMapHandle ? FOG_TWO_PASS_TEXGEN : FOG_TWO_PASS;
      }
      else
         fogMethod = NO_FOG;
   }
   else
   {
      // we can't single pass environment map without texture combine extension...
      wantEMap = wantEMap && mAllowTwoPassEnvironmentMap;
      emapMethod = wantEMap ? ENVIRONMENT_MAP_TWO_PASS : NO_ENVIRONMENT_MAP;
      // ditto for detail map...
      wantDMap = wantDMap && mAllowTwoPassDetailMap;
      dmapMethod = wantDMap ? DETAIL_MAP_TWO_PASS : NO_DETAIL_MAP;
      fogMethod = wantFog ? FOG_TWO_PASS : NO_FOG;
   }

   if (emapMethod == NO_ENVIRONMENT_MAP)
      smRenderData.environmentMapAlpha = 1.0f;
}

void TSShapeInstance::setupFog(F32 fogAmount, const ColorF & fogColor)
{
   smRenderData.fogOn = (fogAmount > 1.0 / 64.0f);
   smRenderData.fogMapHandle = NULL;

   bool refresh = false;

   if (!smRenderData.fogBitmap)
   {
      smRenderData.fogBitmap = new GBitmap(8,8,false,GBitmap::RGBA);

      // clear the bitmap (defaults to 0xff) so if fogColor is 0,0,0
      // we will have a valid bitmap
      dMemset(smRenderData.fogBitmap->getWritableBits(), 0, 256);
   }

   if (smRenderData.fogColor.x != fogColor.red ||
       smRenderData.fogColor.y != fogColor.green ||
       smRenderData.fogColor.z != fogColor.blue)
   {
      U8 *bits = smRenderData.fogBitmap->getWritableBits();
      U8 red = U8(255*fogColor.red);
      U8 green = U8(255*fogColor.green);
      U8 blue = U8(255*fogColor.blue);

      for (U8 i = 0; i < 64; ++i)
      {
         *bits++ = red;
         *bits++ = green;
         *bits++ = blue;
         bits++;
      }
      refresh = true;
   }

   // the ATI Rage 128 needs a forthcoming driver to do do constant alpha blend
   if (smRenderData.fogTexture)
   {
      if (smRenderData.fogColor.w != fogAmount)
      {
         U8 *bits = smRenderData.fogBitmap->getWritableBits();
         U8 fog = U8(255 * fogAmount);

         for (U8 i = 0; i < 64; ++i)
         {
            bits[3] = fog;
            bits += 4;
         }
         refresh = true;
      }
   }

   if (!smRenderData.fogHandle)
      smRenderData.fogHandle = new TextureHandle("fog_texture", smRenderData.fogBitmap);
   else
      if (refresh)
         smRenderData.fogHandle->refresh();

   smRenderData.fogColor.set(fogColor.red,fogColor.green,fogColor.blue,fogAmount);
}

void TSShapeInstance::setupFog(F32 fogAmount, TextureHandle * fogMap, Point4F & s, Point4F & t)
{
   smRenderData.fogColor.w = fogAmount;
   smRenderData.fogOn = true;
   smRenderData.fogMapHandle = fogMap;
   smRenderData.fogTexGenS = s;
   smRenderData.fogTexGenT = t;
}

bool TSShapeInstance::twoPassEnvironmentMap()
{
   return (smRenderData.environmentMapMethod==ENVIRONMENT_MAP_TWO_PASS);
}

bool TSShapeInstance::twoPassDetailMap()
{
   return (smRenderData.detailMapMethod==DETAIL_MAP_TWO_PASS);
}

bool TSShapeInstance::twoPassFog()
{
   return (smRenderData.fogMethod==FOG_TWO_PASS || smRenderData.fogMethod==FOG_TWO_PASS_TEXGEN);
}

void TSShapeInstance::renderEnvironmentMap()
{
   AssertFatal((void *)mEnvironmentMap!=NULL,"TSShapeInstance::renderEnvironmentMap (1)");
   AssertFatal(mEnvironmentMapOn,"TSShapeInstance::renderEnvironmentMap (2)");
   AssertFatal(dglDoesSupportARBMultitexture(),"TSShapeInstance::renderEnvironmentMap (3)");
   AssertFatal(smRenderData.environmentMapMethod==ENVIRONMENT_MAP_TWO_PASS,"TSShapeInstance::renderEnvironmentMap (4)");

   S32 dl = smRenderData.detailLevel;
   const TSDetail * detail = &mShape->details[dl];
   S32 ss = detail->subShapeNum;
   S32 od = detail->objectDetailNum;

   S32 start = mShape->subShapeFirstObject[ss];
   S32 end   = mShape->subShapeNumObjects[ss] + start;
   if (start>=end)
      return;

   // set up gl environment for emap...
   TSMesh::initEnvironmentMapMaterials();

   // run through objects and render
   smRenderData.currentTransform = NULL;
   for (S32 i=start; i<end; i++)
      mMeshObjects[i].renderEnvironmentMap(od,mMaterialList);

   // if we have a matrix pushed, pop it now
   if (smRenderData.currentTransform)
      glPopMatrix();

   // restore gl state
   TSMesh::resetEnvironmentMapMaterials();
}

void TSShapeInstance::renderFog()
{
   AssertFatal(smRenderData.fogMethod==FOG_TWO_PASS || smRenderData.fogMethod==FOG_TWO_PASS_TEXGEN,"TSShapeInstance::renderFog");

   S32 dl = smRenderData.detailLevel;
   const TSDetail * detail = &mShape->details[dl];
   S32 ss = detail->subShapeNum;
   S32 od = detail->objectDetailNum;

   GLboolean wasLit = glIsEnabled(GL_LIGHTING);
   glDisable(GL_LIGHTING);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glEnableClientState(GL_VERTEX_ARRAY);

   if (smRenderData.fogMethod==FOG_TWO_PASS_TEXGEN)
   {
      // set up fog map
      glEnable(GL_TEXTURE_2D);
      glBindTexture(GL_TEXTURE_2D, TSShapeInstance::smRenderData.fogMapHandle->getGLName());

      // set up texgen equations
      glTexGeni(GL_S,GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
      glTexGeni(GL_T,GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
      glEnable(GL_TEXTURE_GEN_S);
      glEnable(GL_TEXTURE_GEN_T);
      glTexGenfv(GL_S,GL_OBJECT_PLANE,&TSShapeInstance::smRenderData.fogTexGenS.x);
      glTexGenfv(GL_T,GL_OBJECT_PLANE,&TSShapeInstance::smRenderData.fogTexGenT.x);
   }
   else
   {
      // just one fog color per shape...
      glColor4fv(smRenderData.fogColor);
      // texture should be disabled already...
   }

   smRenderData.currentTransform = NULL;
   S32 start = smNoRenderNonTranslucent ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss];
   S32 end   = smNoRenderTranslucent ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss];
   for (S32 i=start; i<end; i++)
      mMeshObjects[i].renderFog(od, mMaterialList);

   // if we have a marix pushed, pop it now
   if (smRenderData.currentTransform)
      glPopMatrix();

   // reset gl state
   glDisable(GL_BLEND);
   glDisable(GL_TEXTURE_GEN_S);
   glDisable(GL_TEXTURE_GEN_T);
   glDisable(GL_TEXTURE_2D);
   glBlendFunc(GL_ONE, GL_ZERO);
   glDisableClientState(GL_VERTEX_ARRAY);
   if (wasLit)
      glEnable(GL_LIGHTING);
}

void TSShapeInstance::renderDetailMap()
{
   AssertFatal(smRenderData.detailMapMethod==DETAIL_MAP_TWO_PASS,"TSShapeInstance::renderDetailMap (1)");

   S32 dl = smRenderData.detailLevel;
   const TSDetail * detail = &mShape->details[dl];
   S32 ss = detail->subShapeNum;
   S32 od = detail->objectDetailNum;

   S32 start = mShape->subShapeFirstObject[ss];
   S32 end   = mShape->subShapeNumObjects[ss] + start;

   // set up gl environment for the detail map
   TSMesh::initDetailMapMaterials();

   // run through objects and render detail maps
   smRenderData.currentTransform = NULL;
   for (S32 i=start; i<end; i++)
      mMeshObjects[i].renderDetailMap(od,mMaterialList);

   // if we have a matrix pushed, pop it now
   if (smRenderData.currentTransform)
      glPopMatrix();

   // restore gl state
   TSMesh::resetDetailMapMaterials();
}

S32 TSShapeInstance::getCurrentDetail()
{
   return mCurrentDetailLevel;
}

F32 TSShapeInstance::getCurrentIntraDetail()
{
   return mCurrentIntraDetailLevel;
}

void TSShapeInstance::setCurrentDetail(S32 dl, F32 intraDL)
{
   mCurrentDetailLevel = dl;
   mCurrentIntraDetailLevel = intraDL>1.0f ? 1.0f : (intraDL<0.0f ? 0.0f : intraDL);

   // restrict chosen detail level by cutoff value
   S32 cutoff = getMin(smNumSkipRenderDetails,mShape->mSmallestVisibleDL);
   if (mCurrentDetailLevel>=0 && mCurrentDetailLevel<cutoff)
   {
      mCurrentDetailLevel = cutoff;
      mCurrentIntraDetailLevel = 1.0f;
   }
}

S32 TSShapeInstance::selectCurrentDetail(bool ignoreScale)
{
   if (mShape->mSmallestVisibleDL>=0 && mShape->details[0].maxError>=0)
      // use new scheme
      return selectCurrentDetailEx(ignoreScale);

   MatrixF toCam;
   Point3F p;
   dglGetModelview(&toCam);
   toCam.mulP(mShape->center,&p);
   F32 dist = mDot(p,p);
   F32 scale = 1.0f;
   if (!ignoreScale)
   {
      // any scale?
      Point3F x,y,z;
      toCam.getRow(0,&x);
      toCam.getRow(1,&y);
      toCam.getRow(2,&z);
      F32 scalex = mDot(x,x);
      F32 scaley = mDot(y,y);
      F32 scalez = mDot(z,z);
      scale = scalex;
      if (scaley > scale)
         scale = scaley;
      if (scalez > scale)
         scale = scalez;
   }
   dist /= scale;
   dist = mSqrt(dist);

   F32 pixelRadius = dglProjectRadius(dist,mShape->radius) * dglGetPixelScale() * smDetailAdjust;

   return selectCurrentDetail(pixelRadius);
}

S32 TSShapeInstance::selectCurrentDetailEx(bool ignoreScale)
{
   MatrixF toCam;
   Point3F p;
   dglGetModelview(&toCam);
   toCam.mulP(mShape->center,&p);
   F32 dist = mDot(p,p);
   F32 scale = 1.0f;
   if (!ignoreScale)
   {
      // any scale?
      Point3F x,y,z;
      toCam.getRow(0,&x);
      toCam.getRow(1,&y);
      toCam.getRow(2,&z);
      F32 scalex = mDot(x,x);
      F32 scaley = mDot(y,y);
      F32 scalez = mDot(z,z);
      scale = scalex;
      if (scaley > scale)
         scale = scaley;
      if (scalez > scale)
         scale = scalez;
   }
   dist /= scale;
   dist = mSqrt(dist);

   // find tolerance
   F32 proj = dglProjectRadius(dist,1.0f) * dglGetPixelScale(); // pixel size of 1 meter at given distance
   if ( smFogExemptionOn )
      return selectCurrentDetailEx(F32(0.001)/proj);
   else
      return selectCurrentDetailEx(smScreenError/proj);
}

S32 TSShapeInstance::selectCurrentDetail(Point3F offset, F32 invScale)
{
   F32 dist = mSqrt(mDot(offset,offset));
   dist *= invScale;
   return selectCurrentDetail2(dist);
}

S32 TSShapeInstance::selectCurrentDetail2(F32 adjustedDist)
{
   if (mShape->mSmallestVisibleDL>=0 && mShape->details[0].maxError>=0)
      // use new scheme
      return selectCurrentDetail2Ex(adjustedDist);

   F32 pixelRadius = dglProjectRadius(adjustedDist,mShape->radius) * dglGetPixelScale();
   F32 adjustedPR = pixelRadius * smDetailAdjust;
   if(adjustedPR <= mShape->mSmallestVisibleSize)
      adjustedPR = mShape->mSmallestVisibleSize + 0.01f;

   return selectCurrentDetail(adjustedPR);
}

S32 TSShapeInstance::selectCurrentDetail2Ex(F32 adjustedDist)
{
   // find tolerance
   F32 proj = dglProjectRadius(adjustedDist,1.0f) * dglGetPixelScale(); // pixel size of 1 meter at given distance
   if ( smFogExemptionOn )
      return selectCurrentDetailEx(F32(0.001)/proj);
   else
      return selectCurrentDetailEx(smScreenError/proj);
}

S32 TSShapeInstance::selectCurrentDetail(F32 size)
{
   // check to see if not visible first...

⌨️ 快捷键说明

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