summaryrefslogtreecommitdiff
path: root/libs/assimp/tools/assimp_cmd/Main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/tools/assimp_cmd/Main.cpp')
-rw-r--r--libs/assimp/tools/assimp_cmd/Main.cpp564
1 files changed, 564 insertions, 0 deletions
diff --git a/libs/assimp/tools/assimp_cmd/Main.cpp b/libs/assimp/tools/assimp_cmd/Main.cpp
new file mode 100644
index 0000000..31b92b0
--- /dev/null
+++ b/libs/assimp/tools/assimp_cmd/Main.cpp
@@ -0,0 +1,564 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp 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 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 Main.cpp
+ * @brief main() function of assimp_cmd
+ */
+
+#include "Main.h"
+
+#include <assimp/ProgressHandler.hpp>
+#include <iostream>
+
+class ConsoleProgressHandler : public ProgressHandler {
+public:
+ ConsoleProgressHandler() :
+ ProgressHandler() {
+ // empty
+ }
+
+ ~ConsoleProgressHandler() override {
+ // empty
+ }
+
+ bool Update(float percentage) override {
+ std::cout << percentage * 100.0f << " %\n";
+ return true;
+ }
+};
+const char* AICMD_MSG_ABOUT =
+"------------------------------------------------------ \n"
+"Open Asset Import Library (\"Assimp\", https://github.com/assimp/assimp) \n"
+" -- Commandline toolchain --\n"
+"------------------------------------------------------ \n\n"
+
+"Version %i.%i %s%s%s%s%s(GIT commit %x)\n\n";
+
+const char* AICMD_MSG_HELP =
+"assimp <verb> <parameters>\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"
+" \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 <file> -s ...\'\n"
+" \tversion - Display Assimp version\n"
+"\n Use \'assimp <verb> --help\' for detailed help on a command.\n"
+;
+
+/*extern*/ Assimp::Importer* globalImporter = nullptr;
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+/*extern*/ Assimp::Exporter* globalExporter = nullptr;
+#endif
+
+// ------------------------------------------------------------------------------
+// Application entry point
+int main (int argc, char* argv[])
+{
+ if (argc <= 1) {
+ printf("assimp: No command specified. Use \'assimp help\' for a detailed command list\n");
+ return AssimpCmdError::Success;
+ }
+
+ // assimp version
+ // Display version information
+ if (! strcmp(argv[1], "version")) {
+ const unsigned int flags = aiGetCompileFlags();
+ printf(AICMD_MSG_ABOUT,
+ aiGetVersionMajor(),
+ aiGetVersionMinor(),
+ (flags & ASSIMP_CFLAGS_DEBUG ? "-debug " : ""),
+ (flags & ASSIMP_CFLAGS_NOBOOST ? "-noboost " : ""),
+ (flags & ASSIMP_CFLAGS_SHARED ? "-shared " : ""),
+ (flags & ASSIMP_CFLAGS_SINGLETHREADED ? "-st " : ""),
+ (flags & ASSIMP_CFLAGS_STLPORT ? "-stlport " : ""),
+ aiGetVersionRevision());
+
+ return AssimpCmdError::Success;
+ }
+
+ // assimp help
+ // Display some basic help (--help and -h work as well
+ // because people could try them intuitively)
+ if (!strcmp(argv[1], "help") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
+ printf("%s",AICMD_MSG_HELP);
+ return AssimpCmdError::Success;
+ }
+
+ // assimp cmpdump
+ // Compare two mini model dumps (regression suite)
+ if (! strcmp(argv[1], "cmpdump")) {
+ return Assimp_CompareDump (&argv[2],argc-2);
+ }
+
+ // 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")) {
+ aiString s;
+ imp.GetExtensionList(s);
+
+ printf("%s\n",s.data);
+ return AssimpCmdError::Success;
+ }
+
+#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\n",s.data);
+ return AssimpCmdError::Success;
+ }
+
+
+ // assimp exportinfo
+ // stat an export format
+ if (! strcmp(argv[1], "exportinfo")) {
+ aiString s;
+
+ if (argc<3) {
+ printf("Expected file format id\n");
+ return AssimpCmdError::NoFileFormatSpecified;
+ }
+
+ 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\n",e->id,e->fileExtension,e->description);
+ return AssimpCmdError::Success;
+ }
+ }
+
+ printf("Unknown file format id: \'%s\'\n",argv[2]);
+ return AssimpCmdError::UnknownFileFormat;
+ }
+
+ // 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 file extension");
+ return AssimpCmdError::NoFileExtensionSpecified;
+ }
+ const bool b = imp.IsExtensionSupported(argv[2]);
+ printf("File extension \'%s\' is %sknown\n",argv[2],(b?"":"not "));
+ return b? AssimpCmdError::Success : AssimpCmdError::UnknownFileExtension;
+ }
+
+ // assimp info
+ // Print basic model statistics
+ if (! strcmp(argv[1], "info")) {
+ return Assimp_Info ((const char**)&argv[2],argc-2);
+ }
+
+ // assimp dump
+ // Dump a model to a file
+ if (! strcmp(argv[1], "dump")) {
+ return Assimp_Dump (&argv[2],argc-2);
+ }
+
+ // assimp extract
+ // Extract an embedded texture from a file
+ if (! strcmp(argv[1], "extract")) {
+ return Assimp_Extract (&argv[2],argc-2);
+ }
+
+ // assimp testbatchload
+ // Used by /test/other/streamload.py to load a list of files
+ // using the same importer instance to check for incompatible
+ // importers.
+ if (! strcmp(argv[1], "testbatchload")) {
+ return Assimp_TestBatchLoad (&argv[2],argc-2);
+ }
+
+ printf("Unrecognized command. Use \'assimp help\' for a detailed command list\n");
+ return AssimpCmdError::UnrecognizedCommand;
+}
+
+
+// ------------------------------------------------------------------------------
+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(
+ const ImportData& imp,
+ const std::string& path)
+{
+ // Attach log streams
+ if (imp.log) {
+ SetLogStreams(imp);
+ }
+ printf("Launching asset import ... OK\n");
+
+ // Now validate this flag combination
+ if(!globalImporter->ValidateFlags(imp.ppFlags)) {
+ printf("ERROR: Unsupported post-processing flags \n");
+ return NULL;
+ }
+ printf("Validating postprocessing flags ... OK\n");
+ if (imp.showLog) {
+ PrintHorBar();
+ }
+
+
+ // do the actual import, measure time
+ const clock_t first = clock();
+ ConsoleProgressHandler *ph = new ConsoleProgressHandler;
+ globalImporter->SetProgressHandler(ph);
+
+ const aiScene* scene = globalImporter->ReadFile(path,imp.ppFlags);
+
+ if (imp.showLog) {
+ PrintHorBar();
+ }
+ if (!scene) {
+ printf("ERROR: Failed to load file: %s\n", globalImporter->GetErrorString());
+ return NULL;
+ }
+
+ const clock_t second = ::clock();
+ const double seconds = static_cast<double>(second-first) / CLOCKS_PER_SEC;
+
+ printf("Importing file ... OK \n import took approx. %.5f seconds\n"
+ "\n",seconds);
+
+ if (imp.log) {
+ FreeLogStreams();
+ }
+ globalImporter->SetProgressHandler(nullptr);
+ delete ph;
+
+ 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();
+ }
+
+ aiMatrix4x4 rx, ry, rz;
+ aiMatrix4x4::RotationX(imp.rot.x, rx);
+ aiMatrix4x4::RotationY(imp.rot.y, ry);
+ aiMatrix4x4::RotationZ(imp.rot.z, rz);
+ pOut->mRootNode->mTransformation *= rx;
+ pOut->mRootNode->mTransformation *= ry;
+ pOut->mRootNode->mTransformation *= rz;
+
+ // 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("Failed to write file\n");
+ printf("ERROR: %s\n", globalExporter->GetErrorString());
+ return false;
+ }
+
+ const clock_t second = ::clock();
+ const double seconds = static_cast<double>(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(
+ ImportData& fill,
+ const char* const * params,
+ unsigned int num)
+{
+ // -ptv --pretransform-vertices
+ // -gsn --gen-smooth-normals
+ // -gn --gen-normals
+ // -cts --calc-tangent-space
+ // -jiv --join-identical-vertices
+ // -rrm --remove-redundant-materials
+ // -fd --find-degenerates
+ // -slm --split-large-meshes
+ // -lbw --limit-bone-weights
+ // -vds --validate-data-structure
+ // -icl --improve-cache-locality
+ // -sbpt --sort-by-ptype
+ // -lh --convert-to-lh
+ // -fuv --flip-uv
+ // -fwo --flip-winding-order
+ // -tuv --transform-uv-coords
+ // -guv --gen-uvcoords
+ // -fid --find-invalid-data
+ // -fixn --fix normals
+ // -tri --triangulate
+ // -fi --find-instances
+ // -og --optimize-graph
+ // -om --optimize-meshes
+ // -db --debone
+ // -sbc --split-by-bone-count
+ // -gs --global-scale
+ //
+ // -c<file> --config-file=<file>
+
+ for (unsigned int i = 0; i < num;++i)
+ {
+ const char *param = params[ i ];
+ printf( "param = %s\n", param );
+ if (! strcmp( param, "-ptv") || ! strcmp( param, "--pretransform-vertices")) {
+ fill.ppFlags |= aiProcess_PreTransformVertices;
+ }
+ else if (! strcmp( param, "-gsn") || ! strcmp( param, "--gen-smooth-normals")) {
+ fill.ppFlags |= aiProcess_GenSmoothNormals;
+ }
+ else if (! strcmp( param, "-dn") || ! strcmp( param, "--drop-normals")) {
+ fill.ppFlags |= aiProcess_DropNormals;
+ }
+ else if (! strcmp( param, "-gn") || ! strcmp( param, "--gen-normals")) {
+ fill.ppFlags |= aiProcess_GenNormals;
+ }
+ else if (! strcmp( param, "-jiv") || ! strcmp( param, "--join-identical-vertices")) {
+ fill.ppFlags |= aiProcess_JoinIdenticalVertices;
+ }
+ else if (! strcmp( param, "-rrm") || ! strcmp( param, "--remove-redundant-materials")) {
+ fill.ppFlags |= aiProcess_RemoveRedundantMaterials;
+ }
+ else if (! strcmp( param, "-fd") || ! strcmp( param, "--find-degenerates")) {
+ fill.ppFlags |= aiProcess_FindDegenerates;
+ }
+ else if (! strcmp( param, "-slm") || ! strcmp( param, "--split-large-meshes")) {
+ fill.ppFlags |= aiProcess_SplitLargeMeshes;
+ }
+ else if (! strcmp( param, "-lbw") || ! strcmp( param, "--limit-bone-weights")) {
+ fill.ppFlags |= aiProcess_LimitBoneWeights;
+ }
+ else if (! strcmp( param, "-vds") || ! strcmp( param, "--validate-data-structure")) {
+ fill.ppFlags |= aiProcess_ValidateDataStructure;
+ }
+ else if (! strcmp( param, "-icl") || ! strcmp( param, "--improve-cache-locality")) {
+ fill.ppFlags |= aiProcess_ImproveCacheLocality;
+ }
+ else if (! strcmp( param, "-sbpt") || ! strcmp( param, "--sort-by-ptype")) {
+ fill.ppFlags |= aiProcess_SortByPType;
+ }
+ else if (! strcmp( param, "-lh") || ! strcmp( param, "--left-handed")) {
+ fill.ppFlags |= aiProcess_ConvertToLeftHanded;
+ }
+ else if (! strcmp( param, "-fuv") || ! strcmp( param, "--flip-uv")) {
+ fill.ppFlags |= aiProcess_FlipUVs;
+ }
+ else if (! strcmp( param, "-fwo") || ! strcmp( param, "--flip-winding-order")) {
+ fill.ppFlags |= aiProcess_FlipWindingOrder;
+ }
+ else if (! strcmp( param, "-tuv") || ! strcmp( param, "--transform-uv-coords")) {
+ fill.ppFlags |= aiProcess_TransformUVCoords;
+ }
+ else if (! strcmp( param, "-guv") || ! strcmp( param, "--gen-uvcoords")) {
+ fill.ppFlags |= aiProcess_GenUVCoords;
+ }
+ else if (! strcmp( param, "-fid") || ! strcmp( param, "--find-invalid-data")) {
+ fill.ppFlags |= aiProcess_FindInvalidData;
+ }
+ else if (! strcmp( param, "-fixn") || ! strcmp( param, "--fix-normals")) {
+ fill.ppFlags |= aiProcess_FixInfacingNormals;
+ }
+ else if (! strcmp( param, "-tri") || ! strcmp( param, "--triangulate")) {
+ fill.ppFlags |= aiProcess_Triangulate;
+ }
+ else if (! strcmp( param, "-cts") || ! strcmp( param, "--calc-tangent-space")) {
+ fill.ppFlags |= aiProcess_CalcTangentSpace;
+ }
+ else if (! strcmp( param, "-fi") || ! strcmp( param, "--find-instances")) {
+ fill.ppFlags |= aiProcess_FindInstances;
+ }
+ else if (! strcmp( param, "-og") || ! strcmp( param, "--optimize-graph")) {
+ fill.ppFlags |= aiProcess_OptimizeGraph;
+ }
+ else if (! strcmp( param, "-om") || ! strcmp( param, "--optimize-meshes")) {
+ fill.ppFlags |= aiProcess_OptimizeMeshes;
+ }
+ else if (! strcmp( param, "-db") || ! strcmp( param, "--debone")) {
+ fill.ppFlags |= aiProcess_Debone;
+ }
+ else if (! strcmp( param, "-sbc") || ! strcmp( param, "--split-by-bone-count")) {
+ fill.ppFlags |= aiProcess_SplitByBoneCount;
+ }
+ else if (!strcmp(param, "-embtex") || ! strcmp(param, "--embed-textures")) {
+ fill.ppFlags |= aiProcess_EmbedTextures;
+ }
+ else if (!strcmp(param, "-gs") || ! strcmp(param, "--global-scale")) {
+ fill.ppFlags |= aiProcess_GlobalScale;
+ }
+ else if (! strncmp( param, "-c",2) || ! strncmp( param, "--config=",9)) {
+ const unsigned int ofs = (params[i][1] == '-' ? 9 : 2);
+
+ // use default configurations
+ if (!strncmp( param + ofs, "full", 4 )) {
+ fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
+ } else if (!strncmp( param + ofs, "default", 7 )) {
+ fill.ppFlags |= aiProcessPreset_TargetRealtime_Quality;
+ } else if (! strncmp( param +ofs,"fast",4)) {
+ fill.ppFlags |= aiProcessPreset_TargetRealtime_Fast;
+ }
+ } else if (! strcmp( param, "-l") || ! strcmp( param, "--show-log")) {
+ fill.showLog = true;
+ }
+ else if (! strcmp( param, "-v") || ! strcmp( param, "--verbose")) {
+ fill.verbose = true;
+ }
+ else if (!strncmp(params[i], "-rx=", 4) || !strncmp(params[i], "--rotation-x=", 13)) {
+ std::string value = std::string(params[i] + (params[i][1] == '-' ? 13 : 4));
+ fill.rot.x = std::stof(value);
+ }
+ else if (!strncmp(params[i], "-ry=", 4) || !strncmp(params[i], "--rotation-y=", 13)) {
+ std::string value = std::string(params[i] + (params[i][1] == '-' ? 13 : 4));
+ fill.rot.y = std::stof(value);
+ }
+ else if (!strncmp(params[i], "-rz=", 4) || !strncmp(params[i], "--rotation-z=", 13)) {
+ std::string value = std::string(params[i] + (params[i][1] == '-' ? 13 : 4));
+ fill.rot.z = std::stof(value);
+ }
+ else if (! strncmp( param, "--log-out=",10) || ! strncmp( param, "-lo",3)) {
+ fill.logFile = std::string(params[i]+(params[i][1] == '-' ? 10 : 3));
+ if (!fill.logFile.length()) {
+ fill.logFile = "assimp-log.txt";
+ }
+ }
+ }
+
+ if (fill.logFile.length() || fill.showLog || fill.verbose) {
+ fill.log = true;
+ }
+
+ return AssimpCmdError::Success;
+}
+
+// ------------------------------------------------------------------------------
+int Assimp_TestBatchLoad (
+ const char* const* params,
+ unsigned int num)
+{
+ for(unsigned int i = 0; i < num; ++i) {
+ globalImporter->ReadFile(params[i],aiProcessPreset_TargetRealtime_MaxQuality);
+ // we're totally silent. scene destructs automatically.
+ }
+ return AssimpCmdError::Success;
+}