Skip to content

Commit 01dc679

Browse files
Move build dependencies to mmsolverlibs
This moves the cminpack, Eigen, glog, ceres and OpenMVG to build with mmsolverlibs - not mmsolver. This allows us to keep Maya depending only on the things that it really uses and tries to put as much non-Maya specific logic into mmsolverlibs. This has involved adding wrappers around cminpack and OpenMVG. Ultimately, this should (in theory) allow us to reimplement these functions as we wish without requiring to actually depend on cminpack or OpenMVG.
1 parent 32d3dda commit 01dc679

24 files changed

Lines changed: 972 additions & 148 deletions

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ option(MMSOLVER_BUILD_ICONS "Build and install the icons?" ON)
9292
option(MMSOLVER_BUILD_CONFIG "Build and install the config files?" ON)
9393
option(MMSOLVER_BUILD_TESTS "Build the test files?" OFF)
9494
option(MMSOLVER_DOWNLOAD_DEPENDENCIES "Automatically download and build missing dependencies?" ON)
95-
option(MMSOLVER_USE_GLOG "Use Google glog (for Ceres Solver)? Otherwise, we will use the Ceres embedded miniglog." OFF)
95+
option(MMSOLVER_DEBUG "Enable mmSolver debug mode; prints details and enables debug assertions." OFF)
9696

9797

9898
# Maya SDK
@@ -130,8 +130,9 @@ add_subdirectory(share)
130130

131131
if (MMSOLVER_BUILD_PLUGIN)
132132
# Finds and builds external (third-party) dependencies.
133+
#
134+
# NOTE: Dependencies are handled in mmsolverlibs sub-project.
133135
include(FindAndBuildExternalPackages)
134-
add_subdirectory(lib/thirdparty)
135136

136137
add_subdirectory(src)
137138
endif ()

lib/CMakeLists.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ set(MMSOLVERLIBS_LIB_DIR "/path/to/rust/build/directory/" CACHE PATH
6161

6262
# Add custom modules to the module path
6363
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
64-
${CMAKE_CURRENT_SOURCE_DIR}/../share/cmake/modules)
64+
${CMAKE_CURRENT_SOURCE_DIR}/../share/cmake/modules
65+
${CMAKE_CURRENT_SOURCE_DIR}/share/cmake/modules)
6566

6667
set(cpp_lib_name "mmsolverlibs_cpp")
6768
set(rust_lib_name "mmsolverlibs_rust")
@@ -92,10 +93,17 @@ set(rust_depend_on_libraries "NOT-FOUND")
9293
mm_rust_get_depend_on_libraries(rust_depend_on_libraries)
9394
message(STATUS "Rust Depend On Libraries: ${rust_depend_on_libraries}")
9495

96+
# Build options for mmsolverlibs dependencies are inherited from
97+
# parent scope.
98+
99+
# Finds and builds external (third-party) dependencies for
100+
# mmsolverlibs.
101+
include(FindAndBuildMmsolverDependencies)
102+
95103
# Finds and builds external (third-party) LDPK dependencies.
96-
option(MMSOLVER_DOWNLOAD_DEPENDENCIES "Automatically download and build missing dependencies?" ON)
97104
include(FindAndBuildLdpkPackages)
98105

106+
add_subdirectory(thirdparty)
99107
add_subdirectory(mmsolverlibs/src)
100108

101109
option(MMSOLVERLIBS_BUILD_TESTS "Do you want to build the test files for mmsolverlibs?" OFF)

lib/Config.cmake.in

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,49 @@
11
@PACKAGE_INIT@
22

3+
# Find dependencies needed by mmsolverlibs_cpp targets only if they
4+
# don't already exist. This prevents conflicts when the main build
5+
# has already created these targets and avoids redundant find operations.
6+
7+
# Only include CMakeFindDependencyMacro if we actually need to find dependencies
8+
set(_need_find_dependencies FALSE)
9+
10+
if(NOT TARGET Eigen3::Eigen AND NOT TARGET Eigen3)
11+
set(_need_find_dependencies TRUE)
12+
endif()
13+
14+
if(NOT TARGET cminpack::cminpack AND NOT TARGET cminpack)
15+
set(_need_find_dependencies TRUE)
16+
endif()
17+
18+
if(NOT TARGET Ceres::ceres AND NOT TARGET ceres)
19+
set(_need_find_dependencies TRUE)
20+
endif()
21+
22+
if(NOT TARGET glog::glog AND NOT TARGET glog)
23+
set(_need_find_dependencies TRUE)
24+
endif()
25+
26+
# Only include the find macro and run find operations if needed
27+
if(_need_find_dependencies)
28+
include(CMakeFindDependencyMacro)
29+
30+
if(NOT TARGET Eigen3::Eigen AND NOT TARGET Eigen3)
31+
find_dependency(Eigen3 3.4.0)
32+
endif()
33+
34+
if(NOT TARGET cminpack::cminpack AND NOT TARGET cminpack)
35+
find_dependency(cminpack 1.3.8)
36+
endif()
37+
38+
if(NOT TARGET Ceres::ceres AND NOT TARGET ceres)
39+
find_dependency(Ceres 1.14.0)
40+
endif()
41+
42+
if(NOT TARGET glog::glog AND NOT TARGET glog)
43+
find_dependency(glog 0.7.1)
44+
endif()
45+
endif()
46+
47+
unset(_need_find_dependencies)
48+
349
include("${CMAKE_CURRENT_LIST_DIR}/mmsolverlibs_cppTargets.cmake")
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2025 David Cattermole.
3+
*
4+
* This file is part of mmSolver.
5+
*
6+
* mmSolver is free software: you can redistribute it and/or modify it
7+
* under the terms of the GNU Lesser General Public License as
8+
* published by the Free Software Foundation, either version 3 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* mmSolver is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
18+
* ====================================================================
19+
*
20+
* C++ wrapper for cminpack functionality used by mmSolver.
21+
*/
22+
23+
#ifndef MMSOLVERLIBS_CMINPACK_WRAPPER_H
24+
#define MMSOLVERLIBS_CMINPACK_WRAPPER_H
25+
26+
namespace mmsolverlibs {
27+
namespace cminpack {
28+
29+
// Forward declarations of cminpack function types.
30+
typedef int (*lmdif_func_type)(void *p, int m, int n, const double *x,
31+
double *fvec, int iflag);
32+
typedef int (*lmder_func_type)(void *p, int m, int n, const double *x,
33+
double *fvec, double *fjac, int ldfjac,
34+
int iflag);
35+
36+
// Wrapper functions.
37+
int lmdif(lmdif_func_type fcn, void *p, int m, int n, double *x, double *fvec,
38+
double ftol, double xtol, double gtol, int maxfev, double epsfcn,
39+
double *diag, int mode, double factor, int nprint, int *nfev,
40+
double *fjac, int ldfjac, int *ipvt, double *qtf, double *wa1,
41+
double *wa2, double *wa3, double *wa4);
42+
43+
int lmder(lmder_func_type fcn, void *p, int m, int n, double *x, double *fvec,
44+
double *fjac, int ldfjac, double ftol, double xtol, double gtol,
45+
int maxfev, double *diag, int mode, double factor, int nprint,
46+
int *nfev, int *njev, int *ipvt, double *qtf, double *wa1,
47+
double *wa2, double *wa3, double *wa4);
48+
49+
double enorm(int n, const double *x);
50+
51+
} // namespace cminpack
52+
} // namespace mmsolverlibs
53+
54+
#endif // MMSOLVERLIBS_CMINPACK_WRAPPER_H
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright (C) 2025 David Cattermole.
3+
*
4+
* This file is part of mmSolver.
5+
*
6+
* mmSolver is free software: you can redistribute it and/or modify it
7+
* under the terms of the GNU Lesser General Public License as
8+
* published by the Free Software Foundation, either version 3 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* mmSolver is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
18+
* ====================================================================
19+
*
20+
* OpenMVG API wrapper for OpenMVG functionality.
21+
* This provides a clean C API to decouple Maya code from OpenMVG.
22+
*/
23+
24+
#ifndef MMSOLVERLIBS_OPENMVG_WRAPPER_H
25+
#define MMSOLVERLIBS_OPENMVG_WRAPPER_H
26+
27+
#include <cstddef>
28+
#include <cstdint>
29+
30+
namespace mmsolverlibs {
31+
namespace openmvg {
32+
33+
// Forward declarations for opaque types
34+
struct HomographyMatrix;
35+
struct RelativePoseInfo;
36+
struct CameraIntrinsics;
37+
struct Pose3;
38+
39+
// Point structures
40+
struct Point2d {
41+
double x;
42+
double y;
43+
};
44+
45+
struct Point3d {
46+
double x;
47+
double y;
48+
double z;
49+
};
50+
51+
// Homography functions
52+
HomographyMatrix* homography_matrix_new();
53+
void homography_matrix_free(HomographyMatrix* matrix);
54+
55+
bool compute_homography(std::int32_t image_width_a, std::int32_t image_width_b,
56+
std::int32_t image_height_a,
57+
std::int32_t image_height_b,
58+
const Point2d* marker_coords_a,
59+
std::size_t num_markers_a,
60+
const Point2d* marker_coords_b,
61+
std::size_t num_markers_b,
62+
HomographyMatrix* homography_matrix);
63+
64+
bool robust_homography(
65+
const double* x1_data, std::size_t x1_rows, std::size_t x1_cols,
66+
const double* x2_data, std::size_t x2_rows, std::size_t x2_cols,
67+
HomographyMatrix* homography_matrix, std::uint32_t image_width_1,
68+
std::uint32_t image_height_1, std::uint32_t image_width_2,
69+
std::uint32_t image_height_2, std::uint32_t max_iteration_count);
70+
71+
// Camera relative pose functions
72+
RelativePoseInfo* relative_pose_info_new();
73+
void relative_pose_info_free(RelativePoseInfo* info);
74+
75+
CameraIntrinsics* camera_intrinsics_new_pinhole(std::uint32_t width,
76+
std::uint32_t height,
77+
double focal_length, double ppx,
78+
double ppy);
79+
void camera_intrinsics_free(CameraIntrinsics* intrinsics);
80+
81+
bool robust_relative_pose(
82+
const CameraIntrinsics* intrinsics1, const CameraIntrinsics* intrinsics2,
83+
const double* x1_data, std::size_t x1_rows, std::size_t x1_cols,
84+
const double* x2_data, std::size_t x2_rows, std::size_t x2_cols,
85+
RelativePoseInfo* relative_pose_info, std::uint32_t image_width_1,
86+
std::uint32_t image_height_1, std::uint32_t image_width_2,
87+
std::uint32_t image_height_2, std::uint32_t max_iteration_count);
88+
89+
bool compute_relative_pose(
90+
std::int32_t image_width_a, std::int32_t image_width_b,
91+
std::int32_t image_height_a, std::int32_t image_height_b,
92+
double focal_length_pix_a, double focal_length_pix_b, double ppx_pix_a,
93+
double ppx_pix_b, double ppy_pix_a, double ppy_pix_b,
94+
const Point2d* marker_coords_a, std::size_t num_markers_a,
95+
const Point2d* marker_coords_b, std::size_t num_markers_b,
96+
RelativePoseInfo* relative_pose_info, Point3d* triangulated_points,
97+
std::size_t* num_triangulated_points);
98+
99+
// Camera from known points (PnP) functions
100+
Pose3* pose3_new();
101+
void pose3_free(Pose3* pose);
102+
103+
bool solve_pnp_p3p_nordberg(const Point3d* world_points,
104+
std::size_t num_world_points,
105+
const Point2d* image_points,
106+
std::size_t num_image_points,
107+
const CameraIntrinsics* intrinsics, Pose3* pose,
108+
std::uint32_t max_iteration_count);
109+
110+
// Utility functions for extracting data from opaque types
111+
bool homography_matrix_get_data(const HomographyMatrix* matrix, double* data);
112+
bool relative_pose_info_get_rotation(const RelativePoseInfo* info,
113+
double* rotation_matrix);
114+
bool relative_pose_info_get_translation(const RelativePoseInfo* info,
115+
double* translation_vector);
116+
bool pose3_get_rotation(const Pose3* pose, double* rotation_matrix);
117+
bool pose3_get_translation(const Pose3* pose, double* translation_vector);
118+
119+
} // namespace openmvg
120+
} // namespace mmsolverlibs
121+
122+
#endif // MMSOLVERLIBS_OPENMVG_WRAPPER_H

lib/mmsolverlibs/src/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ configure_file(
4444
# C++ Source Code
4545
set(lib_source_files
4646
${main_build_constant_output_file}
47+
${CMAKE_CURRENT_SOURCE_DIR}/cminpack_wrapper.cpp
48+
${CMAKE_CURRENT_SOURCE_DIR}/openmvg_wrapper.cpp
4749

4850
${mmcolorio_source_dir}/lib.cpp
4951

@@ -118,6 +120,16 @@ target_link_libraries(${cpp_lib_name}
118120
# ldpk to be installed so we have the 'ldpk_INCLUDE_DIR' variable.
119121
add_dependencies(${cpp_lib_name} ldpk::ldpk)
120122

123+
# Link cminpack dependency
124+
target_link_libraries(${cpp_lib_name}
125+
PUBLIC cminpack::cminpack
126+
)
127+
128+
# Link OpenMVG dependency for SFM functions
129+
target_link_libraries(${cpp_lib_name}
130+
PUBLIC openMVG
131+
)
132+
121133
# MM Color IO dependencies
122134
include(MMColorIOUtils)
123135
mmcolorio_find_packages()
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (C) 2025 David Cattermole.
3+
*
4+
* This file is part of mmSolver.
5+
*
6+
* mmSolver is free software: you can redistribute it and/or modify it
7+
* under the terms of the GNU Lesser General Public License as
8+
* published by the Free Software Foundation, either version 3 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* mmSolver is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
18+
* ====================================================================
19+
*
20+
* C++ wrapper implementation for cminpack functionality.
21+
*/
22+
23+
#include "mmsolverlibs/cminpack_wrapper.h"
24+
25+
#include <cminpack.h>
26+
27+
namespace mmsolverlibs {
28+
namespace cminpack {
29+
30+
int lmdif(lmdif_func_type fcn, void *p, int m, int n, double *x, double *fvec,
31+
double ftol, double xtol, double gtol, int maxfev, double epsfcn,
32+
double *diag, int mode, double factor, int nprint, int *nfev,
33+
double *fjac, int ldfjac, int *ipvt, double *qtf, double *wa1,
34+
double *wa2, double *wa3, double *wa4) {
35+
// Call the actual cminpack library function directly to avoid
36+
// recursion.
37+
return ::lmdif(fcn, p, m, n, x, fvec, ftol, xtol, gtol, maxfev, epsfcn,
38+
diag, mode, factor, nprint, nfev, fjac, ldfjac, ipvt, qtf,
39+
wa1, wa2, wa3, wa4);
40+
}
41+
42+
int lmder(lmder_func_type fcn, void *p, int m, int n, double *x, double *fvec,
43+
double *fjac, int ldfjac, double ftol, double xtol, double gtol,
44+
int maxfev, double *diag, int mode, double factor, int nprint,
45+
int *nfev, int *njev, int *ipvt, double *qtf, double *wa1,
46+
double *wa2, double *wa3, double *wa4) {
47+
// Call the actual cminpack library function directly to avoid
48+
// recursion.
49+
return ::lmder(fcn, p, m, n, x, fvec, fjac, ldfjac, ftol, xtol, gtol,
50+
maxfev, diag, mode, factor, nprint, nfev, njev, ipvt, qtf,
51+
wa1, wa2, wa3, wa4);
52+
}
53+
54+
double enorm(int n, const double *x) {
55+
// Call the actual cminpack library function directly to avoid
56+
// recursion.
57+
return ::enorm(n, x);
58+
}
59+
60+
} // namespace cminpack
61+
} // namespace mmsolverlibs

0 commit comments

Comments
 (0)