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

📄 tsshapeinstance.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
   if (size<=mShape->mSmallestVisibleSize)
   {
      // don't render...
      mCurrentDetailLevel=-1;
      mCurrentIntraDetailLevel = 0.0f;
      return -1;
   }

   // same detail level as last time?
   // only search for detail level if the current one isn't the right one already
   if ( mCurrentDetailLevel<0 ||
        (mCurrentDetailLevel==0 && size<=mShape->details[0].size) ||
        (mCurrentDetailLevel>0  && (size<=mShape->details[mCurrentDetailLevel].size || size>mShape->details[mCurrentDetailLevel-1].size)))
   {
      // scan shape for highest detail size smaller than us...
      // shapes details are sorted from largest to smallest...
      // a detail of size <= 0 means it isn't a renderable detail level (utility detail)
      for (S32 i=0; i<mShape->details.size(); i++)
      {
         if (size>mShape->details[i].size)
         {
            mCurrentDetailLevel = i;
            break;
         }
         if (i+1>=mShape->details.size() || mShape->details[i+1].size<0)
         {
            // We've run out of details and haven't found anything?
            // Let's just grab this one.
            mCurrentDetailLevel = i;
            break;
         }
      }
   }

   F32 curSize = mShape->details[mCurrentDetailLevel].size;
   F32 nextSize = mCurrentDetailLevel==0 ? 2.0f * curSize : mShape->details[mCurrentDetailLevel-1].size;
   mCurrentIntraDetailLevel = nextSize-curSize>0.01f ? (size-curSize) / (nextSize-curSize) : 1.0f;
   mCurrentIntraDetailLevel = mCurrentIntraDetailLevel>1.0f ? 1.0f : (mCurrentIntraDetailLevel<0.0f ? 0.0f : mCurrentIntraDetailLevel);

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

   return mCurrentDetailLevel;
}

S32 TSShapeInstance::selectCurrentDetailEx(F32 errorTOL)
{
   // note:  we use 10 time the average error as the metric...this is
   // more robust than the maxError...the factor of 10 is to put average error
   // on about the same scale as maxError.  The errorTOL is how much
   // error we are able to tolerate before going to a more detailed version of the
   // shape.  We look for a pair of details with errors bounding our errorTOL,
   // and then we select an interpolation parameter to tween betwen them.  Ok, so
   // this isn't exactly an error tolerance.  A tween value of 0 is the lower poly
   // model (higher detail number) and a value of 1 is the higher poly model (lower
   // detail number).

   // deal with degenerate case first...
   // if smallest detail corresponds to less than half tolerable error, then don't even draw
   F32 prevErr;
   if (mShape->mSmallestVisibleDL<0)
      prevErr=0.0f;
   else
      prevErr = 10.0f * mShape->details[mShape->mSmallestVisibleDL].averageError * 20.0f;
   if (mShape->mSmallestVisibleDL<0 || prevErr<errorTOL)
   {
      // draw last detail
      mCurrentDetailLevel=mShape->mSmallestVisibleDL;
      mCurrentIntraDetailLevel = 0.0f;
      return mCurrentDetailLevel;
   }

   // this function is a little odd
   // the reason is that the detail numbers correspond to
   // when we stop using a given detail level...
   // we search the details from most error to least error
   // until we fit under the tolerance (errorTOL) and then
   // we use the next highest detail (higher error)
   for (S32 i=mShape->mSmallestVisibleDL; i>=0; i--)
   {
      F32 err0 = 10.0f * mShape->details[i].averageError;
      if (err0 < errorTOL)
      {
         // ok, stop here

         // intraDL = 1 corresponds to fully this detail
         // intraDL = 0 corresponds to the next lower (higher number) detail
         mCurrentDetailLevel = i;
         mCurrentIntraDetailLevel = 1.0f - (errorTOL-err0)/(prevErr-err0);
         return mCurrentDetailLevel;
      }
      prevErr=err0;
   }

   // get here if we are drawing at DL==0
   mCurrentDetailLevel = 1;
   mCurrentIntraDetailLevel = 1.0f;
   return mCurrentDetailLevel;

}

GBitmap * TSShapeInstance::snapshot(TSShape * shape, U32 width, U32 height, bool mip, MatrixF & cameraPos, S32 dl, F32 intraDL, bool hiQuality)
{
   TSShapeInstance * shapeInstance = new TSShapeInstance(shape, true);
   shapeInstance->setCurrentDetail(dl,intraDL);
   shapeInstance->animate();
   GBitmap * bmp = shapeInstance->snapshot(width,height,mip,cameraPos,hiQuality);

   delete shapeInstance;

   return bmp;
}

GBitmap * TSShapeInstance::snapshot(U32 width, U32 height, bool mip, MatrixF & cameraPos, S32 dl, F32 intraDL, bool hiQuality)
{
   setCurrentDetail(dl,intraDL);
   animate();
   return snapshot(width,height,mip,cameraPos,hiQuality);
}

GBitmap * TSShapeInstance::snapshot(U32 width, U32 height, bool mip, MatrixF & cameraMatrix,bool hiQuality)
{
   U32 screenWidth = Platform::getWindowSize().x;
   U32 screenHeight = Platform::getWindowSize().y;
   U32 xcenter = screenWidth >> 1;
   U32 ycenter = screenHeight >> 1;

   if (screenWidth==0 || screenHeight==0)
      return NULL; // probably in exporter...

   AssertFatal(width<screenWidth && height<screenHeight,"TSShapeInstance::snapshot: bitmap cannot be larger than screen resolution");

   S32 scale = 1;
   if (hiQuality)
      while ((scale<<1)*width <= screenWidth && (scale<<1)*height <= screenHeight)
         scale <<= 1;
   if (scale>smMaxSnapshotScale)
      scale = smMaxSnapshotScale;

   // height and width of intermediate bitmaps
   U32 bmpWidth  = width*scale;
   U32 bmpHeight = height*scale;

   Point4F saveClearColor;
   glGetFloatv(GL_COLOR_CLEAR_VALUE,(F32*)&saveClearColor);

   // setup viewport and frustrum (do orthographic projection)
   dglSetViewport(RectI(xcenter-(bmpWidth>>1),ycenter-(bmpHeight>>1),bmpWidth,bmpHeight));
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   dglSetFrustum(-mShape->radius, mShape->radius, -mShape->radius, mShape->radius, 1, 20.0f * mShape->radius,true);

   // position camera...
   glMatrixMode(GL_MODELVIEW);
   Point3F y;
   cameraMatrix.getColumn(1,&y);
   y *= -10.0f * mShape->radius;
   y += mShape->center;
   cameraMatrix.setColumn(3,y);
   cameraMatrix.inverse();
   dglLoadMatrix(&cameraMatrix);

   // set some initial gl states
   glDisable(GL_CULL_FACE);
   glDisable(GL_LIGHTING);
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);

   // take a snapshot of the shape with a black background...
   glClearColor(0,0,0,0);
   glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
   GBitmap * blackBmp = new GBitmap;
   blackBmp->allocateBitmap(bmpWidth,bmpHeight,false,GBitmap::RGB);
   render(mCurrentDetailLevel,mCurrentIntraDetailLevel);
   glReadPixels(xcenter-(bmpWidth>>1),ycenter-(bmpHeight>>1),bmpWidth,bmpHeight,GL_RGB,GL_UNSIGNED_BYTE,(void*)blackBmp->getBits(0));

   // take a snapshot of the shape with a white background...
   glClearColor(1,1,1,1);
   glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
   GBitmap * whiteBmp = new GBitmap;
   whiteBmp->allocateBitmap(bmpWidth,bmpHeight,false,GBitmap::RGB);
   render(mCurrentDetailLevel,mCurrentIntraDetailLevel);
   glReadPixels(xcenter-(bmpWidth>>1),ycenter-(bmpHeight>>1),bmpWidth,bmpHeight,GL_RGB,GL_UNSIGNED_BYTE,(void*)whiteBmp->getBits(0));

   glDisable(GL_DEPTH_TEST);
   glClearColor(saveClearColor.x,saveClearColor.y,saveClearColor.z,saveClearColor.w);

   // now separate the color and alpha channels
   GBitmap * bmp = new GBitmap;
   bmp->allocateBitmap(width,height,mip,GBitmap::RGBA);
   U8 * wbmp = (U8*)whiteBmp->getBits(0);
   U8 * bbmp = (U8*)blackBmp->getBits(0);
   U8 * dst  = (U8*)bmp->getBits(0);
   U32 i,j;
   if (hiQuality)
   {
      for (i=0; i<height; i++)
      {
         for (j=0; j<width; j++)
         {
            F32 alphaTally = 0.0f;
            S32 alphaIntTally = 0;
            S32 alphaCount = 0;
            F32 rTally = 0.0f;
            F32 gTally = 0.0f;
            F32 bTally = 0.0f;
            for (S32 k=0; k<scale; k++)
            {
               for (S32 l=0; l<scale; l++)
               {
                  // shape on black background is alpha * color, shape on white background is alpha * color + (1-alpha) * 255
                  // we want 255 * alpha, or 255 - (white - black)
                  U32 pos = 3*((i*scale+k)*bmpWidth+j*scale+l);
                  U32 alpha = 255 - (wbmp[pos+0] - bbmp[pos+0]);
                  alpha    += 255 - (wbmp[pos+1] - bbmp[pos+1]);
                  alpha    += 255 - (wbmp[pos+2] - bbmp[pos+2]);
                  F32 floatAlpha = ((F32)alpha)/(1.0f*255.0f);
                  if (alpha != 0)
                  {
                     rTally += bbmp[pos+0];
                     gTally += bbmp[pos+1];
                     bTally += bbmp[pos+2];
                     alphaCount++;
                  }
                  alphaTally += floatAlpha;
                  alphaIntTally += alpha;
               }
            }
            F32 invAlpha = alphaTally > 0.01f ? 1.0f / alphaTally : 0.0f;
            U32 pos = 4*(i*width+j);
            dst[pos+0] = (U8)(rTally * invAlpha);
            dst[pos+1] = (U8)(gTally * invAlpha);
            dst[pos+2] = (U8)(bTally * invAlpha);
            dst[pos+3] = (U8)(((F32)alphaIntTally) / (F32) (3*alphaCount));
         }
      }
   }
   else
   {
      // simpler, probably faster...
      for (i=0; i<height*width; i++)
      {
         // shape on black background is alpha * color, shape on white background is alpha * color + (1-alpha) * 255
         // we want 255 * alpha, or 255 - (white - black)
         U32 alpha = 255 - (wbmp[i*3+0] - bbmp[i*3+0]);
         alpha    += 255 - (wbmp[i*3+1] - bbmp[i*3+1]);
         alpha    += 255 - (wbmp[i*3+2] - bbmp[i*3+2]);

         if (alpha != 0)
         {
            F32 floatAlpha = ((F32)alpha)/(3.0f*255.0f);
            dst[i*4+0] = (U8)(bbmp[i*3+0] / floatAlpha);
            dst[i*4+1] = (U8)(bbmp[i*3+1] / floatAlpha);
            dst[i*4+2] = (U8)(bbmp[i*3+2] / floatAlpha);
            dst[i*4+3] = (U8)(alpha/3);
         }
         else
         {
            dst[i*4+0] = dst[i*4+1] = dst[i*4+2] = dst[i*4+3] = 0;
         }
      }
   }

   delete blackBmp;
   delete whiteBmp;

   if (mip)
      bmp->extrudeMipLevels();

   return bmp;
}

void TSShapeInstance::renderShadow(S32 dl, const MatrixF & mat, S32 dim, U32 * bits)
{
   // if dl==-1, nothing to do
   if (dl==-1)
      return;

   AssertFatal(dl>=0 && dl<mShape->details.size(),"TSShapeInstance::renderShadow");

   S32 i;

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

   // assert if we're a billboard detail
   AssertFatal(ss>=0,"TSShapeInstance::renderShadow: not with a billboard detail level");

   // set up render data
   setStatics(dl);

   // run through the meshes
   smRenderData.currentTransform = NULL;
   S32 start = mShape->subShapeFirstObject[ss];
   S32 end   = start + mShape->subShapeNumObjects[ss];
   for (i=start; i<end; i++)
      mMeshObjects[i].renderShadow(od,mat,dim,bits,mMaterialList);

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

   clearStatics();
}

//-------------------------------------------------------------------------------------
// Object (MeshObjectInstance & PluginObjectInstance) render methods
//-------------------------------------------------------------------------------------

void TSShapeInstance::ObjectInstance::render(S32, TSMaterialList *)
{
   AssertFatal(0,"TSShapeInstance::ObjectInstance::render:  no default render method.");
}

void TSShapeInstance::ObjectInstance::renderEnvironmentMap(S32, TSMaterialList *)
{
   AssertFatal(0,"TSShapeInstance::ObjectInstance::renderEnvironmentMap:  no default render method.");
}

void TSShapeInstance::ObjectInstance::renderDetailMap(S32, TSMaterialList *)
{
   AssertFatal(0,"TSShapeInstance::ObjectInstance::renderDetailMap:  no default render method.");
}

void TSShapeInstance::ObjectInstance::renderFog(S32, TSMaterialList*)
{
   AssertFatal(0,"TSShapeInstance::ObjectInstance::renderFog:  no default render method.");
}

S32 TSShapeInstance::MeshObjectInstance::getSizeVB(S32 size)
{
   TSMesh *mesh = getMesh(0);

   if (mesh && mesh->getMeshType() == TSMesh::StandardMeshType && mesh->vertsPerFrame > 0)
   {
      mesh->vbOffset = size;

      return mesh->numFrames*mesh->numMatFrames*mesh->vertsPerFrame;
   }
   else
      return 0;
}

bool TSShapeInstance::MeshObjectInstance::hasMergeIndices()
{
   TSMesh *mesh = getMesh(0);

   return (mesh && mesh->getMeshType() == TSMesh::StandardMeshType && mesh->mergeIndices.size());
}

void TSShapeInstance::MeshObjectInstance::fillVB(S32 vb, TSMaterialList *materials)
{
   TSMesh *mesh = getMesh(0);

   if (!mesh || mesh->getMeshType() != TSMesh::StandardMeshType || mesh->vertsPerFrame <= 0)
      return;

   for (S32 f = 0; f < mesh->numFrames; ++f)
      for (S32 m = 0; m < mesh->numMatFrames; ++m)
         mesh->fillVB(vb,f,m,materials);
}

void TSShapeInstance::MeshObjectInstance::morphVB(S32 vb, S32 &previousMerge, S32 objectDetail, TSMaterialList *materials)
{
   if (visible > 0.01f)
   {
      TSMesh *m0 = getMesh(0);
      TSMesh *mesh = getMesh(objectDetail);

      if (m0 && mesh)
      {
         // render TSSortedMesh's standard
         if (m0->getMeshType() != TSMesh::StandardMeshType)
            return;

         GLuint foffset = (frame*m0->numMatFrames + matFrame)*m0->vertsPerFrame;
         U32 morphSize = mesh->mergeIndices.size();
         S32 merge = mesh->vertsPerFrame-morphSize;

         if (!morphSize)
            return;

         if (previousMerge != -1 && previousMerge < merge)
         {
            S32 tmp = merge;

            merge = previousMerge;
            previousMerge = tmp;
            morphSize = mesh->vertsPerFrame-merge;
         }
         else
            previousMerge 

⌨️ 快捷键说明

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