//----------------------------------------------------------------------------- // Product: OpenCTM tools // File: ctmconv.cpp // Description: 3D file format conversion tool. The program can be used to // convert various 3D file formats to and from the OpenCTM file // format, and also for conversion between other formats. //----------------------------------------------------------------------------- // Copyright (c) 2009-2010 Marcus Geelnard // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not // be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. //----------------------------------------------------------------------------- #include #include #include #include #include #include #include "systimer.h" #include "convoptions.h" #include "mesh.h" #include "meshio.h" using namespace std; //----------------------------------------------------------------------------- // PreProcessMesh() //----------------------------------------------------------------------------- static void PreProcessMesh(Mesh &aMesh, Options &aOptions) { // Nothing to do? if((aOptions.mScale == 1.0f) && (aOptions.mUpAxis == uaZ) && (!aOptions.mFlipTriangles) && (!aOptions.mCalcNormals)) return; // Create 3x3 transformation matrices for the vertices and the normals Vector3 vX, vY, vZ; Vector3 nX, nY, nZ; switch(aOptions.mUpAxis) { case uaX: nX = Vector3(0.0f, 0.0f, 1.0f); nY = Vector3(0.0f, 1.0f, 0.0f); nZ = Vector3(-1.0f, 0.0f, 0.0f); break; case uaY: nX = Vector3(1.0f, 0.0f, 0.0f); nY = Vector3(0.0f, 0.0f, 1.0f); nZ = Vector3(0.0f, -1.0f, 0.0f); break; case uaZ: nX = Vector3(1.0f, 0.0f, 0.0f); nY = Vector3(0.0f, 1.0f, 0.0f); nZ = Vector3(0.0f, 0.0f, 1.0f); break; case uaNX: nX = Vector3(0.0f, 0.0f, -1.0f); nY = Vector3(0.0f, 1.0f, 0.0f); nZ = Vector3(1.0f, 0.0f, 0.0f); break; case uaNY: nX = Vector3(1.0f, 0.0f, 0.0f); nY = Vector3(0.0f, 0.0f, -1.0f); nZ = Vector3(0.0f, 1.0f, 0.0f); break; case uaNZ: nX = Vector3(-1.0f, 0.0f, 0.0f); nY = Vector3(0.0f, 1.0f, 0.0f); nZ = Vector3(0.0f, 0.0f, -1.0f); break; } vX = nX * aOptions.mScale; vY = nY * aOptions.mScale; vZ = nZ * aOptions.mScale; cout << "Processing... " << flush; SysTimer timer; timer.Push(); // Update all vertex coordinates for(CTMuint i = 0; i < aMesh.mVertices.size(); ++ i) aMesh.mVertices[i] = vX * aMesh.mVertices[i].x + vY * aMesh.mVertices[i].y + vZ * aMesh.mVertices[i].z; // Update all normals if(aMesh.HasNormals() && !aOptions.mNoNormals) { for(CTMuint i = 0; i < aMesh.mNormals.size(); ++ i) aMesh.mNormals[i] = nX * aMesh.mNormals[i].x + nY * aMesh.mNormals[i].y + nZ * aMesh.mNormals[i].z; } // Flip trianlges? if(aOptions.mFlipTriangles) { CTMuint triCount = aMesh.mIndices.size() / 3; for(CTMuint i = 0; i < triCount; ++ i) { CTMuint tmp = aMesh.mIndices[i * 3]; aMesh.mIndices[i * 3] = aMesh.mIndices[i * 3 + 1]; aMesh.mIndices[i * 3 + 1] = tmp; } } // Calculate normals? if((!aOptions.mNoNormals) && aOptions.mCalcNormals && (!aMesh.HasNormals())) aMesh.CalculateNormals(); double dt = timer.PopDelta(); cout << 1000.0 * dt << " ms" << endl; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char ** argv) { // Get file names and options Options opt; string inFile; string outFile; try { if(argc < 3) throw runtime_error("Too few arguments."); inFile = string(argv[1]); outFile = string(argv[2]); opt.GetFromArgs(argc, argv, 3); } catch(exception &e) { cout << "Error: " << e.what() << endl << endl; cout << "Usage: " << argv[0] << " infile outfile [options]" << endl << endl; cout << "Options:" << endl; cout << endl << " Data manipulation (all formats)" << endl; cout << " --scale arg Scale the mesh by a scalar factor." << endl; cout << " --upaxis arg Set up axis (X, Y, Z, -X, -Y, -Z). If != Z, the mesh will" << endl; cout << " be flipped." << endl; cout << " --flip Flip triangle orientation." << endl; cout << " --calc-normals If the source file does not contain any normals, calculate" << endl; cout << " them." << endl; cout << " --no-normals Do not export normals." << endl; cout << " --no-texcoords Do not export texture coordinates." << endl; cout << " --no-colors Do not export vertex colors." << endl; cout << endl << " OpenCTM output" << endl; cout << " --method arg Select compression method (RAW, MG1, MG2)" << endl; cout << " --level arg Set the compression level (0 - 9)" << endl; cout << endl << " OpenCTM MG2 method" << endl; cout << " --vprec arg Set vertex precision" << endl; cout << " --vprecrel arg Set vertex precision, relative method" << endl; cout << " --nprec arg Set normal precision" << endl; cout << " --tprec arg Set texture map precision" << endl; cout << " --cprec arg Set color precision" << endl; cout << endl << " Miscellaneous" << endl; cout << " --comment arg Set the file comment (default is to use the comment" << endl; cout << " from the input file, if any)." << endl; cout << " --texfile arg Set the texture file name reference for the texture" << endl; cout << " (default is to use the texture file name reference" << endl; cout << " from the input file, if any)." << endl; // Show supported formats cout << endl << "Supported file formats:" << endl << endl; list formatList; SupportedFormats(formatList); for(list::iterator i = formatList.begin(); i != formatList.end(); ++ i) cout << " " << (*i) << endl; cout << endl; return 0; } try { // Define mesh Mesh mesh; // Create a timer instance SysTimer timer; double dt; // Load input file cout << "Loading " << inFile << "... " << flush; timer.Push(); ImportMesh(inFile.c_str(), &mesh); dt = timer.PopDelta(); cout << 1000.0 * dt << " ms" << endl; // Manipulate the mesh PreProcessMesh(mesh, opt); // Override comment? if(opt.mComment.size() > 0) mesh.mComment = opt.mComment; // Override texture file name? if(opt.mTexFileName.size() > 0) mesh.mTexFileName = opt.mTexFileName; // Save output file cout << "Saving " << outFile << "... " << flush; timer.Push(); ExportMesh(outFile.c_str(), &mesh, opt); dt = timer.PopDelta(); cout << 1000.0 * dt << " ms" << endl; } catch(exception &e) { cout << "Error: " << e.what() << endl; } return 0; }