2222
2323// These constants define the current software version.
2424// They must be updated when the command line is changed.
25- #define ALICEVISION_SOFTWARE_VERSION_MAJOR 1
25+ #define ALICEVISION_SOFTWARE_VERSION_MAJOR 2
2626#define ALICEVISION_SOFTWARE_VERSION_MINOR 0
2727
2828using namespace aliceVision ;
@@ -36,25 +36,39 @@ namespace fs = std::filesystem;
3636int aliceVision_main (int argc, char ** argv)
3737{
3838 // timer initialization
39-
4039 system::Timer timer;
4140
42- // command-line parameters
41+ // command-line required parameters
4342 std::string inputMeshPath;
44- std::string outputFilePath;
43+ std::string outputMeshPath;
44+
45+ // command-line optional parameters
46+ bool flipNormals = false ;
47+ bool copyTextures = true ;
4548
4649 // clang-format off
4750 po::options_description requiredParams (" Required parameters" );
4851 requiredParams.add_options ()
49- (" inputMesh" , po::value<std::string>(&inputMeshPath)->default_value (inputMeshPath),
50- " Mesh file path (*.obj, *.mesh, *.meshb, *.ply, *.off, *.stl)." )
51- (" output,o" , po::value<std::string>(&outputFilePath)->default_value (outputFilePath),
52- " Output file path for the new mesh file (*.obj, *.mesh, *.meshb, *.ply, *.off, *.stl)." );
52+ (" inputMesh" , po::value<std::string>(&inputMeshPath)->required (),
53+ " Mesh file path (*.obj, *.fbx, *.gltf, *.glb, *.stl, *.ply)." )
54+ (" output,o" , po::value<std::string>(&outputMeshPath)->required (),
55+ " Output file path (*.obj, *.fbx, *.gltf, *.glb, *.stl *.ply)." );
56+
57+ po::options_description optionalParams (" Optional parameters" );
58+ optionalParams.add_options ()
59+ (" flipNormals" , po::value<bool >(&flipNormals)->default_value (flipNormals),
60+ " Flip face normals. It can be needed as it depends on the vertices order in triangles and the "
61+ " convention changes from one software to another." )
62+ (" copyTextures" , po::value<bool >(©Textures)->default_value (copyTextures),
63+ " Copy input mesh texture files to the output mesh folder." );
5364 // clang-format on
5465
5566 CmdLine cmdline (" The program allows to convert a mesh to another mesh format.\n "
5667 " AliceVision convertMesh" );
68+
5769 cmdline.add (requiredParams);
70+ cmdline.add (optionalParams);
71+
5872 if (!cmdline.execute (argc, argv))
5973 {
6074 return EXIT_FAILURE;
@@ -68,15 +82,15 @@ int aliceVision_main(int argc, char** argv)
6882 }
6983
7084 // check output file path
71- if (outputFilePath .empty ())
85+ if (outputMeshPath .empty ())
7286 {
7387 ALICEVISION_LOG_ERROR (" Invalid output" );
7488 return EXIT_FAILURE;
7589 }
7690
7791 // ensure output folder exists
7892 {
79- const std::string outputFolderPart = fs::path (outputFilePath ).parent_path ().string ();
93+ const std::string outputFolderPart = fs::path (outputMeshPath ).parent_path ().string ();
8094
8195 if (!outputFolderPart.empty () && !utils::exists (outputFolderPart))
8296 {
@@ -89,26 +103,61 @@ int aliceVision_main(int argc, char** argv)
89103 }
90104
91105 // load input mesh
106+ ALICEVISION_LOG_INFO (" Loading input mesh." );
92107 mesh::Texturing texturing;
93- texturing.loadWithAtlas (inputMeshPath);
108+ texturing.loadWithMaterial (inputMeshPath, flipNormals );
94109 mesh::Mesh* inputMesh = texturing.mesh ;
95110
111+ // check if mesh is loaded
96112 if (!inputMesh)
97113 {
98114 ALICEVISION_LOG_ERROR (" Unable to read input mesh from the file: " << inputMeshPath);
99115 return EXIT_FAILURE;
100116 }
101117
118+ // check if mesh is not empty
102119 if (inputMesh->pts .empty () || inputMesh->tris .empty ())
103120 {
104- ALICEVISION_LOG_ERROR (" Error: empty mesh from the file " << inputMeshPath);
121+ ALICEVISION_LOG_ERROR (" Empty input mesh from the file: " << inputMeshPath);
105122 ALICEVISION_LOG_ERROR (" Input mesh: " << inputMesh->pts .size () << " vertices and " << inputMesh->tris .size () << " facets." );
106123 return EXIT_FAILURE;
107124 }
108125
126+ // copy textures files from the input mesh folder to the output mesh folder
127+ if (copyTextures)
128+ {
129+ const std::string outTypeStr = std::filesystem::path (outputMeshPath).extension ().string ().substr (1 );
130+ const mesh::EFileType outType = mesh::EFileType_stringToEnum (outTypeStr);
131+
132+ // only copy textures for mesh formats that support textures
133+ if (outType == mesh::EFileType::OBJ ||
134+ outType == mesh::EFileType::FBX ||
135+ outType == mesh::EFileType::GLTF ||
136+ outType == mesh::EFileType::GLB)
137+ {
138+ std::vector<std::string> texturePaths;
139+ texturing.material .getAllTexturePaths (texturePaths);
140+
141+ for (const auto & texturePath : texturePaths)
142+ {
143+ ALICEVISION_LOG_DEBUG (" Copying texture file: " << texturePath);
144+
145+ const fs::path srcPath = fs::path (inputMeshPath).parent_path () / texturePath;
146+ const fs::path dstPath = fs::path (outputMeshPath).parent_path () / texturePath;
147+
148+ fs::copy (srcPath, dstPath);
149+ }
150+ }
151+ }
152+
109153 // save output mesh
110- ALICEVISION_LOG_INFO (" Convert mesh." );
111- inputMesh->save (outputFilePath);
154+ ALICEVISION_LOG_INFO (" Saving output mesh." );
155+ {
156+ const auto outPath = std::filesystem::path (outputMeshPath);
157+ const mesh::EFileType outFileType = mesh::EFileType_stringToEnum (outPath.extension ().string ().substr (1 ));
158+
159+ texturing.saveAs (outPath.parent_path ().string (), outPath.stem ().string (), outFileType);
160+ }
112161
113162 ALICEVISION_LOG_INFO (" Task done in (s): " + std::to_string (timer.elapsed ()));
114163
0 commit comments