mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 15:44:36 +00:00
Merge pull request #1756 from jamesu/hw_skinning_fix
Fix load with DTS shapes introduced with HW skinning changes
This commit is contained in:
commit
2add87a702
8 changed files with 228 additions and 77 deletions
|
|
@ -2606,7 +2606,7 @@ void TSMesh::disassemble()
|
||||||
tsalloc.copyToBuffer32( (S32*)&mCenter, 3 );
|
tsalloc.copyToBuffer32( (S32*)&mCenter, 3 );
|
||||||
tsalloc.set32( (S32)mRadius );
|
tsalloc.set32( (S32)mRadius );
|
||||||
|
|
||||||
bool shouldMakeEditable = TSShape::smVersion < 27;
|
bool shouldMakeEditable = TSShape::smVersion < 27 || mVertSize == 0;
|
||||||
|
|
||||||
// Re-create the vectors
|
// Re-create the vectors
|
||||||
if (shouldMakeEditable)
|
if (shouldMakeEditable)
|
||||||
|
|
@ -2799,6 +2799,18 @@ void TSSkinMesh::assemble( bool skip )
|
||||||
batchData.initialNorms.set((Point3F*)ptr32, numVerts);
|
batchData.initialNorms.set((Point3F*)ptr32, numVerts);
|
||||||
encodedNorms.set(NULL, 0);
|
encodedNorms.set(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sometimes we'll have a mesh with 0 verts but initialVerts is set,
|
||||||
|
// so set these accordingly
|
||||||
|
if (verts.size() == 0)
|
||||||
|
{
|
||||||
|
verts = batchData.initialVerts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (norms.size() == 0)
|
||||||
|
{
|
||||||
|
norms = batchData.initialNorms;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3429,8 +3441,8 @@ void TSBasicVertexFormat::addMeshRequirements(TSMesh *mesh)
|
||||||
bool hasTexcoord2 = false;
|
bool hasTexcoord2 = false;
|
||||||
bool hasSkin = false;
|
bool hasSkin = false;
|
||||||
|
|
||||||
hasColors = mesh->getHasColor() || (texCoordOffset != -1);
|
hasColors = mesh->getHasColor() || (colorOffset != -1);
|
||||||
hasTexcoord2 = mesh->getHasTVert2() || (colorOffset != -1);
|
hasTexcoord2 = mesh->getHasTVert2() || (texCoordOffset != -1);
|
||||||
hasSkin = (mesh->getMeshType() == TSMesh::SkinMeshType) || (boneOffset != -1);
|
hasSkin = (mesh->getMeshType() == TSMesh::SkinMeshType) || (boneOffset != -1);
|
||||||
|
|
||||||
S32 offset = sizeof(TSMesh::__TSMeshVertexBase);
|
S32 offset = sizeof(TSMesh::__TSMeshVertexBase);
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ TSShape::TSShape()
|
||||||
mShapeDataSize = 0;
|
mShapeDataSize = 0;
|
||||||
|
|
||||||
mUseDetailFromScreenError = false;
|
mUseDetailFromScreenError = false;
|
||||||
|
mNeedReinit = false;
|
||||||
|
|
||||||
mDetailLevelLookup.setSize( 1 );
|
mDetailLevelLookup.setSize( 1 );
|
||||||
mDetailLevelLookup[0].set( -1, 0 );
|
mDetailLevelLookup[0].set( -1, 0 );
|
||||||
|
|
@ -413,43 +414,51 @@ void TSShape::getObjectDetails(S32 objIndex, Vector<S32>& objDetails)
|
||||||
|
|
||||||
void TSShape::init()
|
void TSShape::init()
|
||||||
{
|
{
|
||||||
S32 numSubShapes = subShapeFirstNode.size();
|
initObjects();
|
||||||
AssertFatal(numSubShapes==subShapeFirstObject.size(),"TSShape::init");
|
initVertexFeatures();
|
||||||
|
initMaterialList();
|
||||||
|
mNeedReinit = false;
|
||||||
|
}
|
||||||
|
|
||||||
S32 i,j;
|
void TSShape::initObjects()
|
||||||
|
{
|
||||||
|
S32 numSubShapes = subShapeFirstNode.size();
|
||||||
|
AssertFatal(numSubShapes == subShapeFirstObject.size(), "TSShape::initObjects");
|
||||||
|
|
||||||
|
S32 i, j;
|
||||||
|
|
||||||
// set up parent/child relationships on nodes and objects
|
// set up parent/child relationships on nodes and objects
|
||||||
for (i=0; i<nodes.size(); i++)
|
for (i = 0; i<nodes.size(); i++)
|
||||||
nodes[i].firstObject = nodes[i].firstChild = nodes[i].nextSibling = -1;
|
nodes[i].firstObject = nodes[i].firstChild = nodes[i].nextSibling = -1;
|
||||||
for (i=0; i<nodes.size(); i++)
|
for (i = 0; i<nodes.size(); i++)
|
||||||
{
|
{
|
||||||
S32 parentIndex = nodes[i].parentIndex;
|
S32 parentIndex = nodes[i].parentIndex;
|
||||||
if (parentIndex>=0)
|
if (parentIndex >= 0)
|
||||||
{
|
{
|
||||||
if (nodes[parentIndex].firstChild<0)
|
if (nodes[parentIndex].firstChild<0)
|
||||||
nodes[parentIndex].firstChild=i;
|
nodes[parentIndex].firstChild = i;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
S32 child = nodes[parentIndex].firstChild;
|
S32 child = nodes[parentIndex].firstChild;
|
||||||
while (nodes[child].nextSibling>=0)
|
while (nodes[child].nextSibling >= 0)
|
||||||
child = nodes[child].nextSibling;
|
child = nodes[child].nextSibling;
|
||||||
nodes[child].nextSibling = i;
|
nodes[child].nextSibling = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i=0; i<objects.size(); i++)
|
for (i = 0; i<objects.size(); i++)
|
||||||
{
|
{
|
||||||
objects[i].nextSibling = -1;
|
objects[i].nextSibling = -1;
|
||||||
|
|
||||||
S32 nodeIndex = objects[i].nodeIndex;
|
S32 nodeIndex = objects[i].nodeIndex;
|
||||||
if (nodeIndex>=0)
|
if (nodeIndex >= 0)
|
||||||
{
|
{
|
||||||
if (nodes[nodeIndex].firstObject<0)
|
if (nodes[nodeIndex].firstObject<0)
|
||||||
nodes[nodeIndex].firstObject = i;
|
nodes[nodeIndex].firstObject = i;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
S32 objectIndex = nodes[nodeIndex].firstObject;
|
S32 objectIndex = nodes[nodeIndex].firstObject;
|
||||||
while (objects[objectIndex].nextSibling>=0)
|
while (objects[objectIndex].nextSibling >= 0)
|
||||||
objectIndex = objects[objectIndex].nextSibling;
|
objectIndex = objects[objectIndex].nextSibling;
|
||||||
objects[objectIndex].nextSibling = i;
|
objects[objectIndex].nextSibling = i;
|
||||||
}
|
}
|
||||||
|
|
@ -457,7 +466,7 @@ void TSShape::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
mFlags = 0;
|
mFlags = 0;
|
||||||
for (i=0; i<sequences.size(); i++)
|
for (i = 0; i<sequences.size(); i++)
|
||||||
{
|
{
|
||||||
if (!sequences[i].animatesScale())
|
if (!sequences[i].animatesScale())
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -465,32 +474,32 @@ void TSShape::init()
|
||||||
U32 curVal = mFlags & AnyScale;
|
U32 curVal = mFlags & AnyScale;
|
||||||
U32 newVal = sequences[i].flags & AnyScale;
|
U32 newVal = sequences[i].flags & AnyScale;
|
||||||
mFlags &= ~(AnyScale);
|
mFlags &= ~(AnyScale);
|
||||||
mFlags |= getMax(curVal,newVal); // take the larger value (can only convert upwards)
|
mFlags |= getMax(curVal, newVal); // take the larger value (can only convert upwards)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up alphaIn and alphaOut vectors...
|
// set up alphaIn and alphaOut vectors...
|
||||||
alphaIn.setSize(details.size());
|
alphaIn.setSize(details.size());
|
||||||
alphaOut.setSize(details.size());
|
alphaOut.setSize(details.size());
|
||||||
|
|
||||||
for (i=0; i<details.size(); i++)
|
for (i = 0; i<details.size(); i++)
|
||||||
{
|
{
|
||||||
if (details[i].size<0)
|
if (details[i].size<0)
|
||||||
{
|
{
|
||||||
// we don't care...
|
// we don't care...
|
||||||
alphaIn[i] = 0.0f;
|
alphaIn[i] = 0.0f;
|
||||||
alphaOut[i] = 0.0f;
|
alphaOut[i] = 0.0f;
|
||||||
}
|
}
|
||||||
else if (i+1==details.size() || details[i+1].size<0)
|
else if (i + 1 == details.size() || details[i + 1].size<0)
|
||||||
{
|
{
|
||||||
alphaIn[i] = 0.0f;
|
alphaIn[i] = 0.0f;
|
||||||
alphaOut[i] = smAlphaOutLastDetail;
|
alphaOut[i] = smAlphaOutLastDetail;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (details[i+1].subShapeNum<0)
|
if (details[i + 1].subShapeNum<0)
|
||||||
{
|
{
|
||||||
// following detail is a billboard detail...treat special...
|
// following detail is a billboard detail...treat special...
|
||||||
alphaIn[i] = smAlphaInBillboard;
|
alphaIn[i] = smAlphaInBillboard;
|
||||||
alphaOut[i] = smAlphaOutBillboard;
|
alphaOut[i] = smAlphaOutBillboard;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -502,7 +511,7 @@ void TSShape::init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=mSmallestVisibleDL-1; i>=0; i--)
|
for (i = mSmallestVisibleDL - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (i<smNumSkipLoadDetails)
|
if (i<smNumSkipLoadDetails)
|
||||||
{
|
{
|
||||||
|
|
@ -510,19 +519,19 @@ void TSShape::init()
|
||||||
// is larger than our cap...zap all the meshes and decals
|
// is larger than our cap...zap all the meshes and decals
|
||||||
// associated with it and use the next detail level
|
// associated with it and use the next detail level
|
||||||
// instead...
|
// instead...
|
||||||
S32 ss = details[i].subShapeNum;
|
S32 ss = details[i].subShapeNum;
|
||||||
S32 od = details[i].objectDetailNum;
|
S32 od = details[i].objectDetailNum;
|
||||||
|
|
||||||
if (ss==details[i+1].subShapeNum && od==details[i+1].objectDetailNum)
|
if (ss == details[i + 1].subShapeNum && od == details[i + 1].objectDetailNum)
|
||||||
// doh! already done this one (init can be called multiple times on same shape due
|
// doh! already done this one (init can be called multiple times on same shape due
|
||||||
// to sequence importing).
|
// to sequence importing).
|
||||||
continue;
|
continue;
|
||||||
details[i].subShapeNum = details[i+1].subShapeNum;
|
details[i].subShapeNum = details[i + 1].subShapeNum;
|
||||||
details[i].objectDetailNum = details[i+1].objectDetailNum;
|
details[i].objectDetailNum = details[i + 1].objectDetailNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<details.size(); i++)
|
for (i = 0; i<details.size(); i++)
|
||||||
{
|
{
|
||||||
S32 count = 0;
|
S32 count = 0;
|
||||||
S32 ss = details[i].subShapeNum;
|
S32 ss = details[i].subShapeNum;
|
||||||
|
|
@ -534,13 +543,13 @@ void TSShape::init()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
S32 start = subShapeFirstObject[ss];
|
S32 start = subShapeFirstObject[ss];
|
||||||
S32 end = start + subShapeNumObjects[ss];
|
S32 end = start + subShapeNumObjects[ss];
|
||||||
for (j=start; j<end; j++)
|
for (j = start; j<end; j++)
|
||||||
{
|
{
|
||||||
Object & obj = objects[j];
|
Object & obj = objects[j];
|
||||||
if (od<obj.numMeshes)
|
if (od<obj.numMeshes)
|
||||||
{
|
{
|
||||||
TSMesh * mesh = meshes[obj.startMeshIndex+od];
|
TSMesh * mesh = meshes[obj.startMeshIndex + od];
|
||||||
count += mesh ? mesh->getNumPolys() : 0;
|
count += mesh ? mesh->getNumPolys() : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -555,11 +564,11 @@ void TSShape::init()
|
||||||
{
|
{
|
||||||
ConvexHullAccelerator* accel = detailCollisionAccelerators[dca];
|
ConvexHullAccelerator* accel = detailCollisionAccelerators[dca];
|
||||||
if (accel != NULL) {
|
if (accel != NULL) {
|
||||||
delete [] accel->vertexList;
|
delete[] accel->vertexList;
|
||||||
delete [] accel->normalList;
|
delete[] accel->normalList;
|
||||||
for (S32 j = 0; j < accel->numVerts; j++)
|
for (S32 j = 0; j < accel->numVerts; j++)
|
||||||
delete [] accel->emitStrings[j];
|
delete[] accel->emitStrings[j];
|
||||||
delete [] accel->emitStrings;
|
delete[] accel->emitStrings;
|
||||||
delete accel;
|
delete accel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -576,7 +585,12 @@ void TSShape::init()
|
||||||
if (!mesh)
|
if (!mesh)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mesh->parentMesh >= 0)
|
if (mesh->parentMesh >= meshes.size())
|
||||||
|
{
|
||||||
|
Con::warnf("Mesh %i has a bad parentMeshObject (%i)", iter - meshes.begin(), mesh->parentMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh->parentMesh >= 0 && mesh->parentMesh < meshes.size())
|
||||||
{
|
{
|
||||||
mesh->parentMeshObject = meshes[mesh->parentMesh];
|
mesh->parentMeshObject = meshes[mesh->parentMesh];
|
||||||
}
|
}
|
||||||
|
|
@ -587,9 +601,6 @@ void TSShape::init()
|
||||||
|
|
||||||
mesh->mVertexFormat = &mVertexFormat;
|
mesh->mVertexFormat = &mVertexFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
initVertexFeatures();
|
|
||||||
initMaterialList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSShape::initVertexBuffers()
|
void TSShape::initVertexBuffers()
|
||||||
|
|
@ -736,7 +747,7 @@ void TSShape::initVertexBufferPointers()
|
||||||
if (mesh->mVertSize > 0 && !mesh->mVertexData.isReady())
|
if (mesh->mVertSize > 0 && !mesh->mVertexData.isReady())
|
||||||
{
|
{
|
||||||
U32 boneOffset = 0;
|
U32 boneOffset = 0;
|
||||||
U32 colorOffset = 0;
|
U32 texCoordOffset = 0;
|
||||||
AssertFatal(mesh->mVertSize == mVertexFormat.getSizeInBytes(), "mismatch in format size");
|
AssertFatal(mesh->mVertSize == mVertexFormat.getSizeInBytes(), "mismatch in format size");
|
||||||
|
|
||||||
if (mBasicVertexFormat.boneOffset >= 0)
|
if (mBasicVertexFormat.boneOffset >= 0)
|
||||||
|
|
@ -744,13 +755,13 @@ void TSShape::initVertexBufferPointers()
|
||||||
boneOffset = mBasicVertexFormat.boneOffset;
|
boneOffset = mBasicVertexFormat.boneOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBasicVertexFormat.colorOffset >= 0)
|
if (mBasicVertexFormat.texCoordOffset >= 0)
|
||||||
{
|
{
|
||||||
colorOffset = mBasicVertexFormat.colorOffset;
|
texCoordOffset = mBasicVertexFormat.texCoordOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the vertex data
|
// Initialize the vertex data
|
||||||
mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, colorOffset, boneOffset, false);
|
mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, texCoordOffset, boneOffset, false);
|
||||||
mesh->mVertexData.setReady(true);
|
mesh->mVertexData.setReady(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -856,6 +867,7 @@ void TSShape::initVertexFeatures()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can create the VBO
|
// Now we can create the VBO
|
||||||
|
mShapeVertexData.set(NULL, 0);
|
||||||
U8 *vertexData = (U8*)dMalloc_aligned(destVertex, 16);
|
U8 *vertexData = (U8*)dMalloc_aligned(destVertex, 16);
|
||||||
U8 *vertexDataPtr = vertexData;
|
U8 *vertexDataPtr = vertexData;
|
||||||
mShapeVertexData.set(vertexData, destVertex);
|
mShapeVertexData.set(vertexData, destVertex);
|
||||||
|
|
@ -872,7 +884,7 @@ void TSShape::initVertexFeatures()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
U32 boneOffset = 0;
|
U32 boneOffset = 0;
|
||||||
U32 colorOffset = 0;
|
U32 texCoordOffset = 0;
|
||||||
AssertFatal(mesh->mVertSize == mVertexFormat.getSizeInBytes(), "mismatch in format size");
|
AssertFatal(mesh->mVertSize == mVertexFormat.getSizeInBytes(), "mismatch in format size");
|
||||||
|
|
||||||
if (mBasicVertexFormat.boneOffset >= 0)
|
if (mBasicVertexFormat.boneOffset >= 0)
|
||||||
|
|
@ -880,9 +892,9 @@ void TSShape::initVertexFeatures()
|
||||||
boneOffset = mBasicVertexFormat.boneOffset;
|
boneOffset = mBasicVertexFormat.boneOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBasicVertexFormat.colorOffset >= 0)
|
if (mBasicVertexFormat.texCoordOffset >= 0)
|
||||||
{
|
{
|
||||||
colorOffset = mBasicVertexFormat.colorOffset;
|
texCoordOffset = mBasicVertexFormat.texCoordOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump everything
|
// Dump everything
|
||||||
|
|
@ -891,7 +903,14 @@ void TSShape::initVertexFeatures()
|
||||||
AssertFatal(mesh->mVertOffset == vertexDataPtr - vertexData, "vertex offset mismatch");
|
AssertFatal(mesh->mVertOffset == vertexDataPtr - vertexData, "vertex offset mismatch");
|
||||||
mesh->mNumVerts = mesh->getNumVerts();
|
mesh->mNumVerts = mesh->getNumVerts();
|
||||||
|
|
||||||
mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, colorOffset, boneOffset, false);
|
// Correct bad meshes
|
||||||
|
if (mesh->mNumVerts != 0 && mesh->vertsPerFrame > mesh->mNumVerts)
|
||||||
|
{
|
||||||
|
Con::warnf("Shape mesh has bad vertsPerFrame (%i, should be <= %i)", mesh->vertsPerFrame, mesh->mNumVerts);
|
||||||
|
mesh->vertsPerFrame = mesh->mNumVerts;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, texCoordOffset, boneOffset, false);
|
||||||
mesh->convertToVertexData();
|
mesh->convertToVertexData();
|
||||||
mesh->mVertexData.setReady(true);
|
mesh->mVertexData.setReady(true);
|
||||||
|
|
||||||
|
|
@ -1494,7 +1513,7 @@ void TSShape::assembleShape()
|
||||||
}
|
}
|
||||||
|
|
||||||
// read in the meshes (sans skins)...straightforward read one at a time
|
// read in the meshes (sans skins)...straightforward read one at a time
|
||||||
ptr32 = tsalloc.allocShape32(numMeshes + numSkins*numDetails); // leave room for skins on old shapes
|
TSMesh **ptrmesh = (TSMesh**)tsalloc.allocShape32((numMeshes + numSkins*numDetails) * (sizeof(TSMesh*) / 4));
|
||||||
S32 curObject = 0; // for tracking skipped meshes
|
S32 curObject = 0; // for tracking skipped meshes
|
||||||
for (i=0; i<numMeshes; i++)
|
for (i=0; i<numMeshes; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -1504,10 +1523,9 @@ void TSShape::assembleShape()
|
||||||
// decal mesh deprecated
|
// decal mesh deprecated
|
||||||
skip = true;
|
skip = true;
|
||||||
TSMesh * mesh = TSMesh::assembleMesh(meshType,skip);
|
TSMesh * mesh = TSMesh::assembleMesh(meshType,skip);
|
||||||
if (ptr32)
|
if (ptrmesh)
|
||||||
{
|
{
|
||||||
ptr32[i] = skip ? 0 : (intptr_t)mesh; // @todo 64bit
|
ptrmesh[i] = skip ? 0 : mesh;
|
||||||
meshes.push_back(skip ? 0 : mesh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill in location of verts, tverts, and normals for detail levels
|
// fill in location of verts, tverts, and normals for detail levels
|
||||||
|
|
@ -1536,6 +1554,7 @@ void TSShape::assembleShape()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
meshes.set(ptrmesh, numMeshes);
|
||||||
|
|
||||||
tsalloc.checkGuard();
|
tsalloc.checkGuard();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,7 @@ class TSShape
|
||||||
GFXPrimitiveBufferHandle mShapeVertexIndices;
|
GFXPrimitiveBufferHandle mShapeVertexIndices;
|
||||||
|
|
||||||
bool mSequencesConstructed;
|
bool mSequencesConstructed;
|
||||||
|
bool mNeedReinit;
|
||||||
|
|
||||||
|
|
||||||
// shape class has few methods --
|
// shape class has few methods --
|
||||||
|
|
@ -428,6 +429,9 @@ class TSShape
|
||||||
|
|
||||||
void setupBillboardDetails( const String &cachePath );
|
void setupBillboardDetails( const String &cachePath );
|
||||||
|
|
||||||
|
/// Inits object list (no geometry buffers)
|
||||||
|
void initObjects();
|
||||||
|
|
||||||
/// Initializes the main vertex buffer
|
/// Initializes the main vertex buffer
|
||||||
void initVertexBuffers();
|
void initVertexBuffers();
|
||||||
|
|
||||||
|
|
@ -557,8 +561,6 @@ class TSShape
|
||||||
|
|
||||||
const GFXVertexFormat* getVertexFormat() const { return &mVertexFormat; }
|
const GFXVertexFormat* getVertexFormat() const { return &mVertexFormat; }
|
||||||
|
|
||||||
bool needsBufferUpdate();
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// @name Alpha Transitions
|
/// @name Alpha Transitions
|
||||||
|
|
@ -685,6 +687,10 @@ class TSShape
|
||||||
|
|
||||||
bool setSequenceBlend(const String& seqName, bool blend, const String& blendRefSeqName, S32 blendRefFrame);
|
bool setSequenceBlend(const String& seqName, bool blend, const String& blendRefSeqName, S32 blendRefFrame);
|
||||||
bool setSequenceGroundSpeed(const String& seqName, const Point3F& trans, const Point3F& rot);
|
bool setSequenceGroundSpeed(const String& seqName, const Point3F& trans, const Point3F& rot);
|
||||||
|
|
||||||
|
void makeEditable();
|
||||||
|
bool needsReinit();
|
||||||
|
bool needsBufferUpdate();
|
||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@ void TSShapeConstructor::_onTSShapeLoaded( Resource< TSShape >& resource )
|
||||||
TSShapeConstructor* ctor = findShapeConstructor( resource.getPath().getFullPath() );
|
TSShapeConstructor* ctor = findShapeConstructor( resource.getPath().getFullPath() );
|
||||||
if( ctor )
|
if( ctor )
|
||||||
ctor->_onLoad( resource );
|
ctor->_onLoad( resource );
|
||||||
|
|
||||||
|
if (ctor && ctor->mShape && ctor->mShape->needsReinit())
|
||||||
|
{
|
||||||
|
ctor->mShape->init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSShapeConstructor::_onTSShapeUnloaded( const Torque::Path& path, TSShape* shape )
|
void TSShapeConstructor::_onTSShapeUnloaded( const Torque::Path& path, TSShape* shape )
|
||||||
|
|
@ -128,7 +133,7 @@ static void SplitSequencePathAndName( String& srcPath, String& srcName )
|
||||||
IMPLEMENT_CONOBJECT(TSShapeConstructor);
|
IMPLEMENT_CONOBJECT(TSShapeConstructor);
|
||||||
|
|
||||||
TSShapeConstructor::TSShapeConstructor()
|
TSShapeConstructor::TSShapeConstructor()
|
||||||
: mShapePath("")
|
: mShapePath(""), mLoadingShape(false)
|
||||||
{
|
{
|
||||||
mShape = NULL;
|
mShape = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -374,9 +379,15 @@ bool TSShapeConstructor::onAdd()
|
||||||
|
|
||||||
// If an instance of this shape has already been loaded, call onLoad now
|
// If an instance of this shape has already been loaded, call onLoad now
|
||||||
Resource<TSShape> shape = ResourceManager::get().find( mShapePath );
|
Resource<TSShape> shape = ResourceManager::get().find( mShapePath );
|
||||||
|
|
||||||
if ( shape )
|
if ( shape )
|
||||||
_onLoad( shape );
|
_onLoad( shape );
|
||||||
|
|
||||||
|
if (mShape && mShape->needsReinit())
|
||||||
|
{
|
||||||
|
mShape->init();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,6 +405,7 @@ void TSShapeConstructor::_onLoad(TSShape* shape)
|
||||||
|
|
||||||
mShape = shape;
|
mShape = shape;
|
||||||
mChangeSet.clear();
|
mChangeSet.clear();
|
||||||
|
mLoadingShape = true;
|
||||||
|
|
||||||
// Add sequences defined using field syntax
|
// Add sequences defined using field syntax
|
||||||
for ( S32 i = 0; i < mSequences.size(); i++ )
|
for ( S32 i = 0; i < mSequences.size(); i++ )
|
||||||
|
|
@ -411,6 +423,7 @@ void TSShapeConstructor::_onLoad(TSShape* shape)
|
||||||
|
|
||||||
// Call script function
|
// Call script function
|
||||||
onLoad_callback();
|
onLoad_callback();
|
||||||
|
mLoadingShape = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -3279,3 +3292,15 @@ bool TSShapeConstructor::ChangeSet::addCmd_removeImposter( const TSShapeConstruc
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TSShapeConstructor::onActionPerformed()
|
||||||
|
{
|
||||||
|
// Reinit shape if we modify stuff in the shape editor, otherwise delay
|
||||||
|
if (!mLoadingShape)
|
||||||
|
{
|
||||||
|
if (mShape && mShape->needsReinit())
|
||||||
|
{
|
||||||
|
mShape->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,7 @@ public:
|
||||||
|
|
||||||
TSShape* mShape; // Edited shape; NULL while not loaded; not a Resource<TSShape> as we don't want it to prevent from unloading.
|
TSShape* mShape; // Edited shape; NULL while not loaded; not a Resource<TSShape> as we don't want it to prevent from unloading.
|
||||||
ColladaUtils::ImportOptions mOptions;
|
ColladaUtils::ImportOptions mOptions;
|
||||||
|
bool mLoadingShape;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -261,6 +262,7 @@ public:
|
||||||
bool onAdd();
|
bool onAdd();
|
||||||
|
|
||||||
void onScriptChanged(const Torque::Path& path);
|
void onScriptChanged(const Torque::Path& path);
|
||||||
|
void onActionPerformed();
|
||||||
|
|
||||||
bool writeField(StringTableEntry fieldname, const char *value);
|
bool writeField(StringTableEntry fieldname, const char *value);
|
||||||
void writeChangeSet();
|
void writeChangeSet();
|
||||||
|
|
@ -383,8 +385,16 @@ typedef domUpAxisType TSShapeConstructorUpAxis;
|
||||||
typedef ColladaUtils::ImportOptions::eLodType TSShapeConstructorLodType;
|
typedef ColladaUtils::ImportOptions::eLodType TSShapeConstructorLodType;
|
||||||
|
|
||||||
DefineEnumType( TSShapeConstructorUpAxis );
|
DefineEnumType( TSShapeConstructorUpAxis );
|
||||||
DefineEnumType( TSShapeConstructorLodType );
|
DefineEnumType(TSShapeConstructorLodType);
|
||||||
|
|
||||||
|
class TSShapeConstructorMethodActionCallback
|
||||||
|
{
|
||||||
|
TSShapeConstructor* mObject;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TSShapeConstructorMethodActionCallback(TSShapeConstructor *object) : mObject(object) { ; }
|
||||||
|
~TSShapeConstructorMethodActionCallback() { mObject->onActionPerformed(); }
|
||||||
|
};
|
||||||
|
|
||||||
/* This macro simplifies the definition of a TSShapeConstructor API method. It
|
/* This macro simplifies the definition of a TSShapeConstructor API method. It
|
||||||
wraps the actual EngineMethod definition and automatically calls the real
|
wraps the actual EngineMethod definition and automatically calls the real
|
||||||
|
|
@ -403,6 +413,7 @@ DefineEnumType( TSShapeConstructorLodType );
|
||||||
Con::errorf( "TSShapeConstructor::" #name " - shape not loaded" ); \
|
Con::errorf( "TSShapeConstructor::" #name " - shape not loaded" ); \
|
||||||
return defRet; \
|
return defRet; \
|
||||||
} \
|
} \
|
||||||
|
TSShapeConstructorMethodActionCallback actionCallback(object); \
|
||||||
return object->name rawArgs ; \
|
return object->name rawArgs ; \
|
||||||
} \
|
} \
|
||||||
/* Define the real TSShapeConstructor method */ \
|
/* Define the real TSShapeConstructor method */ \
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,9 @@ bool TSShape::addNode(const String& name, const String& parentName, const Point3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Insert node at the end of the subshape
|
// Insert node at the end of the subshape
|
||||||
S32 subShapeIndex = (parentIndex >= 0) ? getSubShapeForNode(parentIndex) : 0;
|
S32 subShapeIndex = (parentIndex >= 0) ? getSubShapeForNode(parentIndex) : 0;
|
||||||
S32 nodeIndex = subShapeNumNodes[subShapeIndex];
|
S32 nodeIndex = subShapeNumNodes[subShapeIndex];
|
||||||
|
|
@ -493,8 +496,7 @@ bool TSShape::addNode(const String& name, const String& parentName, const Point3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -548,6 +550,9 @@ bool TSShape::removeNode(const String& name)
|
||||||
((nodeParentIndex >= 0) ? getName(nodes[nodeParentIndex].nameIndex).c_str() : "null"));
|
((nodeParentIndex >= 0) ? getName(nodes[nodeParentIndex].nameIndex).c_str() : "null"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Update animation sequences
|
// Update animation sequences
|
||||||
for (S32 iSeq = 0; iSeq < sequences.size(); iSeq++)
|
for (S32 iSeq = 0; iSeq < sequences.size(); iSeq++)
|
||||||
{
|
{
|
||||||
|
|
@ -626,8 +631,7 @@ bool TSShape::removeNode(const String& name)
|
||||||
// Remove the sequence name if it is no longer in use
|
// Remove the sequence name if it is no longer in use
|
||||||
removeName(name);
|
removeName(name);
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -742,9 +746,26 @@ void TSShape::removeMeshFromObject(S32 objIndex, S32 meshIndex)
|
||||||
{
|
{
|
||||||
if (meshIndex < objects[i].numMeshes)
|
if (meshIndex < objects[i].numMeshes)
|
||||||
{
|
{
|
||||||
meshes.erase(objects[i].startMeshIndex + meshIndex);
|
U32 idxToRemove = objects[i].startMeshIndex + meshIndex;
|
||||||
|
meshes.erase(idxToRemove);
|
||||||
objects[i].numMeshes--;
|
objects[i].numMeshes--;
|
||||||
|
|
||||||
|
// Clear invalid parent
|
||||||
|
for (U32 k = 0; k < meshes.size(); k++)
|
||||||
|
{
|
||||||
|
if (meshes[k] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (meshes[k]->parentMesh == idxToRemove)
|
||||||
|
{
|
||||||
|
meshes[k]->parentMesh = -1;
|
||||||
|
}
|
||||||
|
else if (meshes[k]->parentMesh > idxToRemove)
|
||||||
|
{
|
||||||
|
meshes[k]->parentMesh--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (S32 j = 0; j < objects.size(); j++)
|
for (S32 j = 0; j < objects.size(); j++)
|
||||||
{
|
{
|
||||||
if (objects[j].startMeshIndex > objects[i].startMeshIndex)
|
if (objects[j].startMeshIndex > objects[i].startMeshIndex)
|
||||||
|
|
@ -770,7 +791,25 @@ void TSShape::removeMeshFromObject(S32 objIndex, S32 meshIndex)
|
||||||
S32 oldNumMeshes = obj.numMeshes;
|
S32 oldNumMeshes = obj.numMeshes;
|
||||||
while (obj.numMeshes && !meshes[obj.startMeshIndex + obj.numMeshes - 1])
|
while (obj.numMeshes && !meshes[obj.startMeshIndex + obj.numMeshes - 1])
|
||||||
{
|
{
|
||||||
meshes.erase(obj.startMeshIndex + obj.numMeshes - 1);
|
U32 idxToRemove = obj.startMeshIndex + obj.numMeshes - 1;
|
||||||
|
meshes.erase(idxToRemove);
|
||||||
|
|
||||||
|
// Clear invalid parent
|
||||||
|
for (U32 k = 0; k < meshes.size(); k++)
|
||||||
|
{
|
||||||
|
if (meshes[k] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (meshes[k]->parentMesh == idxToRemove)
|
||||||
|
{
|
||||||
|
meshes[k]->parentMesh = -1;
|
||||||
|
}
|
||||||
|
else if (meshes[k]->parentMesh > idxToRemove)
|
||||||
|
{
|
||||||
|
meshes[k]->parentMesh--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
obj.numMeshes--;
|
obj.numMeshes--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -820,6 +859,9 @@ bool TSShape::removeObject(const String& name)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Destroy all meshes in the object
|
// Destroy all meshes in the object
|
||||||
TSShape::Object& obj = objects[objIndex];
|
TSShape::Object& obj = objects[objIndex];
|
||||||
while ( obj.numMeshes )
|
while ( obj.numMeshes )
|
||||||
|
|
@ -858,8 +900,7 @@ bool TSShape::removeObject(const String& name)
|
||||||
// Update smallest visible detail
|
// Update smallest visible detail
|
||||||
updateSmallestVisibleDL();
|
updateSmallestVisibleDL();
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -920,6 +961,9 @@ bool TSShape::addMesh(TSMesh* mesh, const String& meshName)
|
||||||
// Ensure mesh is in editable state
|
// Ensure mesh is in editable state
|
||||||
mesh->makeEditable();
|
mesh->makeEditable();
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Determine the object name and detail size from the mesh name
|
// Determine the object name and detail size from the mesh name
|
||||||
S32 detailSize = 999;
|
S32 detailSize = 999;
|
||||||
String objName(String::GetTrailingNumber(meshName, detailSize));
|
String objName(String::GetTrailingNumber(meshName, detailSize));
|
||||||
|
|
@ -1008,8 +1052,7 @@ bool TSShape::addMesh(TSMesh* mesh, const String& meshName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1099,6 +1142,9 @@ bool TSShape::setMeshSize(const String& meshName, S32 size)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Remove the mesh from the object, but don't destroy it
|
// Remove the mesh from the object, but don't destroy it
|
||||||
TSShape::Object& obj = objects[objIndex];
|
TSShape::Object& obj = objects[objIndex];
|
||||||
TSMesh* mesh = meshes[obj.startMeshIndex + meshIndex];
|
TSMesh* mesh = meshes[obj.startMeshIndex + meshIndex];
|
||||||
|
|
@ -1110,8 +1156,7 @@ bool TSShape::setMeshSize(const String& meshName, S32 size)
|
||||||
// Update smallest visible detail
|
// Update smallest visible detail
|
||||||
updateSmallestVisibleDL();
|
updateSmallestVisibleDL();
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1126,6 +1171,9 @@ bool TSShape::removeMesh(const String& meshName)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Destroy and remove the mesh
|
// Destroy and remove the mesh
|
||||||
TSShape::Object& obj = objects[objIndex];
|
TSShape::Object& obj = objects[objIndex];
|
||||||
destructInPlace(meshes[obj.startMeshIndex + meshIndex]);
|
destructInPlace(meshes[obj.startMeshIndex + meshIndex]);
|
||||||
|
|
@ -1138,8 +1186,7 @@ bool TSShape::removeMesh(const String& meshName)
|
||||||
// Update smallest visible detail
|
// Update smallest visible detail
|
||||||
updateSmallestVisibleDL();
|
updateSmallestVisibleDL();
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1253,8 +1300,8 @@ S32 TSShape::setDetailSize(S32 oldSize, S32 newSize)
|
||||||
// Update smallest visible detail
|
// Update smallest visible detail
|
||||||
updateSmallestVisibleDL();
|
updateSmallestVisibleDL();
|
||||||
|
|
||||||
// Re-initialise the shape
|
// Nothing major, just reint object lists
|
||||||
init();
|
initObjects();
|
||||||
|
|
||||||
return newIndex;
|
return newIndex;
|
||||||
}
|
}
|
||||||
|
|
@ -1269,6 +1316,9 @@ bool TSShape::removeDetail( S32 size )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make everything editable since node indexes etc will change
|
||||||
|
makeEditable();
|
||||||
|
|
||||||
// Destroy and remove each mesh in the detail level
|
// Destroy and remove each mesh in the detail level
|
||||||
for ( S32 objIndex = objects.size()-1; objIndex >= 0; objIndex-- )
|
for ( S32 objIndex = objects.size()-1; objIndex >= 0; objIndex-- )
|
||||||
{
|
{
|
||||||
|
|
@ -1301,8 +1351,7 @@ bool TSShape::removeDetail( S32 size )
|
||||||
// Update smallest visible detail
|
// Update smallest visible detail
|
||||||
updateSmallestVisibleDL();
|
updateSmallestVisibleDL();
|
||||||
|
|
||||||
// Re-initialise the shape
|
initObjects();
|
||||||
init();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2068,7 +2117,7 @@ bool TSShape::setSequenceGroundSpeed(const String& seqName, const Point3F& trans
|
||||||
|
|
||||||
// Fixup ground frame indices
|
// Fixup ground frame indices
|
||||||
seq.numGroundFrames += frameAdjust;
|
seq.numGroundFrames += frameAdjust;
|
||||||
for (S32 i = seqIndex+1; i < sequences.size(); i++)
|
for (S32 i = seqIndex + 1; i < sequences.size(); i++)
|
||||||
sequences[i].firstGroundFrame += frameAdjust;
|
sequences[i].firstGroundFrame += frameAdjust;
|
||||||
|
|
||||||
// Generate the ground-frames
|
// Generate the ground-frames
|
||||||
|
|
@ -2093,3 +2142,25 @@ bool TSShape::setSequenceGroundSpeed(const String& seqName, const Point3F& trans
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TSShape::makeEditable()
|
||||||
|
{
|
||||||
|
mNeedReinit = true;
|
||||||
|
if (mShapeVertexData.base == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < meshes.size(); i++)
|
||||||
|
{
|
||||||
|
if (meshes[i])
|
||||||
|
{
|
||||||
|
meshes[i]->makeEditable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mShapeVertexData.set(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TSShape::needsReinit()
|
||||||
|
{
|
||||||
|
return mVertexSize == 0 || mShapeVertexData.base == NULL || mNeedReinit;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ void TSShapeInstance::buildInstanceData(TSShape * _shape, bool loadMaterials)
|
||||||
// material list...
|
// material list...
|
||||||
mMaterialList = NULL;
|
mMaterialList = NULL;
|
||||||
mOwnMaterialList = false;
|
mOwnMaterialList = false;
|
||||||
|
mUseOwnBuffer = false;
|
||||||
|
|
||||||
//
|
//
|
||||||
mData = 0;
|
mData = 0;
|
||||||
|
|
@ -532,7 +533,7 @@ void TSShapeInstance::render( const TSRenderState &rdata, S32 dl, F32 intraDL )
|
||||||
S32 end = rdata.isNoRenderTranslucent() ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss];
|
S32 end = rdata.isNoRenderTranslucent() ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss];
|
||||||
TSVertexBufferHandle *realBuffer;
|
TSVertexBufferHandle *realBuffer;
|
||||||
|
|
||||||
if (TSShape::smUseHardwareSkinning)
|
if (TSShape::smUseHardwareSkinning && !mUseOwnBuffer)
|
||||||
{
|
{
|
||||||
// For hardware skinning, just using the buffer associated with the shape will work fine
|
// For hardware skinning, just using the buffer associated with the shape will work fine
|
||||||
realBuffer = &mShape->mShapeVertexBuffer;
|
realBuffer = &mShape->mShapeVertexBuffer;
|
||||||
|
|
@ -893,3 +894,7 @@ bool TSShapeInstance::hasAccumulation()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TSShapeInstance::setUseOwnBuffer()
|
||||||
|
{
|
||||||
|
mUseOwnBuffer = true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,7 @@ protected:
|
||||||
TSVertexBufferHandle mSoftwareVertexBuffer;
|
TSVertexBufferHandle mSoftwareVertexBuffer;
|
||||||
|
|
||||||
bool mOwnMaterialList; ///< Does this own the material list pointer?
|
bool mOwnMaterialList; ///< Does this own the material list pointer?
|
||||||
|
bool mUseOwnBuffer; ///< Force using our own copy of the vertex buffer
|
||||||
|
|
||||||
bool mAlphaAlways;
|
bool mAlphaAlways;
|
||||||
F32 mAlphaAlwaysValue;
|
F32 mAlphaAlwaysValue;
|
||||||
|
|
@ -341,6 +342,7 @@ protected:
|
||||||
/// an optional feature set.
|
/// an optional feature set.
|
||||||
void initMaterialList( const FeatureSet *features = NULL );
|
void initMaterialList( const FeatureSet *features = NULL );
|
||||||
|
|
||||||
|
void setUseOwnBuffer();
|
||||||
bool ownMaterialList() const { return mOwnMaterialList; }
|
bool ownMaterialList() const { return mOwnMaterialList; }
|
||||||
|
|
||||||
/// Get the number of material targets in this shape instance
|
/// Get the number of material targets in this shape instance
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue