elalish/manifold
GitHub: elalish/manifold
保证拓扑正确性的高性能流形网格几何库,提供可靠布尔运算和跨语言支持。
Stars: 1910 | Forks: 194
# 关于 Manifold
[](https://codecov.io/github/elalish/manifold)
[](https://badge.fury.io/py/manifold3d)
[](https://badge.fury.io/js/manifold-3d)
[](https://twitter.com/intent/follow?screen_name=manifoldcad)
[**C++ 文档**](https://manifoldcad.org/docs/html/classmanifold_1_1_manifold.html) | [**ManifoldCAD 用户指南**](https://manifoldcad.org/docs/jsuser/) | [**JS/TS/WASM API**](https://manifoldcad.org/docs/jsapi/) | [**算法文档**](https://github.com/elalish/manifold/wiki/Manifold-Library) | [**博客文章**](https://elalish.blogspot.com/search/label/Manifold) | [**Web 示例**](https://manifoldcad.org/model-viewer.html)
[Manifold](https://github.com/elalish/manifold) 是一个专注于创建和操作流形三角形网格的几何库。[流形网格](https://github.com/elalish/manifold/wiki/Manifold-Library#manifoldness) 是一种表示实体对象的网格,因此在制造、CAD、结构分析等领域非常重要。Manifold 还支持任意顶点属性,并能够映射材质以用于渲染场景。我们的首要目标是可靠性:保证输出流形网格,没有任何例外或边缘情况。我们的次要目标是性能:通过广泛使用并行化(或在单线程可用时使用流水线技术)的高效算法。
## 用户
这是我们不完整的用户列表,他们的集成可能处于进行中或已发布状态。请随时发送 PR 用您自己的项目更新此列表 —— 我们很难追踪所有项目。
| | | |
| --- | --- | --- |
| [OpenSCAD](https://openscad.org/) | [Blender](https://www.blender.org/) | [IFCjs](https://ifcjs.github.io/info/) |
| [Nomad Sculpt](https://apps.apple.com/us/app/id1519508653?mt=8&platform=ipad) | [Grid.Space](https://grid.space/) | [badcad](https://github.com/wrongbad/badcad) |
| [Godot Engine](https://godotengine.org/) | [OCADml](https://github.com/OCADml/OManifold) | [Flitter](https://flitter.readthedocs.io/en/latest/) |
| [BRL-CAD](https://brlcad.org/) | [PolygonJS](https://polygonjs.com/) | [Spherene](https://spherene.ch/) |
| [Babylon.js](https://doc.babylonjs.com/features/featuresDeepDive/mesh/mergeMeshes#merging-meshes-with-constructive-solid-geometry) | [trimesh](https://trimesh.org/) | [Gypsum](https://github.com/playkostudios/gypsum) |
| [Valence 3D](https://apps.apple.com/us/app/valence-3d/id6450967410?mt=8&platform=ipad) | [bitbybit.dev](https://bitbybit.dev) | [PythonOpenSCAD](https://github.com/owebeeone/pythonopenscad) |
| [Conversation](https://james-bern.github.io/conversation.html) | [AnchorSCAD](https://github.com/owebeeone/anchorscad-core) | [Dactyl Web Configurator](https://github.com/rianadon/dactyl-configurator) |
| [Arcol](https://arcol.io) | [Bento3D](https://bento3d.design) | [SKÅPA](https://skapa.build) |
| [Cadova](https://github.com/tomasf/Cadova) | [BREP.io](https://github.com/mmiscool/BREP) | [Otterplans](https://otterplans.com) |
| [Bracket Engineer](https://bracket.engineer) | [Nodillo](https://nodillo3d.com) | |
### 绑定与包
Manifold 有多种语言的绑定,有些在此仓库中维护,有些在其他地方。它也可以通过 [vcpkg](https://github.com/microsoft/vcpkg.git) 在 C++ 中构建。
| 语言 | 包管理器 | 名称 | 维护状态 |
| --- | --- | --- | --- |
| C | N/A | N/A | 内部 |
| C++ | vcpkg | [manifold](https://github.com/microsoft/vcpkg/tree/master/ports/manifold) | 外部 |
| TS/JS | npm | [manifold-3d](https://www.npmjs.com/package/manifold-3d) | 内部 |
| Python | PyPI | [manifold3d](https://pypi.org/project/manifold3d/) | 内部 |
| Java | N/A | [manifold](https://github.com/SovereignShop/manifold) | 外部 |
| Clojure | N/A | [clj-manifold3d](https://github.com/SovereignShop/clj-manifold3d) | 外部 |
| C# | NuGet | [ManifoldNET](https://www.nuget.org/packages/ManifoldNET) | 外部 |
| Julia | Packages | [ManifoldBindings.jl](https://juliapackages.com/p/manifoldbindings) | 外部 |
| OCaml | N/A | [OManifold](https://ocadml.github.io/OManifold/OManifold/index.html) | 外部 |
| Swift | SPM | [Manifold-Swift](https://github.com/tomasf/manifold-swift) | 外部 |
## 前端沙盒
### [ManifoldCAD.org]
如果您喜欢 OpenSCAD / JSCAD,可能也会喜欢 [ManifoldCAD][ManifoldCAD.org] —— 这是我们自己的实体建模 Web 应用,您可以使用 JS/TS 编写脚本。它使用我们的 npm 包 [manifold-3d](https://www.npmjs.com/package/manifold-3d),通过 WASM 构建。虽然不如我们的原生 C++ 快,但在互操作性方面很难被超越。
### [Python Colab 示例]
如果您更喜欢 Python 而不是 JS/TS,请复制 [notebook][Python Colab Example]。它演示了我们的 [`manifold3d`](https://pypi.org/project/manifold3d/) PyPI 库与流行的 [`trimesh`](https://pypi.org/project/trimesh/) 库之间的互操作性,包括直接在 notebook 中显示交互式模型和保存 3D 模型输出。

## Manifold 库
该库速度快且保证输出流形网格。因此,您需要流形网格作为输入,该库可以使用受 OpenSCAD API 启发的构造函数以及用于评估有符号距离函数 (SDF) 的水平集函数来创建这些网格,其效果比 Marching Cubes 有显著提升。您也可以传入自己的网格数据,但如果导入的网格不是流形的,您将收到错误状态。我们提供了 [`Merge`](https://manifoldcad.org/docs/html/structmanifold_1_1_mesh_g_l_p.html) 函数来修复轻微的非流形网格,但通常您可能需要使用主要用于 3D 打印的自动修复工具之一。
这里最重要的贡献是一个保证流形的 [网格布尔](https://github.com/elalish/manifold/wiki/Manifold-Library#mesh-boolean) 算法,我认为这是同类中的首创。如果您知道其他的,请开启一个讨论 —— 一个对边缘情况鲁棒的网格布尔算法多年来一直是一个开放问题。同样,如果这里的布尔运算曾经让您失败,请提交 issue!这个布尔运算构成了 CAD 内核的基础,因为它允许将简单形状组合成更复杂的形状。
Manifold 完全支持任意顶点属性,并且具有 ID,可以轻松跟踪材质以及哪些表面属于哪些输入对象或面。请参阅我们的 [Web 示例](https://manifoldcad.org/model-viewer.html),了解组合具有独特纹理的对象的简单演示。
还包括一套新颖且强大的细化函数,用于平滑网格插值。它们处理三角形和四边形的平滑,以及保持多边形面的平整。您可以轻松地在需要的地方创建锐利或小半径边缘,甚至可以通过法向量驱动曲率。
为了提高速度,该库广泛使用了 TBB 进行并行化(如果已启用)。并非所有内容都可以并行化,例如包含的 [多边形三角剖分](https://github.com/elalish/manifold/wiki/Manifold-Library#polygon-triangulation) 算法是串行的。即使使用并行后端编译,如果问题规模较小,代码仍将回退到算法的串行版本。WASM 构建目前仅限串行,但仍然很快。
在 [samples](https://github.com/elalish/manifold/tree/master/samples) 目录中查看有关如何使用此库制作有趣 3D 模型的示例。您可能会注意到其中一些示例与我在 [Thingiverse](https://www.thingiverse.com/emmett) 上的 OpenSCAD 设计有某些相似之处,这并非偶然。虽然我非常喜欢 OpenSCAD,但我的库速度明显更快,而且代码更灵活。
### 依赖项
Manifold **不再有任何** 必需的依赖项!但是,我们确实有几个可选依赖项,其中前两个强烈推荐:
| 名称 | CMake 标志 | 提供功能 |
| --- | --- | --- |
| [`TBB`](https://github.com/oneapi-src/oneTBB/) |`MANIFOLD_PAR=ON` | 并行加速 |
| [`Clipper2`](https://github.com/AngusJohnson/Clipper2) | `MANIFOLD_CROSS_SECTION=ON` | 2D: [`CrossSection`](https://manifoldcad.org/docs/html/classmanifold_1_1_cross_section.html) |
| [`Nanobind`](https://github.com/wjakob/nanobind) | `MANIFOLD_PYBIND=ON` | Python 绑定 |
| [`Emscripten`](https://github.com/emscripten-core/emscripten) | `MANIFOLD_JSBIND=ON` | 通过 WASM 的 JS 绑定 |
| [`GTest`](https://github.com/google/googletest/) | `MANIFOLD_TEST=ON` | 测试框架 |
| [`Assimp`](https://github.com/assimp/assimp) | `ASSIMP_ENABLE=ON` | `extras` 中的实用程序 |
| [`Tracy`](https://github.com/wolfpld/tracy) | `TRACY_ENABLE=ON` | 性能分析 |
### 3D 格式
请避免保存为 STL 文件!它们是有损且低效的 —— 将流形网格保存为 STL 时,无法保证重新导入的网格仍然是流形的,因为拓扑丢失了。请考虑改用 [3MF](https://3mf.io/),因为这种格式从一开始就是为表示实体对象的流形网格设计的。
如果您使用顶点属性(如插值法线或纹理 UV 坐标),建议使用 [glTF](https://www.khronos.org/Gltf),特别是使用 [`EXT_mesh_manifold`](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_manifold/README.md) 扩展。这允许即使存在属性边界,也能无损且高效地传输流形性。尝试我们的 [make-manifold](https://manifoldcad.org/make-manifold) 页面,将此扩展添加到您现有的 glTF/GLB 模型中。
Manifold 提供高精度的 OBJ 文件 IO,但功能有限,主要用于辅助测试。如果您使用的是我们的 npm 模块,我们有一个功能更强大的 [gltf-io.ts](https://github.com/elalish/manifold/blob/master/bindings/wasm/examples/gltf-io.ts) 供您使用。对于其他语言,我们强烈建议使用专注于 3D 文件 I/O 的现有包,例如 Python 的 [trimesh](https://trimesh.org/),特别是在使用顶点属性或材质时。
与 [Assimp](https://github.com/assimp/assimp) 集成的示例在 `extras/meshIO.cpp` 中,该文件被 `extras/convert_file.cpp` 等文件使用。
## 构建
只需要安装并设置 CMake、C++ 编译器和 Python 即可构建此库(已使用 GCC、LLVM、MSVC 进行测试)。但是,各种可选依赖项可以带来更多功能,见下文。
构建并测试(Ubuntu 或类似系统):
```
git clone --recurse-submodules https://github.com/elalish/manifold.git
cd manifold
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON .. && make
make test
```
CMake 标志(用法例如 `-DMANIFOLD_DEBUG=ON`):
- `MANIFOLD_JSBIND=[OFF, ]`:构建 js 绑定(使用 emscripten 工具链时)。
- `MANIFOLD_CBIND=[, ON]`:构建 C FFI 绑定。
- `MANIFOLD_PYBIND=[OFF, ]`:构建 python 绑定,需要 `nanobind`。
- `MANIFOLD_PAR=[, ON]`:启用多线程并行化,需要 `tbb`。
- `MANIFOLD_CROSS_SECTION=[OFF, ]`:构建用于 2D 支持的 CrossSection(语言绑定需要),需要 `Clipper2`。
- `MANIFOLD_DEBUG=[, ON]`:启用异常、计时、详细输出、OBJ 测试转储。其本身几乎没有影响,但启用进一步的运行时参数以转储各种输出。
- `MANIFOLD_ASSERT=[, ON]`:启用内部断言。这会产生约 20% 的运行时开销。需要 MANIFOLD_DEBUG 才能工作。
- `MANIFOLD_TEST=[OFF, ]`:构建单元测试,需要 `GTest`。
- `TRACY_ENABLE=[, ON]`:启用与 tracy profiler 的集成。
请参阅下面的分析部分。
- `ASSIMP_ENABLE=[, ON]`:启用与 assimp 的集成,这是 `extras` 中某些实用程序所需要的。
- `MANIFOLD_STRICT=[, ON]`:将编译警告视为致命构建错误。
依赖版本覆盖:
- `MANIFOLD_USE_BUILTIN_TBB=[, ON]`:使用内置版本的 tbb。
- `MANIFOLD_USE_BUILTIN_CLIPPER2=[, ON]`:使用内置版本的 clipper2。
- `MANIFOLD_USE_BUILTIN_NANOBIND=[, ON]`:使用内置版本的 nanobind。
离线构建(缺少依赖项/依赖项版本覆盖):
- `MANIFOLD_DOWNLOADS=[OFF, ]`:自动下载缺少的依赖项。
如果缺少依赖项 `*`,则需要设置 `FETCHCONTENT_SOURCE_DIR_*`。
- `FETCHCONTENT_SOURCE_DIR_TBB`:tbb 源代码的路径(如果启用了 `MANIFOLD_PAR`)。
- `FETCHCONTENT_SOURCE_DIR_CLIPPER2`:tbb 源代码的路径(如果启用了 `MANIFOLD_CROSS_SECTION`)。
- `FETCHCONTENT_SOURCE_DIR_NANOBIND`:nanobind 源代码的路径(如果启用了 `MANIFOLD_PYBIND`)。
- `FETCHCONTENT_SOURCE_DIR_GOOGLETEST`:googletest 源代码路径(如果启用了 `MANIFOLD_TEST`)。
我们的 CI 使用的构建说明在 [manifold.yml](https://github.com/elalish/manifold/blob/master/.github/workflows/manifold.yml) 中,如果出现问题以及查找特定于其他平台(如 Windows)的说明,这是一个很好的检查来源。
### WASM
要构建 JS WASM 库,首先安装 NodeJS 并设置 emscripten:
(在 Mac 上):
```
brew install nodejs
brew install emscripten
```
(在 Linux 上):
```
sudo apt install nodejs
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk/emsdk_env.sh
```
然后构建:
```
cd manifold
mkdir buildWASM
cd buildWASM
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel .. && emmake make
cd test
node ./manifold_test.js
```
### Python
CMake 脚本将自动构建 python 绑定 `manifold3d`。要
使用该扩展,请将 `$BUILD_DIR/bindings/python` 添加到您的 `PYTHONPATH`,其中
`$BUILD_DIR` 是 CMake 的构建目录。使用 python 绑定的示例
可以在 `bindings/python/examples` 中找到。要查看导出的示例,请运行:
```
sudo apt install pkg-config libpython3-dev python3 python3-distutils python3-pip
pip install trimesh pytest
python3 run_all.py -e
```
在解释器中运行以下代码以
查看 python 绑定文档:
```
>>> import manifold3d
>>> help(manifold3d)
```
有关更详细的文档,请参阅 C++ API。
### Windows 的特殊情况
Windows 用户应使用 `-DBUILD_SHARED_LIBS=OFF` 构建,因为启用
共享库通常会使事情变得非常复杂。
使用 msvc 构建时的 manifoldc(C FFI 绑定)DLL 文件位于 `${CMAKE_BINARY_DIR}/bin/${BUILD_TYPE}/manifoldc.dll`。
例如,对于以下命令,相对于项目根目录的路径是 `build/bin/Release/manifoldc.dll`。
```
cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DMANIFOLD_DEBUG=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} -A x64 -B build
```
### 格式化
有一个格式化脚本 `format.sh` 可以自动格式化所有内容。
它需要 clang-format,python 的 black 格式化器和 [gersemi](https://github.com/BlankSpruce/gersemi) 来格式化 cmake 文件。
请注意,我们的脚本可以在 18 之前的 clang-format 版本上运行,但 GitHub
操作检查可能会由于不同版本的
clang-format 之间的细微差异而失败。在这种情况下,请更新您的 clang-format 版本或应用
GitHub 操作日志中的补丁。
### 性能分析
现在为我们的测试提供了对 [Tracy profiler](https://github.com/wolfpld/tracy) 的基本支持。
要启用跟踪,请使用 `-DTRACY_ENABLE=on` cmake 选项编译,并在 Tracy 服务器运行的情况下运行测试。
除了跟踪之外还要启用内存分析,除了 `-DTRACY_ENABLE=ON` 之外,还需使用 `-DTRACY_MEMORY_USAGE=ON` 编译。
### 模糊测试
要在启用模糊测试支持的情况下构建,您应该使用 CMake 进行以下设置:
- 通过设置 `-DMANIFOLD_FUZZ=ON` 启用模糊测试
- 通过设置 `-DMANIFOLD_PYBIND=OFF` 禁用 python 绑定
- 通过设置 `-DCMAKE_CXX_COMPILER=clang++` 使用 `clang` 进行编译
- 您可能需要通过设置 `-DMANIFOLD_PAR=OFF` 禁用并行化,并在 MacOS 上构建二进制文件时设置 `ASAN_OPTIONS=detect_container_overflow=0`。
## 关于作者
这个库由 [Emmett Lalish](https://elalish.blogspot.com/) 发起,目前是 Wētā FX 的高级渲染工程师。这是我在 Google 员工时的 20% 项目,尽管我的日常工作是维护 [](https://modelviewer.dev/)。我是 3D 视频初创公司 [Omnivor](https://www.omnivor.io/) 的第一位员工,在此之前我在 Microsoft 从事 3D 打印工作,包括 [3D Builder](https://www.microsoft.com/en-us/p/3d-builder/9wzdncrfj3t6?activetab=pivot%3Aoverviewtab)。最初作为一名航空航天工程师,我在一家小型 DARPA 承包商开始了我的职业生涯,从事种子项目,其中一个成为了 [Sea Hunter](https://en.wikipedia.org/wiki/Sea_Hunter)。我在华盛顿大学获得了控制理论博士学位,并发表了一些 [论文](https://www.researchgate.net/scientific-contributions/75011026_Emmett_Lalish)。
标签:3D建模, 3D打印, AI工具, Bash脚本, Blender, C++, CAD, CMS安全, JavaScript, ManifoldCAD, OpenSCAD, Python, TypeScript, WebAssembly, 几何库, 制造, 安全插件, 布尔运算, 并行计算, 开源库, 拓扑稳健性, 搜索引擎爬虫, 数据可视化, 数据擦除, 无后门, 材质映射, 流形三角形网格, 结构分析, 网格处理, 计算几何, 计算机图形学, 逆向工具