diff --git a/modules/odm_25dmeshing/CMakeLists.txt b/modules/odm_25dmeshing/CMakeLists.txt index 9447e90c..4c19bbbe 100644 --- a/modules/odm_25dmeshing/CMakeLists.txt +++ b/modules/odm_25dmeshing/CMakeLists.txt @@ -22,6 +22,13 @@ if ( CGAL_FOUND ) include( ${CGAL_USE_FILE} ) + find_package( TBB ) + if( TBB_FOUND ) + include(${TBB_USE_FILE}) + else() + message(WARNING "TBB not found, parallel processing will be disabled.") + endif() + # Add compiler options. add_definitions(-Wall -Wextra -std=c++11) @@ -31,7 +38,7 @@ if ( CGAL_FOUND ) # Add exectuteable add_executable(${PROJECT_NAME} ${SRC_LIST}) - target_link_libraries(odm_25dmeshing ${CGAL_LIBRARIES}) + target_link_libraries(odm_25dmeshing ${CGAL_LIBRARIES} ${TBB_LIBRARIES}) else() message(FATAL_ERROR "This program requires the CGAL library, and will not be compiled.") diff --git a/modules/odm_25dmeshing/src/Odm25dMeshing.cpp b/modules/odm_25dmeshing/src/Odm25dMeshing.cpp index 197a6a6c..33fead8e 100644 --- a/modules/odm_25dmeshing/src/Odm25dMeshing.cpp +++ b/modules/odm_25dmeshing/src/Odm25dMeshing.cpp @@ -24,16 +24,13 @@ int Odm25dMeshing::run(int argc, char **argv) { } try { + parseArguments(argc, argv); loadPointCloud(); buildMesh(); - log << "Done!" << "\n"; - - // TODO - } catch (const Odm25dMeshingException& e) { log.setIsPrintingInCout(true); log << e.what() << "\n"; @@ -61,6 +58,7 @@ void Odm25dMeshing::parseArguments(int argc, char **argv) { if (argument == "-help") { printHelp(); + exit(0); } else if (argument == "-verbose") { log.setIsPrintingInCout(true); } else if (argument == "-maxVertexCount" && argIndex < argc) { @@ -149,11 +147,14 @@ void Odm25dMeshing::loadPointCloud(){ "Error when reading points and normals from:\n" + inputFile + "\n"); } + flipFaces = interpreter.flip_faces(); + log << "Successfully loaded " << points.size() << " points from file\n"; } void Odm25dMeshing::buildMesh(){ size_t pointCountBeforeOutRemoval = points.size(); + if (outliersRemovalPercentage > 0) log << "Removing outliers\n"; @@ -232,9 +233,15 @@ void Odm25dMeshing::buildMesh(){ } for (DT::Face_iterator face = dt.faces_begin(); face != dt.faces_end(); ++face) { - vertexIndicies.push_back(face->vertex(0)->info()); - vertexIndicies.push_back(face->vertex(1)->info()); - vertexIndicies.push_back(face->vertex(2)->info()); + if (flipFaces){ + vertexIndicies.push_back(face->vertex(2)->info()); + vertexIndicies.push_back(face->vertex(1)->info()); + vertexIndicies.push_back(face->vertex(0)->info()); + }else{ + vertexIndicies.push_back(face->vertex(0)->info()); + vertexIndicies.push_back(face->vertex(1)->info()); + vertexIndicies.push_back(face->vertex(2)->info()); + } } log << "Saving mesh to file.\n"; @@ -245,7 +252,7 @@ void Odm25dMeshing::buildMesh(){ tinyply::PlyFile plyFile; plyFile.add_properties_to_element("vertex", {"x", "y", "z"}, vertices); - plyFile.add_properties_to_element("face", { "vertex_index" }, vertexIndicies, 3, tinyply::PlyProperty::Type::INT8); + plyFile.add_properties_to_element("face", { "vertex_index" }, vertexIndicies, 3, tinyply::PlyProperty::Type::UINT8); plyFile.write(outputStream, false); fb.close(); diff --git a/modules/odm_25dmeshing/src/Odm25dMeshing.hpp b/modules/odm_25dmeshing/src/Odm25dMeshing.hpp index 9c349cc1..e3384c8f 100644 --- a/modules/odm_25dmeshing/src/Odm25dMeshing.hpp +++ b/modules/odm_25dmeshing/src/Odm25dMeshing.hpp @@ -65,6 +65,7 @@ private: double outliersRemovalPercentage = 2; unsigned int wlopIterations = 35; std::vector points; + bool flipFaces = false; }; class Odm25dMeshingException: public std::exception { diff --git a/modules/odm_25dmeshing/src/PlyInterpreter.cpp b/modules/odm_25dmeshing/src/PlyInterpreter.cpp index 42f54bbc..888360f7 100644 --- a/modules/odm_25dmeshing/src/PlyInterpreter.cpp +++ b/modules/odm_25dmeshing/src/PlyInterpreter.cpp @@ -25,5 +25,11 @@ void PlyInterpreter::process_line(CGAL::Ply_reader& reader) { Point3 p(x, y, z); Vector3 n(nx, ny, nz); + zNormalsDirectionCount += nz >= 0 ? 1 : -1; + points.push_back(std::make_pair(p, n)); } + +bool PlyInterpreter::flip_faces(){ + return zNormalsDirectionCount < 0; +} diff --git a/modules/odm_25dmeshing/src/PlyInterpreter.hpp b/modules/odm_25dmeshing/src/PlyInterpreter.hpp index b2270756..79716fcc 100644 --- a/modules/odm_25dmeshing/src/PlyInterpreter.hpp +++ b/modules/odm_25dmeshing/src/PlyInterpreter.hpp @@ -19,11 +19,13 @@ typedef std::pair Pwn; class PlyInterpreter { std::vector& points; + int zNormalsDirectionCount; public: PlyInterpreter (std::vector& points) - : points (points) + : points (points), zNormalsDirectionCount(0) { } bool is_applicable (CGAL::Ply_reader& reader); void process_line (CGAL::Ply_reader& reader); + bool flip_faces(); }; diff --git a/opendm/config.py b/opendm/config.py index 05384e18..2bddb640 100644 --- a/opendm/config.py +++ b/opendm/config.py @@ -252,6 +252,16 @@ def config(): 'times slightly but helps reduce memory usage. ' 'Default: %(default)s')) + parser.add_argument('--25d-mesh-size', + metavar='', + default=50000, + type=int, + help=('The maximum vertex count of the 2.5D output mesh ' + 'Smaller values produce smoother orthophotos but ' + 'could introduce distortion ' + 'Applies to 2.5D mesh only. ' + 'Default: %(default)s')) + parser.add_argument('--mesh-remove-outliers', metavar='', default=2, diff --git a/opendm/tasks.py b/opendm/tasks.py index 339b9a17..0305049c 100644 --- a/opendm/tasks.py +++ b/opendm/tasks.py @@ -13,7 +13,6 @@ tasks_dict = {'1': 'resize', '3': 'cmvs', '4': 'pmvs', '5': 'odm_meshing', -# '6': 'odm_texturing', '6': 'mvs_texturing', '7': 'odm_georeferencing', '8': 'odm_orthophoto', diff --git a/scripts/odm_app.py b/scripts/odm_app.py index 30c2d6cb..fabe2463 100644 --- a/scripts/odm_app.py +++ b/scripts/odm_app.py @@ -13,7 +13,6 @@ from odm_slam import ODMSlamCell from pmvs import ODMPmvsCell from cmvs import ODMCmvsCell from odm_meshing import ODMeshingCell -#from odm_texturing import ODMTexturingCell from mvstex import ODMMvsTexCell from odm_georeferencing import ODMGeoreferencingCell from odm_orthophoto import ODMOrthoPhotoCell @@ -59,6 +58,7 @@ class ODMApp(ecto.BlackBox): oct_tree=p.args.mesh_octree_depth, samples=p.args.mesh_samples, solver=p.args.mesh_solver_divide, + max_vertex_25d=getattr(p.args, '25d_mesh_size'), remove_outliers=p.args.mesh_remove_outliers, wlop_iterations=p.args.mesh_wlop_iterations, verbose=p.args.verbose), diff --git a/scripts/odm_meshing.py b/scripts/odm_meshing.py index fa4346c0..cf67622d 100644 --- a/scripts/odm_meshing.py +++ b/scripts/odm_meshing.py @@ -20,6 +20,7 @@ class ODMeshingCell(ecto.Cell): 'Increasing this value increases computation ' 'times slightly but helps reduce memory usage.', 9) + params.declare("max_vertex_25d", 'The maximum vertex count of the 2.5D output mesh.', 50000) params.declare("remove_outliers", 'Percentage of outliers to remove from the point set. Set to 0 to disable. ' 'Applies to 2.5D mesh only.', 2) @@ -96,7 +97,7 @@ class ODMeshingCell(ecto.Cell): 'infile': infile, 'log': tree.odm_25dmeshing_log, 'verbose': verbose, - 'max_vertex': self.params.max_vertex, + 'max_vertex': self.params.max_vertex_25d, 'remove_outliers': self.params.remove_outliers, 'wlop_iterations': self.params.wlop_iterations }