Directional is a directional-field processing library used here as a standalone C++ package and as a Python extension module.
This fork now supports two build workflows:
- pure CMake for native C++ consumers
- Python packaging builds via
setup.pyandpip
The top-level project can build:
directional— shared C++ library_directional— Python extension moduledirectional_cli— optional native executable installed asdirectionaldirectional_cli_backend— shared C++ command implementation used by both CLIs
The Python console script and native executable intentionally expose the same commands and option parsing through the C++ CLI backend.
- CMake 3.21 or newer
- C++20-capable compiler
- Git submodules initialized, including Eigen
- Python only when building Python bindings or invoking
setup.py
Python 3.13 is verified in this repository. Install the build dependencies with:
python -m pip install setuptools wheel pybind11For PEP 517 builds, install any additional requirements declared by the project build configuration or disable build isolation when the active environment already contains them.
Eigen is required and included as a repository submodule.
git submodule update --init --recursiveGMP is optional and enables the preferred exact-arithmetic implementation.
- CMake option:
DIRECTIONAL_ENABLE_GMP - Default:
ON - MSVC builds can auto-install it when it is not already available
- Other platforms should provide GMP and GMPXX through the system or toolchain
When GMP cannot be found, CMake emits a warning and continues without GMP.
DirectionalReMesher supports three optional integration solver backends:
- Intel oneMKL PARDISO
- NVIDIA cuDSS
- SuiteSparse / UMFPACK
Only one backend is enabled in a build. If more than one is requested, both CMake and setup.py emit a warning and select the first available request in this fixed order:
PARDISO > CUDSS > SUITESPARSE
Relevant CMake options:
DIRECTIONAL_ENABLE_PARDISO=ON|OFF
DIRECTIONAL_ENABLE_CUDSS=ON|OFF
DIRECTIONAL_ENABLE_SUITESPARSE=ON|OFF
CUDSS_ROOT=<path>
CMake defaults are:
PARDISO=OFF
CUDSS=OFF
SUITESPARSE=ON
The current setup.py defaults request all three backends and therefore resolve to PARDISO unless overridden.
PARDISO uses Intel oneMKL and is the highest-priority backend. On supported MSVC builds, the dependency logic can install oneMKL automatically. Required runtime modules are copied beside the native library, native CLI, and Python extension during build and install.
cuDSS requires an NVIDIA cuDSS installation and the imported CMake target CUDSS::cudss. Set CUDSS_ROOT when automatic discovery is insufficient.
Example:
cmake -S . -B build\cudss `
-DDIRECTIONAL_ENABLE_PARDISO=OFF `
-DDIRECTIONAL_ENABLE_CUDSS=ON `
-DDIRECTIONAL_ENABLE_SUITESPARSE=OFF `
-DCUDSS_ROOT="C:\Program Files\NVIDIA cuDSS\v0.8"SuiteSparse is the default CMake backend. Supported MSVC builds can auto-install it when necessary. Other platforms should provide a usable SuiteSparse package or CMake configuration.
| Option | Default | Purpose |
|---|---|---|
BUILD_PYTHON |
OFF |
Build the Python extension |
DIRECTIONAL_BUILD_CLI |
OFF |
Build the native CLI executable |
DIRECTIONAL_ENABLE_GMP |
ON |
Enable GMP exact arithmetic |
DIRECTIONAL_ENABLE_SUITESPARSE |
ON |
Request SuiteSparse |
DIRECTIONAL_ENABLE_PARDISO |
OFF |
Request Intel oneMKL PARDISO |
DIRECTIONAL_ENABLE_CUDSS |
OFF |
Request NVIDIA cuDSS |
CUDSS_ROOT |
empty | cuDSS installation root |
CMAKE_INSTALL_PREFIX |
platform default | Installation destination |
cmake -S . -B build\standalone `
-DCMAKE_INSTALL_PREFIX="$PWD\build\standalone\install" `
-DBUILD_PYTHON=OFF `
-DDIRECTIONAL_BUILD_CLI=OFF `
-DDIRECTIONAL_ENABLE_GMP=ON `
-DDIRECTIONAL_ENABLE_PARDISO=OFF `
-DDIRECTIONAL_ENABLE_CUDSS=OFF `
-DDIRECTIONAL_ENABLE_SUITESPARSE=ON
cmake --build build\standalone --config Release --target directional
cmake --install build\standalone --config Releasecmake -S . -B build\pardiso `
-DCMAKE_INSTALL_PREFIX="$PWD\build\pardiso\install" `
-DBUILD_PYTHON=OFF `
-DDIRECTIONAL_ENABLE_PARDISO=ON `
-DDIRECTIONAL_ENABLE_CUDSS=OFF `
-DDIRECTIONAL_ENABLE_SUITESPARSE=OFF
cmake --build build\pardiso --config Release --target directional
cmake --install build\pardiso --config Releasecmake -S . -B build\native-cli `
-DCMAKE_INSTALL_PREFIX="$PWD\build\native-cli-release" `
-DBUILD_PYTHON=OFF `
-DDIRECTIONAL_BUILD_CLI=ON `
-DDIRECTIONAL_ENABLE_PARDISO=ON
cmake --build build\native-cli --config Release --target directional_cli
cmake --install build\native-cli --config ReleaseThe installed executable is normally:
<install-prefix>/bin/directional.exe
Run:
directional --help
directional infopython -m pip install pybind11
$pybind11Dir = python -m pybind11 --cmakedir
cmake -S . -B build\python `
-DCMAKE_INSTALL_PREFIX="$PWD\build\python\install" `
-DBUILD_PYTHON=ON `
-DDIRECTIONAL_BUILD_CLI=OFF `
-Dpybind11_DIR="$pybind11Dir" `
-DDIRECTIONAL_ENABLE_PARDISO=ON
cmake --build build\python --config Release --target _directional
cmake --install build\python --config ReleaseThe extension and Python package files are installed beneath:
build/python/install/directional/
find_package(Directional CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE Directional::directional)For a nonstandard installation prefix:
cmake -S . -B build `
-DCMAKE_PREFIX_PATH="D:\path\to\DirectionalReMesher\build\standalone\install"setup.py forwards build features to CMake and uses the same solver-selection priority.
--enable-gmp / --disable-gmp
--enable-suitesparse / --disable-suitesparse
--enable-pardiso / --disable-pardiso
--enable-cudss / --disable-cudss
--build-cli / --no-build-cli
python setup.py standaloneDefault paths:
build tree: build/standalone/
install tree: build/standalone/install/
Build the library and native CLI together:
python setup.py standalone --build-cliSelect a solver explicitly:
python setup.py standalone `
--enable-pardiso `
--disable-cudss `
--disable-suitesparse `
--build-cliBuild the extension:
python setup.py build_extBuild a wheel:
python setup.py bdist_wheelPass feature flags through build_ext when creating a wheel:
python setup.py build_ext `
--enable-pardiso `
--disable-cudss `
--disable-suitesparse `
bdist_wheelBuild and package the native executable with the wheel:
python setup.py build_ext --build-cli bdist_wheelWhen enabled, the installed native CLI and its runtime dependency closure are packaged beneath:
directional/bin/
The Python console script remains available as directional and forwards commands to the same C++ backend through the extension module.
The custom build backend accepts short and namespaced configuration keys.
| Short key | Namespaced key | Environment variable |
|---|---|---|
enable-gmp |
directional.enable-gmp |
DIRECTIONAL_ENABLE_GMP |
enable-suitesparse |
directional.enable-suitesparse |
DIRECTIONAL_ENABLE_SUITESPARSE |
enable-pardiso |
directional.enable-pardiso |
DIRECTIONAL_ENABLE_PARDISO |
enable-cudss |
directional.enable-cudss |
DIRECTIONAL_ENABLE_CUDSS |
build-cli |
directional.build-cli |
DIRECTIONAL_BUILD_CLI |
Boolean values accept:
1, 0, on, off, true, false, yes, no
python -m pip install . --no-build-isolationpython -m pip wheel . `
--no-deps `
--no-build-isolation `
-Cdirectional.enable-pardiso=true `
-Cdirectional.enable-cudss=false `
-Cdirectional.enable-suitesparse=falsepython -m pip wheel . `
--no-deps `
--no-build-isolation `
-Cdirectional.build-cli=true$env:DIRECTIONAL_ENABLE_GMP = "1"
$env:DIRECTIONAL_ENABLE_PARDISO = "1"
$env:DIRECTIONAL_ENABLE_CUDSS = "0"
$env:DIRECTIONAL_ENABLE_SUITESPARSE = "0"
$env:DIRECTIONAL_BUILD_CLI = "1"
python -m pip wheel . --no-build-isolationThe legacy GMP environment variable DIRECTIONAL_DIRECTIONAL_ENABLE_GMP remains accepted as an alias.
Both the Python command and native executable support the same command set:
directional info
directional cross-field <input.obj|input.off> <output-field> [options]
directional convert-field <input-field> <output-field> [options]
directional remesh <input.obj|input.off> <output.obj|output.off> [options]
directional --version
directional --help
The Python module form is also supported:
python -m directional --help| Format | Extensions | Description |
|---|---|---|
crossfield |
.vec, .txt |
Alpha and beta vectors; six values per row |
rosy |
.rosy |
Count/degree header followed by one alpha vector per face |
rawfield |
.rawfield |
Degree/count header followed by 3 × degree values per face |
directional cross-field input.obj output.rosy `
--output-format rosy `
--singularities output.singsOptions:
--output-format <auto|crossfield|rosy|rawfield>
--no-normalize-directions
--no-normalize
--no-matching
--singularities <path>
--diagnostics-prefix <prefix>
--verbose
directional convert-field input.rosy output.txt `
--input-format rosy `
--output-format crossfield `
--mesh input.objOptions:
--input-format <auto|crossfield|rosy|rawfield>
--output-format <auto|crossfield|rosy|rawfield>
--mesh <input.obj|input.off>
--degree <2|4>
The mesh is required when conversion must reconstruct beta directions from face normals.
Compute a cross field automatically and remesh:
directional remesh input.obj output.obj --length-ratio 0.02Use an existing field:
directional remesh input.obj output.off `
--field input.rosy `
--field-format rosy `
--length-ratio 0.02Options:
--field <path>
--field-format <auto|crossfield|rosy|rawfield>
--raw-field <path>
--primary-directions <path>
--secondary-directions <path>
--length-ratio <value>
--no-integral-seamless
--round-seams
--no-normalize-directions
--diagnostics-prefix <prefix>
--verbose
Without --verbose, long-running remeshing stages use in-place top-level progress reporting. With --verbose, detailed phase timing and solver diagnostics are printed as regular log lines.
The extension exposes the headless remeshing API, including:
directional.RemeshOptions
directional.RemeshResult
directional.remesh_from_cross_field(...)
directional.remesh_from_raw_cross_field(...)
Minimal example:
import numpy as np
import directional
vertices = np.array(
[
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
],
dtype=np.float64,
)
faces = np.array([[0, 1, 2]], dtype=np.int32)
primary_directions = np.array([[1.0, 0.0, 0.0]], dtype=np.float64)
options = directional.RemeshOptions()
result = directional.remesh_from_cross_field(
vertices,
faces,
primary_directions,
options,
)
print(result.success)Use pure CMake when:
- you want to link Directional from another native C++ project
- you want a standard installed CMake package via
find_package
Use setup.py when:
- you want the fastest local build entrypoint
- you want to produce a Python wheel
- you want one-command tutorial builds
Use pip when:
- you want a standard PEP 517 install path
- you want to drive GMP options through
--config-settings
- The installed C++ package exports
Directional::directional. - The current standalone library is intentionally minimal; most functionality remains header-driven.
- The Python wheel is platform-specific because it contains a compiled extension module.
- Tutorial and Python builds depend on the same top-level CMake project;
setup.pyis only a wrapper over that build.
Build all tutorials:
python setup.py tutorialsBuild a selected tutorial:
python setup.py tutorials --tutorial=501Build several selected tutorials:
python setup.py tutorials --tutorial=501,502,601Custom build directory:
python setup.py tutorials `
--tutorial=501 `
--build-dir=build\tutorial-501Solver options are also supported:
python setup.py tutorials `
--enable-pardiso `
--disable-cudss `
--disable-suitesparseThe tutorial command configures:
BUILD_SHARED_LIBS=OFF
BUILD_TUTORIALS=ON
BUILD_PYTHON=OFF
DIRECTIONAL_BUILD_CLI=OFF
DIRECTIONAL_TUTORIALS=<selection or ALL>
Install test dependencies and run the Python tests:
python -m pip install -e .[test] --no-build-isolation
python -m pytestFor native validation, configure and build the desired CMake targets, then run any CTest targets included by the current source tree:
ctest --test-dir build\standalone -C Release --output-on-failureA native install typically contains:
bin/ directional executable and runtime DLLs
lib/ directional import/static artifacts
include/ Directional and Eigen headers
lib/cmake/Directional/ exported CMake package
A Python install contains:
directional/
__init__.py
_directional*.pyd|so
bin/ optional native CLI and runtime files
Use direct CMake when:
- embedding DirectionalReMesher into another C++ project
- producing an installed
find_package-compatible package - controlling dependency discovery and runtime deployment directly
Use setup.py when:
- iterating locally on the Python extension
- building the standalone library through a Python command
- building the optional native CLI alongside the extension
Use PEP 517 / pip when:
- producing standard wheels
- integrating with build automation
- controlling solver and CLI options through
--config-settings
- Only one integration solver backend is compiled into a build.
- The selection priority is always PARDISO, then cuDSS, then SuiteSparse.
- The C++ package exports
Directional::directional. - Python wheels are platform-specific because they contain a compiled extension.
- PARDISO builds deploy the oneMKL runtime modules needed by
mkl_rtbeside installed binaries. - The native CLI and Python CLI share the same C++ implementation; command behavior should remain consistent between them.
Original source: avaxman/Directional
If you use this project in research, cite the original Directional work:
@misc{Directional,
author = {Amir Vaxman and others},
title = {Directional: A library for Directional Field Synthesis, Design, and Processing},
doi = {10.5281/zenodo.3338174},
url = {https://doi.org/10.5281/zenodo.3338174}
}