diff --git a/tools/assimp_cmd/Export.cpp b/tools/assimp_cmd/Export.cpp new file mode 100644 index 000000000..4f3c9b505 --- /dev/null +++ b/tools/assimp_cmd/Export.cpp @@ -0,0 +1,168 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2010, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Export.cpp + * @brief Implementation of the 'assimp export' utility + */ + +#include "Main.h" + +#ifndef ASSIMP_BUILD_NO_EXPORT + +const char* AICMD_MSG_EXPORT_HELP_E = +"assimp export [] [-f] [common parameters]\n" +"\t -f Specify the file format. If ommitted, the output format is \n" +"\t\tderived from the file extension of the given output file \n" +"\t[See the assimp_cmd docs for a full list of all common parameters] \n" +; + + +// ----------------------------------------------------------------------------------- +size_t GetMatchingFormat(const std::string& outf,bool byext=false) +{ + for(size_t i = 0, end = globalExporter->GetExportFormatCount(); i < end; ++i) { + const aiExportFormatDesc* const e = globalExporter->GetExportFormatDescription(i); + if (outf == (byext ? e->fileExtension : e->id)) { + return i; + } + } + return SIZE_MAX; +} + + +// ----------------------------------------------------------------------------------- +int Assimp_Export(const char* const* params, unsigned int num) +{ + const char* const invalid = "assimp export: Invalid number of arguments. See \'assimp export --help\'\n"; + if (num < 1) { + printf(invalid); + return 1; + } + + // --help + if (!strcmp( params[0], "-h") || !strcmp( params[0], "--help") || !strcmp( params[0], "-?") ) { + printf("%s",AICMD_MSG_EXPORT_HELP_E); + return 0; + } + + std::string in = std::string(params[0]); + std::string out = (num > 1 ? std::string(params[1]) : "-"), outext; + + // + const std::string::size_type s = out.find_last_of('.'); + if (s != std::string::npos) { + outext = out.substr(s+1,in.length()-(s+1)); + out = out.substr(0,s); + } + + // get import flags + ImportData import; + ProcessStandardArguments(import,params+1,num-1); + + // process other flags + std::string outf = ""; + for (unsigned int i = (out[0] == '-' ? 1 : 2); i < num;++i) { + if (!params[i]) { + continue; + } + if (!strncmp( params[i], "-f",2)) { + outf = std::string(params[i]+2); + } + else if ( !strncmp( params[i], "--format=",9)) { + outf = std::string(params[i]+9); + } + } + + std::transform(outf.begin(),outf.end(),outf.begin(),::tolower); + + // convert the output format to a format id + size_t outfi = GetMatchingFormat(outf); + if (outfi == SIZE_MAX) { + if (outf.length()) { + printf("assimp export: warning, format id \'%s\' is unknown\n",outf.c_str()); + } + + // retry to see if we know it as file extension + outfi = GetMatchingFormat(outf,true); + if (outfi == SIZE_MAX) { + // retry to see if we know the file extension of the output file + outfi = GetMatchingFormat(outext,true); + + if (outfi == SIZE_MAX) { + // still no match -> failure + printf("assimp export: no output format specified and I failed to guess it"); + return -23; + } + } + else { + outext = outf; + } + } + + // if no output file is specified, take the file name from input file + if (out[0] == '-') { + std::string::size_type s = in.find_last_of('.'); + if (s == std::string::npos) { + s = in.length(); + } + + out = in.substr(0,s); + } + + const aiExportFormatDesc* const e = globalExporter->GetExportFormatDescription(outfi); + printf("assimp export: select file format: \'%s\' (%s)\n",e->id,e->description); + + // import the model + const aiScene* scene = ImportModel(import,in); + + // derive the final file name + out += "."+outext; + + // and call the export routine + if(!ExportModel(scene, import, out,e->id)) { + return -25; + } + printf("assimp export: wrote output file: %s",out.c_str()); + return 0; +} + +#endif // no export + \ No newline at end of file diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index 1e3e1fade..e4f92ca8f 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -47,28 +47,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. const char* AICMD_MSG_ABOUT = "------------------------------------------------------ \n" -"Open Asset Import Library - Assimp \n" -"http://assimp.sourceforge.net \n" -"Command-line tools \n" +"Open Asset Import Library (\"Assimp\", http://assimp.sourceforge.net) \n" +" -- Commandline toolchain --\n" "------------------------------------------------------ \n\n" "Version %i.%i-%s%s%s%s%s (SVNREV %i)\n\n"; const char* AICMD_MSG_HELP = -"assimp \n\n" -"\tverbs:\n" -"\t\tinfo - Display statistics and structure of a 3D model\n" -"\t\tversion - Display Assimp version\n" -"\t\tlistext - List all known file extension\n" -"\t\tknowext - Check whether a file extension is recognized by Assimp\n" -"\t\textract - Extract an embedded texture from a model\n" -"\t\tdump - Convert a model to binary or XML dumps (ASSBIN/ASSXML)\n" -"\t\tcmpdump - Compare two file dumps produced with \'assimp dump -s ...\'\n" -"\n\n\tUse \'assimp --help\' to get detailed help for a command.\n" +"assimp \n\n" +" verbs:\n" +" \tinfo - Quick file stats\n" +" \tlistext - List all known file extensions available for import\n" +" \tknowext - Check whether a file extension is recognized by Assimp\n" +#ifndef ASSIMP_BUILD_NO_EXPORT +" \texport - Export a file to one of the supported output formats\n" +" \tlistexport - List all supported export formats\n" +" \tknowexport - Check whether a particular export format is supported\n" +" \texportinfo - Show basic information on a specific export format\n" +#endif +" \textract - Extract embedded texture images\n" +" \tdump - Convert models to a binary or textual dump (ASSBIN/ASSXML)\n" +" \tcmpdump - Compare dumps created using \'assimp dump -s ...\'\n" +" \tversion - Display Assimp version\n" +"\n\n Use \'assimp --help\' for detailed help on a command.\n" ; /*extern*/ Assimp::Importer* globalImporter = NULL; +#ifndef ASSIMP_BUILD_NO_EXPORT +/*extern*/ Assimp::Exporter* globalExporter = NULL; +#endif + // ------------------------------------------------------------------------------ // Application entry point int main (int argc, char* argv[]) @@ -109,12 +118,17 @@ int main (int argc, char* argv[]) return Assimp_CompareDump (&argv[2],argc-2); } - // construct a global Assimp::Importer instance - // because all further tools rely on it + // construct global importer and exporter instances Assimp::Importer imp; imp.SetPropertyBool("GLOB_MEASURE_TIME",true); globalImporter = &imp; +#ifndef ASSIMP_BUILD_NO_EXPORT + // + Assimp::Exporter exp; + globalExporter = &exp; +#endif + // assimp listext // List all file extensions supported by Assimp if (! strcmp(argv[1], "listext")) { @@ -125,11 +139,59 @@ int main (int argc, char* argv[]) return 0; } +#ifndef ASSIMP_BUILD_NO_EXPORT + // assimp listexport + // List all export file formats supported by Assimp (not the file extensions, just the format identifiers!) + if (! strcmp(argv[1], "listexport")) { + aiString s; + + for(size_t i = 0, end = exp.GetExportFormatCount(); i < end; ++i) { + const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); + s.Append( e->id ); + if (i!=end-1) { + s.Append("\n"); + } + } + + printf("%s",s.data); + return 0; + } + + // assimp exportinfo + // stat an export format + if (! strcmp(argv[1], "exportinfo")) { + aiString s; + + if (argc<3) { + printf("Expected file format id"); + return -11; + } + + for(size_t i = 0, end = exp.GetExportFormatCount(); i < end; ++i) { + const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); + if (!strcmp(e->id,argv[2])) { + printf("%s\n%s\n%s",e->id,e->fileExtension,e->description); + return 0; + } + } + + printf("Unknown file format id: %s",argv[2]); + return -12; + } + + // assimp export + // Export a model to a file + if (! strcmp(argv[1], "export")) { + return Assimp_Export (&argv[2],argc-2); + } + +#endif + // assimp knowext // Check whether a particular file extension is known by us, return 0 on success if (! strcmp(argv[1], "knowext")) { if (argc<3) { - printf("Expected a file extension to check for!"); + printf("Expected file extension"); return -10; } const bool b = imp.IsExtensionSupported(argv[2]); @@ -167,6 +229,37 @@ int main (int argc, char* argv[]) return 1; } + +// ------------------------------------------------------------------------------ +void SetLogStreams(const ImportData& imp) +{ + printf("\nAttaching log stream ... OK\n"); + + unsigned int flags = 0; + if (imp.logFile.length()) { + flags |= aiDefaultLogStream_FILE; + } + if (imp.showLog) { + flags |= aiDefaultLogStream_STDERR; + } + DefaultLogger::create(imp.logFile.c_str(),imp.verbose ? Logger::VERBOSE : Logger::NORMAL,flags); +} + + +// ------------------------------------------------------------------------------ +void FreeLogStreams() +{ + DefaultLogger::kill(); +} + + +// ------------------------------------------------------------------------------ +void PrintHorBar() +{ + printf("-----------------------------------------------------------------\n"); +} + + // ------------------------------------------------------------------------------ // Import a specific file const aiScene* ImportModel( @@ -175,18 +268,9 @@ const aiScene* ImportModel( { // Attach log streams if (imp.log) { - printf("\nAttaching log stream ... OK\n"); - - unsigned int flags = 0; - if (imp.logFile.length()) { - flags |= aiDefaultLogStream_FILE; - } - if (imp.showLog) { - flags |= aiDefaultLogStream_STDERR; - } - DefaultLogger::create(imp.logFile.c_str(),imp.verbose ? Logger::VERBOSE : Logger::NORMAL,flags); + SetLogStreams(imp); } - printf("Launching model import ... OK\n"); + printf("Launching asset import ... OK\n"); // Now validate this flag combination if(!globalImporter->ValidateFlags(imp.ppFlags)) { @@ -194,15 +278,17 @@ const aiScene* ImportModel( return NULL; } printf("Validating postprocessing flags ... OK\n"); - if (imp.showLog) - printf("-----------------------------------------------------------------\n"); + if (imp.showLog) { + PrintHorBar(); + } + // do the actual import, measure time const clock_t first = clock(); const aiScene* scene = globalImporter->ReadFile(path,imp.ppFlags); if (imp.showLog) { - printf("-----------------------------------------------------------------\n"); + PrintHorBar(); } if (!scene) { printf("ERROR: Failed to load file\n"); @@ -210,17 +296,60 @@ const aiScene* ImportModel( } const clock_t second = ::clock(); - const float seconds = (float)(second-first) / CLOCKS_PER_SEC; + const double seconds = static_cast(second-first) / CLOCKS_PER_SEC; printf("Importing file ... OK \n import took approx. %.5f seconds\n" "\n",seconds); if (imp.log) { - DefaultLogger::kill(); + FreeLogStreams(); } return scene; } +#ifndef ASSIMP_BUILD_NO_EXPORT +// ------------------------------------------------------------------------------ +bool ExportModel(const aiScene* pOut, + const ImportData& imp, + const std::string& path, + const char* pID) +{ + // Attach log streams + if (imp.log) { + SetLogStreams(imp); + } + printf("Launching asset export ... OK\n"); + + if (imp.showLog) { + PrintHorBar(); + } + + // do the actual export, measure time + const clock_t first = clock(); + const aiReturn res = globalExporter->Export(pOut,pID,path); + + if (imp.showLog) { + PrintHorBar(); + } + if (res != AI_SUCCESS) { + printf("ERROR: Failed to write file\n"); + return false; + } + + const clock_t second = ::clock(); + const double seconds = static_cast(second-first) / CLOCKS_PER_SEC; + + printf("Exporting file ... OK \n export took approx. %.5f seconds\n" + "\n",seconds); + + if (imp.log) { + FreeLogStreams(); + } + + return true; +} +#endif + // ------------------------------------------------------------------------------ // Process standard arguments int ProcessStandardArguments( diff --git a/tools/assimp_cmd/Main.h b/tools/assimp_cmd/Main.h index faf6c37ee..09c689c53 100644 --- a/tools/assimp_cmd/Main.h +++ b/tools/assimp_cmd/Main.h @@ -58,6 +58,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef ASSIMP_BUILD_NO_EXPORT +# include +#endif + #include <../code/AssimpPCH.h> /* to get stdint.h */ #include <../code/fast_atof.h> #include <../code/StringComparison.h> @@ -67,9 +71,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; + // Global assimp importer instance extern Assimp::Importer* globalImporter; +#ifndef ASSIMP_BUILD_NO_EXPORT +// Global assimp exporter instance +extern Assimp::Exporter* globalExporter; +#endif + // ------------------------------------------------------------------------------ /** Defines common import parameters */ struct ImportData @@ -113,11 +123,24 @@ int ProcessStandardArguments(ImportData& fill, // ------------------------------------------------------------------------------ /** Import a specific model file * @param imp Import configuration to be used - * @param path Path to the file to be opened */ + * @param path Path to the file to be read */ const aiScene* ImportModel( const ImportData& imp, const std::string& path); +#ifndef ASSIMP_BUILD_NO_EXPORT + +// ------------------------------------------------------------------------------ +/** Export a specific model file + * @param imp Import configuration to be used + * @param path Path to the file to be written + * @param format Format id*/ +bool ExportModel(const aiScene* pOut, + const ImportData& imp, + const std::string& path, + const char* pID); + +#endif // ------------------------------------------------------------------------------ /** assimp_dump utility @@ -128,6 +151,15 @@ int Assimp_Dump ( const char* const* params, unsigned int num); +// ------------------------------------------------------------------------------ +/** assimp_export utility + * @param params Command line parameters to 'assimp export' + * @param Number of params + * @return 0 for success*/ +int Assimp_Export ( + const char* const* params, + unsigned int num); + // ------------------------------------------------------------------------------ /** assimp_extract utility * @param params Command line parameters to 'assimp extract'