📄 tsshapeinstance.cc
字号:
void TSShapeInstance::render(S32 dl, F32 intraDL, const Point3F * objectScale)
{
// if dl==-1, nothing to do
if (dl==-1)
return;
AssertFatal(dl>=0 && dl<mShape->details.size(),"TSShapeInstance::render");
S32 i;
const TSDetail * detail = &mShape->details[dl];
S32 ss = detail->subShapeNum;
S32 od = detail->objectDetailNum;
// set up static data
setStatics(dl,intraDL,objectScale);
// if we're a billboard detail, draw it and exit
PROFILE_START(TSShapeInstanceRenderBillboards);
if (ss<0)
{
if (!smNoRenderTranslucent)
mShape->billboardDetails[dl]->render(mAlphaAlways ? mAlphaAlwaysValue : 1.0f, smRenderData.fogOn);
PROFILE_END();
return;
}
PROFILE_END();
PROFILE_START(TSShapeInstanceMaterials);
// set up animating ifl materials
for (i=0; i<mIflMaterialInstances.size(); i++)
{
IflMaterialInstance * iflMaterialInstance = &mIflMaterialInstances[i];
const TSShape::IflMaterial * iflMaterial = iflMaterialInstance->iflMaterial;
mMaterialList->remap(iflMaterial->materialSlot, iflMaterial->firstFrame + iflMaterialInstance->frame);
}
// decide how to use gl resources
setupTexturing(dl,intraDL);
// set up gl environment for drawing mesh materials
TSMesh::initMaterials();
PROFILE_END();
S32 start;
S32 end;
bool supportBuffers = dglDoesSupportVertexBuffer();
if (!supportBuffers || !renderMeshesX(ss,od))
{
// run through the meshes
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 (i=start; i<end; i++)
mMeshObjects[i].render(od,mMaterialList);
}
// if we have a matrix pushed, pop it now
if (smRenderData.currentTransform)
glPopMatrix();
// restore gl state
TSMesh::resetMaterials();
// render detail maps using a second pass?
if (twoPassDetailMap())
renderDetailMap();
// render environment map using second pass?
if (twoPassEnvironmentMap())
renderEnvironmentMap();
if (!supportBuffers || !renderDecalsX(ss,od))
{
start = mShape->subShapeFirstDecal[ss];
end = mShape->subShapeNumDecals[ss] + start;
if( smRenderData.renderDecals && !smNoRenderTranslucent && start<end)
{
// set up gl environment for decals...
TSDecalMesh::initDecalMaterials();
// render decals...
smRenderData.currentTransform = NULL;
for (i=start; i<end; i++)
mDecalObjects[i].render(od,mMaterialList);
// if we have a matrix pushed, pop it now
if (smRenderData.currentTransform)
glPopMatrix();
// restore gl state
TSDecalMesh::resetDecalMaterials();
}
}
// render fog if 2-passing it
if (twoPassFog())
renderFog();
// restore gl state
TSMesh::resetMaterials();
clearStatics();
}
bool TSShapeInstance::fillVB()
{
S32 i,start,end,vb;
if ((vb = mShape->mVertexBuffer) == -1)
{
// find out before we calc the needed buffer size if there are any free
if (!glAvailableVertexBufferEXT())
{
PROFILE_END();
return false;
}
GLsizei size = 0;
start = mShape->subShapeFirstObject[0];
end = mShape->subShapeFirstObject[0] + mShape->subShapeNumObjects[0];
for (i = start; i < end; ++i)
size += mMeshObjects[i].getSizeVB(size);
mShape->mMorphable = false;
for (i = start; i < end; ++i)
if (mMeshObjects[i].hasMergeIndices())
{
mShape->mMorphable = true;
break;
}
vb = mShape->mVertexBuffer = glAllocateVertexBufferEXT(size,GL_V12MTNVFMT_EXT,true);
if (vb == -1)
{
PROFILE_END();
return false;
}
if (mShape->mCallbackKey == -1)
mShape->mCallbackKey = TextureManager::registerEventCallback(tsShapeTextureEventCB, mShape);
// run through the meshes -- fill vertex buffer
glLockVertexBufferEXT(vb,0);
for (i = start; i < end; ++i)
mMeshObjects[i].fillVB(vb,mMaterialList);
glUnlockVertexBufferEXT(vb);
}
return true;
}
bool TSShapeInstance::renderMeshesX(S32 ss, S32 od)
{
// TODO: find out why this case doesn't work
if (smRenderData.vertexAlpha.current < 1.0)
return false;
PROFILE_START(TSShapeInstanceMeshes);
S32 i,start,end,vb;
if ((vb = mShape->mVertexBuffer) == -1)
{
// find out before we calc the needed buffer size if there are any free
if (!glAvailableVertexBufferEXT())
{
PROFILE_END();
return false;
}
GLsizei size = 0;
start = mShape->subShapeFirstObject[0];
end = mShape->subShapeFirstObject[0] + mShape->subShapeNumObjects[0];
for (i = start; i < end; ++i)
size += mMeshObjects[i].getSizeVB(size);
mShape->mMorphable = false;
for (i = start; i < end; ++i)
if (mMeshObjects[i].hasMergeIndices())
{
mShape->mMorphable = true;
break;
}
vb = mShape->mVertexBuffer = glAllocateVertexBufferEXT(size,GL_V12MTNVFMT_EXT,true);
if (vb == -1)
{
PROFILE_END();
return false;
}
if (mShape->mCallbackKey == -1)
mShape->mCallbackKey = TextureManager::registerEventCallback(tsShapeTextureEventCB, mShape);
// run through the meshes -- fill vertex buffer
glLockVertexBufferEXT(vb,0);
for (i = start; i < end; ++i)
mMeshObjects[i].fillVB(vb,mMaterialList);
glUnlockVertexBufferEXT(vb);
}
// run through the meshes
start = smNoRenderNonTranslucent ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss];
end = smNoRenderTranslucent ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss];
if (mShape->mMorphable)
{
PROFILE_START(TSShapeInstanceMorphVB);
glLockVertexBufferEXT(vb,0);
for (i = start; i < end; ++i)
mMeshObjects[i].morphVB(vb,mShape->mPreviousMerge[i],od,mMaterialList);
glUnlockVertexBufferEXT(vb);
PROFILE_END();
}
smRenderData.currentTransform = NULL;
PROFILE_START(TSShapeInstanceRenderVB);
for (i = start; i < end; ++i)
mMeshObjects[i].renderVB(vb,od,mMaterialList);
PROFILE_END();
PROFILE_END();
return true;
}
bool TSShapeInstance::renderDecalsX(S32 ss, S32 od)
{
return false;
ss,od;
// I don't know why, but this doesn't quite work -- no time to fix
#if 0
if (supportBuffers)
{
S32 i,start,end,vb;
vb = mShape->mVertexBuffer;
start = mShape->subShapeFirstDecal[ss];
end = mShape->subShapeNumDecals[ss] + start;
if (smRenderData.renderDecals && start<end)
{
// set up gl environment for decals...
TSDecalMesh::initDecalMaterials();
// render decals...
smRenderData.currentTransform = NULL;
for (i=start; i<end; i++)
{
TSDecalMesh *decal0 = mDecalObjects[i].getDecalMesh(0);
if (!decal0)
continue;
TSMesh *target0 = decal0->targetMesh;
TSDecalMesh *decal;
if (!target0 ||
mDecalObjects[i].targetObject->visible <= 0.01f ||
!(decal = mDecalObjects[i].getDecalMesh(od)) ||
mDecalObjects[i].frame < 0 ||
!decal->targetMesh ||
decal->texgenS.empty() ||
decal->texgenT.empty())
continue;
GLuint foffset = mDecalObjects[i].frame*target0->numMatFrames*target0->vertsPerFrame;
glSetVertexBufferEXT(vb);
glOffsetVertexBufferEXT(vb,target0->vbOffset+foffset);
mDecalObjects[i].render(od,mMaterialList);
}
// if we have a matrix pushed, pop it now
if (smRenderData.currentTransform)
glPopMatrix();
// restore gl state
TSDecalMesh::resetDecalMaterials();
}
}
else
#endif
}
void TSShapeInstance::setStatics(S32 dl, F32 intraDL, const Point3F * objectScale)
{
ObjectInstance::smTransforms = mNodeTransforms.address();
smRenderData.objectScale = objectScale;
smRenderData.detailLevel = dl;
smRenderData.intraDetailLevel = intraDL;
smRenderData.alwaysAlpha = mAlphaAlways;
smRenderData.alwaysAlphaValue = getAlphaAlwaysValue();
smRenderData.balloonShape = mBalloonShape;
smRenderData.balloonValue = getBalloonValue();
smRenderData.useOverride = mUseOverrideTexture;
smRenderData.override = mOverrideTexture;
S32 ss = mShape->details[dl].subShapeNum;
S32 od = mShape->details[dl].objectDetailNum;
TSMesh::smSaveVerts.setSize(mShape->mMergeBufferSize);
TSMesh::smSaveTVerts.setSize(mShape->mMergeBufferSize);
// If we have a billboard, skip the rest
if (ss < 0)
return;
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++)
{
TSMesh * mesh = mMeshObjects[i].getMesh(od);
if (mesh)
mesh->saveMergeVerts();
}
}
void TSShapeInstance::clearStatics()
{
ObjectInstance::smTransforms = NULL;
smRenderData.override = NULL;
S32 ss = mShape->details[smRenderData.detailLevel].subShapeNum;
S32 od = mShape->details[smRenderData.detailLevel].objectDetailNum;
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++)
{
TSMesh * mesh = mMeshObjects[i].getMesh(od);
if (mesh)
mesh->restoreMergeVerts();
}
}
void TSShapeInstance::setupTexturing(S32 dl, F32 intraDL)
{
// first we'll decide what maps we want
// then we'll decide how we can implement them (1-pass or 2-pass or not at all)
// we need to set up these variables
S32 & emapMethod = smRenderData.environmentMapMethod;
S32 & dmapMethod = smRenderData.detailMapMethod;
S32 & fogMethod = smRenderData.fogMethod;
S32 & dmapTE = smRenderData.detailMapTE;
S32 & emapTE = smRenderData.environmentMapTE;
S32 & baseTE = smRenderData.baseTE;
S32 & fogTE = smRenderData.fogTE;
baseTE = 0; // initially assume base texture will go in first TE
// -------------------------------------------------
// what do we want to do?
bool wantEMap = ((mShape->mExportMerge && dl<=mShape->mSmallestVisibleDL/2) ||
(!mShape->mExportMerge && dl<=mMaxEnvironmentMapDL)) &&
mEnvironmentMapOn && (TextureObject*)mEnvironmentMap && mEnvironmentMapAlpha>0.01f;
bool wantDMap = dl<=mMaxDetailMapDL;
bool wantFog = smRenderData.fogOn && !smSkipFog;
smRenderData.detailMapAlpha = (dl<mMaxDetailMapDL || intraDL>0.5f) ? 1.0f : 2.0f * intraDL;
smRenderData.environmentMapAlpha = mEnvironmentMapAlpha *
(
(((mShape->mExportMerge && dl<mShape->mSmallestVisibleDL/2) ||
(!mShape->mExportMerge && dl<mMaxEnvironmentMapDL)) ||
intraDL>0.5f) ? 1.0f : 2.0f * intraDL );
smRenderData.environmentMapGLName = wantEMap ? mEnvironmentMap.getGLName() : 0;
// -------------------------------------------------
// what can we do?
if (!dglDoesSupportARBMultitexture())
{
// we don't support multitexturing -- early out
emapMethod = NO_ENVIRONMENT_MAP;
dmapMethod = (wantDMap && mAllowTwoPassDetailMap) ? DETAIL_MAP_TWO_PASS : NO_DETAIL_MAP;
fogMethod = wantFog ? FOG_TWO_PASS : NO_FOG;
return;
}
// how many texture environments (TE's) do we have?
GLint numTE = 1, numUsedTE = 1;
if (dglDoesSupportARBMultitexture())
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&numTE);
// what we do with the TE's will depend on whether the following extension is supported
if (dglDoesSupportTextureEnvCombine())
{
// environment map...
if (wantEMap)
{
if (mAlphaIsReflectanceMap)
{
emapMethod = ENVIRONMENT_MAP_MULTI_1;
emapTE = numUsedTE;
numUsedTE++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -