#!/bin/sh

# colmap_openmvs_pipeline.sh
# 2025-11-24
# by Gernot Walzl

# This script runs the COLMAP and OpenMVS pipeline.
# COLMAP generates a sparse point cloud. OpenMVS reconstructs a textured mesh.
# Based on:
# COLMAP usage: https://colmap.github.io/cli.html#example
# OpenMVS usage: https://github.com/cdcseacave/openMVS/wiki/Usage

export PATH="/usr/bin/OpenMVS:$PATH"

set -e

colmap_sparse () {
  # Perform feature extraction
  colmap feature_extractor \
    --database_path database.db \
    --image_path images

  # Perform feature matching
  colmap exhaustive_matcher \
    --database_path database.db

  # Sparse 3D reconstruction
  mkdir sparse
  colmap mapper \
    --database_path database.db \
    --image_path images \
    --output_path sparse

  # Find largest sub-model
  MODEL=$(du sparse/* | sort -nr | head -n1 | awk '{print $2}')

  # Undistort images and export them for dense reconstruction
  mkdir dense
  colmap image_undistorter \
    --image_path images \
    --input_path "$MODEL" \
    --output_path dense \
    --output_type COLMAP
}

openmvs_texture () {
  # Import from COLMAP
  InterfaceCOLMAP -i dense -o scene.mvs --image-folder dense/images

  # Dense Point Cloud Reconstruction
  DensifyPointCloud scene.mvs

  # Mesh Reconstruction
  # To halve the number of faces: --decimate 0.5
  # To smooth the mesh with 5 iterations: --smooth 5
  ReconstructMesh scene_dense.mvs -p scene_dense.ply --smooth 5

  # Mesh Refinement (optional)
  # It will create a more regular mesh with similarly sized faces.
  # To specify the size of the faces: --max-face-area 256
  RefineMesh scene_dense.mvs -m scene_dense_mesh.ply

  # Mesh Texturing
  # To halve the resolution of the texture: --resolution-level 1
  # Set the color of unseen faces to white: --empty-color 16777215 # = 0xFFFFFF
  TextureMesh scene_dense.mvs -m scene_dense_refine.ply --empty-color 16777215
}

PROJECT=$1
if [ -z "$PROJECT" ]; then
  echo "ERROR: Project directory missing."
  echo "Usage: $0 PROJECT"
  exit 1
fi
if [ ! -d "$PROJECT/images" ]; then
  echo "ERROR: Project '$PROJECT' does not contain 'images'."
  exit 1
fi
cd "$PROJECT" || exit 1
if [ ! -d 'dense' ]; then
  colmap_sparse
fi
openmvs_texture