T3D 1.2 - Collada import leads to wrong data in DTS (with second UV or vertex paint)
by Fyodor -bank- Osokin · in Torque 3D Professional · 05/19/2012 (6:00 am) · 4 replies
Build: Torque 3D 1.2 (and all previous version with Collada import support)
Platform: Any
Target: TSShape assembling Colldata-imported models with second UV or with vertex paint
Issues: TSShape::assembleShape() doesn't set addresses for smTVerts2List and smColorsList vectors.
Note:
I'll try to be short on this (as the whole DTS loading routine is a bit... "mess"):
Under certain circumstances, the TSShape::assembleShape() method can lead to some memory corruption, or better - to wrong data being used (this happens when you import Collada/DAE models with more than one mesh and when you are using second UV or vertex paint features).
The bug:
The TSMesh::smTVerts2List and TSMesh::smColorsList Vectors initialized properly (using correct data) only for the first mesh of the model being assembled.
The fix:
Inside TSShape::assembleShape() replace this code block
Platform: Any
Target: TSShape assembling Colldata-imported models with second UV or with vertex paint
Issues: TSShape::assembleShape() doesn't set addresses for smTVerts2List and smColorsList vectors.
Note:
I'll try to be short on this (as the whole DTS loading routine is a bit... "mess"):
Under certain circumstances, the TSShape::assembleShape() method can lead to some memory corruption, or better - to wrong data being used (this happens when you import Collada/DAE models with more than one mesh and when you are using second UV or vertex paint features).
The bug:
The TSMesh::smTVerts2List and TSMesh::smColorsList Vectors initialized properly (using correct data) only for the first mesh of the model being assembled.
The fix:
Inside TSShape::assembleShape() replace this code block
..//skipped
// fill in location of verts, tverts, and normals for detail levels
if (mesh && meshType!=TSMesh::DecalMeshType)
{
TSMesh::smVertsList[i] = mesh->verts.address();
TSMesh::smTVertsList[i] = mesh->tverts.address();
TSMesh::smNormsList[i] = mesh->norms.address();
TSMesh::smEncodedNormsList[i] = mesh->encodedNorms.address();
..//skippedwith:..//skipped
// fill in location of verts, tverts, and normals for detail levels
if (mesh && meshType!=TSMesh::DecalMeshType)
{
TSMesh::smVertsList[i] = mesh->verts.address();
TSMesh::smTVertsList[i] = mesh->tverts.address();
if ( smReadVersion >= 26 )
{
TSMesh::smTVerts2List[i] = mesh->tverts2.address();
TSMesh::smColorsList[i] = mesh->colors.address();
}
TSMesh::smNormsList[i] = mesh->norms.address();
TSMesh::smEncodedNormsList[i] = mesh->encodedNorms.address();
..//skippedAs you see, I've added address assignment to the TSMesh::smTVerts2List and TSMesh::smColorsList Vectors, like the rest.About the author
Game developer.
#2
In TSShape::assembleShape() method locate:
More down, replace:
05/19/2012 (6:17 am)
P.S. More fixes for skinned meshes, if anyone uses this (initialization included):In TSShape::assembleShape() method locate:
..//skipped
for (i=0; i<numSkins; i++)
{
TSMesh::smVertsList[i]=NULL;
TSMesh::smTVertsList[i]=NULL;
TSMesh::smNormsList[i]=NULL;
TSMesh::smEncodedNormsList[i]=NULL;
TSMesh::smDataCopied[i]=false;
..//skippedand replace it with..//skipped
for (i=0; i<numSkins; i++)
{
TSMesh::smVertsList[i]=NULL;
TSMesh::smTVertsList[i]=NULL;
if ( smReadVersion >= 26 )
{
TSMesh::smTVerts2List[i] = NULL;
TSMesh::smColorsList[i] = NULL;
}
TSMesh::smNormsList[i]=NULL;
TSMesh::smEncodedNormsList[i]=NULL;
TSMesh::smDataCopied[i]=false;
..//skippedMore down, replace:
..//skipped
// fill in location of verts, tverts, and normals for shared detail levels
if (skin)
{
TSMesh::smVertsList[i] = skin->batchData.initialVerts.address();
TSMesh::smTVertsList[i] = skin->tverts.address();
TSMesh::smNormsList[i] = skin->batchData.initialNorms.address();
TSMesh::smEncodedNormsList[i] = skin->encodedNorms.address();
TSMesh::smDataCopied[i] = !skip; // as long as we didn't skip this mesh, the data should be in shape now
..//skippedwith:..//skipped
// fill in location of verts, tverts, and normals for shared detail levels
if (skin)
{
TSMesh::smVertsList[i] = skin->batchData.initialVerts.address();
TSMesh::smTVertsList[i] = skin->tverts.address();
if ( smReadVersion >= 26 )
{
TSMesh::smTVerts2List[i] = skin->tverts2.address();
TSMesh::smColorsList[i] = skin->colors.address();
}
TSMesh::smNormsList[i] = skin->batchData.initialNorms.address();
TSMesh::smEncodedNormsList[i] = skin->encodedNorms.address();
TSMesh::smDataCopied[i] = !skip; // as long as we didn't skip this mesh, the data should be in shape now
..//skipped
#3
05/19/2012 (9:01 am)
Well spotted!
#4
05/19/2012 (10:40 pm)
winner winner chicken dinner
Associate Fyodor -bank- Osokin
Dedicated Logic
If you read through the TSShape::assembleShape() method you may notice, that all of the Vectors are first sized properly:
..//skipped TSMesh::smVertsList.setSize(scratchSize); TSMesh::smTVertsList.setSize(scratchSize); if ( smReadVersion >= 26 ) { TSMesh::smTVerts2List.setSize(scratchSize); TSMesh::smColorsList.setSize(scratchSize); } TSMesh::smNormsList.setSize(scratchSize); TSMesh::smEncodedNormsList.setSize(scratchSize); TSMesh::smDataCopied.setSize(scratchSize);A bit down the code, it properly too being set to NULL:..//skipped for (i=0; i<numMeshes; i++) { TSMesh::smVertsList[i]=NULL; TSMesh::smTVertsList[i]=NULL; if ( smReadVersion >= 26 ) { TSMesh::smTVerts2List[i] = NULL; TSMesh::smColorsList[i] = NULL; } TSMesh::smNormsList[i]=NULL; TSMesh::smEncodedNormsList[i]=NULL; TSMesh::smDataCopied[i]=false; ..//skippedAnd then - used.You may think that when it sets the addresses for Vectors, the TSMesh::smTVerts2List and TSMesh::smColorsList will stay NULL?
Look at the TSMesh::assembleMesh() method:
..//skipped numTVerts = tsalloc.get32(); ptr32 = getSharedData32( parentMesh, 2 * numTVerts, (S32**)smTVerts2List.address(), skip ); tverts2.set( (Point2F*)ptr32, numTVerts ); S32 numVColors = tsalloc.get32(); ptr32 = getSharedData32( parentMesh, numVColors, (S32**)smColorsList.address(), skip ); colors.set( (ColorI*)ptr32, numVColors ); ..//skippedFor the first mesh everything is fine, but meshes after will get wrong data.After my fix applied, I can safely use Forest's "wind" feature for a tree (for example) with many LODs, and I can use vertex paint for any LOD (or all) in this model without any side effects. Same for using second UV feature.
Happy TORQUEing!