📄 tsshapeinstance.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "ts/tsShapeInstance.h"
#include "dgl/dgl.h"
#include "ts/tsLastDetail.h"
#include "console/consoleTypes.h"
#include "ts/tsDecal.h"
#include "platform/profiler.h"
#include "core/frameAllocator.h"
TSShapeInstance::RenderData TSShapeInstance::smRenderData;
MatrixF * TSShapeInstance::ObjectInstance::smTransforms = NULL;
S32 TSShapeInstance::smMaxSnapshotScale = 2;
bool TSShapeInstance::smNoRenderTranslucent = false;
bool TSShapeInstance::smNoRenderNonTranslucent = false;
F32 TSShapeInstance::smDetailAdjust = 1.0f;
F32 TSShapeInstance::smScreenError = 5.0f;
bool TSShapeInstance::smFogExemptionOn = false;
S32 TSShapeInstance::smNumSkipRenderDetails = 0;
bool TSShapeInstance::smSkipFirstFog = false;
bool TSShapeInstance::smSkipFog = false;
Vector<QuatF> TSShapeInstance::smNodeCurrentRotations(__FILE__, __LINE__);
Vector<Point3F> TSShapeInstance::smNodeCurrentTranslations(__FILE__, __LINE__);
Vector<F32> TSShapeInstance::smNodeCurrentUniformScales(__FILE__, __LINE__);
Vector<Point3F> TSShapeInstance::smNodeCurrentAlignedScales(__FILE__, __LINE__);
Vector<TSScale> TSShapeInstance::smNodeCurrentArbitraryScales(__FILE__, __LINE__);
Vector<TSThread*> TSShapeInstance::smRotationThreads(__FILE__, __LINE__);
Vector<TSThread*> TSShapeInstance::smTranslationThreads(__FILE__, __LINE__);
Vector<TSThread*> TSShapeInstance::smScaleThreads(__FILE__, __LINE__);
namespace {
void tsShapeTextureEventCB(const U32 eventCode, void *userData)
{
TSShape* pShape = reinterpret_cast<TSShape*>(userData);
if (eventCode == TextureManager::BeginZombification &&
pShape->mVertexBuffer != -1)
{
// ideally we would de-register the callback here, but that would screw up the loop
if (dglDoesSupportVertexBuffer())
glFreeVertexBufferEXT(pShape->mVertexBuffer);
else
AssertFatal(false,"Vertex buffer should have already been freed!");
pShape->mVertexBuffer = -1;
for (S32 i = 0; i < pShape->objects.size(); ++i)
pShape->mPreviousMerge[i] = -1;
}
}
}
//-------------------------------------------------------------------------------------
// constructors, destructors, initialization
//-------------------------------------------------------------------------------------
TSShapeInstance::TSShapeInstance(const Resource<TSShape> & shape, bool loadMaterials)
{
VECTOR_SET_ASSOCIATION(mMeshObjects);
VECTOR_SET_ASSOCIATION(mDecalObjects);
VECTOR_SET_ASSOCIATION(mIflMaterialInstances);
VECTOR_SET_ASSOCIATION(mNodeTransforms);
VECTOR_SET_ASSOCIATION(mNodeReferenceRotations);
VECTOR_SET_ASSOCIATION(mNodeReferenceTranslations);
VECTOR_SET_ASSOCIATION(mNodeReferenceUniformScales);
VECTOR_SET_ASSOCIATION(mNodeReferenceScaleFactors);
VECTOR_SET_ASSOCIATION(mNodeReferenceArbitraryScaleRots);
VECTOR_SET_ASSOCIATION(mThreadList);
VECTOR_SET_ASSOCIATION(mTransitionThreads);
// check all skin modifier slots
for (U32 ss=0; ss<MaxSkinModifiers; ss++)
mSkinModifiers[ss].skinName = StringTable->getBlank();
hShape = shape;
mShape = hShape;
buildInstanceData(mShape, loadMaterials);
}
TSShapeInstance::TSShapeInstance(TSShape * _shape, bool loadMaterials)
{
VECTOR_SET_ASSOCIATION(mMeshObjects);
VECTOR_SET_ASSOCIATION(mDecalObjects);
VECTOR_SET_ASSOCIATION(mIflMaterialInstances);
VECTOR_SET_ASSOCIATION(mNodeTransforms);
VECTOR_SET_ASSOCIATION(mNodeReferenceRotations);
VECTOR_SET_ASSOCIATION(mNodeReferenceTranslations);
VECTOR_SET_ASSOCIATION(mNodeReferenceUniformScales);
VECTOR_SET_ASSOCIATION(mNodeReferenceScaleFactors);
VECTOR_SET_ASSOCIATION(mNodeReferenceArbitraryScaleRots);
VECTOR_SET_ASSOCIATION(mThreadList);
VECTOR_SET_ASSOCIATION(mTransitionThreads);
// check all skin modifier slots
for (U32 ss=0; ss<MaxSkinModifiers; ss++)
mSkinModifiers[ss].skinName = StringTable->getBlank();
mShape = _shape;
buildInstanceData(mShape, loadMaterials);
}
TSShapeInstance::~TSShapeInstance()
{
S32 i;
for (i=0; i<mMeshObjects.size(); i++)
destructInPlace(&mMeshObjects[i]);
for (i=0; i<mDecalObjects.size(); i++)
destructInPlace(&mDecalObjects[i]);
while (mThreadList.size())
destroyThread(mThreadList.last());
clearSkinModifiers();//skin modifier
setMaterialList(NULL);
delete [] mDirtyFlags;
}
void TSShapeInstance::init()
{
smRenderData.fogTexture = false;
smRenderData.fogBitmap = NULL;
smRenderData.fogHandle = NULL;
smRenderData.fogMapHandle = NULL;
smRenderData.renderDecals = true;
Con::addVariable("$pref::TS::fogTexture", TypeBool, &smRenderData.fogTexture);
Con::addVariable("$pref::TS::detailAdjust", TypeF32, &smDetailAdjust);
Con::addVariable("$pref::TS::skipLoadDLs", TypeS32, &TSShape::smNumSkipLoadDetails);
Con::addVariable("$pref::TS::skipRenderDLs", TypeS32, &smNumSkipRenderDetails);
Con::addVariable("$pref::TS::skipFirstFog", TypeBool, &smSkipFirstFog);
Con::addVariable("$pref::TS::screenError", TypeF32, &smScreenError);
Con::addVariable("$pref::TS::UseTriangles", TypeBool, &TSMesh::smUseTriangles);
}
void TSShapeInstance::destroy()
{
delete smRenderData.fogHandle;
}
void TSShapeInstance::buildInstanceData(TSShape * _shape, bool loadMaterials)
{
S32 i,dl;
mShape = _shape;
debrisRefCount = 0;
mEnvironmentMapOn = false;
mEnvironmentMapAlpha = 0.f;
mAllowTwoPassEnvironmentMap = false;
mAlphaIsReflectanceMap = true; // turn this off below if we find an exception
mAllowTwoPassDetailMap = true;
mMaxEnvironmentMapDL = 1; // for shapes < version 23
mMaxDetailMapDL = 0;
// clear callback function and data
mCallback = NULL;
mCallbackData = 0;
mCurrentDetailLevel = 0;
mCurrentIntraDetailLevel = 1.0f;
// all triggers off at start
mTriggerStates = 0;
//
mAlphaAlways = false;
mAlphaAlwaysValue = 1.0f;
mBalloonShape = false;
mBalloonValue = 1.0f;
mUseOverrideTexture = false;
// if never set, never draw fog -- do this here just in case
smRenderData.fogOn = false;
// material list...
mMaterialList = NULL;
mOwnMaterialList = false;
//
mData = 0;
mScaleCurrentlyAnimated = false;
if(loadMaterials)
{
setMaterialList(mShape->materialList);
}
// set up node data
S32 numNodes = mShape->nodes.size();
mNodeTransforms.setSize(numNodes);
// add objects to trees
S32 numObjects = mShape->objects.size();
mMeshObjects.setSize(numObjects);
for (i=0; i<numObjects; i++)
{
const TSObject * obj = &mShape->objects[i];
MeshObjectInstance * objInst = &mMeshObjects[i];
// call objInst constructor
constructInPlace(objInst);
// hook up the object to it's node
objInst->nodeIndex = obj->nodeIndex;
// set up list of meshes
if (obj->numMeshes)
objInst->meshList = &mShape->meshes[obj->startMeshIndex];
else
objInst->meshList = NULL;
objInst->object = obj;
}
// set up decal objects
mDecalObjects.setSize(mShape->decals.size());
for (i=0; i<mShape->decals.size(); i++)
{
const TSShape::Decal * decal = &mShape->decals[i];
DecalObjectInstance * decalInst = &mDecalObjects[i];
// call constructor
constructInPlace(decalInst);
decalInst->decalObject = decal;
// hook up to node
decalInst->targetObject = &mMeshObjects[decal->objectIndex];
decalInst->nodeIndex = decalInst->targetObject->nodeIndex;
// set up list of decal meshes
if (decal->numMeshes)
{
decalInst->decalList = (TSDecalMesh**)&mShape->meshes[decal->startMeshIndex];
for (S32 j=0; j<decal->numMeshes; j++)
if (decalInst->getDecalMesh(j))
{
// point the decal mesh at it's target...
// this is safe since meshes aren't shared between shapes
TSDecalMesh * decalMesh = const_cast<TSDecalMesh*>(decalInst->getDecalMesh(j));
decalMesh->targetMesh = decalInst->targetObject->getMesh(j);
if (!decalMesh->targetMesh)
{
// detecting this a little late, but we don't need this decal since it isn't doing anything
// should only happen on shapes exported before dtsexp 1.18
delete decalMesh;
TSDecalMesh ** dm = const_cast<TSDecalMesh**>(decalInst->decalList+j);
*dm = NULL;
}
}
}
else
decalInst->decalList = NULL;
decalInst->frame = mShape->decalStates[i].frameIndex;
}
// construct ifl material objects
if(loadMaterials)
{
for (i=0; i<mShape->iflMaterials.size(); i++)
{
mIflMaterialInstances.increment();
mIflMaterialInstances.last().iflMaterial = &mShape->iflMaterials[i];
mIflMaterialInstances.last().frame = -1;
}
}
// check to see which dl's have detail texturing
mMaxDetailMapDL = -1;
if(loadMaterials)
{
for (dl=0; dl<mShape->details.size(); dl++)
{
// check meshes on this detail level...
S32 ss = mShape->details[dl].subShapeNum;
S32 od = mShape->details[dl].objectDetailNum;
if (ss<0)
continue; // this is a billboard detail level
S32 start = mShape->subShapeFirstObject[ss];
S32 end = mShape->subShapeNumObjects[ss] + start;
for (i=start; i<end; i++)
{
TSMesh * mesh = mMeshObjects[i].getMesh(od);
if (!mesh)
continue;
for (S32 j=0; j<mesh->primitives.size(); j++)
{
if (mesh->primitives[j].matIndex & TSDrawPrimitive::NoMaterial)
continue;
if (mMaterialList->getDetailMap(mesh->primitives[j].matIndex & TSDrawPrimitive::MaterialMask))
{
mesh->setFlags(TSMesh::HasDetailTexture);
if (dl>mMaxDetailMapDL)
mMaxDetailMapDL = dl;
}
}
}
}
}
// set up subtree data
S32 ss = mShape->subShapeFirstNode.size(); // we have this many subtrees
mDirtyFlags = new U32[ss];
mGroundThread = NULL;
mCurrentDetailLevel = 0;
animateSubtrees();
// Construct billboards if not done already
if(loadMaterials)
((TSShape *) mShape)->setupBillboardDetails(this);
// Scan out the collision hulls...
for (U32 i = 0; i < 16; i++)
{
char buff[128];
dSprintf(buff, sizeof(buff), "Collision-%d", i + 1);
S32 colDetail = mShape->findDetail(buff);
if (colDetail != -1)
{
S32 dl = colDetail;
// get subshape and object detail
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)
{
// run through objects and validate names...
for (S32 i=start; i<end; i++)
{
MeshObjectInstance * mesh = &mMeshObjects[i];
if (od >= mesh->object->numMeshes)
continue;
// Yell at them if they named something!
if (dStrnicmp(mShape->names[mesh->object->nameIndex], "Col", 3) != 0 && dStrnicmp(mShape->names[mesh->object->nameIndex], "LOSCol", 3) != 0)
{
Con::errorf("%s.dts - Collision mesh names should start with Col or LOSCol, encountered '%s' in detail level %d", mShape->mSourceResource->path,mShape->names[mesh->object->nameIndex], dl);
continue;
}
}
}
}
}
}
void TSShapeInstance::setMaterialList(TSMaterialList * ml)
{
// get rid of old list
if (mOwnMaterialList)
delete mMaterialList;
mMaterialList = ml;
mOwnMaterialList = false;
if (mMaterialList && StringTable) // material lists need the string table to load...
{
// read ifl materials if necessary -- this is here rather than in shape because we can't open 2 files at once :(
if (mShape->materialList == mMaterialList)
((TSShape*)mShape)->readIflMaterials(hShape.getFilePath());
mMaterialList->load(MeshTexture,hShape.getFilePath(),true);
// check for reflectance map not in alpha of texture -- will require more work to emap
for (U32 i=0; i<mMaterialList->getMaterialCount(); i++)
{
if (mMaterialList->getFlags(i) & (TSMaterialList::AuxiliaryMap|TSMaterialList::NeverEnvMap))
continue;
if (!mMaterialList->reflectionInAlpha(i))
{
mAlphaIsReflectanceMap = false;
break; // found our exception
}
}
}
}
void TSShapeInstance::cloneMaterialList()
{
if (mOwnMaterialList)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -