Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 6 additions & 16 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Install dependencies (Ubuntu)
if: runner.os == 'Linux'
Expand Down Expand Up @@ -68,34 +68,26 @@ jobs:
if: runner.os != 'Windows'
run: |
mkdir -p artifacts
find build -name MeshSDFilter -type f -exec cp {} artifacts/ \;
find build -name MeshDenoiser -type f -exec cp {} artifacts/ \;
cp MeshDenoiserDefaults.txt artifacts/
cp README.md artifacts/
chmod +x artifacts/MeshSDFilter
chmod +x artifacts/MeshDenoiser

# Bundle OpenMesh libraries and fix rpath
if [ "$RUNNER_OS" == "macOS" ]; then
mkdir -p artifacts/lib
find build -name "libOpenMesh*.dylib" -exec cp {} artifacts/lib/ \;

# Fix rpath for both executables
for exe in artifacts/MeshSDFilter artifacts/MeshDenoiser; do
for exe in artifacts/MeshDenoiser; do
if [ -f "$exe" ]; then
# Get list of OpenMesh libraries this executable depends on
otool -L "$exe" | grep libOpenMesh | awk '{print $1}' | while read lib; do
libname=$(basename "$lib")
# Change the rpath to look in the lib directory next to the executable
install_name_tool -change "$lib" "@executable_path/lib/$libname" "$exe"
done

# Ad-hoc code sign to avoid some security warnings
codesign --force --deep --sign - "$exe"
fi
done

# Also sign the libraries
for lib in artifacts/lib/*.dylib; do
if [ -f "$lib" ]; then
codesign --force --sign - "$lib"
Expand All @@ -105,8 +97,7 @@ jobs:
mkdir -p artifacts/lib
find build -name "libOpenMesh*.so*" -exec cp {} artifacts/lib/ \;

# Set rpath for both executables to look in lib directory
for exe in artifacts/MeshSDFilter artifacts/MeshDenoiser; do
for exe in artifacts/MeshDenoiser; do
if [ -f "$exe" ]; then
patchelf --set-rpath '$ORIGIN/lib' "$exe" || true
fi
Expand All @@ -117,13 +108,12 @@ jobs:
if: runner.os == 'Windows'
run: |
mkdir artifacts
Get-ChildItem -Path build -Recurse -Filter MeshSDFilter.exe | ForEach-Object { Copy-Item $_.FullName -Destination artifacts\ }
Get-ChildItem -Path build -Recurse -Filter MeshDenoiser.exe | ForEach-Object { Copy-Item $_.FullName -Destination artifacts\ }
copy MeshDenoiserDefaults.txt artifacts\
copy README.md artifacts\

- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ${{ matrix.artifact_name }}
path: artifacts/
Expand All @@ -143,14 +133,14 @@ jobs:

- name: Upload to release (Linux/macOS)
if: github.event_name == 'release' && runner.os != 'Windows'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
files: ${{ matrix.artifact_name }}.tar.gz
token: ${{ secrets.GITHUB_TOKEN }}

- name: Upload to release (Windows)
if: github.event_name == 'release' && runner.os == 'Windows'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
files: ${{ matrix.artifact_name }}.zip
token: ${{ secrets.GITHUB_TOKEN }}
103 changes: 88 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,37 +1,110 @@
cmake_minimum_required(VERSION 3.18)
project(meshsdfilter-builder LANGUAGES CXX)
project(MeshDenoiser LANGUAGES CXX)

# Set C++17 standard for filesystem support
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include(FetchContent)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

# Option: enable/disable OpenMP (MeshSDFilter uses it if available)
# Compiler flags (applied per-target below, not globally, to avoid breaking fetched deps)

# OpenMP (optional)
option(ENABLE_OPENMP "Enable OpenMP if available" ON)
if(ENABLE_OPENMP)
find_package(OpenMP QUIET)
endif()

# Eigen (required, header-only)
find_package(Eigen3 3.3 QUIET)
if(NOT TARGET Eigen3::Eigen)
# Retry without version constraint
find_package(Eigen3 QUIET)
endif()
if(NOT TARGET Eigen3::Eigen)
# Try user-provided include dir
if(DEFINED EIGEN3_INCLUDE_DIR AND EXISTS "${EIGEN3_INCLUDE_DIR}")
set(_eigen_dir "${EIGEN3_INCLUDE_DIR}")
else()
# Probe common system locations
find_path(_eigen_dir NAMES Eigen/Dense
PATHS /usr/include/eigen3 /usr/local/include/eigen3 /opt/homebrew/include/eigen3
NO_DEFAULT_PATH)
if(NOT _eigen_dir)
find_path(_eigen_dir NAMES Eigen/Dense)
endif()
endif()
if(_eigen_dir)
message(STATUS "Using Eigen from ${_eigen_dir}")
add_library(Eigen3::Eigen INTERFACE IMPORTED)
set_target_properties(Eigen3::Eigen PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_eigen_dir}")
else()
message(FATAL_ERROR "Eigen3 not found. Install via system package manager or set -DEIGEN3_INCLUDE_DIR=...")
endif()
endif()

# --- Fetch the AliceVision source at the requested commit ---
set(ALICEVISION_COMMIT "14b0b8f8b3026765d165dfc3f219ed8c53635f52")
include(FetchMeshSDFilter)
# Fetch OpenMesh, tinygltf, tinyusdz, and optionally detect CHOLMOD
include(FetchDependencies)

# On MSVC, use static runtime if desired (optional)
# On MSVC, optionally link static runtime
option(USE_STATIC_MSVC_RUNTIME "Link static MSVC runtime (/MT)" OFF)
if(MSVC AND USE_STATIC_MSVC_RUNTIME)
foreach(flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_MINSIZEREL)
CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_MINSIZEREL)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif()
endforeach()
endif()

if(ENABLE_OPENMP)
find_package(OpenMP)
if(OpenMP_CXX_FOUND)
message(STATUS "OpenMP found: enabling for targets built in MeshSDFilter")
# ---------- MeshDenoiser executable ----------
add_executable(MeshDenoiser
src/EigenTypes.h
src/MeshTypes.h
src/SDFilter.h
src/MeshNormalFilter.h
src/MeshNormalDenoising.h
src/AppMetrics.h
src/MeshDenoiser.cpp
)

# Per-target compiler flags
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU|AppleClang")
target_compile_options(MeshDenoiser PRIVATE -Wall -Wextra)
target_compile_options(MeshDenoiser PRIVATE "$<$<CONFIG:Release>:-march=native;-mtune=native>")
elseif(MSVC)
target_compile_definitions(MeshDenoiser PRIVATE USE_MSVC _USE_MATH_DEFINES)
endif()

target_include_directories(MeshDenoiser PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${tinygltf_SOURCE_DIR}"
"${tinyusdz_SOURCE_DIR}/src"
)

target_link_libraries(MeshDenoiser PRIVATE
Eigen3::Eigen
OpenMeshCore
tinyusdz_static
)

# OpenMP
if(OpenMP_CXX_FOUND)
target_compile_definitions(MeshDenoiser PRIVATE USE_OPENMP)
target_link_libraries(MeshDenoiser PRIVATE OpenMP::OpenMP_CXX)
endif()

# CHOLMOD
if(SDFILTER_ENABLE_CHOLMOD)
target_compile_definitions(MeshDenoiser PRIVATE USE_CHOLMOD)
if(SDFILTER_CHOLMOD_INCLUDE_DIRS)
target_include_directories(MeshDenoiser PRIVATE ${SDFILTER_CHOLMOD_INCLUDE_DIRS})
endif()
if(SDFILTER_CHOLMOD_LINK_LIBS)
target_link_libraries(MeshDenoiser PRIVATE ${SDFILTER_CHOLMOD_LINK_LIBS})
endif()
endif()
25 changes: 24 additions & 1 deletion MeshDenoiserDefaults.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
# Default options for MeshDenoiser tuned for detail-preserving cleanup.
#
# Reduce OuterIterations or Lambda for even lighter touch; raise them (or Eta) if you need more smoothing.
# Reduce OuterIterations or Lambda for even lighter touch;
# raise them (or Eta) if you need more smoothing.

## Regularization weight. Higher = more smoothing per iteration.
Lambda 0.15

## Spatial Gaussian sigma, scaled by average face-centroid distance.
Eta 2.2

## Guidance normal difference weight.
Mu 0.2

## Signal normal difference weight.
Nu 0.25

## Closeness weight for mesh update (vertex position fidelity).
MeshUpdateClosenessWeight 0.001

## Max iterations for mesh vertex update per outer iteration.
MeshUpdateIterations 20

## Early-stop threshold for mesh update RMS displacement (<=0 disables).
MeshUpdateDisplacementEps 0.1

## Number of full filtering passes.
OuterIterations 1

## Force single-threaded execution for reproducible output (0/1).
DeterministicMode 0

## Linear solver backend: 0=CG, 1=Eigen LDLT, 2=CHOLMOD (falls back to 1 if unavailable).
LinearSolverType 1
Loading
Loading