📄 tsshapeinstance.cc
字号:
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 + -