pyinstantmeshes 1.0.0
Python bindings for Instant Meshes - fast automatic retopology
License: BSD-3-Clause
Requires Python: >=3.11
Keywords: mesh, simplification, optimization, remeshing

# pyinstantmeshes

[![CI](https://github.com/greenbrettmichael/pyinstantmeshes/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/greenbrettmichael/pyinstantmeshes/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/greenbrettmichael/pyinstantmeshes/branch/main/graph/badge.svg)](https://codecov.io/gh/greenbrettmichael/pyinstantmeshes)

Python bindings for [Instant Meshes](https://github.com/wjakob/instant-meshes) - a fast automatic retopology tool.

## Overview

pyinstantmeshes provides a Python interface to the Instant Meshes library, allowing you to perform automatic retopology and remeshing of 3D meshes directly from Python using numpy arrays.

Instant Meshes is based on the research paper:
> **Instant Field-Aligned Meshes**  
> Wenzel Jakob, Marco Tarini, Daniele Panozzo, Olga Sorkine-Hornung  
> In *ACM Transactions on Graphics (Proceedings of SIGGRAPH Asia 2015)*

## Installation

### From PyPI

The easiest way to install pyinstantmeshes is via pip:

```bash
pip install pyinstantmeshes
```

Pre-built binary wheels are available for:
- **Linux** (manylinux)
- **macOS**
- **Windows**
- **Python versions**: 3.11, 3.12, 3.13, 3.14

### From source

```bash
git clone --recursive https://github.com/greenbrettmichael/pyinstantmeshes.git
cd pyinstantmeshes
pip install .
```

### Requirements

- Python 3.8+
- NumPy
- CMake 3.15+
- C++11 compiler
- pybind11

## Usage

### Basic Example

```python
import numpy as np
import pyinstantmeshes

# Create or load your mesh data
vertices = np.array([
    [0.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    [0.0, 1.0, 0.0],
    [0.0, 0.0, 1.0]
], dtype=np.float32)

faces = np.array([
    [0, 1, 2],
    [0, 1, 3],
    [0, 2, 3],
    [1, 2, 3]
], dtype=np.int32)

# Remesh with target vertex count
output_vertices, output_faces = pyinstantmeshes.remesh(
    vertices, 
    faces, 
    target_vertex_count=100
)

print(f"Input: {len(vertices)} vertices, {len(faces)} faces")
print(f"Output: {len(output_vertices)} vertices, {len(output_faces)} faces")
```

### Remeshing from Files

```python
import pyinstantmeshes

# Remesh a file directly
output_vertices, output_faces = pyinstantmeshes.remesh_file(
    "input_mesh.obj",
    "output_mesh.obj",
    target_vertex_count=5000
)
```

### Advanced Parameters

```python
output_vertices, output_faces = pyinstantmeshes.remesh(
    vertices,
    faces,
    target_vertex_count=1000,      # Target number of vertices
    target_face_count=-1,           # Target number of faces (alternative to vertex count)
    target_edge_length=-1.0,        # Target edge length (alternative sizing method)
    rosy=4,                         # Orientation symmetry (4 or 6)
    posy=4,                         # Position symmetry (4 for quads, 3 for triangles)
    crease_angle=-1.0,              # Crease angle threshold (-1 to disable)
    extrinsic=False,                # Use extrinsic mode
    align_to_boundaries=False,      # Align field to boundaries
    smooth_iterations=2,            # Number of smoothing iterations
    knn_points=10,                  # kNN for point cloud processing
    pure_quad=False,                # Generate pure quad mesh (vs quad-dominant)
    deterministic=False             # Use deterministic mode
)
```

## API Reference

### `remesh(vertices, faces, **kwargs)`

Remesh a triangular or quad mesh for better topology.

**Parameters:**
- `vertices` (numpy.ndarray): Input vertex positions as Nx3 float array
- `faces` (numpy.ndarray): Input face indices as Nx3 or Nx4 int array
- `target_vertex_count` (int, optional): Desired vertex count (default: -1, uses 1/16 of input)
- `target_face_count` (int, optional): Desired face count (default: -1)
- `target_edge_length` (float, optional): Desired edge length (default: -1)
- `rosy` (int, optional): Orientation symmetry type (default: 4)
- `posy` (int, optional): Position symmetry type (default: 4)
- `crease_angle` (float, optional): Crease angle threshold in degrees (default: -1)
- `extrinsic` (bool, optional): Use extrinsic mode (default: False)
- `align_to_boundaries` (bool, optional): Align field to boundaries (default: False)
- `smooth_iterations` (int, optional): Number of smoothing iterations (default: 2)
- `knn_points` (int, optional): kNN points for point clouds (default: 10)
- `pure_quad` (bool, optional): Generate pure quad mesh (default: False)
- `deterministic` (bool, optional): Use deterministic mode (default: False)

**Returns:**
- `vertices` (numpy.ndarray): Output vertex positions as Nx3 float array
- `faces` (numpy.ndarray): Output face indices as Nx3 or Nx4 int array

### `remesh_file(input_path, output_path, **kwargs)`

Remesh a mesh from an input file and save to an output file.

**Parameters:**
- `input_path` (str): Path to input mesh file (OBJ, PLY, etc.)
- `output_path` (str): Path to output mesh file (OBJ)
- Additional parameters same as `remesh()`

**Returns:**
- `vertices` (numpy.ndarray): Output vertex positions as Nx3 float array
- `faces` (numpy.ndarray): Output face indices as Nx3 or Nx4 int array

## Development

### Running Tests

The project includes a comprehensive test suite using pytest. To run the tests locally:

1. Install the package with test dependencies:
   ```bash
   pip install -e .[test]
   ```

2. Run the tests:
   ```bash
   pytest
   ```

3. Run tests with coverage report:
   ```bash
   pytest --cov=pyinstantmeshes --cov-report=term-missing --cov-report=html
   ```
   
   The coverage report will be available in `htmlcov/index.html`.

### Continuous Integration

The project uses GitHub Actions for continuous integration. Tests are automatically run on:
- **Operating Systems**: Linux (Ubuntu), macOS, and Windows
- **Python Versions**: 3.8, 3.9, 3.10, 3.11, and 3.12

The CI pipeline:
1. Builds the C++ extension for each platform and Python version
2. Runs the full test suite
3. Generates coverage reports
4. Uploads coverage to Codecov

All pull requests must pass the CI checks before merging.

## License

This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.

The underlying Instant Meshes library is also licensed under the BSD 3-Clause License.

## Citation

If you use this software in academic work, please cite the original Instant Meshes paper:

```bibtex
@article{Jakob2015Instant,
   author = {Wenzel Jakob and Marco Tarini and Daniele Panozzo and Olga Sorkine-Hornung},
   title = {Instant Field-Aligned Meshes},
   journal = {ACM Trans. Graph.},
   volume = {34},
   number = {6},
   year = {2015},
   publisher = {ACM}
}
```

## Acknowledgments

- Original Instant Meshes by Wenzel Jakob: https://github.com/wjakob/instant-meshes
- pybind11 for C++/Python bindings: https://github.com/pybind/pybind11