Rudimentary dts to obj converter
by Thomas -elfprince13- Dickerson · 10/29/2009 (9:19 pm) · 26 comments
This resource adds a console function which statically (as in, no bones or animations) dumps the first mesh of a TSShapeInstance loaded from .dts to an .obj file, should be fairly easy to make it iterate (the function sets up i as an iterator variable to be used in an outer for loop, and then just doesn't have the for loop) and convert the rest of the meshes as well, but this filled my needs so I didn't bother. It should also note that it doesn't bother exporting materials, but it does keep your UV coordinates. This was originally going to conver to Milkshape 3D ASCII format, but there are some incompatibilities in how the normal vectors are handled between the two formats (DTS interpolates to a single normal vector per vertex), so I went with .obj instead.
ConsoleFunction(dumpDTStoObj, void, 3, 3, "(string objfile, string dts)")
{
Resource<TSShape> shape;
shape = ResourceManager->load(argv[2]);
const char * str;
if(shape.isNull())
return;
TSShapeInstance *shapeinst = new TSShapeInstance(shape, true);
if(!shapeinst)
return;
FileStream stream;
stream.open(argv[1], FileStream::Write);
TSShape* mShape = shapeinst->getShape();
Con::printf("Dumping %s to %s", argv[2], argv[1]);
dumpLine("#obj file rn");
U32 i;
/*S32 frameCount = 0;
for(i = 0; i < mShape->sequences.size(); i++){
frameCount += mShape->sequences[i].numKeyframes;
}
//dumpLine(avar("Frames: %irn", frameCount));
dumpLine("Frames: 1rn"); //only STATIC meshes for now, kthxbai
dumpLine("Frame: 1rnrn");
dumpLine(avar("Meshes: %irn", mShape->meshes.size()));*/
// mesh: name, flags, material index
i = 0; //make this loopy eventually
TSMesh* tsm = mShape->meshes[i];
// number of vertices
dumpLine(avar("#%irnrn", tsm->verts.size()));
ToolVector<Point2F> uvs;
tsm->getUVs(TSMesh::tDiffuse, uvs);
U32 j; // inner loopiness
for(j = 0; j<tsm->verts.size(); j++){
Point3F xyz = tsm->verts[j];
// vertex: flags, x, y, z, u, v, bone index
dumpLine(avar("v %f %f %frn", xyz.x, xyz.y, xyz.z));
}
dumpLine("rn");
for(j = 0; j<tsm->verts.size(); j++){
Point2F uv = uvs[j];
dumpLine(avar("vt %f %frn", uv.x, uv.y));
}
dumpLine("rn");
// number of normals
U32 normcount = tsm->getFlags(TSMesh::UseEncodedNormals) ? tsm->encodedNorms.size() : tsm->norms.size();
dumpLine(avar("#%irnrn", normcount));
const Point3F * norms = tsm->getNormals(0);
for(j = 0; j<normcount; j++){
Point3F xyz = norms[j];
// normal: x, y, z
dumpLine(avar("vn %f %f %frn", xyz.x, xyz.y, xyz.z));
}
dumpLine("rn");
// number of triangles
U32 tris = 0;
for(j = 0; j<tsm->primitives.size(); j++)
tris += tsm->primitives[j].numElements;
dumpLine(avar("# %irnrn",tris));
dumpLine(avar("g Mesh%irnrn",i));
for(j = 0; j<tsm->primitives.size(); j++){
TSDrawPrimitive draw = tsm->primitives[j];
// triangle: flags, vertex index1, vertex index2, vertex index3, normal index1, normal index 2, normal index 3, smoothing group
if ( (draw.matIndex & TSDrawPrimitive::TypeMask) == TSDrawPrimitive::Triangles)
{
for (S32 k=0; k<draw.numElements; )
{
U32 idx0 = tsm->indices[draw.start + k + 0];
U32 idx1 =tsm->indices[draw.start + k + 1];
U32 idx2 = tsm->indices[draw.start + k + 2];
dumpLine(avar("f %i/%i/%i %i/%i/%i %i/%i/%irn", (idx0+1), (idx0+1), (idx0+1), (idx1+1), (idx1+1), (idx1+1), (idx2+1), (idx2+1), (idx2+1)));
k += 3;
}
} else if((draw.matIndex & TSDrawPrimitive::TypeMask) == TSDrawPrimitive::Strip){
U32 idx0 = tsm->indices[draw.start + 0];
U32 idx1;
U32 idx2 = tsm->indices[draw.start + 1];
U32 * nextIdx = &idx1;
for (S32 k=2; k<draw.numElements; k++)
{
*nextIdx = idx2;
nextIdx = (U32*) ( (dsize_t)nextIdx ^ (dsize_t)&idx0 ^ (dsize_t)&idx1);
idx2 = tsm->indices[draw.start + k];
if (idx0 == idx1 || idx0 == idx2 || idx1 == idx2)
Con::printf("Warning, vertex redundancy: %i, %i, %i", idx0, idx1, idx2);
//continue;
dumpLine(avar("f %i/%i/%i %i/%i/%i %i/%i/%irn", (idx0+1), (idx0+1), (idx0+1), (idx1+1), (idx1+1), (idx1+1), (idx2+1), (idx2+1), (idx2+1)));
}
} else{
dumpLine("# oops--don't really know how to handle thisrn");
}
}
dumpLine("rn");
stream.close();
Con::printf("...dump complete");
}About the author
C.S. PhD student at Brown University. Project lead for FreeBuild. Administrator, Cemetech tech community. Webmaster for the Village2Village Projects and the Vermont Sustainable Heating Initiative.
#22
Hers a debug screen dump:
i566.photobucket.com/albums/ss101/CS_MP/MPGE/Bugs/DTSDumpDebug2.jpg
btw, is this the way this line should look?
11/04/2009 (10:45 pm)
Ok, added the new code and now it crashes (CSK Jeep model) with only "#obj file" inside of the jeep.obj...Hers a debug screen dump:
i566.photobucket.com/albums/ss101/CS_MP/MPGE/Bugs/DTSDumpDebug2.jpg
btw, is this the way this line should look?
Con::printf("Mesh Type:\r\nTSMesh::StMT %i\r\nTSMesh::SkMT %i\r\nTSMesh::DMT %i\r\nTSMesh::SoMT %i\r\nTSMesh::NMT %i\r\nTSMesh::Flags\r\nTSMesh::Billboard %i\r\nTSMesh::HasDetailTexture %i\r\nTSMesh::BillboardZAxis %i\r\nTSMesh::EncodedNorms %i\r\nTSMesh::HasLightTexture %i\r\n",(mt & TSMesh::StandardMeshType),(mt & TSMesh::SkinMeshType),(mt & TSMesh::DecalMeshType),(mt & TSMesh::SortedMeshType),(mt & TSMesh::NullMeshType), (flags & TSMesh::Billboard), (flags & TSMesh::HasDetailTexture), (flags & TSMesh::BillboardZAxis), (flags & TSMesh::UseEncodedNormals), (flags & TSMesh::HasLightTexture));
#23
I'm honestly not familiar with enough with TSShapeInstance, TSShape, and TSMesh to know what's going wrong here, but if you can at least get me the console output from the models you had converting without crashes that would be great. I'll dig around and see if I can find some code examples that might hint at what I'm doing wrong.
11/04/2009 (10:57 pm)
Huh, that's really bizarre, and suggests to me that somehow the jeep hasn't been initialized properly. I'll dig around some more. And that's more or less correct. The TSMesh:: inside the quoted string is unecessary since that's just text to explain the values I'm printing. And I forced it to return after the line (if it had actually reached it, which clearly it hasn't if it's crashing at getType()) so that nothing later in the script could cause a crash, and we'd only get the relevant debugging information. Does the CSK Jeep load okay as a TSStatic in game?I'm honestly not familiar with enough with TSShapeInstance, TSShape, and TSMesh to know what's going wrong here, but if you can at least get me the console output from the models you had converting without crashes that would be great. I'll dig around and see if I can find some code examples that might hint at what I'm doing wrong.
#24
11/10/2009 (4:50 pm)
CSMP, did you ever run the other models through to get the log information?
#25
11/15/2009 (11:35 am)
Ah yes, I've been offline for awhile so I'll try and test those out for you tomorrow and post up the results.
#26
11/15/2009 (11:51 am)
Thanks :) 
Torque 3D Owner Thomas -elfprince13- Dickerson
and yes.