Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf2a603432 | ||
|
|
b722d7f4f8 | ||
|
|
552103eec8 | ||
|
|
7332399d5e | ||
|
|
6c9da566cc | ||
|
|
aa0dc12da8 | ||
|
|
1f6d1dbad2 | ||
|
|
46e8a6dc86 | ||
|
|
3a799fa5a5 | ||
|
|
9e1fa6d544 | ||
|
|
61c4af291c | ||
|
|
0bfc0d64f8 | ||
|
|
747559170a | ||
|
|
497cfb5d0b | ||
|
|
cbcf7dc0c8 | ||
|
|
fa6be648b7 | ||
|
|
93bea2834f | ||
|
|
e2c39536fd | ||
|
|
b5e9bfeb8e | ||
|
|
8b27763c8f | ||
|
|
896bdf5ac4 | ||
|
|
634aee5fe0 | ||
|
|
db58939b58 | ||
|
|
6860502494 | ||
|
|
d5c0e6c29e | ||
|
|
a850f73d51 | ||
|
|
301c165a20 | ||
|
|
539f58d325 | ||
|
|
1d44fa463d | ||
|
|
cadec11542 | ||
|
|
bf7031f2ea | ||
|
|
213bcc5bd1 | ||
|
|
8732952b5f | ||
|
|
e4ccce3c03 | ||
|
|
6c05639c1b | ||
|
|
34e3e1bbf3 | ||
|
|
2e3f0e6272 | ||
|
|
31214804c9 | ||
|
|
38e143d8e0 | ||
|
|
b918447ad1 | ||
|
|
b2c6ddd2e3 | ||
|
|
71c9c59f1c | ||
|
|
e031fc471c | ||
|
|
3b00ea4ace | ||
|
|
18fb6d6315 | ||
|
|
7ea0c707a9 | ||
|
|
58034ad362 | ||
|
|
d315ce22f5 | ||
|
|
337e13fba0 | ||
|
|
3a96fcc80f | ||
|
|
704540c873 | ||
|
|
499347bb9f | ||
|
|
628037b26e | ||
|
|
750f92aee2 | ||
|
|
0560cd043a | ||
|
|
29c3e3b194 | ||
|
|
04f210d112 | ||
|
|
50fcc28a55 | ||
|
|
5c90c777bc | ||
|
|
526280ef20 | ||
|
|
7f037e5189 | ||
|
|
cf3b517dfa | ||
|
|
db18317e42 | ||
|
|
04cb690671 | ||
|
|
798d83c8d7 | ||
|
|
652a95320b | ||
|
|
a06d4502cd | ||
|
|
aea74b56ff | ||
|
|
b51858f648 | ||
|
|
b479c67510 | ||
|
|
3b589b94cb | ||
|
|
84f9a8ce76 | ||
|
|
75390fe5cb | ||
|
|
7054c63029 | ||
|
|
55776ac3b5 | ||
|
|
9e127e455d | ||
|
|
6726ad2eeb | ||
|
|
d4acf92ced | ||
|
|
e93f95dc04 | ||
|
|
fcd67c97b1 | ||
|
|
b72a676caf | ||
|
|
c181da63e5 | ||
|
|
3087302edc | ||
|
|
097d487e96 | ||
|
|
8604c48a2f | ||
|
|
ff0162907d | ||
|
|
f6005ffa83 | ||
|
|
5cb7e6444e | ||
|
|
50548dcc25 | ||
|
|
bd68fe6d78 | ||
|
|
54d0a2e210 | ||
|
|
533fc6a86e | ||
|
|
edd20e03f5 | ||
|
|
f0747c3420 | ||
|
|
64c7d229bc | ||
|
|
34da5f0629 | ||
|
|
f18a4c7c38 | ||
|
|
557b320729 | ||
|
|
e93393bcdc | ||
|
|
ccece0bf69 | ||
|
|
5fe1e365fb | ||
|
|
ca375ea079 | ||
|
|
59361d8d99 | ||
|
|
818f7b3024 | ||
|
|
e047ba6362 | ||
|
|
ae57329b67 | ||
|
|
3124ad45e4 | ||
|
|
3a29e9566f | ||
|
|
7d5d78b957 | ||
|
|
bf93b97221 | ||
|
|
34afe21c31 | ||
|
|
b4e0dbb763 | ||
|
|
4b4eb9a8ec | ||
|
|
9457a4e889 | ||
|
|
f1962a723c | ||
|
|
56f2b6730b | ||
|
|
e4c8defdff | ||
|
|
dad5deeccc | ||
|
|
76208dc02b | ||
|
|
6754a3cf7c | ||
|
|
73f3afdfc2 | ||
|
|
39e3cd3f6e | ||
|
|
c18032c31e | ||
|
|
83ddd27063 | ||
|
|
8610651942 | ||
|
|
da4997bd29 | ||
|
|
52c5ef592e | ||
|
|
8c63b864d8 | ||
|
|
87b8167659 | ||
|
|
982c339abc | ||
|
|
3a83b83ca3 | ||
|
|
75dc3219fa | ||
|
|
90cab6e2bb | ||
|
|
186dc69f52 | ||
|
|
d013ddec32 | ||
|
|
182188b805 | ||
|
|
2f4741e0b1 | ||
|
|
023bb59be9 | ||
|
|
2984626cb2 | ||
|
|
551e1a12cf | ||
|
|
2cf3dfd0ec | ||
|
|
b252782489 | ||
|
|
39934bca55 | ||
|
|
1d18e60d74 | ||
|
|
061c5e7a48 | ||
|
|
e3ff2a0019 | ||
|
|
3027282259 | ||
|
|
1ec20369ca | ||
|
|
cd57073179 | ||
|
|
3ba3175f2c | ||
|
|
5145d3422b | ||
|
|
41d8d97d7c | ||
|
|
54baa62b4a | ||
|
|
f3a6a477da | ||
|
|
994814921e | ||
|
|
138815a127 | ||
|
|
85b0cd211c | ||
|
|
9756892b09 | ||
|
|
3015a81c07 | ||
|
|
272a22439f | ||
|
|
4ba67b8fcf | ||
|
|
09fb03cff2 | ||
|
|
b8dd573a9c | ||
|
|
63a36e678a | ||
|
|
7c2b7b407b | ||
|
|
29d2b1dbe9 | ||
|
|
90f83a98be | ||
|
|
ca7d6c326c | ||
|
|
00a589dafe | ||
|
|
7c8fbe186a | ||
|
|
4fabfc327b | ||
|
|
75b592f38c | ||
|
|
444399393a | ||
|
|
2a4e9bae06 | ||
|
|
bdb0b880c9 | ||
|
|
33a69413c2 | ||
|
|
4edd442297 | ||
|
|
beb9ca6122 | ||
|
|
fab833e7e1 | ||
|
|
1f188036d1 | ||
|
|
808c261b33 | ||
|
|
bc70f58990 | ||
|
|
d4439bccec | ||
|
|
8e34f97194 | ||
|
|
954df798b2 | ||
|
|
0451671bd3 | ||
|
|
cba9e35bb1 | ||
|
|
5399bd4760 | ||
|
|
06b10e7149 | ||
|
|
f178cd1d73 | ||
|
|
5ae22f0d57 | ||
|
|
a97b150bb5 | ||
|
|
c16b521193 | ||
|
|
c149dd5088 | ||
|
|
a857f008dd | ||
|
|
f2da5eab66 | ||
|
|
447921cf97 | ||
|
|
ac82767927 | ||
|
|
56fec978c6 | ||
|
|
ae813ddecb | ||
|
|
1b3dbc29e2 | ||
|
|
98b8142519 | ||
|
|
b7a02755aa | ||
|
|
be1dec2ef0 | ||
|
|
3a0c251b0e | ||
|
|
209350fd1e | ||
|
|
1917ce0844 | ||
|
|
f48111c43c | ||
|
|
3db0969d1d | ||
|
|
c50b0f80ff | ||
|
|
25ce1b1d53 | ||
|
|
926d2e7a7d | ||
|
|
af5d95ec1b | ||
|
|
ec0bbca3d9 | ||
|
|
aacf37aa4d | ||
|
|
847016c069 | ||
|
|
517a224f44 | ||
|
|
a13ceab979 | ||
|
|
36035428bc | ||
|
|
f1a8693016 | ||
|
|
fb29e8586e | ||
|
|
8556840558 | ||
|
|
2162d8d91f | ||
|
|
11387fb871 | ||
|
|
ddc0a18d87 | ||
|
|
f8c9dc9c8b | ||
|
|
3ea3e7e5e5 | ||
|
|
bc08d41dc0 | ||
|
|
560e37e985 | ||
|
|
db08c23988 | ||
|
|
7d27a437ab | ||
|
|
b77abde57b | ||
|
|
70abe63963 | ||
|
|
75f42f9c53 | ||
|
|
978f84107f | ||
|
|
7d6c285b3e | ||
|
|
78915ae28d | ||
|
|
a557225c29 | ||
|
|
f22435f1e5 | ||
|
|
5d127e57fb | ||
|
|
125dbd41cd | ||
|
|
182adae00a | ||
|
|
7f298aa9db | ||
|
|
18101057b5 | ||
|
|
7de71d4c93 | ||
|
|
d9bc83a7ad | ||
|
|
ee32b3025d | ||
|
|
e7e0780114 | ||
|
|
0b957bf8df | ||
|
|
b26007e76c | ||
|
|
0f7cecaf1a | ||
|
|
a41a361123 | ||
|
|
74f340a8e7 | ||
|
|
12b43f50c4 | ||
|
|
66bca6e3fd | ||
|
|
55722a0ce3 | ||
|
|
2b29dca503 | ||
|
|
82140d3479 | ||
|
|
8e9bdb2614 | ||
|
|
4076b14dd6 | ||
|
|
f11ed8da6c | ||
|
|
a8a90c7d34 | ||
|
|
649b69a140 | ||
|
|
97cb8dbffa | ||
|
|
d1a8de2e00 | ||
|
|
a0d2c3ab25 | ||
|
|
80221a3511 | ||
|
|
5ba3c24112 | ||
|
|
85675f2723 | ||
|
|
e647093bbe | ||
|
|
54517b7546 | ||
|
|
e45df5dd3a | ||
|
|
97423a07f9 | ||
|
|
0a51ae2a0c | ||
|
|
e718288cbf | ||
|
|
005102c1a3 | ||
|
|
6ade357e4b | ||
|
|
e06765346e | ||
|
|
bd52d301ff | ||
|
|
370375ebf0 | ||
|
|
9d3fd48b01 | ||
|
|
451829f1d1 | ||
|
|
3febd48dcd | ||
|
|
658d3e037a | ||
|
|
cc1e97442a | ||
|
|
5719926db8 | ||
|
|
3c8d486e36 | ||
|
|
5a157a07fe | ||
|
|
acb4f8c5e4 | ||
|
|
5cab42f165 | ||
|
|
ea91395878 | ||
|
|
4d7613bd4f | ||
|
|
9f62dbb048 | ||
|
|
31d6da0973 | ||
|
|
359274d01b | ||
|
|
a24cca1f06 | ||
|
|
c1d96a6404 | ||
|
|
a8e533c790 | ||
|
|
fa6a632545 | ||
|
|
cff8d903e8 | ||
|
|
fcc707585b | ||
|
|
456b8ceb3b | ||
|
|
9257734c0f | ||
|
|
ced53e2109 | ||
|
|
a017f0e614 | ||
|
|
22c66051df | ||
|
|
4760ba3a33 | ||
|
|
c75f068a03 | ||
|
|
51ee91e356 | ||
|
|
2e41fef203 | ||
|
|
9124a68032 | ||
|
|
6f009ca13f | ||
|
|
5b2a95e6d2 | ||
|
|
e9c065bd5e | ||
|
|
b95b88f026 | ||
|
|
492c3a8b23 | ||
|
|
d0d5106add | ||
|
|
fbf07bf92a | ||
|
|
a0e4d1b558 | ||
|
|
db4470c3f3 | ||
|
|
fd485f62d5 | ||
|
|
74e15b1574 | ||
|
|
d4fb82d4d1 | ||
|
|
952546b761 | ||
|
|
e26e01a231 | ||
|
|
844334380a | ||
|
|
e01d31611e | ||
|
|
af2304d305 | ||
|
|
75c340f4f4 | ||
|
|
7ad7703964 | ||
|
|
a37d59ef5b | ||
|
|
3bf7f4b33d | ||
|
|
a93c0c6ca1 | ||
|
|
ccb682fc44 | ||
|
|
0617d344bc | ||
|
|
a6ee198b88 | ||
|
|
dad73e1bf4 | ||
|
|
610fd3a073 | ||
|
|
46f199c200 | ||
|
|
fa1a342e1c | ||
|
|
e46938b498 | ||
|
|
ddb3cbeb3a | ||
|
|
b817d07a9d | ||
|
|
85d71f5cef | ||
|
|
ab1a96a96a | ||
|
|
7b10590d89 | ||
|
|
5e7a576cea | ||
|
|
80a5f2e0c5 | ||
|
|
67c4647464 | ||
|
|
edd149e753 | ||
|
|
b5c175162a | ||
|
|
1df22bee48 | ||
|
|
d5c0418309 | ||
|
|
7a5d5421d4 | ||
|
|
69437096d0 | ||
|
|
3931b3296d | ||
|
|
62d0f25ce0 | ||
|
|
1bd16f4c02 | ||
|
|
3afe846570 | ||
|
|
12b9494fdd | ||
|
|
0577aabe7f | ||
|
|
bdae9dd11a | ||
|
|
5f4059ab1f | ||
|
|
9cb3969f70 | ||
|
|
4fb3520287 | ||
|
|
376d317f14 | ||
|
|
bf18c9f759 | ||
|
|
cdd1475fe1 | ||
|
|
55a0221f9b | ||
|
|
d78b1e2042 | ||
|
|
562ff02232 | ||
|
|
8e2b1dd485 | ||
|
|
5ef09daf45 | ||
|
|
6d932a2c7f | ||
|
|
fd81cd6172 | ||
|
|
6b4a4ed841 | ||
|
|
887f631b8c | ||
|
|
443863d09e | ||
|
|
5301542254 | ||
|
|
a122bde778 | ||
|
|
c9810fd517 | ||
|
|
4c57a56355 | ||
|
|
cdcbd329e6 | ||
|
|
c738f1eea1 | ||
|
|
a8b8bf71b1 | ||
|
|
c60df1b704 | ||
|
|
8d67ba3a3a | ||
|
|
3258152e2c | ||
|
|
78729599a5 | ||
|
|
32eefe9157 | ||
|
|
3e05284250 | ||
|
|
c9ec16969d | ||
|
|
9b1d255931 | ||
|
|
22d94d5688 | ||
|
|
e073141f14 | ||
|
|
f54e535c6a | ||
|
|
c6801c82ea | ||
|
|
a67aa13133 | ||
|
|
d43709715d | ||
|
|
2ddbd0a1a0 | ||
|
|
dc4afa950b | ||
|
|
c03a5ac3ad | ||
|
|
cae5a01af1 | ||
|
|
d59b9b93bd | ||
|
|
f3c5ada9f0 | ||
|
|
4395ab622c | ||
|
|
994956d7c3 | ||
|
|
79f735c59a | ||
|
|
dd67e992bd | ||
|
|
5bdb8bc233 | ||
|
|
c9ae400647 | ||
|
|
9c1517e54e | ||
|
|
3b8282e1d5 | ||
|
|
1635864cbc | ||
|
|
65b2ef8198 | ||
|
|
a9055a8abf | ||
|
|
0b7ee87489 | ||
|
|
9690305b8d | ||
|
|
aa88959899 | ||
|
|
dbb0ca76b4 | ||
|
|
9018b2ac45 | ||
|
|
f407e43e5b | ||
|
|
d7cbcb8c2e | ||
|
|
e27c9c100f | ||
|
|
8ad5f8e427 | ||
|
|
afc64f248a | ||
|
|
c0fb3766e4 | ||
|
|
887a5021af | ||
|
|
e83b9bd158 | ||
|
|
2d0c705839 | ||
|
|
b36ec2ce0e | ||
|
|
b8d143dd72 | ||
|
|
be022a58e4 | ||
|
|
30e0af942a | ||
|
|
8c77a6aa05 | ||
|
|
54fa822408 | ||
|
|
7d564cfbc1 | ||
|
|
bc0bded294 | ||
|
|
d52decc4f1 | ||
|
|
8060376e12 | ||
|
|
eba866d266 | ||
|
|
cc4966f062 | ||
|
|
3216a24be8 | ||
|
|
5e566c8c36 | ||
|
|
80edfee978 | ||
|
|
0e0d1c4f69 | ||
|
|
e15f4cf375 | ||
|
|
c9322ca63a | ||
|
|
45826d6c47 | ||
|
|
dd781cdbdf | ||
|
|
638badaf9b | ||
|
|
0149e482bc | ||
|
|
f683e8c9c0 | ||
|
|
1f8e8037f1 | ||
|
|
10a15c1dd4 | ||
|
|
6e1629ddce | ||
|
|
e273f6b09d | ||
|
|
67c468211d |
@@ -1 +1,4 @@
|
||||
BasedOnStyle: Google
|
||||
PointerAlignment: Left
|
||||
ReferenceAlignment: Left
|
||||
DerivePointerAlignment: false
|
||||
@@ -0,0 +1,2 @@
|
||||
line_length: 80
|
||||
indent: 2
|
||||
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -1,6 +1,9 @@
|
||||
name: build_wheels
|
||||
|
||||
on: [release, workflow_dispatch]
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_wheels:
|
||||
@@ -8,18 +11,21 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, windows-latest, macos-latest]
|
||||
# macos-15-intel: x86-64
|
||||
# macos-15: arm64
|
||||
os: [ubuntu-22.04, ubuntu-22.04-arm, windows-2025, macos-15-intel, macos-15]
|
||||
steps:
|
||||
- run: |
|
||||
git config --global submodule.fetchJobs 8
|
||||
git config --global core.longpaths true
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- if: matrix.os == 'macos-15'
|
||||
run: echo "CIBW_ARCHS=arm64 universal2" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.15.0
|
||||
- uses: actions/upload-artifact@v3
|
||||
uses: pypa/cibuildwheel@v2.23.0
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: python-${{ matrix.os }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
make_sdist:
|
||||
@@ -27,15 +33,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Optional, use if you use setuptools_scm
|
||||
submodules: true # Optional, use if you have submodules
|
||||
|
||||
- name: Build SDist
|
||||
run: pipx run build --sdist
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- name: Confirm SDist can be built
|
||||
run: |
|
||||
# FIXME: why doesn't scikit_build_core automatically download ninja?
|
||||
sudo apt-get update
|
||||
sudo apt-get install ninja-build libtbb-dev
|
||||
pip wheel dist/*.tar.gz
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: python-sdist
|
||||
path: dist/*.tar.gz
|
||||
|
||||
pypi-publish:
|
||||
@@ -47,10 +55,12 @@ jobs:
|
||||
url: https://pypi.org/p/manifold3d
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: artifact
|
||||
pattern: python-*
|
||||
merge-multiple: true
|
||||
path: dist
|
||||
- name: Publish package distributions to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
|
||||
@@ -8,17 +8,26 @@ on:
|
||||
|
||||
jobs:
|
||||
check_format:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: DoozyX/clang-format-lint-action@v0.14
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DoozyX/clang-format-lint-action@v0.20
|
||||
with:
|
||||
source: '.'
|
||||
exclude: '*/third_party'
|
||||
extensions: 'h,cpp,js,ts,html'
|
||||
clangFormatVersion: 12
|
||||
clangFormatVersion: 20
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
- uses: psf/black@stable
|
||||
with:
|
||||
options: "--check --verbose"
|
||||
src: "./bindings/python/examples"
|
||||
# - name: "gersemi cmake check"
|
||||
# run: |
|
||||
# pip3 install gersemi
|
||||
# ./scripts/gersemi-check.sh
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
name: Deploy documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
workflow_run:
|
||||
workflows: [CI]
|
||||
types:
|
||||
- completed
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
deploy_github_pages:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Doxygen Action
|
||||
uses: mattnotmitt/doxygen-action@v1
|
||||
uses: mattnotmitt/doxygen-action@edge
|
||||
|
||||
- name: Move deployables
|
||||
run: |
|
||||
@@ -21,12 +23,15 @@ jobs:
|
||||
mv ./samples ./public
|
||||
mv ./docs ./public
|
||||
|
||||
- name: Download built examples
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
- name: Download manifoldCAD editor, examples and documentation
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: manifold.yml
|
||||
workflow_conclusion: completed
|
||||
pr: ${{github.event.pull_request.number}}
|
||||
# specific to the triggering workflow
|
||||
run_id: ${{github.event.workflow_run.id}}
|
||||
# do not download from old run
|
||||
check_artifacts: true
|
||||
name: wasm
|
||||
path: ./public
|
||||
|
||||
@@ -37,4 +42,4 @@ jobs:
|
||||
publish_branch: gh-pages
|
||||
force_orphan: true
|
||||
cname: manifoldcad.org
|
||||
publish_dir: ./public
|
||||
publish_dir: ./public
|
||||
|
||||
@@ -10,225 +10,379 @@ on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: GCC ${{matrix.gcc}} (CrossSection:${{matrix.cross_section}}, TBB:${{matrix.parallelization}})
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
matrix:
|
||||
parallel_backend: [NONE, TBB]
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event.pull_request.draft == false
|
||||
cross_section: [ON]
|
||||
parallelization: [OFF, ON]
|
||||
os: [ubuntu-24.04]
|
||||
gcc: [13, 14]
|
||||
include:
|
||||
- cross_section: OFF
|
||||
parallelization: ON
|
||||
os: ubuntu-24.04
|
||||
gcc: 14
|
||||
- cross_section: ON
|
||||
parallelization: ON
|
||||
os: ubuntu-22.04
|
||||
gcc: 11
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: gcc-${{ matrix.gcc }}
|
||||
CXX: g++-${{ matrix.gcc }}
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y libglm-dev libgtest-dev libassimp-dev git libtbb-dev libthrust-dev pkg-config libpython3-dev python3 python3-distutils python3-pip lcov
|
||||
pip install trimesh
|
||||
- uses: actions/checkout@v3
|
||||
sudo apt-get update
|
||||
sudo apt-get install libgtest-dev libassimp-dev git libtbb-dev pkg-config libpython3-dev lcov
|
||||
python -m pip install -U trimesh pytest
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: jwlawson/actions-setup-cmake@v1.12
|
||||
- name: Build ${{matrix.backend}}
|
||||
if: matrix.parallel_backend != 'NONE'
|
||||
cmake-version: 4.0.2
|
||||
- name: Build ${{matrix.parallelization}}
|
||||
if: matrix.parallelization != 'OFF'
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_EXPORT=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} .. && make
|
||||
- name: Test ${{matrix.parallel_backend}}
|
||||
if: matrix.parallel_backend != 'NONE'
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_STRICT=ON -DMANIFOLD_PYBIND=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_ASSERT=ON -DMANIFOLD_FLAGS=-UNDEBUG -DMANIFOLD_CROSS_SECTION=${{matrix.cross_section}} -DASSIMP_ENABLE=ON -DMANIFOLD_PAR=${{matrix.parallelization}} .. && make
|
||||
- name: Test ${{matrix.parallelization}}
|
||||
if: matrix.parallelization != 'OFF'
|
||||
run: |
|
||||
export PYTHONPATH=$PYTHONPATH:$(pwd)/build/bindings/python
|
||||
cd build/test
|
||||
./manifold_test
|
||||
cd ../../
|
||||
- name: Test Python bindings ${{matrix.parallelization}}
|
||||
if: matrix.parallelization != 'OFF' && matrix.cross_section == 'ON'
|
||||
run: |
|
||||
export PYTHONPATH=$PYTHONPATH:$(pwd)/build/bindings/python
|
||||
python3 bindings/python/examples/run_all.py -e
|
||||
python3 -m pytest
|
||||
- name: Coverage Report
|
||||
# only do code coverage for default sequential backend, it seems that TBB
|
||||
# backend will cause failure
|
||||
# perhaps issue related to invalid memory access?
|
||||
if: matrix.parallel_backend == 'NONE'
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} -DCODE_COVERAGE=ON .. && make
|
||||
lcov --capture --initial --directory . --output-file ./code_coverage_init.info
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_STRICT=ON -DMANIFOLD_CROSS_SECTION=${{matrix.cross_section}} -DMANIFOLD_PAR=${{matrix.parallelization}} -DCODE_COVERAGE=ON .. && make
|
||||
lcov --capture --gcov-tool gcov-${{ matrix.gcc }} --ignore-errors mismatch --initial --directory . --output-file ./code_coverage_init.info
|
||||
cd test
|
||||
./manifold_test
|
||||
cd ../
|
||||
lcov --capture --directory . --output-file ./code_coverage_test.info
|
||||
lcov --capture --gcov-tool gcov-${{ matrix.gcc }} --ignore-errors mismatch --directory . --output-file ./code_coverage_test.info
|
||||
lcov --add-tracefile ./code_coverage_init.info --add-tracefile ./code_coverage_test.info --output-file ./code_coverage_total.info
|
||||
lcov --remove ./code_coverage_total.info '/usr/*' '*/third_party/*' '*/test/*' '*/extras/*' '*/bindings/*' --output-file ./code_coverage.info
|
||||
- uses: codecov/codecov-action@v2
|
||||
if: matrix.parallel_backend == 'NONE'
|
||||
lcov --extract ./code_coverage_total.info "/*/manifold/src/*" --output-file ./code_coverage.info
|
||||
cd ../
|
||||
- uses: codecov/codecov-action@v5
|
||||
if: matrix.parallelization == 'OFF'
|
||||
with:
|
||||
disable_search: true
|
||||
files: build/code_coverage.info
|
||||
fail_ci_if_error: false
|
||||
name: ${{matrix.parallel_backend}}
|
||||
|
||||
build_cbind:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event.pull_request.draft == false
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
name: ${{matrix.parallelization}}
|
||||
token: ${{secrets.CODECOV_TOKEN}}
|
||||
verbose: true
|
||||
- name: test cmake consumer
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y libgtest-dev libglm-dev libassimp-dev git libtbb-dev pkg-config libpython3-dev python3 python3-distutils python3-pip
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: jwlawson/actions-setup-cmake@v1.12
|
||||
- name: Build C bindings with TBB
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_CBIND=ON -DMANIFOLD_PAR=TBB .. && make
|
||||
- name: Test ${{matrix.parallel_backend}}
|
||||
run: |
|
||||
cd build/test
|
||||
./manifold_test --gtest_filter=CBIND.*
|
||||
sudo cmake --install .
|
||||
cd ..
|
||||
./scripts/test-cmake.sh
|
||||
|
||||
build_wasm:
|
||||
name: WASM (TBB:${{matrix.parallelization}}, DEBUG:${{matrix.debug}})
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event.pull_request.draft == false
|
||||
strategy:
|
||||
matrix:
|
||||
parallelization: [OFF, ON]
|
||||
debug: [OFF, ON]
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y nodejs libglm-dev
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y nodejs
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup WASM
|
||||
run: |
|
||||
# setup emscripten
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install 3.1.45
|
||||
./emsdk activate 3.1.45
|
||||
- uses: jwlawson/actions-setup-cmake@v1.12
|
||||
- name: Build WASM
|
||||
./emsdk install 3.1.64
|
||||
./emsdk activate 3.1.64
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
- name: Build WASM ${{matrix.parallelization}}
|
||||
run: |
|
||||
source ./emsdk/emsdk_env.sh
|
||||
mkdir build
|
||||
cd build
|
||||
emcmake cmake -DCMAKE_BUILD_TYPE=Release .. && emmake make
|
||||
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DMANIFOLD_STRICT=ON -DMANIFOLD_PAR=${{matrix.parallelization}} -DMANIFOLD_USE_BUILTIN_TBB=ON -DMANIFOLD_DEBUG=${{matrix.debug}} -DMANIFOLD_ASSERT=${{matrix.debug}} .. && emmake make
|
||||
- name: Test WASM
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
cd build/test
|
||||
node ./manifold_test.js
|
||||
- name: Test examples
|
||||
- name: Run unit tests
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
cd bindings/wasm/examples
|
||||
cd bindings/wasm
|
||||
npm ci
|
||||
npm run build
|
||||
npm test
|
||||
- name: Upload WASM files
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Isolated npm smoke test
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
set -ev -o pipefail
|
||||
cd bindings/wasm
|
||||
wasmpath=$(pwd)
|
||||
npmtestpath=../npmtest
|
||||
# Create an npm package.
|
||||
npm ci && npm pack
|
||||
# Install it in an empty directory.
|
||||
mkdir -p ${npmtestpath} && cd ${npmtestpath}
|
||||
npm install ${wasmpath}/manifold-3d*.tgz
|
||||
cp ${wasmpath}/test/fixtures/npm/* .
|
||||
# Positive case smoke test.
|
||||
npx manifold-cad ./unitSphere.mjs ./unitSphere.glb && echo "Positive smoke test succeeded"
|
||||
# Negative case smoke test.
|
||||
npx manifold-cad ./unitSphereNoManifoldImport.mjs ./unitSphereNoManifoldImport.glb || echo "Negative smoke test failed as expected"
|
||||
- name: Build manifoldCAD editor
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
cd bindings/wasm
|
||||
npm run ci:editor
|
||||
npm run build:editor
|
||||
- name: Build WASM examples
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
cd bindings/wasm/examples
|
||||
npm run ci:examples
|
||||
npm run build:examples
|
||||
- name: Build WASM documentation and site
|
||||
if: matrix.parallelization == 'OFF'
|
||||
run: |
|
||||
cd bindings/wasm
|
||||
npm run docs
|
||||
npm run public
|
||||
- name: Upload manifoldCAD editor, examples and documentation
|
||||
uses: actions/upload-artifact@v4
|
||||
if: github.event_name == 'push' && matrix.parallelization == 'OFF' && matrix.debug == 'OFF'
|
||||
with:
|
||||
name: wasm
|
||||
path: bindings/wasm/examples/dist/
|
||||
path: bindings/wasm/public/
|
||||
retention-days: 90
|
||||
overwrite: true
|
||||
|
||||
build_fuzzer:
|
||||
name: fuzzer
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y libgtest-dev clang
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMANIFOLD_STRICT=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_FUZZ=ON -DMANIFOLD_PYBIND=OFF -DCMAKE_CXX_COMPILER=clang++ ..
|
||||
make
|
||||
|
||||
build_fuzzer_mac:
|
||||
name: fuzzer mac
|
||||
timeout-minutes: 30
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install common dependencies
|
||||
run: |
|
||||
brew install googletest
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
cmake-version: 3.31.6
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMANIFOLD_STRICT=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_FUZZ=ON -DMANIFOLD_PYBIND=OFF -DCMAKE_CXX_COMPILER=clang++ -DMANIFOLD_PAR=OFF ..
|
||||
ASAN_OPTIONS=detect_container_overflow=0 make
|
||||
|
||||
build_windows:
|
||||
name: Windows (TBB:${{matrix.parallelization}}, SHARED:${{matrix.shared}})
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
parallel_backend: [NONE, TBB]
|
||||
max-parallel: 1
|
||||
runs-on: windows-2019
|
||||
if: github.event.pull_request.draft == false
|
||||
parallelization: [OFF, ON]
|
||||
shared: [OFF, ON]
|
||||
runs-on: windows-2025
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: jwlawson/actions-setup-cmake@v1.12
|
||||
cmake-version: 4.0.2
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Build ${{matrix.backend}}
|
||||
- name: Build ${{matrix.parallelization}}
|
||||
shell: powershell
|
||||
run: |
|
||||
cmake . -DCMAKE_BUILD_TYPE=Release -B build -DMANIFOLD_DEBUG=ON -DPYBIND11_FINDPYTHON=OFF -DMANIFOLD_PAR=${{matrix.parallel_backend}} -A x64
|
||||
cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=${{matrix.shared}} -DMANIFOLD_STRICT=ON -DMANIFOLD_USE_BUILTIN_TBB=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_ASSERT=ON -DMANIFOLD_PAR=${{matrix.parallelization}} -A x64 -B build
|
||||
cd build
|
||||
cmake --build . --target ALL_BUILD --config Release
|
||||
- name: Test ${{matrix.parallel_backend}}
|
||||
- name: Test dll location
|
||||
if: matrix.shared == 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
cd build/test
|
||||
./Release/manifold_test.exe
|
||||
ls ./build/lib/Release
|
||||
[ -f ./build/lib/Release/manifold.dll ]
|
||||
[ -f ./build/lib/Release/manifoldc.dll ]
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
cp ./build/lib/Release/* ./build/bin/Release
|
||||
cd build/bin/Release
|
||||
./manifold_test.exe
|
||||
cd ../../
|
||||
- name: test cmake consumer
|
||||
run: |
|
||||
cd build
|
||||
cmake --install .
|
||||
cd ..
|
||||
./scripts/test-cmake.sh
|
||||
|
||||
build_mxe:
|
||||
name: MXE (TBB:${{matrix.parallelization == 'ON'}})
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
parallel_backend: [NONE, TBB]
|
||||
max-parallel: 1
|
||||
parallelization: [OFF, ON]
|
||||
runs-on: ubuntu-latest
|
||||
container: openscad/mxe-x86_64-gui:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_PYBIND=OFF -DMANIFOLD_DEBUG=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} .. && make
|
||||
- name: Test
|
||||
run: |
|
||||
cd build/test
|
||||
./manifold_test
|
||||
export MXEDIR=/mxe
|
||||
export MXE_TARGETS=x86_64-w64-mingw32.static.posix
|
||||
export MXEDIR=$HOME/openscad_deps/mxe
|
||||
export MXETARGETDIR=$MXEDIR/usr/$MXE_TARGETS
|
||||
export PATH=/mxe/usr/bin:$PATH
|
||||
export CMAKE=$MXE_TARGETS-cmake
|
||||
$CMAKE -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DMANIFOLD_STRICT=ON -DMANIFOLD_PYBIND=OFF -DMANIFOLD_CBIND=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_PAR=${{matrix.parallelization}} .. && make
|
||||
|
||||
build_mac:
|
||||
name: MacOS (TBB:${{matrix.parallelization == 'ON'}}, shared lib:${{matrix.shared == 'ON'}}, ${{matrix.os}})
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
parallel_backend: [NONE, TBB]
|
||||
runs-on: macos-latest
|
||||
if: github.event.pull_request.draft == false
|
||||
parallelization: [OFF, ON]
|
||||
shared: [OFF, ON]
|
||||
# macos-15-intel: intel
|
||||
# macos-latest: arm
|
||||
os: [macos-15-intel, macos-latest]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- name: Install common dependencies
|
||||
run: |
|
||||
brew install pkg-config googletest assimp
|
||||
pip install trimesh
|
||||
brew install googletest assimp
|
||||
pip install trimesh pytest
|
||||
- name: Install TBB
|
||||
if: matrix.parallel_backend == 'TBB'
|
||||
if: matrix.parallelization == 'ON'
|
||||
run: brew install tbb
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: jwlawson/actions-setup-cmake@v1.12
|
||||
cmake-version: 4.0.2
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_EXPORT=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} .. && make
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=${{matrix.shared}} -DMANIFOLD_STRICT=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_ASSERT=ON -DMANIFOLD_PYBIND=ON -DASSIMP_ENABLE=ON -DMANIFOLD_PAR=${{matrix.parallelization}} .. && make
|
||||
- name: Test
|
||||
run: |
|
||||
cd build/test
|
||||
./manifold_test
|
||||
cd ../../
|
||||
- name: test cmake consumer
|
||||
run: |
|
||||
cd build
|
||||
sudo cmake --install .
|
||||
cd ..
|
||||
./scripts/test-cmake.sh
|
||||
- name: test pkg-config consumer
|
||||
if: matrix.shared == 'ON'
|
||||
run: |
|
||||
LDFLAGS=-Wl,-rpath,/usr/local/lib ./scripts/test-pkgconfig.sh
|
||||
|
||||
build_mac_builtin_tbb:
|
||||
timeout-minutes: 30
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Install common dependencies
|
||||
run: |
|
||||
brew install googletest
|
||||
pip install trimesh pytest
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
cmake-version: 4.0.2
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_STRICT=ON -DMANIFOLD_USE_BUILTIN_TBB=ON -DMANIFOLD_DEBUG=ON -DMANIFOLD_ASSERT=ON -DMANIFOLD_PYBIND=OFF -DMANIFOLD_PAR=ON .. && make
|
||||
- name: Test
|
||||
run: |
|
||||
cd build/test
|
||||
./manifold_test
|
||||
cd ../../
|
||||
- name: test cmake consumer
|
||||
run: |
|
||||
cd build
|
||||
sudo cmake --install .
|
||||
cd ..
|
||||
./scripts/test-cmake.sh
|
||||
LDFLAGS=-Wl,-rpath,/usr/local/lib ./scripts/test-pkgconfig.sh
|
||||
|
||||
build_mac_builtin_tbb_subdir:
|
||||
timeout-minutes: 30
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Install common dependencies
|
||||
run: |
|
||||
brew install googletest
|
||||
pip install trimesh pytest
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
cmake-version: 4.0.2
|
||||
- name: test cmake consumer
|
||||
run: |
|
||||
cd ..
|
||||
./manifold/scripts/test-cmake-subdir.sh
|
||||
|
||||
build_nix:
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
variant: [none, tbb, js]
|
||||
variant: [manifold-none, manifold-tbb, manifold-js, manifold-js-tbb, manifold3d]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.draft == false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: cachix/install-nix-action@v22
|
||||
- run: nix build -L '.?submodules=1#manifold-${{matrix.variant}}'
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- run: nix build -L '.?submodules=1#${{matrix.variant}}'
|
||||
|
||||
build_nix_python:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.draft == false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: cachix/install-nix-action@v22
|
||||
- run: nix build -L '.?submodules=1#manifold3d'
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
name: publish_npm
|
||||
|
||||
on: [release, workflow_dispatch]
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy_github_pages:
|
||||
runs-on: ubuntu-20.04
|
||||
publish_npm:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Download built examples
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: manifold.yml
|
||||
workflow_conclusion: completed
|
||||
branch: master
|
||||
check_artifacts: true
|
||||
name: wasm
|
||||
path: ./bindings/wasm/
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
cd ./bindings/wasm/
|
||||
npm install
|
||||
npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
name: Release File
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
upload_archive:
|
||||
name: Upload archive
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
ref=${{ github.ref_name }}
|
||||
echo "release_name=manifold-${ref#v}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: ${{ env.release_name }}
|
||||
submodules: recursive
|
||||
- name: Build archive
|
||||
run: >
|
||||
tar --exclude=".git*" -cz ${{ env.release_name }} -f ${{ env.release_name }}.tar.gz
|
||||
- name: Log checksum
|
||||
run: >
|
||||
sha256sum ${{ env.release_name }}.tar.gz
|
||||
- name: Add file to release
|
||||
run: |
|
||||
cd ${{ env.release_name }} || exit 1
|
||||
gh release upload ${{ github.ref_name }} ../${{ env.release_name }}.tar.gz
|
||||
env:
|
||||
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
@@ -9,7 +9,6 @@
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
@@ -112,11 +111,27 @@ node_modules/
|
||||
bindings/wasm/examples/built
|
||||
bindings/wasm/examples/dist
|
||||
bindings/wasm/examples/public/manifold*
|
||||
bindings/wasm/docs
|
||||
__pycache__
|
||||
.vscode/c_cpp_properties.json
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
.cache
|
||||
CMakeUserPresets.json
|
||||
CMakeSettings.json
|
||||
|
||||
# PyCharm
|
||||
.idea
|
||||
.idea
|
||||
|
||||
# Temporary files
|
||||
*~
|
||||
\#*\#
|
||||
.\#*
|
||||
[._]*.s[a-v][a-z]
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-v][a-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
# Benchmark stl files
|
||||
extras/ember_tests/testfiles/raw_meshes
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
[submodule "src/third_party/clipper2"]
|
||||
path = src/third_party/clipper2
|
||||
url = https://github.com/AngusJohnson/clipper2
|
||||
[submodule "src/third_party/quickhull"]
|
||||
path = src/third_party/quickhull
|
||||
url = https://github.com/akuukka/quickhull
|
||||
[submodule "bindings/python/third_party/nanobind"]
|
||||
path = bindings/python/third_party/nanobind
|
||||
url = https://github.com/wjakob/nanobind
|
||||
@@ -6,12 +6,13 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "manifold test",
|
||||
"type": "cppdbg",
|
||||
"type": "lldb-dap",
|
||||
"MIMode": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/test/manifold_test",
|
||||
"args": [
|
||||
"--gtest_break_on_failure",
|
||||
"--gtest_filter=Manifold.GetMesh"
|
||||
"--gtest_catch_exceptions=0",
|
||||
"--gtest_filter=SDF.SineSurface"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/build/test",
|
||||
@@ -20,7 +21,8 @@
|
||||
"name": "MALLOC_CHECK_",
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
],
|
||||
"externalConsole": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -108,17 +108,29 @@
|
||||
"latch": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"span": "cpp",
|
||||
"__sso_allocator": "cpp"
|
||||
"__sso_allocator": "cpp",
|
||||
"source_location": "cpp",
|
||||
"format": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ranges": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"execution": "cpp",
|
||||
"csetjmp": "cpp",
|
||||
"cuchar": "cpp",
|
||||
"propagate_const": "cpp",
|
||||
"scoped_allocator": "cpp"
|
||||
},
|
||||
"C_Cpp.clang_format_fallbackStyle": "google",
|
||||
"editor.formatOnSave": true,
|
||||
"cmake.configureArgs": [
|
||||
"-DBUILD_SHARED_LIBS=ON",
|
||||
"-DMANIFOLD_CBIND=ON",
|
||||
"-DMANIFOLD_PYBIND=ON",
|
||||
"-DMANIFOLD_EXPORT=ON",
|
||||
"-DMANIFOLD_DEBUG=ON",
|
||||
"-DMANIFOLD_USE_CUDA=OFF",
|
||||
"-DMANIFOLD_PAR=TBB",
|
||||
"-DMANIFOLD_ASSERT=ON",
|
||||
"-DMANIFOLD_PAR=ON",
|
||||
"-DMANIFOLD_FUZZ=OFF",
|
||||
"-DCODE_COVERAGE=OFF",
|
||||
"-DCMAKE_CXX_FLAGS=''" //'-fsanitize=address,undefined'"
|
||||
],
|
||||
@@ -136,8 +148,11 @@
|
||||
"Gyroid",
|
||||
"halfedge",
|
||||
"halfedges",
|
||||
"Minkowski",
|
||||
"Tris",
|
||||
"Verts"
|
||||
"Verts",
|
||||
"Voxel",
|
||||
"voxels"
|
||||
],
|
||||
"javascript.format.semicolons": "insert",
|
||||
"[python]": {
|
||||
@@ -145,4 +160,8 @@
|
||||
},
|
||||
"python.formatting.provider": "none",
|
||||
"clang-format.executable": "clang-format",
|
||||
"clangd.arguments": [
|
||||
"--header-insertion=never"
|
||||
],
|
||||
"editor.defaultFormatter": "xaver.clang-format",
|
||||
}
|
||||
@@ -15,83 +15,309 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(manifold LANGUAGES CXX)
|
||||
|
||||
# Use C++17
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
set(MANIFOLD_PAR "NONE" CACHE STRING "Parallel backend, either \"TBB\" or \"NONE\"")
|
||||
set(MANIFOLD_FLAGS "" CACHE STRING "Manifold compiler flags")
|
||||
option(MANIFOLD_EXPORT "Build mesh export (via assimp) utility library" OFF)
|
||||
option(MANIFOLD_TEST "Enable testing suite" ON)
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
include(GNUInstallDirs)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
# Define Manifold version
|
||||
set(MANIFOLD_VERSION_MAJOR 3)
|
||||
set(MANIFOLD_VERSION_MINOR 4)
|
||||
set(MANIFOLD_VERSION_PATCH 0)
|
||||
set(
|
||||
MANIFOLD_VERSION
|
||||
"${MANIFOLD_VERSION_MAJOR}.${MANIFOLD_VERSION_MINOR}.${MANIFOLD_VERSION_PATCH}"
|
||||
)
|
||||
|
||||
# Primary user facing options
|
||||
option(MANIFOLD_CROSS_SECTION "Build CrossSection for 2D support" ON)
|
||||
option(MANIFOLD_DEBUG "Enable debug tracing/timing" OFF)
|
||||
option(MANIFOLD_ASSERT "Enable assertions - requires MANIFOLD_DEBUG" OFF)
|
||||
option(MANIFOLD_STRICT "Treat compile warnings as fatal build errors" OFF)
|
||||
option(
|
||||
MANIFOLD_DOWNLOADS
|
||||
"Allow Manifold build to download missing dependencies"
|
||||
ON
|
||||
)
|
||||
option(MANIFOLD_PAR "Enable Parallel backend" OFF)
|
||||
option(
|
||||
MANIFOLD_OPTIMIZED
|
||||
"Force optimized build, even with debugging enabled"
|
||||
OFF
|
||||
)
|
||||
option(MANIFOLD_TEST "Enable testing suite" ON)
|
||||
option(MANIFOLD_PYBIND "Build python bindings" OFF)
|
||||
# MANIFOLD_CBIND is only available when MANIFOLD_CROSS_SECTION is enabled
|
||||
cmake_dependent_option(
|
||||
MANIFOLD_CBIND
|
||||
"Build C (FFI) bindings"
|
||||
ON
|
||||
"MANIFOLD_CROSS_SECTION"
|
||||
OFF
|
||||
)
|
||||
# MANIFOLD_JSBIND is only available when building with Emscripten
|
||||
cmake_dependent_option(
|
||||
MANIFOLD_JSBIND
|
||||
"Build js binding"
|
||||
ON
|
||||
"EMSCRIPTEN"
|
||||
OFF
|
||||
)
|
||||
# These three options can force the build to avoid using the system version of
|
||||
# the dependency
|
||||
# This will either use the provided source directory via
|
||||
# FETCHCONTENT_SOURCE_DIR_XXX, or fetch the source from GitHub.
|
||||
# Note that the dependency will be built as static dependency to avoid dynamic
|
||||
# library conflict.
|
||||
# When the system package is unavailable, the option will be automatically set
|
||||
# to true.
|
||||
option(MANIFOLD_USE_BUILTIN_TBB "Use builtin tbb" OFF)
|
||||
option(MANIFOLD_USE_BUILTIN_CLIPPER2 "Use builtin clipper2" OFF)
|
||||
option(MANIFOLD_USE_BUILTIN_NANOBIND "Use builtin nanobind" OFF)
|
||||
|
||||
option(MANIFOLD_PYBIND "Build python bindings" ON)
|
||||
option(MANIFOLD_CBIND "Build C (FFI) bindings" OFF)
|
||||
option(MANIFOLD_JSBIND "Build js binding" ${EMSCRIPTEN})
|
||||
# default to Release build
|
||||
option(CMAKE_BUILD_TYPE "Build type" Release)
|
||||
# default to building shared library
|
||||
option(BUILD_SHARED_LIBS "Build shared library" ON)
|
||||
# Set some option values in the CMake cache
|
||||
set(MANIFOLD_FLAGS "" CACHE STRING "Manifold compiler flags")
|
||||
|
||||
option(TRACY_ENABLE "Use tracy profiling" OFF)
|
||||
# Development options
|
||||
option(TRACY_ENABLE "Use tracy profiling" OFF)
|
||||
option(TRACY_MEMORY_USAGE "Track memory allocation with tracy (expensive)" OFF)
|
||||
option(BUILD_TEST_CGAL "Build CGAL performance comparisons" OFF)
|
||||
option(MANIFOLD_FUZZ "Enable fuzzing tests" OFF)
|
||||
option(ASSIMP_ENABLE "Enable ASSIMP for utilities in extras" OFF)
|
||||
mark_as_advanced(TRACY_ENABLE)
|
||||
mark_as_advanced(TRACY_MEMORY_USAGE)
|
||||
mark_as_advanced(MANIFOLD_FUZZ)
|
||||
mark_as_advanced(ASSIMP_ENABLE)
|
||||
|
||||
# Always build position independent code for relocatability
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# Various Compiler Flags
|
||||
if(MANIFOLD_FUZZ)
|
||||
# we should enable debug checks
|
||||
set(MANIFOLD_DEBUG ON)
|
||||
# enable fuzztest fuzzing mode
|
||||
set(FUZZTEST_FUZZING_MODE ON)
|
||||
# address sanitizer required
|
||||
add_compile_options(-fsanitize=address)
|
||||
add_link_options(-fsanitize=address)
|
||||
endif()
|
||||
|
||||
if(TRACY_ENABLE)
|
||||
option(CMAKE_BUILD_TYPE "Build type" RelWithDebInfo)
|
||||
if(TRACY_MEMORY_USAGE)
|
||||
set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} -DTRACY_MEMORY_USAGE)
|
||||
endif()
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
|
||||
endif()
|
||||
else()
|
||||
option(CMAKE_BUILD_TYPE "Build type" Release)
|
||||
endif()
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
message("Building for Emscripten")
|
||||
set(MANIFOLD_FLAGS -fexceptions -D_LIBCUDACXX_HAS_THREAD_API_EXTERNAL -D_LIBCUDACXX_HAS_THREAD_API_CUDA)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sALLOW_MEMORY_GROWTH=1 -fexceptions -sDISABLE_EXCEPTION_CATCHING=0")
|
||||
set(MANIFOLD_PYBIND OFF)
|
||||
endif()
|
||||
|
||||
if(MANIFOLD_PYBIND)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
if(Python_VERSION VERSION_LESS 3.12)
|
||||
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
|
||||
else()
|
||||
find_package(Python COMPONENTS Interpreter Development.SABIModule REQUIRED)
|
||||
add_link_options(-sALLOW_MEMORY_GROWTH=1)
|
||||
add_link_options(-sMAXIMUM_MEMORY=4294967296)
|
||||
if(MANIFOLD_PAR)
|
||||
set(CMAKE_THREAD_LIBS_INIT "-pthread")
|
||||
add_compile_options(-pthread)
|
||||
# mimalloc is needed for good performance
|
||||
add_link_options(-sMALLOC=mimalloc)
|
||||
add_link_options(-sPTHREAD_POOL_SIZE=4)
|
||||
# The default stack size apparently causes problem when parallelization is
|
||||
# enabled.
|
||||
add_link_options(-sSTACK_SIZE=30MB)
|
||||
add_link_options(-sINITIAL_MEMORY=32MB)
|
||||
endif()
|
||||
if(MANIFOLD_DEBUG)
|
||||
list(APPEND MANIFOLD_FLAGS -fexceptions)
|
||||
add_link_options(-fexceptions)
|
||||
add_link_options(-sDISABLE_EXCEPTION_CATCHING=0)
|
||||
endif()
|
||||
set(MANIFOLD_PYBIND OFF)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
endif()
|
||||
|
||||
if(CMAKE_EXPORT_COMPILE_COMMANDS AND NOT EMSCRIPTEN)
|
||||
# for nixos
|
||||
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES
|
||||
${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
|
||||
set(
|
||||
CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES
|
||||
${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} /DNOMINMAX)
|
||||
if(MSVC)
|
||||
list(APPEND MANIFOLD_FLAGS /DNOMINMAX /bigobj)
|
||||
else()
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(WARNING_FLAGS -Werror -Wall -Wno-sign-compare -Wno-unused -Wno-array-bounds -Wno-stringop-overflow)
|
||||
else()
|
||||
set(WARNING_FLAGS -Werror -Wall -Wno-sign-compare -Wno-unused)
|
||||
list(
|
||||
APPEND
|
||||
WARNING_FLAGS
|
||||
-Wall
|
||||
-Wno-unknown-warning-option
|
||||
-Wno-unused
|
||||
-Wno-shorten-64-to-32
|
||||
-Wno-alloc-size-larger-than
|
||||
)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
list(APPEND WARNING_FLAGS -Wno-format)
|
||||
endif()
|
||||
elseif(PROJECT_IS_TOP_LEVEL)
|
||||
# only do -Werror if we are the top level project and
|
||||
# MANIFOLD_STRICT is on
|
||||
if(MANIFOLD_STRICT)
|
||||
list(APPEND WARNING_FLAGS -Werror)
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND MANIFOLD_FLAGS ${WARNING_FLAGS})
|
||||
if(
|
||||
MANIFOLD_OPTIMIZED
|
||||
OR "${CMAKE_BUILD_TYPE}" STREQUAL "Release"
|
||||
OR "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo"
|
||||
)
|
||||
list(APPEND MANIFOLD_FLAGS -O3)
|
||||
endif()
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
|
||||
list(APPEND MANIFOLD_FLAGS -fno-omit-frame-pointer)
|
||||
endif()
|
||||
# disable fp math optimizations, e.g. FMA for supported architectures, as
|
||||
# this changes floating-point results
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-ffp-contract=off HAS_FP_CONTRACT)
|
||||
check_cxx_compiler_flag(-fexcess-precision=standard HAS_FP_PRECISION)
|
||||
if(HAS_FP_CONTRACT)
|
||||
list(APPEND MANIFOLD_FLAGS -ffp-contract=off)
|
||||
endif()
|
||||
if(HAS_FP_PRECISION)
|
||||
list(APPEND MANIFOLD_FLAGS -fexcess-precision=standard)
|
||||
endif()
|
||||
if(CODE_COVERAGE)
|
||||
list(
|
||||
APPEND
|
||||
MANIFOLD_FLAGS
|
||||
-coverage
|
||||
-fno-inline-small-functions
|
||||
-fkeep-inline-functions
|
||||
-fkeep-static-functions
|
||||
)
|
||||
add_link_options(-coverage)
|
||||
endif()
|
||||
set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} ${WARNING_FLAGS} -O3)
|
||||
endif()
|
||||
|
||||
if(CODE_COVERAGE AND NOT MSVC)
|
||||
set(COVERAGE_FLAGS -coverage -fno-inline-small-functions -fkeep-inline-functions -fkeep-static-functions)
|
||||
set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} ${COVERAGE_FLAGS})
|
||||
add_link_options("-coverage")
|
||||
endif()
|
||||
# RPath settings
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
list(
|
||||
FIND
|
||||
CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
|
||||
${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
|
||||
isSystemDir
|
||||
)
|
||||
if("${isSystemDir}" STREQUAL "-1")
|
||||
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
endif("${isSystemDir}" STREQUAL "-1")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/manifoldDeps.cmake)
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/configHelper.cmake)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(bindings)
|
||||
|
||||
if(MANIFOLD_EXPORT)
|
||||
add_subdirectory(meshIO)
|
||||
endif()
|
||||
|
||||
if(MANIFOLD_TEST)
|
||||
add_subdirectory(samples)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(extras)
|
||||
endif()
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/info.cmake)
|
||||
|
||||
# note that the path ${CMAKE_CURRENT_BINARY_DIR}/include is included when we
|
||||
# build the manifold target (as ${PROJECT_SOURCE_DIR}/include), so users can
|
||||
# include manifold/version.h without installing our library.
|
||||
configure_file(
|
||||
cmake/version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/manifold/version.h
|
||||
@ONLY
|
||||
)
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/manifold/version.h
|
||||
PROPERTIES GENERATED TRUE
|
||||
)
|
||||
|
||||
# If it's an EMSCRIPTEN build, we're done
|
||||
if(EMSCRIPTEN)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# CMake exports
|
||||
configure_file(
|
||||
cmake/manifoldConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/manifoldConfig.cmake
|
||||
@ONLY
|
||||
)
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/manifoldConfigVersion.cmake
|
||||
VERSION ${MANIFOLD_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
# Location of inputs for CMake find_package - see:
|
||||
# https://cmake.org/cmake/help/latest/command/find_package.html
|
||||
set(EXPORT_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake)
|
||||
|
||||
install(
|
||||
EXPORT manifoldTargets
|
||||
NAMESPACE manifold::
|
||||
DESTINATION ${EXPORT_INSTALL_DIR}/manifold
|
||||
)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/manifoldConfigVersion.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/manifoldConfig.cmake
|
||||
DESTINATION ${EXPORT_INSTALL_DIR}/manifold
|
||||
)
|
||||
|
||||
# install public headers
|
||||
set(
|
||||
MANIFOLD_PUBLIC_HDRS
|
||||
common.h
|
||||
linalg.h
|
||||
manifold.h
|
||||
optional_assert.h
|
||||
polygon.h
|
||||
vec_view.h
|
||||
$<$<BOOL:${MANIFOLD_CROSS_SECTION}>:cross_section.h>
|
||||
)
|
||||
list(TRANSFORM MANIFOLD_PUBLIC_HDRS PREPEND include/manifold/)
|
||||
list(
|
||||
APPEND
|
||||
MANIFOLD_PUBLIC_HDRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/manifold/version.h
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${MANIFOLD_PUBLIC_HDRS}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/manifold
|
||||
)
|
||||
|
||||
# PkgConfig file
|
||||
if(MANIFOLD_PAR)
|
||||
set(TEMPLATE_OPTIONAL_TBB "tbb")
|
||||
endif()
|
||||
if(MANIFOLD_CROSS_SECTION)
|
||||
set(TEMPLATE_OPTIONAL_CLIPPER "Clipper2")
|
||||
endif()
|
||||
configure_file(
|
||||
cmake/manifold.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/manifold.pc
|
||||
@ONLY
|
||||
)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/manifold.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
|
||||
@@ -3,19 +3,6 @@
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
just a few small guidelines you need to follow.
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
Contributions to this project must be accompanied by a Contributor License
|
||||
Agreement (CLA). You (or your employer) retain the copyright to your
|
||||
contribution; this simply gives us permission to use and redistribute your
|
||||
contributions as part of the project. Head over to
|
||||
<https://cla.developers.google.com/> to see your current agreements on file or
|
||||
to sign a new one.
|
||||
|
||||
You generally only need to submit a CLA once, so if you've already submitted one
|
||||
(even if it was for a different project), you probably don't need to do it
|
||||
again.
|
||||
|
||||
## Code Reviews
|
||||
|
||||
All submissions, including submissions by project members, require review. We
|
||||
@@ -26,4 +13,4 @@ information on using pull requests.
|
||||
## Community Guidelines
|
||||
|
||||
This project follows
|
||||
[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
|
||||
[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
|
||||
|
||||
@@ -1,56 +1,100 @@
|
||||
# About 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++ Documentation**](https://manifoldcad.org/docs/html/classmanifold_1_1_manifold.html) | [**ManifoldCAD User Guide**](https://manifoldcad.org/docs/jsuser/) | [**JS/TS/WASM API**](https://manifoldcad.org/docs/jsapi/) | [**Algorithm Documentation**](https://github.com/elalish/manifold/wiki/Manifold-Library) | [**Blog Posts**](https://elalish.blogspot.com/search/label/Manifold) | [**Web Examples**](https://manifoldcad.org/model-viewer.html)
|
||||
|
||||
[Manifold](https://github.com/elalish/manifold) is a geometry library dedicated to creating and operating on manifold triangle meshes. A [manifold mesh](https://github.com/elalish/manifold/wiki/Manifold-Library#manifoldness) is a mesh that represents a solid object, and so is very important in manufacturing, CAD, structural analysis, etc. Manifold also supports arbitrary vertex properties and enables mapping of materials for rendering use-cases. Our primary goal is reliability: guaranteed manifold output without caveats or edge cases. Our secondary goal is performance: efficient algorithms that make extensive use of parallelization, or pipelining when only a single thread is available.
|
||||
|
||||
## Users
|
||||
|
||||
[OpenSCAD](https://openscad.org/), [IFCjs](https://ifcjs.github.io/info/), [Grid.Space](https://grid.space/), and [OCADml](https://github.com/OCADml/OManifold) have all integrated our Manifold geometry kernel! Why? Because its reliability is guaranteed and it's 1,000 times faster than other libraries. See our [usage](https://github.com/elalish/manifold/discussions/340) and [performance](https://github.com/elalish/manifold/discussions/383) discussions for all the latest and to add your own projects & analyses.
|
||||
Here is an incomplete list of our users, whose integrations may be anywhere from in-progress to released. Please feel free to send a PR to update this list with your own project - it's quite difficult for us to keep track.
|
||||
|
||||
## [ManifoldCAD.org](https://manifoldcad.org)
|
||||
| | | |
|
||||
| --- | --- | --- |
|
||||
| [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) | | |
|
||||
|
||||
If you like OpenSCAD / JSCAD, you might also like ManifoldCAD - our own solid modelling web app. Our WASM is not multithreaded yet, but it's still quite fast and a good way to test out our Manifold library.
|
||||
### Bindings & Packages
|
||||
|
||||

|
||||
Manifold has bindings to many other languages, some maintained in this repository, and others elsewhere. It can also be built in C++ via [vcpkg](https://github.com/microsoft/vcpkg.git).
|
||||
|
||||
### Note for Firefox users
|
||||
| Language | Packager | Name | Maintenance |
|
||||
| --- | --- | --- | --- |
|
||||
| C | N/A | N/A | internal |
|
||||
| C++ | vcpkg | [manifold](https://github.com/microsoft/vcpkg/tree/master/ports/manifold) | external |
|
||||
| TS/JS | npm | [manifold-3d](https://www.npmjs.com/package/manifold-3d) | internal |
|
||||
| Python | PyPI | [manifold3d](https://pypi.org/project/manifold3d/) | internal |
|
||||
| Java | N/A | [manifold](https://github.com/SovereignShop/manifold) | external |
|
||||
| Clojure | N/A | [clj-manifold3d](https://github.com/SovereignShop/clj-manifold3d) | external |
|
||||
| C# | NuGet | [ManifoldNET](https://www.nuget.org/packages/ManifoldNET) | external |
|
||||
| Julia | Packages | [ManifoldBindings.jl](https://juliapackages.com/p/manifoldbindings) | external |
|
||||
| OCaml | N/A | [OManifold](https://ocadml.github.io/OManifold/OManifold/index.html) | external |
|
||||
| Swift | SPM | [Manifold-Swift](https://github.com/tomasf/manifold-swift) | external |
|
||||
|
||||
If you find the editor is stuck on **Loading...**, setting
|
||||
`dom.workers.modules.enabled: true` in your `about:config`, as mentioned in the
|
||||
discussion of the
|
||||
[issue#328](https://github.com/elalish/manifold/issues/328#issuecomment-1473847102)
|
||||
of this repository may solve the problem.
|
||||
## Frontend Sandboxes
|
||||
|
||||
# Manifold
|
||||
[ManifoldCAD.org]: https://manifoldcad.org
|
||||
[Python Colab Example]: https://colab.research.google.com/drive/1VxrFYHPSHZgUbl9TeWzCeovlpXrPQ5J5?usp=sharing
|
||||
|
||||
[**API Documentation**](https://elalish.github.io/manifold/docs/html/modules.html) | [**Algorithm Documentation**](https://github.com/elalish/manifold/wiki/Manifold-Library) | [**Blog Posts**](https://elalish.blogspot.com/search/label/Manifold) | [**Web Examples**](https://elalish.github.io/manifold/model-viewer.html)
|
||||
### [ManifoldCAD.org]
|
||||
|
||||
[Manifold](https://github.com/elalish/manifold) is a geometry library dedicated to creating and operating on manifold triangle meshes. A [manifold mesh](https://github.com/elalish/manifold/wiki/Manifold-Library#manifoldness) is a mesh that represents a solid object, and so is very important in manufacturing, CAD, structural analysis, etc. Further information can be found on the [wiki](https://github.com/elalish/manifold/wiki/Manifold-Library).
|
||||
If you like OpenSCAD / JSCAD, you might also like [ManifoldCAD][ManifoldCAD.org] - our own solid modelling web app where you script in JS/TS. This uses our npm package, [manifold-3d](https://www.npmjs.com/package/manifold-3d), built via WASM. It's not quite as fast as our raw C++, but it's hard to beat for interoperability.
|
||||
|
||||
This is a modern C++ library that Github's CI verifies builds and runs on a variety of platforms. Additionally, we build bindings for JavaScript ([manifold-3d](https://www.npmjs.com/package/manifold-3d) on npm), Python ([manifold3d](https://pypi.org/project/manifold3d/)), and C to make this library more portable and easy to use.
|
||||
### [Python Colab Example]
|
||||
|
||||
System Dependencies (note that we will automatically download the dependency if there is no such package on the system):
|
||||
- [`GLM`](https://github.com/g-truc/glm/): A compact header-only vector library.
|
||||
- [`Thrust`](https://github.com/NVIDIA/thrust): NVIDIA's parallel algorithms library (basically a superset of C++17 std::parallel_algorithms)
|
||||
- [`tbb`](https://github.com/oneapi-src/oneTBB/): Intel's thread building blocks library. (only when `MANIFOLD_PAR=TBB` is enabled)
|
||||
- [`gtest`](https://github.com/google/googletest/): Google test library (only when test is enabled, i.e. `MANIFOLD_TEST=ON`)
|
||||
If you prefer Python to JS/TS, make your own copy of [the notebook][Python Colab Example]. It demonstrates interop between our [`manifold3d`](https://pypi.org/project/manifold3d/) PyPI library and the popular [`trimesh`](https://pypi.org/project/trimesh/) library, including showing the interactive model right in the notebook and saving 3D model output.
|
||||
|
||||
Other dependencies:
|
||||
- [`Clipper2`](https://github.com/AngusJohnson/Clipper2): provides our 2D subsystem
|
||||
- [`quickhull`](https://github.com/akuukka/quickhull): 3D convex hull algorithm.
|
||||

|
||||
|
||||
## What's here
|
||||
## Manifold Library
|
||||
|
||||
This library is fast with guaranteed manifold output. As such you need manifold meshes as input, which this library can create using constructors inspired by the OpenSCAD API, as well as more advanced features like smoothing and signed-distance function (SDF) level sets. You can also pass in your own mesh data, but you'll get an error status if the imported mesh isn't manifold. Various automated repair tools exist online for fixing non manifold models, usually for 3D printing.
|
||||
This library is fast with guaranteed manifold output. As such you need manifold meshes as input, which this library can create using constructors inspired by the OpenSCAD API, as well as a level set function for evaluating signed-distance functions (SDF) that improves significantly over Marching Cubes. You can also pass in your own mesh data, but you'll get an error status if the imported mesh isn't manifold. We provide a [`Merge`](https://manifoldcad.org/docs/html/structmanifold_1_1_mesh_g_l_p.html) function to fix slightly non-manifold meshes, but in general you may need one of the automated repair tools that exist mostly for 3D printing.
|
||||
|
||||
The most significant contribution here is a guaranteed-manifold [mesh Boolean](https://github.com/elalish/manifold/wiki/Manifold-Library#mesh-boolean) algorithm, which I believe is the first of its kind. If you know of another, please open a discussion - a mesh Boolean algorithm robust to edge cases has been an open problem for many years. Likewise, if the Boolean here ever fails you, please submit an issue! This Boolean forms the basis of a CAD kernel, as it allows simple shapes to be combined into more complex ones.
|
||||
|
||||
To aid in speed, this library makes extensive use of parallelization, generally through Nvidia's Thrust library. You can switch between the TBB, and serial C++ backends by setting a CMake flag. Not everything is so parallelizable, for instance a [polygon triangulation](https://github.com/elalish/manifold/wiki/Manifold-Library#polygon-triangulation) algorithm is included which is serial. Even if compiled with parallel backend, the code will still fall back to the serial version of the algorithms if the problem size is small. The WASM build is serial-only for now, but still fast.
|
||||
Manifold has full support for arbitrary vertex properties, and also has IDs that make it easy to keep track of materials and what surfaces belong to what input objects or faces. See our [web example](https://manifoldcad.org/model-viewer.html) for a simple demonstration of combining objects with unique textures.
|
||||
|
||||
> Note: OMP and CUDA backends are now removed
|
||||
Also included are a novel and powerful suite of refining functions for smooth mesh interpolation. They handle smoothing both triangles and quads, as well as keeping polygonal faces flat. You can easily create sharp or small-radius edges where desired, or even drive the curvature by normal vectors.
|
||||
|
||||
To aid in speed, this library makes extensive use of parallelization through TBB, if enabled. Not everything is so parallelizable, for instance a [polygon triangulation](https://github.com/elalish/manifold/wiki/Manifold-Library#polygon-triangulation) algorithm is included which is serial. Even if compiled with parallel backend, the code will still fall back to the serial version of the algorithms if the problem size is small. The WASM build is serial-only for now, but still fast.
|
||||
|
||||
Look in the [samples](https://github.com/elalish/manifold/tree/master/samples) directory for examples of how to use this library to make interesting 3D models. You may notice that some of these examples bare a certain resemblance to my OpenSCAD designs on [Thingiverse](https://www.thingiverse.com/emmett), which is no accident. Much as I love OpenSCAD, my library is dramatically faster and the code is more flexible.
|
||||
|
||||
### Dependencies
|
||||
|
||||
Manifold no longer has **any** required dependencies! However, we do have several optional dependencies, of which the first two are strongly encouraged:
|
||||
| Name | CMake Flag | Provides |
|
||||
| --- | --- | --- |
|
||||
| [`TBB`](https://github.com/oneapi-src/oneTBB/) |`MANIFOLD_PAR=ON` | Parallel acceleration |
|
||||
| [`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 bindings |
|
||||
| [`Emscripten`](https://github.com/emscripten-core/emscripten) | `MANIFOLD_JSBIND=ON` | JS bindings via WASM |
|
||||
| [`GTest`](https://github.com/google/googletest/) | `MANIFOLD_TEST=ON` | Testing framework |
|
||||
| [`Assimp`](https://github.com/assimp/assimp) | `ASSIMP_ENABLE=ON` | Utilities in `extras` |
|
||||
| [`Tracy`](https://github.com/wolfpld/tracy) | `TRACY_ENABLE=ON` | Performance analysis |
|
||||
|
||||
|
||||
### 3D Formats
|
||||
|
||||
Please avoid saving to STL files! They are lossy and inefficient - when saving a manifold mesh to STL there is no guarantee that the re-imported mesh will still be manifold, as the topology is lost. Please consider using [3MF](https://3mf.io/) instead, as this format was designed from the beginning for manifold meshes representing solid objects.
|
||||
|
||||
If you use vertex properties for things like interpolated normals or texture UV coordinates, [glTF](https://www.khronos.org/Gltf) is recommended, specifically using the [`EXT_mesh_manifold`](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_manifold/README.md) extension. This allows for the lossless and efficient transmission of manifoldness even with property boundaries. Try our [make-manifold](https://manifoldcad.org/make-manifold) page to add this extension to your existing glTF/GLB models.
|
||||
|
||||
Manifold provides high precision OBJ file IO, but it is limited in functionality and is primarily to aid in testing. If you are using our npm module, we have a much more capable [gltf-io.ts](https://github.com/elalish/manifold/blob/master/bindings/wasm/examples/gltf-io.ts) you can use instead. For other languages we strongly recommend using existing packages that focus on 3D file I/O, e.g. [trimesh](https://trimesh.org/) for Python, particularly when using vertex properties or materials.
|
||||
Example for integrating with [Assimp](https://github.com/assimp/assimp) is in `extras/meshIO.cpp`, which is used by files such as `extras/convert_file.cpp`.
|
||||
|
||||
## Building
|
||||
|
||||
Only CMake, a C++ compiler, and Python are required to be installed and set up to build this library (it has been tested with GCC, LLVM, MSVC). However, a variety of optional dependencies can bring in more functionality, see below.
|
||||
@@ -62,32 +106,61 @@ cd manifold
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON .. && make
|
||||
test/manifold_test
|
||||
make test
|
||||
```
|
||||
|
||||
CMake flags (usage e.g. `-DMANIFOLD_DEBUG=ON`):
|
||||
- `MANIFOLD_JSBIND=[OFF, <ON>]`: Build js binding when using emscripten.
|
||||
- `MANIFOLD_JSBIND=[OFF, <ON>]`: Build js binding (when using the emscripten toolchain).
|
||||
- `MANIFOLD_CBIND=[<OFF>, ON]`: Build C FFI binding.
|
||||
- `MANIFOLD_PYBIND=[OFF, <ON>]`: Build python binding.
|
||||
- `MANIFOLD_PAR=[<NONE>, TBB]`: Provides multi-thread parallelization, requires `libtbb-dev` if `TBB` backend is selected.
|
||||
- `MANIFOLD_EXPORT=[<OFF>, ON]`: Enables GLB export of 3D models from the tests, requires `libassimp-dev`.
|
||||
- `MANIFOLD_DEBUG=[<OFF>, ON]`: Enables internal assertions and exceptions.
|
||||
- `MANIFOLD_TEST=[OFF, <ON>]`: Build unittests.
|
||||
- `MANIFOLD_PYBIND=[OFF, <ON>]`: Build python binding, requires `nanobind`.
|
||||
- `MANIFOLD_PAR=[<OFF>, ON]`: Enables multi-thread parallelization, requires `tbb`.
|
||||
- `MANIFOLD_CROSS_SECTION=[OFF, <ON>]`: Build CrossSection for 2D support (needed by language bindings), requires `Clipper2`.
|
||||
- `MANIFOLD_DEBUG=[<OFF>, ON]`: Enables exceptions, timing, verbosity, OBJ test dumps. Has almost no effect on its own, but enables further runtime parameters to dump various outputs.
|
||||
- `MANIFOLD_ASSERT=[<OFF>, ON]`: Enables internal assertions. This incurs around 20% runtime overhead. Requires MANIFOLD_DEBUG to work.
|
||||
- `MANIFOLD_TEST=[OFF, <ON>]`: Build unit tests, requires `GTest`.
|
||||
- `TRACY_ENABLE=[<OFF>, ON]`: Enable integration with tracy profiler.
|
||||
See profiling section below.
|
||||
- `BUILD_TEST_CGAL=[<OFF>, ON]`: Builds a CGAL-based performance [comparison](https://github.com/elalish/manifold/tree/master/extras), requires `libcgal-dev`.
|
||||
- `ASSIMP_ENABLE=[<OFF>, ON]`: Enable integration with assimp, which is needed for some of the utilities in `extras`.
|
||||
- `MANIFOLD_STRICT=[<OFF>, ON]`: Treat compile warnings as fatal build errors.
|
||||
|
||||
Offline building:
|
||||
- `FETCHCONTENT_SOURCE_DIR_GLM`: path to glm source.
|
||||
- `FETCHCONTENT_SOURCE_DIR_GOOGLETEST`: path to googletest source.
|
||||
- `FETCHCONTENT_SOURCE_DIR_THRUST`: path to NVIDIA thrust source.
|
||||
Dependency version override:
|
||||
- `MANIFOLD_USE_BUILTIN_TBB=[<OFF>, ON]`: Use builtin version of tbb.
|
||||
- `MANIFOLD_USE_BUILTIN_CLIPPER2=[<OFF>, ON]`: Use builtin version of clipper2.
|
||||
- `MANIFOLD_USE_BUILTIN_NANOBIND=[<OFF>, ON]`: Use builtin version of nanobind.
|
||||
|
||||
> Note: These three options can force the build to avoid using the system
|
||||
> version of the dependency. This will either use the provided source directory
|
||||
> via `FETCHCONTENT_SOURCE_DIR_*` (see below), or fetch the source from GitHub.
|
||||
> Note that the dependency will be built as static dependency to avoid dynamic
|
||||
> library conflict. When the system package is unavailable, the option will be
|
||||
> automatically set to true (except for tbb).
|
||||
|
||||
> WARNING: These packages are statically linked to the library, which may be
|
||||
> unexpected for other consumers of the library. In particular, for tbb, this
|
||||
> create two versions of tbb when another library also bring their own tbb,
|
||||
> which may cause performance issues or crash the system.
|
||||
> It is not recommended to install manifold compiled with builtin tbb, and this
|
||||
> option requires explicit opt-in now.
|
||||
|
||||
Offline building (with missing dependencies/dependency version override):
|
||||
- `MANIFOLD_DOWNLOADS=[OFF, <ON>]`: Automatically download missing dependencies.
|
||||
Need to set `FETCHCONTENT_SOURCE_DIR_*` if the dependency `*` is missing.
|
||||
- `FETCHCONTENT_SOURCE_DIR_TBB`: path to tbb source (if `MANIFOLD_PAR` is enabled).
|
||||
- `FETCHCONTENT_SOURCE_DIR_CLIPPER2`: path to tbb source (if `MANIFOLD_CROSS_SECTION` is enabled).
|
||||
- `FETCHCONTENT_SOURCE_DIR_NANOBIND`: path to nanobind source (if `MANIFOLD_PYBIND` is enabled).
|
||||
- `FETCHCONTENT_SOURCE_DIR_GOOGLETEST`: path to googletest source (if `MANIFOLD_TEST` is enabled).
|
||||
|
||||
> Note: When `FETCHCONTENT_SOURCE_DIR_*` is set, CMake will use the provided
|
||||
> source directly without downloading regardless of the value of
|
||||
> `MANIFOLD_DOWNLOADS`.
|
||||
|
||||
The build instructions used by our CI are in [manifold.yml](https://github.com/elalish/manifold/blob/master/.github/workflows/manifold.yml), which is a good source to check if something goes wrong and for instructions specific to other platforms, like Windows.
|
||||
|
||||
### WASM
|
||||
|
||||
> Note that we have only tested emscripten version 3.1.45. It is known that
|
||||
3.1.48 has some issues compiling manifold.
|
||||
> Note: While we support compiling with `MANIFOLD_PAR=ON` in recent emscripten
|
||||
> versions, this is not recommended as there can potentially be memory
|
||||
> corruption issues.
|
||||
|
||||
To build the JS WASM library, first install NodeJS and set up emscripten:
|
||||
|
||||
@@ -110,8 +183,9 @@ Then build:
|
||||
cd manifold
|
||||
mkdir buildWASM
|
||||
cd buildWASM
|
||||
emcmake cmake -DCMAKE_BUILD_TYPE=Release .. && emmake make
|
||||
node test/manifold_test.js
|
||||
emcmake cmake -DCMAKE_BUILD_TYPE=MinSizeRel .. && emmake make
|
||||
cd test
|
||||
node ./manifold_test.js
|
||||
```
|
||||
|
||||
### Python
|
||||
@@ -122,7 +196,7 @@ use the extension, please add `$BUILD_DIR/bindings/python` to your `PYTHONPATH`,
|
||||
can be found in `bindings/python/examples`. To see exported samples, run:
|
||||
```
|
||||
sudo apt install pkg-config libpython3-dev python3 python3-distutils python3-pip
|
||||
pip install trimesh
|
||||
pip install trimesh pytest
|
||||
python3 run_all.py -e
|
||||
```
|
||||
|
||||
@@ -136,15 +210,46 @@ python binding documentation:
|
||||
|
||||
For more detailed documentation, please refer to the C++ API.
|
||||
|
||||
### Windows Shenanigans
|
||||
|
||||
Windows users should build with `-DBUILD_SHARED_LIBS=OFF`, as enabling shared
|
||||
libraries in general makes things very complicated.
|
||||
|
||||
The DLL file for manifoldc (C FFI bindings) when built with msvc is in `${CMAKE_BINARY_DIR}/bin/${BUILD_TYPE}/manifoldc.dll`.
|
||||
For example, for the following command, the path relative to the project root directory is `build/bin/Release/manifoldc.dll`.
|
||||
```sh
|
||||
cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DMANIFOLD_DEBUG=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} -A x64 -B build
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! A lower barrier contribution is to simply make a PR that adds a test, especially if it repros an issue you've found. Simply name it prepended with DISABLED_, so that it passes the CI. That will be a very strong signal to me to fix your issue. However, if you know how to fix it yourself, then including the fix in your PR would be much appreciated!
|
||||
|
||||
## Profiling
|
||||
### Formatting
|
||||
|
||||
There is a formatting script `format.sh` that automatically formats everything.
|
||||
It requires clang-format, black formatter for python and [gersemi](https://github.com/BlankSpruce/gersemi) for formatting cmake files.
|
||||
|
||||
Note that our script can run with clang-format older than 18, but the GitHub
|
||||
action check may fail due to slight differences between different versions of
|
||||
clang-format. In that case, either update your clang-format version or apply the
|
||||
patch from the GitHub action log.
|
||||
|
||||
### Profiling
|
||||
|
||||
There is now basic support for the [Tracy profiler](https://github.com/wolfpld/tracy) for our tests.
|
||||
To enable tracing, compile with `-DTRACY_ENABLE=on` cmake option, and run the test with Tracy server running.
|
||||
To enable memory profiling in addition to tracing, compile with `-DTRACY_MEMORY_USAGE=ON` in addition to `-DTRACY_ENABLE=ON`.
|
||||
|
||||
### Fuzzing
|
||||
|
||||
To build with fuzzing support, you should set the following with CMake:
|
||||
|
||||
- Enable fuzzing by setting `-DMANIFOLD_FUZZ=ON`
|
||||
- Disable python bindings by setting `-DMANIFOLD_PYBIND=OFF`
|
||||
- Use `clang` for compiling by setting `-DCMAKE_CXX_COMPILER=clang++`
|
||||
- You may need to disable parallelization by setting `-DMANIFOLD_PAR=OFF`, and set `ASAN_OPTIONS=detect_container_overflow=0` when building the binary on MacOS.
|
||||
|
||||
## About the author
|
||||
|
||||
This library was started by [Emmett Lalish](https://elalish.blogspot.com/). I am currently a Google employee and this is my 20% project, not an official Google project. At my day job I'm the maintainer of [\<model-viewer\>](https://modelviewer.dev/). I was the first employee at a 3D video startup, [Omnivor](https://www.omnivor.io/), and before that I worked on 3D printing at Microsoft, including [3D Builder](https://www.microsoft.com/en-us/p/3d-builder/9wzdncrfj3t6?activetab=pivot%3Aoverviewtab). Originally an aerospace engineer, I started at a small DARPA contractor doing seedling projects, one of which became [Sea Hunter](https://en.wikipedia.org/wiki/Sea_Hunter). I earned my doctorate from the University of Washington in control theory and published some [papers](https://www.researchgate.net/scientific-contributions/75011026_Emmett_Lalish).
|
||||
This library was started by [Emmett Lalish](https://elalish.blogspot.com/), currently a senior rendering engineer at Wētā FX. This was my 20% project when I was a Google employee, though my day job was maintaining [\<model-viewer\>](https://modelviewer.dev/). I was the first employee at a 3D video startup, [Omnivor](https://www.omnivor.io/), and before that I worked on 3D printing at Microsoft, including [3D Builder](https://www.microsoft.com/en-us/p/3d-builder/9wzdncrfj3t6?activetab=pivot%3Aoverviewtab). Originally an aerospace engineer, I started at a small DARPA contractor doing seedling projects, one of which became [Sea Hunter](https://en.wikipedia.org/wiki/Sea_Hunter). I earned my doctorate from the University of Washington in control theory and published some [papers](https://www.researchgate.net/scientific-contributions/75011026_Emmett_Lalish).
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
1. Go through Github issues to verify bugs have been fixed and closed.
|
||||
1. Verify [ManifoldCAD.org](https://manifoldcad.org) - check a few examples, run them, download a GLB and a 3MF.
|
||||
1. Verify our three.js [example](https://manifoldcad.org/three) is functional.
|
||||
1. Verify our model-viewer [example](https://manifoldcad.org/model-viewer) is functional - select Union and Intersection.
|
||||
1. Verify [make-manifold](https://manifoldcad.org/make-manifold) is functional. Try dropping [DragonAttenuation.glb](https://github.com/KhronosGroup/glTF-Sample-Assets/blob/main/Models/DragonAttenuation/glTF-Binary/DragonAttenuation.glb) in and verify you can select "View Manifold GLB" and that the dragon is still present while the backdrop is removed. Download the GLB.
|
||||
1. Make a new branch called the version, e.g. v2.3.0.
|
||||
1. Use VSCode to search and replace the old version with the new - so far in test-cmake.sh, flake.nix, pyproject.toml, and package.json.
|
||||
1. Also update CMakeLists.txt version by searching for "set(MANIFOLD_VERSION_".
|
||||
1. Commit, push, open a PR, verify tests pass, manually trigger build_wheels CI, merge.
|
||||
1. On Github, draft a new release, make a new tag with the version number, add release notes, and publish.
|
||||
1. Check the Actions and verify that both PyPI and npm publishing actions ran successfully.
|
||||
1. Verify the npm [package](https://www.npmjs.com/package/manifold-3d?activeTab=code) looks good - unpacked size should be close to 1MB.
|
||||
1. Verify PyPI [package](https://pypi.org/project/manifold3d/#files) looks good - a bunch of built distributions ranging from ~600kB to ~1.1MB.
|
||||
1. If there's a problem with release deployment, the release workflows can be triggered separately, manually for any branch, under the Actions tab.
|
||||
@@ -12,14 +12,18 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if(NOT EMSCRIPTEN AND MANIFOLD_CBIND)
|
||||
add_subdirectory(c)
|
||||
if(NOT MANIFOLD_CROSS_SECTION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(MANIFOLD_CBIND)
|
||||
add_subdirectory(c)
|
||||
endif()
|
||||
|
||||
if(NOT EMSCRIPTEN AND MANIFOLD_PYBIND)
|
||||
add_subdirectory(python)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
if(EMSCRIPTEN AND MANIFOLD_JSBIND)
|
||||
add_subdirectory(wasm)
|
||||
add_subdirectory(wasm)
|
||||
endif()
|
||||
|
||||
@@ -1,33 +1,45 @@
|
||||
project(manifoldc)
|
||||
# Copyright 2024 The Manifold Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_library(${PROJECT_NAME} manifoldc.cpp conv.cpp)
|
||||
|
||||
if(MANIFOLD_USE_CUDA)
|
||||
set_source_files_properties(manifoldc.cpp conv.cpp PROPERTIES LANGUAGE CUDA)
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY CUDA_ARCHITECTURES 61)
|
||||
endif()
|
||||
|
||||
if(MANIFOLD_EXPORT)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE meshIO)
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC -DMANIFOLD_EXPORT)
|
||||
endif()
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE manifold sdf cross_section
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../include
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${MANIFOLD_FLAGS})
|
||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
|
||||
add_library(
|
||||
manifoldc
|
||||
manifoldc.cpp
|
||||
conv.cpp
|
||||
box.cpp
|
||||
cross.cpp
|
||||
rect.cpp
|
||||
)
|
||||
exportlib(manifoldc)
|
||||
|
||||
target_link_libraries(manifoldc PRIVATE manifold)
|
||||
|
||||
target_include_directories(
|
||||
manifoldc
|
||||
PUBLIC
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
)
|
||||
target_compile_options(manifoldc PRIVATE ${MANIFOLD_FLAGS})
|
||||
|
||||
install(TARGETS manifoldc EXPORT manifoldTargets)
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
|
||||
COMPONENT bindings
|
||||
)
|
||||
install(
|
||||
FILES include/manifoldc.h include/types.h
|
||||
DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/manifold
|
||||
COMPONENT devel
|
||||
FILES include/manifold/manifoldc.h include/manifold/types.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/manifold
|
||||
)
|
||||
|
||||
@@ -13,86 +13,91 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "conv.h"
|
||||
#include "manifold.h"
|
||||
#include "public.h"
|
||||
#include "types.h"
|
||||
#include "manifold/common.h"
|
||||
#include "manifold/types.h"
|
||||
|
||||
ManifoldBox *manifold_box(void *mem, float x1, float y1, float z1, float x2,
|
||||
float y2, float z2) {
|
||||
auto p1 = glm::vec3(x1, y1, z1);
|
||||
auto p2 = glm::vec3(x2, y2, z2);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
ManifoldBox* manifold_box(void* mem, double x1, double y1, double z1, double x2,
|
||||
double y2, double z2) {
|
||||
auto p1 = vec3(x1, y1, z1);
|
||||
auto p2 = vec3(x2, y2, z2);
|
||||
auto box = new (mem) Box(p1, p2);
|
||||
return to_c(box);
|
||||
}
|
||||
|
||||
ManifoldVec3 manifold_box_min(ManifoldBox *b) { return to_c((*from_c(b)).min); }
|
||||
ManifoldVec3 manifold_box_min(ManifoldBox* b) { return to_c((*from_c(b)).min); }
|
||||
|
||||
ManifoldVec3 manifold_box_max(ManifoldBox *b) { return to_c((*from_c(b)).max); }
|
||||
ManifoldVec3 manifold_box_max(ManifoldBox* b) { return to_c((*from_c(b)).max); }
|
||||
|
||||
ManifoldVec3 manifold_box_dimensions(ManifoldBox *b) {
|
||||
ManifoldVec3 manifold_box_dimensions(ManifoldBox* b) {
|
||||
auto v = from_c(b)->Size();
|
||||
return {v.x, v.y, v.z};
|
||||
}
|
||||
|
||||
ManifoldVec3 manifold_box_center(ManifoldBox *b) {
|
||||
ManifoldVec3 manifold_box_center(ManifoldBox* b) {
|
||||
auto v = from_c(b)->Center();
|
||||
return {v.x, v.y, v.z};
|
||||
}
|
||||
|
||||
float manifold_box_scale(ManifoldBox *b) { return from_c(b)->Scale(); }
|
||||
double manifold_box_scale(ManifoldBox* b) { return from_c(b)->Scale(); }
|
||||
|
||||
int manifold_box_contains_pt(ManifoldBox *b, float x, float y, float z) {
|
||||
auto p = glm::vec3(x, y, z);
|
||||
int manifold_box_contains_pt(ManifoldBox* b, double x, double y, double z) {
|
||||
auto p = vec3(x, y, z);
|
||||
return from_c(b)->Contains(p);
|
||||
}
|
||||
|
||||
int manifold_box_contains_box(ManifoldBox *a, ManifoldBox *b) {
|
||||
int manifold_box_contains_box(ManifoldBox* a, ManifoldBox* b) {
|
||||
auto outer = *from_c(a);
|
||||
auto inner = *from_c(b);
|
||||
return outer.Contains(inner);
|
||||
}
|
||||
|
||||
void manifold_box_include_pt(ManifoldBox *b, float x, float y, float z) {
|
||||
void manifold_box_include_pt(ManifoldBox* b, double x, double y, double z) {
|
||||
auto box = *from_c(b);
|
||||
auto p = glm::vec3(x, y, z);
|
||||
auto p = vec3(x, y, z);
|
||||
box.Union(p);
|
||||
}
|
||||
|
||||
ManifoldBox *manifold_box_union(void *mem, ManifoldBox *a, ManifoldBox *b) {
|
||||
ManifoldBox* manifold_box_union(void* mem, ManifoldBox* a, ManifoldBox* b) {
|
||||
auto box = from_c(a)->Union(*from_c(b));
|
||||
return to_c(new (mem) Box(box));
|
||||
}
|
||||
|
||||
ManifoldBox *manifold_box_transform(void *mem, ManifoldBox *b, float x1,
|
||||
float y1, float z1, float x2, float y2,
|
||||
float z2, float x3, float y3, float z3,
|
||||
float x4, float y4, float z4) {
|
||||
auto mat = glm::mat4x3(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
|
||||
ManifoldBox* manifold_box_transform(void* mem, ManifoldBox* b, double x1,
|
||||
double y1, double z1, double x2, double y2,
|
||||
double z2, double x3, double y3, double z3,
|
||||
double x4, double y4, double z4) {
|
||||
auto mat = mat3x4({x1, y1, z1}, {x2, y2, z2}, {x3, y3, z3}, {x4, y4, z4});
|
||||
auto transformed = from_c(b)->Transform(mat);
|
||||
return to_c(new (mem) Box(transformed));
|
||||
}
|
||||
|
||||
ManifoldBox *manifold_box_translate(void *mem, ManifoldBox *b, float x, float y,
|
||||
float z) {
|
||||
auto p = glm::vec3(x, y, z);
|
||||
ManifoldBox* manifold_box_translate(void* mem, ManifoldBox* b, double x,
|
||||
double y, double z) {
|
||||
auto p = vec3(x, y, z);
|
||||
auto translated = (*from_c(b)) + p;
|
||||
return to_c(new (mem) Box(translated));
|
||||
}
|
||||
|
||||
ManifoldBox *manifold_box_mul(void *mem, ManifoldBox *b, float x, float y,
|
||||
float z) {
|
||||
auto p = glm::vec3(x, y, z);
|
||||
ManifoldBox* manifold_box_mul(void* mem, ManifoldBox* b, double x, double y,
|
||||
double z) {
|
||||
auto p = vec3(x, y, z);
|
||||
auto scaled = (*from_c(b)) * p;
|
||||
return to_c(new (mem) Box(scaled));
|
||||
}
|
||||
|
||||
int manifold_box_does_overlap_pt(ManifoldBox *b, float x, float y, float z) {
|
||||
auto p = glm::vec3(x, y, z);
|
||||
int manifold_box_does_overlap_pt(ManifoldBox* b, double x, double y, double z) {
|
||||
auto p = vec3(x, y, z);
|
||||
return from_c(b)->DoesOverlap(p);
|
||||
}
|
||||
|
||||
int manifold_box_does_overlap_box(ManifoldBox *a, ManifoldBox *b) {
|
||||
int manifold_box_does_overlap_box(ManifoldBox* a, ManifoldBox* b) {
|
||||
return from_c(a)->DoesOverlap(*from_c(b));
|
||||
}
|
||||
|
||||
int manifold_box_is_finite(ManifoldBox *b) { return from_c(b)->IsFinite(); }
|
||||
int manifold_box_is_finite(ManifoldBox* b) { return from_c(b)->IsFinite(); }
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,42 +16,41 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cross_section.h"
|
||||
#include "manifold.h"
|
||||
#include "public.h"
|
||||
#include "sdf.h"
|
||||
#include "types.h"
|
||||
#include "manifold/common.h"
|
||||
#include "manifold/cross_section.h"
|
||||
#include "manifold/manifold.h"
|
||||
#include "manifold/types.h"
|
||||
|
||||
ManifoldManifold *to_c(manifold::Manifold *m) {
|
||||
return reinterpret_cast<ManifoldManifold *>(m);
|
||||
ManifoldManifold* to_c(manifold::Manifold* m) {
|
||||
return reinterpret_cast<ManifoldManifold*>(m);
|
||||
}
|
||||
|
||||
ManifoldManifoldVec *to_c(ManifoldVec *ms) {
|
||||
return reinterpret_cast<ManifoldManifoldVec *>(ms);
|
||||
ManifoldManifoldVec* to_c(ManifoldVec* ms) {
|
||||
return reinterpret_cast<ManifoldManifoldVec*>(ms);
|
||||
}
|
||||
|
||||
ManifoldCrossSection *to_c(manifold::CrossSection *cs) {
|
||||
return reinterpret_cast<ManifoldCrossSection *>(cs);
|
||||
ManifoldCrossSection* to_c(manifold::CrossSection* cs) {
|
||||
return reinterpret_cast<ManifoldCrossSection*>(cs);
|
||||
}
|
||||
|
||||
ManifoldCrossSectionVec *to_c(CrossSectionVec *csv) {
|
||||
return reinterpret_cast<ManifoldCrossSectionVec *>(csv);
|
||||
ManifoldCrossSectionVec* to_c(CrossSectionVec* csv) {
|
||||
return reinterpret_cast<ManifoldCrossSectionVec*>(csv);
|
||||
}
|
||||
|
||||
ManifoldSimplePolygon *to_c(manifold::SimplePolygon *m) {
|
||||
return reinterpret_cast<ManifoldSimplePolygon *>(m);
|
||||
ManifoldSimplePolygon* to_c(manifold::SimplePolygon* m) {
|
||||
return reinterpret_cast<ManifoldSimplePolygon*>(m);
|
||||
}
|
||||
|
||||
ManifoldPolygons *to_c(manifold::Polygons *m) {
|
||||
return reinterpret_cast<ManifoldPolygons *>(m);
|
||||
ManifoldPolygons* to_c(manifold::Polygons* m) {
|
||||
return reinterpret_cast<ManifoldPolygons*>(m);
|
||||
}
|
||||
|
||||
ManifoldMesh *to_c(manifold::Mesh *m) {
|
||||
return reinterpret_cast<ManifoldMesh *>(m);
|
||||
ManifoldMeshGL* to_c(manifold::MeshGL* m) {
|
||||
return reinterpret_cast<ManifoldMeshGL*>(m);
|
||||
}
|
||||
|
||||
ManifoldMeshGL *to_c(manifold::MeshGL *m) {
|
||||
return reinterpret_cast<ManifoldMeshGL *>(m);
|
||||
ManifoldMeshGL64* to_c(manifold::MeshGL64* m) {
|
||||
return reinterpret_cast<ManifoldMeshGL64*>(m);
|
||||
}
|
||||
|
||||
ManifoldOpType to_c(manifold::OpType optype) {
|
||||
@@ -107,58 +106,61 @@ ManifoldError to_c(manifold::Manifold::Error error) {
|
||||
case Manifold::Error::InvalidConstruction:
|
||||
e = MANIFOLD_INVALID_CONSTRUCTION;
|
||||
break;
|
||||
case Manifold::Error::ResultTooLarge:
|
||||
e = MANIFOLD_RESULT_TOO_LARGE;
|
||||
break;
|
||||
};
|
||||
return e;
|
||||
}
|
||||
|
||||
ManifoldBox *to_c(manifold::Box *m) {
|
||||
return reinterpret_cast<ManifoldBox *>(m);
|
||||
ManifoldBox* to_c(manifold::Box* m) {
|
||||
return reinterpret_cast<ManifoldBox*>(m);
|
||||
}
|
||||
|
||||
ManifoldRect *to_c(manifold::Rect *m) {
|
||||
return reinterpret_cast<ManifoldRect *>(m);
|
||||
ManifoldRect* to_c(manifold::Rect* m) {
|
||||
return reinterpret_cast<ManifoldRect*>(m);
|
||||
}
|
||||
|
||||
ManifoldVec2 to_c(glm::vec2 v) { return {v.x, v.y}; }
|
||||
ManifoldVec2 to_c(vec2 v) { return {v.x, v.y}; }
|
||||
|
||||
ManifoldVec3 to_c(glm::vec3 v) { return {v.x, v.y, v.z}; }
|
||||
ManifoldVec3 to_c(vec3 v) { return {v.x, v.y, v.z}; }
|
||||
|
||||
ManifoldIVec3 to_c(glm::ivec3 v) { return {v.x, v.y, v.z}; }
|
||||
ManifoldIVec3 to_c(ivec3 v) { return {v.x, v.y, v.z}; }
|
||||
|
||||
ManifoldProperties to_c(manifold::Properties p) {
|
||||
return {p.surfaceArea, p.volume};
|
||||
ManifoldTriangulation* to_c(std::vector<ivec3>* m) {
|
||||
return reinterpret_cast<ManifoldTriangulation*>(m);
|
||||
}
|
||||
|
||||
const manifold::Manifold *from_c(ManifoldManifold *m) {
|
||||
return reinterpret_cast<manifold::Manifold const *>(m);
|
||||
const manifold::Manifold* from_c(ManifoldManifold* m) {
|
||||
return reinterpret_cast<manifold::Manifold const*>(m);
|
||||
}
|
||||
|
||||
ManifoldVec *from_c(ManifoldManifoldVec *ms) {
|
||||
return reinterpret_cast<ManifoldVec *>(ms);
|
||||
ManifoldVec* from_c(ManifoldManifoldVec* ms) {
|
||||
return reinterpret_cast<ManifoldVec*>(ms);
|
||||
}
|
||||
|
||||
const manifold::CrossSection *from_c(ManifoldCrossSection *cs) {
|
||||
return reinterpret_cast<manifold::CrossSection *>(cs);
|
||||
const manifold::CrossSection* from_c(ManifoldCrossSection* cs) {
|
||||
return reinterpret_cast<manifold::CrossSection*>(cs);
|
||||
}
|
||||
|
||||
CrossSectionVec *from_c(ManifoldCrossSectionVec *csv) {
|
||||
return reinterpret_cast<CrossSectionVec *>(csv);
|
||||
CrossSectionVec* from_c(ManifoldCrossSectionVec* csv) {
|
||||
return reinterpret_cast<CrossSectionVec*>(csv);
|
||||
}
|
||||
|
||||
const manifold::SimplePolygon *from_c(ManifoldSimplePolygon *m) {
|
||||
return reinterpret_cast<manifold::SimplePolygon const *>(m);
|
||||
const manifold::SimplePolygon* from_c(ManifoldSimplePolygon* m) {
|
||||
return reinterpret_cast<manifold::SimplePolygon const*>(m);
|
||||
}
|
||||
|
||||
const manifold::Polygons *from_c(ManifoldPolygons *m) {
|
||||
return reinterpret_cast<manifold::Polygons const *>(m);
|
||||
const manifold::Polygons* from_c(ManifoldPolygons* m) {
|
||||
return reinterpret_cast<manifold::Polygons const*>(m);
|
||||
}
|
||||
|
||||
const manifold::Mesh *from_c(ManifoldMesh *m) {
|
||||
return reinterpret_cast<manifold::Mesh const *>(m);
|
||||
const manifold::MeshGL* from_c(ManifoldMeshGL* m) {
|
||||
return reinterpret_cast<manifold::MeshGL const*>(m);
|
||||
}
|
||||
|
||||
const manifold::MeshGL *from_c(ManifoldMeshGL *m) {
|
||||
return reinterpret_cast<manifold::MeshGL const *>(m);
|
||||
const manifold::MeshGL64* from_c(ManifoldMeshGL64* m) {
|
||||
return reinterpret_cast<manifold::MeshGL64 const*>(m);
|
||||
}
|
||||
|
||||
OpType from_c(ManifoldOpType optype) {
|
||||
@@ -205,45 +207,52 @@ CrossSection::JoinType from_c(ManifoldJoinType join_type) {
|
||||
case MANIFOLD_JOIN_TYPE_MITER:
|
||||
jt = CrossSection::JoinType::Miter;
|
||||
break;
|
||||
case MANIFOLD_JOIN_TYPE_BEVEL:
|
||||
jt = CrossSection::JoinType::Bevel;
|
||||
break;
|
||||
};
|
||||
return jt;
|
||||
}
|
||||
|
||||
const manifold::Box *from_c(ManifoldBox *m) {
|
||||
return reinterpret_cast<manifold::Box const *>(m);
|
||||
const manifold::Box* from_c(ManifoldBox* m) {
|
||||
return reinterpret_cast<manifold::Box const*>(m);
|
||||
}
|
||||
|
||||
const manifold::Rect *from_c(ManifoldRect *m) {
|
||||
return reinterpret_cast<manifold::Rect const *>(m);
|
||||
const manifold::Rect* from_c(ManifoldRect* m) {
|
||||
return reinterpret_cast<manifold::Rect const*>(m);
|
||||
}
|
||||
|
||||
glm::vec2 from_c(ManifoldVec2 v) { return glm::vec2(v.x, v.y); }
|
||||
vec2 from_c(ManifoldVec2 v) { return vec2(v.x, v.y); }
|
||||
|
||||
glm::vec3 from_c(ManifoldVec3 v) { return glm::vec3(v.x, v.y, v.z); }
|
||||
vec3 from_c(ManifoldVec3 v) { return vec3(v.x, v.y, v.z); }
|
||||
|
||||
glm::ivec3 from_c(ManifoldIVec3 v) { return glm::ivec3(v.x, v.y, v.z); }
|
||||
ivec3 from_c(ManifoldIVec3 v) { return ivec3(v.x, v.y, v.z); }
|
||||
|
||||
glm::vec4 from_c(ManifoldVec4 v) { return glm::vec4(v.x, v.y, v.z, v.w); }
|
||||
vec4 from_c(ManifoldVec4 v) { return vec4(v.x, v.y, v.z, v.w); }
|
||||
|
||||
std::vector<glm::vec3> vector_of_vec_array(ManifoldVec3 *vs, size_t length) {
|
||||
auto vec = std::vector<glm::vec3>();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
const std::vector<ivec3>* from_c(ManifoldTriangulation* m) {
|
||||
return reinterpret_cast<std::vector<ivec3> const*>(m);
|
||||
}
|
||||
|
||||
std::vector<vec3> vector_of_vec_array(ManifoldVec3* vs, size_t length) {
|
||||
auto vec = std::vector<vec3>();
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
vec.push_back(from_c(vs[i]));
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<glm::ivec3> vector_of_vec_array(ManifoldIVec3 *vs, size_t length) {
|
||||
auto vec = std::vector<glm::ivec3>();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
std::vector<ivec3> vector_of_vec_array(ManifoldIVec3* vs, size_t length) {
|
||||
auto vec = std::vector<ivec3>();
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
vec.push_back(from_c(vs[i]));
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<glm::vec4> vector_of_vec_array(ManifoldVec4 *vs, size_t length) {
|
||||
auto vec = std::vector<glm::vec4>();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
std::vector<vec4> vector_of_vec_array(ManifoldVec4* vs, size_t length) {
|
||||
auto vec = std::vector<vec4>();
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
vec.push_back(from_c(vs[i]));
|
||||
}
|
||||
return vec;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright 2023 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "manifold/common.h"
|
||||
#include "manifold/cross_section.h"
|
||||
#include "manifold/manifold.h"
|
||||
#include "manifold/types.h"
|
||||
|
||||
using namespace manifold;
|
||||
using ManifoldVec = std::vector<Manifold>;
|
||||
using CrossSectionVec = std::vector<CrossSection>;
|
||||
|
||||
ManifoldManifold* to_c(manifold::Manifold* m);
|
||||
ManifoldManifoldVec* to_c(ManifoldVec* ms);
|
||||
ManifoldCrossSection* to_c(manifold::CrossSection* cs);
|
||||
ManifoldCrossSectionVec* to_c(CrossSectionVec* csv);
|
||||
ManifoldSimplePolygon* to_c(manifold::SimplePolygon* p);
|
||||
ManifoldPolygons* to_c(manifold::Polygons* ps);
|
||||
ManifoldMeshGL* to_c(manifold::MeshGL* m);
|
||||
ManifoldMeshGL64* to_c(manifold::MeshGL64* m);
|
||||
ManifoldBox* to_c(manifold::Box* m);
|
||||
ManifoldRect* to_c(manifold::Rect* m);
|
||||
ManifoldError to_c(manifold::Manifold::Error error);
|
||||
ManifoldVec2 to_c(vec2 v);
|
||||
ManifoldVec3 to_c(vec3 v);
|
||||
ManifoldIVec3 to_c(ivec3 v);
|
||||
ManifoldTriangulation* to_c(std::vector<ivec3>* m);
|
||||
|
||||
const manifold::Manifold* from_c(ManifoldManifold* m);
|
||||
ManifoldVec* from_c(ManifoldManifoldVec* ms);
|
||||
const manifold::CrossSection* from_c(ManifoldCrossSection* cs);
|
||||
CrossSectionVec* from_c(ManifoldCrossSectionVec* csv);
|
||||
const manifold::SimplePolygon* from_c(ManifoldSimplePolygon* m);
|
||||
const manifold::Polygons* from_c(ManifoldPolygons* m);
|
||||
const manifold::MeshGL* from_c(ManifoldMeshGL* m);
|
||||
const manifold::MeshGL64* from_c(ManifoldMeshGL64* m);
|
||||
OpType from_c(ManifoldOpType op);
|
||||
CrossSection::FillRule from_c(ManifoldFillRule fillrule);
|
||||
CrossSection::JoinType from_c(ManifoldJoinType jt);
|
||||
const manifold::Box* from_c(ManifoldBox* m);
|
||||
const manifold::Rect* from_c(ManifoldRect* r);
|
||||
vec2 from_c(ManifoldVec2 v);
|
||||
vec3 from_c(ManifoldVec3 v);
|
||||
ivec3 from_c(ManifoldIVec3 v);
|
||||
vec4 from_c(ManifoldVec4 v);
|
||||
const std::vector<ivec3>* from_c(ManifoldTriangulation* m);
|
||||
|
||||
std::vector<vec3> vector_of_vec_array(ManifoldVec3* vs, size_t length);
|
||||
std::vector<ivec3> vector_of_vec_array(ManifoldIVec3* vs, size_t length);
|
||||
std::vector<vec4> vector_of_vec_array(ManifoldVec4* vs, size_t length);
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> vector_of_array(T* ts, size_t length) {
|
||||
auto vec = std::vector<T>();
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
vec.push_back(ts[i]);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* copy_data(void* mem, std::vector<T> v) {
|
||||
T* ts = reinterpret_cast<T*>(mem);
|
||||
memcpy(ts, v.data(), sizeof(T) * v.size());
|
||||
return ts;
|
||||
}
|
||||
@@ -12,235 +12,242 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "conv.h"
|
||||
#include "cross_section.h"
|
||||
#include "manifold.h"
|
||||
#include "public.h"
|
||||
#include "types.h"
|
||||
#include "manifold/common.h"
|
||||
#include "manifold/cross_section.h"
|
||||
#include "manifold/types.h"
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_empty(void *mem) {
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
ManifoldCrossSection* manifold_cross_section_empty(void* mem) {
|
||||
return to_c(new (mem) CrossSection());
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_copy(void *mem,
|
||||
ManifoldCrossSection *cs) {
|
||||
ManifoldCrossSection* manifold_cross_section_copy(void* mem,
|
||||
ManifoldCrossSection* cs) {
|
||||
auto cross = *from_c(cs);
|
||||
return to_c(new (mem) CrossSection(cross));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_of_simple_polygon(
|
||||
void *mem, ManifoldSimplePolygon *p, ManifoldFillRule fr) {
|
||||
ManifoldCrossSection* manifold_cross_section_of_simple_polygon(
|
||||
void* mem, ManifoldSimplePolygon* p, ManifoldFillRule fr) {
|
||||
return to_c(new (mem) CrossSection(*from_c(p), from_c(fr)));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_of_polygons(void *mem,
|
||||
ManifoldPolygons *p,
|
||||
ManifoldCrossSection* manifold_cross_section_of_polygons(void* mem,
|
||||
ManifoldPolygons* p,
|
||||
ManifoldFillRule fr) {
|
||||
return to_c(new (mem) CrossSection(*from_c(p), from_c(fr)));
|
||||
}
|
||||
|
||||
ManifoldCrossSectionVec *manifold_cross_section_empty_vec(void *mem) {
|
||||
ManifoldCrossSectionVec* manifold_cross_section_empty_vec(void* mem) {
|
||||
return to_c(new (mem) CrossSectionVec());
|
||||
}
|
||||
|
||||
ManifoldCrossSectionVec *manifold_cross_section_vec(void *mem, size_t sz) {
|
||||
ManifoldCrossSectionVec* manifold_cross_section_vec(void* mem, size_t sz) {
|
||||
return to_c(new (mem) CrossSectionVec(sz));
|
||||
}
|
||||
|
||||
void manifold_cross_section_vec_reserve(ManifoldCrossSectionVec *csv,
|
||||
void manifold_cross_section_vec_reserve(ManifoldCrossSectionVec* csv,
|
||||
size_t sz) {
|
||||
from_c(csv)->reserve(sz);
|
||||
}
|
||||
|
||||
size_t manifold_cross_section_vec_length(ManifoldCrossSectionVec *csv) {
|
||||
size_t manifold_cross_section_vec_length(ManifoldCrossSectionVec* csv) {
|
||||
return from_c(csv)->size();
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_vec_get(
|
||||
void *mem, ManifoldCrossSectionVec *csv, int idx) {
|
||||
ManifoldCrossSection* manifold_cross_section_vec_get(
|
||||
void* mem, ManifoldCrossSectionVec* csv, size_t idx) {
|
||||
auto cs = (*from_c(csv))[idx];
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
void manifold_cross_section_vec_set(ManifoldCrossSectionVec *csv, int idx,
|
||||
ManifoldCrossSection *cs) {
|
||||
void manifold_cross_section_vec_set(ManifoldCrossSectionVec* csv, size_t idx,
|
||||
ManifoldCrossSection* cs) {
|
||||
(*from_c(csv))[idx] = *from_c(cs);
|
||||
}
|
||||
|
||||
void manifold_cross_section_vec_push_back(ManifoldCrossSectionVec *csv,
|
||||
ManifoldCrossSection *cs) {
|
||||
void manifold_cross_section_vec_push_back(ManifoldCrossSectionVec* csv,
|
||||
ManifoldCrossSection* cs) {
|
||||
return from_c(csv)->push_back(*from_c(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_square(void *mem, float x, float y,
|
||||
int center) {
|
||||
auto cs = CrossSection::Square(glm::vec2(x, y), center);
|
||||
ManifoldCrossSection* manifold_cross_section_square(void* mem, double x,
|
||||
double y, int center) {
|
||||
auto cs = CrossSection::Square(vec2(x, y), center);
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_circle(void *mem, float radius,
|
||||
ManifoldCrossSection* manifold_cross_section_circle(void* mem, double radius,
|
||||
int circular_segments) {
|
||||
auto cs = CrossSection::Circle(radius, circular_segments);
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_boolean(void *mem,
|
||||
ManifoldCrossSection *a,
|
||||
ManifoldCrossSection *b,
|
||||
ManifoldCrossSection* manifold_cross_section_boolean(void* mem,
|
||||
ManifoldCrossSection* a,
|
||||
ManifoldCrossSection* b,
|
||||
ManifoldOpType op) {
|
||||
auto cs = from_c(a)->Boolean(*from_c(b), from_c(op));
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_batch_boolean(
|
||||
void *mem, ManifoldCrossSectionVec *csv, ManifoldOpType op) {
|
||||
ManifoldCrossSection* manifold_cross_section_batch_boolean(
|
||||
void* mem, ManifoldCrossSectionVec* csv, ManifoldOpType op) {
|
||||
auto cs = CrossSection::BatchBoolean(*from_c(csv), from_c(op));
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_union(void *mem,
|
||||
ManifoldCrossSection *a,
|
||||
ManifoldCrossSection *b) {
|
||||
ManifoldCrossSection* manifold_cross_section_union(void* mem,
|
||||
ManifoldCrossSection* a,
|
||||
ManifoldCrossSection* b) {
|
||||
auto cs = (*from_c(a)) + (*from_c(b));
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_difference(
|
||||
void *mem, ManifoldCrossSection *a, ManifoldCrossSection *b) {
|
||||
ManifoldCrossSection* manifold_cross_section_difference(
|
||||
void* mem, ManifoldCrossSection* a, ManifoldCrossSection* b) {
|
||||
auto cs = (*from_c(a)) - (*from_c(b));
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_intersection(
|
||||
void *mem, ManifoldCrossSection *a, ManifoldCrossSection *b) {
|
||||
ManifoldCrossSection* manifold_cross_section_intersection(
|
||||
void* mem, ManifoldCrossSection* a, ManifoldCrossSection* b) {
|
||||
auto cs = (*from_c(a)) ^ (*from_c(b));
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_hull(void *mem,
|
||||
ManifoldCrossSection *cs) {
|
||||
ManifoldCrossSection* manifold_cross_section_hull(void* mem,
|
||||
ManifoldCrossSection* cs) {
|
||||
auto hulled = from_c(cs)->Hull();
|
||||
return to_c(new (mem) CrossSection(hulled));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_batch_hull(
|
||||
void *mem, ManifoldCrossSectionVec *css) {
|
||||
ManifoldCrossSection* manifold_cross_section_batch_hull(
|
||||
void* mem, ManifoldCrossSectionVec* css) {
|
||||
auto hulled = CrossSection::Hull(*from_c(css));
|
||||
return to_c(new (mem) CrossSection(hulled));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_hull_simple_polygon(
|
||||
void *mem, ManifoldSimplePolygon *ps) {
|
||||
ManifoldCrossSection* manifold_cross_section_hull_simple_polygon(
|
||||
void* mem, ManifoldSimplePolygon* ps) {
|
||||
auto hulled = CrossSection::Hull(*from_c(ps));
|
||||
return to_c(new (mem) CrossSection(hulled));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_hull_polygons(
|
||||
void *mem, ManifoldPolygons *ps) {
|
||||
ManifoldCrossSection* manifold_cross_section_hull_polygons(
|
||||
void* mem, ManifoldPolygons* ps) {
|
||||
auto hulled = CrossSection::Hull(*from_c(ps));
|
||||
return to_c(new (mem) CrossSection(hulled));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_translate(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float x, float y) {
|
||||
auto translated = from_c(cs)->Translate(glm::vec2(x, y));
|
||||
ManifoldCrossSection* manifold_cross_section_translate(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double x, double y) {
|
||||
auto translated = from_c(cs)->Translate(vec2(x, y));
|
||||
return to_c(new (mem) CrossSection(translated));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_rotate(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float deg) {
|
||||
ManifoldCrossSection* manifold_cross_section_rotate(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double deg) {
|
||||
auto rotated = from_c(cs)->Rotate(deg);
|
||||
return to_c(new (mem) CrossSection(rotated));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_scale(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float x, float y) {
|
||||
auto scaled = from_c(cs)->Scale(glm::vec2(x, y));
|
||||
ManifoldCrossSection* manifold_cross_section_scale(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double x, double y) {
|
||||
auto scaled = from_c(cs)->Scale(vec2(x, y));
|
||||
return to_c(new (mem) CrossSection(scaled));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_mirror(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float ax_x, float ax_y) {
|
||||
auto mirrored = from_c(cs)->Mirror(glm::vec2(ax_x, ax_y));
|
||||
ManifoldCrossSection* manifold_cross_section_mirror(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double ax_x, double ax_y) {
|
||||
auto mirrored = from_c(cs)->Mirror(vec2(ax_x, ax_y));
|
||||
return to_c(new (mem) CrossSection(mirrored));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_transform(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3) {
|
||||
auto mat = glm::mat3x2(x1, y1, x2, y2, x3, y3);
|
||||
ManifoldCrossSection* manifold_cross_section_transform(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) {
|
||||
auto mat = mat2x3({x1, y1}, {x2, y2}, {x3, y3});
|
||||
auto transformed = from_c(cs)->Transform(mat);
|
||||
return to_c(new (mem) CrossSection(transformed));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_warp(
|
||||
void *mem, ManifoldCrossSection *cs, ManifoldVec2 (*fun)(float, float)) {
|
||||
std::function<void(glm::vec2 & v)> warp = [fun](glm::vec2 &v) {
|
||||
v = from_c(fun(v.x, v.y));
|
||||
ManifoldCrossSection* manifold_cross_section_warp(
|
||||
void* mem, ManifoldCrossSection* cs,
|
||||
ManifoldVec2 (*fun)(double, double, void*), void* ctx) {
|
||||
// Bind function with context argument to one without
|
||||
using namespace std::placeholders;
|
||||
std::function<ManifoldVec2(double, double)> f2 = std::bind(fun, _1, _2, ctx);
|
||||
std::function<void(vec2 & v)> warp = [f2](vec2& v) {
|
||||
v = from_c(f2(v.x, v.y));
|
||||
};
|
||||
auto warped = from_c(cs)->Warp(warp);
|
||||
return to_c(new (mem) CrossSection(warped));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_simplify(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
ManifoldCrossSection* manifold_cross_section_simplify(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double epsilon) {
|
||||
auto simplified = from_c(cs)->Simplify(epsilon);
|
||||
return to_c(new (mem) CrossSection(simplified));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_offset(
|
||||
void *mem, ManifoldCrossSection *cs, double delta, ManifoldJoinType jt,
|
||||
ManifoldCrossSection* manifold_cross_section_offset(
|
||||
void* mem, ManifoldCrossSection* cs, double delta, ManifoldJoinType jt,
|
||||
double miter_limit, int circular_segments) {
|
||||
auto offset =
|
||||
from_c(cs)->Offset(delta, from_c(jt), miter_limit, circular_segments);
|
||||
return to_c(new (mem) CrossSection(offset));
|
||||
}
|
||||
|
||||
double manifold_cross_section_area(ManifoldCrossSection *cs) {
|
||||
double manifold_cross_section_area(ManifoldCrossSection* cs) {
|
||||
return from_c(cs)->Area();
|
||||
}
|
||||
|
||||
int manifold_cross_section_num_vert(ManifoldCrossSection *cs) {
|
||||
size_t manifold_cross_section_num_vert(ManifoldCrossSection* cs) {
|
||||
return from_c(cs)->NumVert();
|
||||
}
|
||||
|
||||
int manifold_cross_section_num_contour(ManifoldCrossSection *cs) {
|
||||
size_t manifold_cross_section_num_contour(ManifoldCrossSection* cs) {
|
||||
return from_c(cs)->NumContour();
|
||||
}
|
||||
|
||||
int manifold_cross_section_is_empty(ManifoldCrossSection *cs) {
|
||||
int manifold_cross_section_is_empty(ManifoldCrossSection* cs) {
|
||||
return from_c(cs)->IsEmpty();
|
||||
}
|
||||
|
||||
ManifoldRect *manifold_cross_section_bounds(void *mem,
|
||||
ManifoldCrossSection *cs) {
|
||||
ManifoldRect* manifold_cross_section_bounds(void* mem,
|
||||
ManifoldCrossSection* cs) {
|
||||
auto rect = from_c(cs)->Bounds();
|
||||
return to_c(new (mem) Rect(rect));
|
||||
}
|
||||
|
||||
ManifoldPolygons *manifold_cross_section_to_polygons(void *mem,
|
||||
ManifoldCrossSection *cs) {
|
||||
ManifoldPolygons* manifold_cross_section_to_polygons(void* mem,
|
||||
ManifoldCrossSection* cs) {
|
||||
auto ps = from_c(cs)->ToPolygons();
|
||||
return to_c(new (mem) Polygons(ps));
|
||||
}
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_compose(
|
||||
void *mem, ManifoldCrossSectionVec *csv) {
|
||||
ManifoldCrossSection* manifold_cross_section_compose(
|
||||
void* mem, ManifoldCrossSectionVec* csv) {
|
||||
auto cs = CrossSection::Compose(*from_c(csv));
|
||||
return to_c(new (mem) CrossSection(cs));
|
||||
}
|
||||
|
||||
ManifoldCrossSectionVec *manifold_cross_section_decompose(
|
||||
void *mem, ManifoldCrossSection *cs) {
|
||||
ManifoldCrossSectionVec* manifold_cross_section_decompose(
|
||||
void* mem, ManifoldCrossSection* cs) {
|
||||
auto comps = from_c(cs)->Decompose();
|
||||
return to_c(new (mem) CrossSectionVec(comps));
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
// Copyright 2023 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "cross_section.h"
|
||||
#include "manifold.h"
|
||||
#include "public.h"
|
||||
#include "sdf.h"
|
||||
#include "types.h"
|
||||
|
||||
using namespace manifold;
|
||||
using ManifoldVec = std::vector<Manifold>;
|
||||
using CrossSectionVec = std::vector<CrossSection>;
|
||||
|
||||
ManifoldManifold *to_c(manifold::Manifold *m);
|
||||
ManifoldManifoldVec *to_c(ManifoldVec *ms);
|
||||
ManifoldCrossSection *to_c(manifold::CrossSection *cs);
|
||||
ManifoldCrossSectionVec *to_c(CrossSectionVec *csv);
|
||||
ManifoldSimplePolygon *to_c(manifold::SimplePolygon *p);
|
||||
ManifoldPolygons *to_c(manifold::Polygons *ps);
|
||||
ManifoldMesh *to_c(manifold::Mesh *m);
|
||||
ManifoldMeshGL *to_c(manifold::MeshGL *m);
|
||||
ManifoldBox *to_c(manifold::Box *m);
|
||||
ManifoldRect *to_c(manifold::Rect *m);
|
||||
ManifoldError to_c(manifold::Manifold::Error error);
|
||||
ManifoldVec2 to_c(glm::vec2 v);
|
||||
ManifoldVec3 to_c(glm::vec3 v);
|
||||
ManifoldIVec3 to_c(glm::ivec3 v);
|
||||
ManifoldProperties to_c(manifold::Properties p);
|
||||
|
||||
const manifold::Manifold *from_c(ManifoldManifold *m);
|
||||
ManifoldVec *from_c(ManifoldManifoldVec *ms);
|
||||
const manifold::CrossSection *from_c(ManifoldCrossSection *cs);
|
||||
CrossSectionVec *from_c(ManifoldCrossSectionVec *csv);
|
||||
const manifold::SimplePolygon *from_c(ManifoldSimplePolygon *m);
|
||||
const manifold::Polygons *from_c(ManifoldPolygons *m);
|
||||
const manifold::Mesh *from_c(ManifoldMesh *m);
|
||||
const manifold::MeshGL *from_c(ManifoldMeshGL *m);
|
||||
OpType from_c(ManifoldOpType op);
|
||||
CrossSection::FillRule from_c(ManifoldFillRule fillrule);
|
||||
CrossSection::JoinType from_c(ManifoldJoinType jt);
|
||||
const manifold::Box *from_c(ManifoldBox *m);
|
||||
const manifold::Rect *from_c(ManifoldRect *r);
|
||||
glm::vec2 from_c(ManifoldVec2 v);
|
||||
glm::vec3 from_c(ManifoldVec3 v);
|
||||
glm::ivec3 from_c(ManifoldIVec3 v);
|
||||
glm::vec4 from_c(ManifoldVec4 v);
|
||||
|
||||
std::vector<glm::vec3> vector_of_vec_array(ManifoldVec3 *vs, size_t length);
|
||||
std::vector<glm::ivec3> vector_of_vec_array(ManifoldIVec3 *vs, size_t length);
|
||||
std::vector<glm::vec4> vector_of_vec_array(ManifoldVec4 *vs, size_t length);
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> vector_of_array(T *ts, size_t length) {
|
||||
auto vec = std::vector<T>();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
vec.push_back(ts[i]);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *copy_data(void *mem, std::vector<T> v) {
|
||||
T *ts = reinterpret_cast<T *>(mem);
|
||||
memcpy(ts, v.data(), sizeof(T) * v.size());
|
||||
return ts;
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
// Copyright 2023 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "manifold/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Polygons
|
||||
|
||||
ManifoldSimplePolygon* manifold_simple_polygon(void* mem, ManifoldVec2* ps,
|
||||
size_t length);
|
||||
ManifoldPolygons* manifold_polygons(void* mem, ManifoldSimplePolygon** ps,
|
||||
size_t length);
|
||||
size_t manifold_simple_polygon_length(ManifoldSimplePolygon* p);
|
||||
size_t manifold_polygons_length(ManifoldPolygons* ps);
|
||||
size_t manifold_polygons_simple_length(ManifoldPolygons* ps, size_t idx);
|
||||
ManifoldVec2 manifold_simple_polygon_get_point(ManifoldSimplePolygon* p,
|
||||
size_t idx);
|
||||
ManifoldSimplePolygon* manifold_polygons_get_simple(void* mem,
|
||||
ManifoldPolygons* ps,
|
||||
size_t idx);
|
||||
ManifoldVec2 manifold_polygons_get_point(ManifoldPolygons* ps,
|
||||
size_t simple_idx, size_t pt_idx);
|
||||
|
||||
// Mesh Construction
|
||||
|
||||
ManifoldMeshGL* manifold_meshgl(void* mem, float* vert_props, size_t n_verts,
|
||||
size_t n_props, uint32_t* tri_verts,
|
||||
size_t n_tris);
|
||||
|
||||
ManifoldMeshGL* manifold_meshgl_w_tangents(void* mem, float* vert_props,
|
||||
size_t n_verts, size_t n_props,
|
||||
uint32_t* tri_verts, size_t n_tris,
|
||||
float* halfedge_tangent);
|
||||
ManifoldMeshGL* manifold_meshgl_w_options(void* mem, float* vert_props,
|
||||
size_t n_verts, size_t n_props,
|
||||
uint32_t* tri_verts, size_t n_tris,
|
||||
ManifoldMeshGLOptions* options);
|
||||
ManifoldMeshGL* manifold_get_meshgl(void* mem, ManifoldManifold* m);
|
||||
ManifoldMeshGL* manifold_get_meshgl_w_normals(void* mem, ManifoldManifold* m,
|
||||
int32_t normalIdx);
|
||||
ManifoldMeshGL* manifold_meshgl_copy(void* mem, ManifoldMeshGL* m);
|
||||
ManifoldMeshGL* manifold_meshgl_merge(void* mem, ManifoldMeshGL* m);
|
||||
|
||||
ManifoldMeshGL64* manifold_meshgl64(void* mem, double* vert_props,
|
||||
size_t n_verts, size_t n_props,
|
||||
uint64_t* tri_verts, size_t n_tris);
|
||||
|
||||
ManifoldMeshGL64* manifold_meshgl64_w_tangents(void* mem, double* vert_props,
|
||||
size_t n_verts, size_t n_props,
|
||||
uint64_t* tri_verts,
|
||||
size_t n_tris,
|
||||
double* halfedge_tangent);
|
||||
ManifoldMeshGL64* manifold_meshgl64_w_options(void* mem, double* vert_props,
|
||||
size_t n_verts, size_t n_props,
|
||||
uint64_t* tri_verts,
|
||||
size_t n_tris,
|
||||
ManifoldMeshGL64Options* options);
|
||||
ManifoldMeshGL64* manifold_get_meshgl64(void* mem, ManifoldManifold* m);
|
||||
ManifoldMeshGL64* manifold_get_meshgl64_w_normals(void* mem,
|
||||
ManifoldManifold* m,
|
||||
int32_t normalIdx);
|
||||
ManifoldMeshGL64* manifold_meshgl64_copy(void* mem, ManifoldMeshGL64* m);
|
||||
ManifoldMeshGL64* manifold_meshgl64_merge(void* mem, ManifoldMeshGL64* m);
|
||||
|
||||
// SDF
|
||||
// By default, the execution policy (sequential or parallel) of
|
||||
// manifold_level_set will be chosen automatically depending on the size of the
|
||||
// job and whether Manifold has been compiled with a PAR backend. If you are
|
||||
// using these bindings from a language that has a runtime lock preventing the
|
||||
// parallel execution of closures, then you should use manifold_level_set_seq to
|
||||
// force sequential execution.
|
||||
ManifoldManifold* manifold_level_set(void* mem, ManifoldSdf sdf,
|
||||
ManifoldBox* bounds, double edge_length,
|
||||
double level, double tolerance, void* ctx);
|
||||
ManifoldManifold* manifold_level_set_seq(void* mem, ManifoldSdf sdf,
|
||||
ManifoldBox* bounds,
|
||||
double edge_length, double level,
|
||||
double tolerance, void* ctx);
|
||||
|
||||
// Manifold Vectors
|
||||
|
||||
ManifoldManifoldVec* manifold_manifold_empty_vec(void* mem);
|
||||
ManifoldManifoldVec* manifold_manifold_vec(void* mem, size_t sz);
|
||||
void manifold_manifold_vec_reserve(ManifoldManifoldVec* ms, size_t sz);
|
||||
size_t manifold_manifold_vec_length(ManifoldManifoldVec* ms);
|
||||
ManifoldManifold* manifold_manifold_vec_get(void* mem, ManifoldManifoldVec* ms,
|
||||
size_t idx);
|
||||
void manifold_manifold_vec_set(ManifoldManifoldVec* ms, size_t idx,
|
||||
ManifoldManifold* m);
|
||||
void manifold_manifold_vec_push_back(ManifoldManifoldVec* ms,
|
||||
ManifoldManifold* m);
|
||||
|
||||
// Manifold Booleans
|
||||
|
||||
ManifoldManifold* manifold_boolean(void* mem, ManifoldManifold* a,
|
||||
ManifoldManifold* b, ManifoldOpType op);
|
||||
ManifoldManifold* manifold_batch_boolean(void* mem, ManifoldManifoldVec* ms,
|
||||
ManifoldOpType op);
|
||||
ManifoldManifold* manifold_union(void* mem, ManifoldManifold* a,
|
||||
ManifoldManifold* b);
|
||||
ManifoldManifold* manifold_difference(void* mem, ManifoldManifold* a,
|
||||
ManifoldManifold* b);
|
||||
ManifoldManifold* manifold_intersection(void* mem, ManifoldManifold* a,
|
||||
ManifoldManifold* b);
|
||||
ManifoldManifoldPair manifold_split(void* mem_first, void* mem_second,
|
||||
ManifoldManifold* a, ManifoldManifold* b);
|
||||
ManifoldManifoldPair manifold_split_by_plane(void* mem_first, void* mem_second,
|
||||
ManifoldManifold* m,
|
||||
double normal_x, double normal_y,
|
||||
double normal_z, double offset);
|
||||
ManifoldManifold* manifold_trim_by_plane(void* mem, ManifoldManifold* m,
|
||||
double normal_x, double normal_y,
|
||||
double normal_z, double offset);
|
||||
ManifoldManifold* manifold_minkowski_sum(void* mem, ManifoldManifold* a,
|
||||
ManifoldManifold* b);
|
||||
ManifoldManifold* manifold_minkowski_difference(void* mem, ManifoldManifold* a,
|
||||
ManifoldManifold* b);
|
||||
|
||||
// 3D to 2D
|
||||
|
||||
ManifoldPolygons* manifold_slice(void* mem, ManifoldManifold* m, double height);
|
||||
ManifoldPolygons* manifold_project(void* mem, ManifoldManifold* m);
|
||||
|
||||
// Convex Hulls
|
||||
|
||||
ManifoldManifold* manifold_hull(void* mem, ManifoldManifold* m);
|
||||
ManifoldManifold* manifold_batch_hull(void* mem, ManifoldManifoldVec* ms);
|
||||
ManifoldManifold* manifold_hull_pts(void* mem, ManifoldVec3* ps, size_t length);
|
||||
|
||||
// Manifold Transformations
|
||||
|
||||
ManifoldManifold* manifold_translate(void* mem, ManifoldManifold* m, double x,
|
||||
double y, double z);
|
||||
ManifoldManifold* manifold_rotate(void* mem, ManifoldManifold* m, double x,
|
||||
double y, double z);
|
||||
ManifoldManifold* manifold_scale(void* mem, ManifoldManifold* m, double x,
|
||||
double y, double z);
|
||||
ManifoldManifold* manifold_transform(void* mem, ManifoldManifold* m, double x1,
|
||||
double y1, double z1, double x2, double y2,
|
||||
double z2, double x3, double y3, double z3,
|
||||
double x4, double y4, double z4);
|
||||
ManifoldManifold* manifold_mirror(void* mem, ManifoldManifold* m, double nx,
|
||||
double ny, double nz);
|
||||
ManifoldManifold* manifold_warp(void* mem, ManifoldManifold* m,
|
||||
ManifoldVec3 (*fun)(double, double, double,
|
||||
void*),
|
||||
void* ctx);
|
||||
ManifoldManifold* manifold_smooth_by_normals(void* mem, ManifoldManifold* m,
|
||||
int normalIdx);
|
||||
ManifoldManifold* manifold_smooth_out(void* mem, ManifoldManifold* m,
|
||||
double minSharpAngle,
|
||||
double minSmoothness);
|
||||
ManifoldManifold* manifold_refine(void* mem, ManifoldManifold* m, int refine);
|
||||
ManifoldManifold* manifold_refine_to_length(void* mem, ManifoldManifold* m,
|
||||
double length);
|
||||
ManifoldManifold* manifold_refine_to_tolerance(void* mem, ManifoldManifold* m,
|
||||
double tolerance);
|
||||
|
||||
// Manifold Shapes / Constructors
|
||||
|
||||
ManifoldManifold* manifold_empty(void* mem);
|
||||
ManifoldManifold* manifold_copy(void* mem, ManifoldManifold* m);
|
||||
ManifoldManifold* manifold_tetrahedron(void* mem);
|
||||
ManifoldManifold* manifold_cube(void* mem, double x, double y, double z,
|
||||
int center);
|
||||
ManifoldManifold* manifold_cylinder(void* mem, double height, double radius_low,
|
||||
double radius_high, int circular_segments,
|
||||
int center);
|
||||
ManifoldManifold* manifold_sphere(void* mem, double radius,
|
||||
int circular_segments);
|
||||
ManifoldManifold* manifold_of_meshgl(void* mem, ManifoldMeshGL* mesh);
|
||||
ManifoldManifold* manifold_of_meshgl64(void* mem, ManifoldMeshGL64* mesh);
|
||||
ManifoldManifold* manifold_smooth(void* mem, ManifoldMeshGL* mesh,
|
||||
size_t* half_edges, double* smoothness,
|
||||
size_t n_idxs);
|
||||
ManifoldManifold* manifold_smooth64(void* mem, ManifoldMeshGL64* mesh,
|
||||
size_t* half_edges, double* smoothness,
|
||||
size_t n_idxs);
|
||||
ManifoldManifold* manifold_extrude(void* mem, ManifoldPolygons* cs,
|
||||
double height, int slices,
|
||||
double twist_degrees, double scale_x,
|
||||
double scale_y);
|
||||
ManifoldManifold* manifold_revolve(void* mem, ManifoldPolygons* cs,
|
||||
int circular_segments,
|
||||
double revolve_degrees);
|
||||
ManifoldManifold* manifold_compose(void* mem, ManifoldManifoldVec* ms);
|
||||
ManifoldManifoldVec* manifold_decompose(void* mem, ManifoldManifold* m);
|
||||
|
||||
ManifoldManifold* manifold_as_original(void* mem, ManifoldManifold* m);
|
||||
|
||||
// Manifold Info
|
||||
|
||||
int manifold_is_empty(ManifoldManifold* m);
|
||||
ManifoldError manifold_status(ManifoldManifold* m);
|
||||
size_t manifold_num_vert(ManifoldManifold* m);
|
||||
size_t manifold_num_edge(ManifoldManifold* m);
|
||||
size_t manifold_num_tri(ManifoldManifold* m);
|
||||
size_t manifold_num_prop(ManifoldManifold* m);
|
||||
ManifoldBox* manifold_bounding_box(void* mem, ManifoldManifold* m);
|
||||
double manifold_epsilon(ManifoldManifold* m);
|
||||
int manifold_genus(ManifoldManifold* m);
|
||||
double manifold_surface_area(ManifoldManifold* m);
|
||||
double manifold_volume(ManifoldManifold* m);
|
||||
int manifold_get_circular_segments(double radius);
|
||||
int manifold_original_id(ManifoldManifold* m);
|
||||
uint32_t manifold_reserve_ids(uint32_t n);
|
||||
ManifoldManifold* manifold_set_properties(
|
||||
void* mem, ManifoldManifold* m, int num_prop,
|
||||
void (*fun)(double* new_prop, ManifoldVec3 position, const double* old_prop,
|
||||
void* ctx),
|
||||
void* ctx);
|
||||
ManifoldManifold* manifold_calculate_curvature(void* mem, ManifoldManifold* m,
|
||||
int gaussian_idx, int mean_idx);
|
||||
double manifold_min_gap(ManifoldManifold* m, ManifoldManifold* other,
|
||||
double searchLength);
|
||||
ManifoldManifold* manifold_calculate_normals(void* mem, ManifoldManifold* m,
|
||||
int normal_idx,
|
||||
double min_sharp_angle);
|
||||
|
||||
// CrossSection Shapes/Constructors
|
||||
ManifoldCrossSection* manifold_cross_section_empty(void* mem);
|
||||
ManifoldCrossSection* manifold_cross_section_copy(void* mem,
|
||||
ManifoldCrossSection* cs);
|
||||
ManifoldCrossSection* manifold_cross_section_of_simple_polygon(
|
||||
void* mem, ManifoldSimplePolygon* p, ManifoldFillRule fr);
|
||||
ManifoldCrossSection* manifold_cross_section_of_polygons(void* mem,
|
||||
ManifoldPolygons* p,
|
||||
ManifoldFillRule fr);
|
||||
ManifoldCrossSection* manifold_cross_section_square(void* mem, double x,
|
||||
double y, int center);
|
||||
ManifoldCrossSection* manifold_cross_section_circle(void* mem, double radius,
|
||||
int circular_segments);
|
||||
ManifoldCrossSection* manifold_cross_section_compose(
|
||||
void* mem, ManifoldCrossSectionVec* csv);
|
||||
ManifoldCrossSectionVec* manifold_cross_section_decompose(
|
||||
void* mem, ManifoldCrossSection* cs);
|
||||
|
||||
// CrossSection Vectors
|
||||
|
||||
ManifoldCrossSectionVec* manifold_cross_section_empty_vec(void* mem);
|
||||
ManifoldCrossSectionVec* manifold_cross_section_vec(void* mem, size_t sz);
|
||||
void manifold_cross_section_vec_reserve(ManifoldCrossSectionVec* csv,
|
||||
size_t sz);
|
||||
size_t manifold_cross_section_vec_length(ManifoldCrossSectionVec* csv);
|
||||
ManifoldCrossSection* manifold_cross_section_vec_get(
|
||||
void* mem, ManifoldCrossSectionVec* csv, size_t idx);
|
||||
void manifold_cross_section_vec_set(ManifoldCrossSectionVec* csv, size_t idx,
|
||||
ManifoldCrossSection* cs);
|
||||
void manifold_cross_section_vec_push_back(ManifoldCrossSectionVec* csv,
|
||||
ManifoldCrossSection* cs);
|
||||
|
||||
// CrossSection Booleans
|
||||
|
||||
ManifoldCrossSection* manifold_cross_section_boolean(void* mem,
|
||||
ManifoldCrossSection* a,
|
||||
ManifoldCrossSection* b,
|
||||
ManifoldOpType op);
|
||||
ManifoldCrossSection* manifold_cross_section_batch_boolean(
|
||||
void* mem, ManifoldCrossSectionVec* csv, ManifoldOpType op);
|
||||
ManifoldCrossSection* manifold_cross_section_union(void* mem,
|
||||
ManifoldCrossSection* a,
|
||||
ManifoldCrossSection* b);
|
||||
ManifoldCrossSection* manifold_cross_section_difference(
|
||||
void* mem, ManifoldCrossSection* a, ManifoldCrossSection* b);
|
||||
ManifoldCrossSection* manifold_cross_section_intersection(
|
||||
void* mem, ManifoldCrossSection* a, ManifoldCrossSection* b);
|
||||
|
||||
// CrossSection Convex Hulls
|
||||
|
||||
ManifoldCrossSection* manifold_cross_section_hull(void* mem,
|
||||
ManifoldCrossSection* cs);
|
||||
ManifoldCrossSection* manifold_cross_section_batch_hull(
|
||||
void* mem, ManifoldCrossSectionVec* css);
|
||||
ManifoldCrossSection* manifold_cross_section_hull_simple_polygon(
|
||||
void* mem, ManifoldSimplePolygon* ps);
|
||||
ManifoldCrossSection* manifold_cross_section_hull_polygons(
|
||||
void* mem, ManifoldPolygons* ps);
|
||||
|
||||
// CrossSection Transformation
|
||||
|
||||
ManifoldCrossSection* manifold_cross_section_translate(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double x, double y);
|
||||
ManifoldCrossSection* manifold_cross_section_rotate(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double deg);
|
||||
ManifoldCrossSection* manifold_cross_section_scale(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double x, double y);
|
||||
ManifoldCrossSection* manifold_cross_section_mirror(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double ax_x, double ax_y);
|
||||
ManifoldCrossSection* manifold_cross_section_transform(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
ManifoldCrossSection* manifold_cross_section_warp(
|
||||
void* mem, ManifoldCrossSection* cs, ManifoldVec2 (*fun)(double, double));
|
||||
ManifoldCrossSection* manifold_cross_section_warp_context(
|
||||
void* mem, ManifoldCrossSection* cs,
|
||||
ManifoldVec2 (*fun)(double, double, void*), void* ctx);
|
||||
ManifoldCrossSection* manifold_cross_section_simplify(void* mem,
|
||||
ManifoldCrossSection* cs,
|
||||
double epsilon);
|
||||
ManifoldCrossSection* manifold_cross_section_offset(
|
||||
void* mem, ManifoldCrossSection* cs, double delta, ManifoldJoinType jt,
|
||||
double miter_limit, int circular_segments);
|
||||
|
||||
// CrossSection Info
|
||||
|
||||
double manifold_cross_section_area(ManifoldCrossSection* cs);
|
||||
size_t manifold_cross_section_num_vert(ManifoldCrossSection* cs);
|
||||
size_t manifold_cross_section_num_contour(ManifoldCrossSection* cs);
|
||||
int manifold_cross_section_is_empty(ManifoldCrossSection* cs);
|
||||
ManifoldRect* manifold_cross_section_bounds(void* mem,
|
||||
ManifoldCrossSection* cs);
|
||||
ManifoldPolygons* manifold_cross_section_to_polygons(void* mem,
|
||||
ManifoldCrossSection* cs);
|
||||
|
||||
// Rectangle
|
||||
|
||||
ManifoldRect* manifold_rect(void* mem, double x1, double y1, double x2,
|
||||
double y2);
|
||||
ManifoldVec2 manifold_rect_min(ManifoldRect* r);
|
||||
ManifoldVec2 manifold_rect_max(ManifoldRect* r);
|
||||
ManifoldVec2 manifold_rect_dimensions(ManifoldRect* r);
|
||||
ManifoldVec2 manifold_rect_center(ManifoldRect* r);
|
||||
double manifold_rect_scale(ManifoldRect* r);
|
||||
int manifold_rect_contains_pt(ManifoldRect* r, double x, double y);
|
||||
int manifold_rect_contains_rect(ManifoldRect* a, ManifoldRect* b);
|
||||
void manifold_rect_include_pt(ManifoldRect* r, double x, double y);
|
||||
ManifoldRect* manifold_rect_union(void* mem, ManifoldRect* a, ManifoldRect* b);
|
||||
ManifoldRect* manifold_rect_transform(void* mem, ManifoldRect* r, double x1,
|
||||
double y1, double x2, double y2,
|
||||
double x3, double y3);
|
||||
ManifoldRect* manifold_rect_translate(void* mem, ManifoldRect* r, double x,
|
||||
double y);
|
||||
ManifoldRect* manifold_rect_mul(void* mem, ManifoldRect* r, double x, double y);
|
||||
int manifold_rect_does_overlap_rect(ManifoldRect* a, ManifoldRect* r);
|
||||
int manifold_rect_is_empty(ManifoldRect* r);
|
||||
int manifold_rect_is_finite(ManifoldRect* r);
|
||||
|
||||
// Bounding Box
|
||||
|
||||
ManifoldBox* manifold_box(void* mem, double x1, double y1, double z1, double x2,
|
||||
double y2, double z2);
|
||||
ManifoldVec3 manifold_box_min(ManifoldBox* b);
|
||||
ManifoldVec3 manifold_box_max(ManifoldBox* b);
|
||||
ManifoldVec3 manifold_box_dimensions(ManifoldBox* b);
|
||||
ManifoldVec3 manifold_box_center(ManifoldBox* b);
|
||||
double manifold_box_scale(ManifoldBox* b);
|
||||
int manifold_box_contains_pt(ManifoldBox* b, double x, double y, double z);
|
||||
int manifold_box_contains_box(ManifoldBox* a, ManifoldBox* b);
|
||||
void manifold_box_include_pt(ManifoldBox* b, double x, double y, double z);
|
||||
ManifoldBox* manifold_box_union(void* mem, ManifoldBox* a, ManifoldBox* b);
|
||||
ManifoldBox* manifold_box_transform(void* mem, ManifoldBox* b, double x1,
|
||||
double y1, double z1, double x2, double y2,
|
||||
double z2, double x3, double y3, double z3,
|
||||
double x4, double y4, double z4);
|
||||
ManifoldBox* manifold_box_translate(void* mem, ManifoldBox* b, double x,
|
||||
double y, double z);
|
||||
ManifoldBox* manifold_box_mul(void* mem, ManifoldBox* b, double x, double y,
|
||||
double z);
|
||||
int manifold_box_does_overlap_pt(ManifoldBox* b, double x, double y, double z);
|
||||
int manifold_box_does_overlap_box(ManifoldBox* a, ManifoldBox* b);
|
||||
int manifold_box_is_finite(ManifoldBox* b);
|
||||
|
||||
// Static Quality Globals
|
||||
|
||||
void manifold_set_min_circular_angle(double degrees);
|
||||
void manifold_set_min_circular_edge_length(double length);
|
||||
void manifold_set_circular_segments(int number);
|
||||
void manifold_reset_to_circular_defaults();
|
||||
|
||||
// Manifold Mesh Extraction
|
||||
|
||||
size_t manifold_meshgl_num_prop(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_num_vert(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_num_tri(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_vert_properties_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_tri_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_merge_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_run_index_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_run_original_id_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_run_transform_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_face_id_length(ManifoldMeshGL* m);
|
||||
size_t manifold_meshgl_tangent_length(ManifoldMeshGL* m);
|
||||
float* manifold_meshgl_vert_properties(void* mem, ManifoldMeshGL* m);
|
||||
uint32_t* manifold_meshgl_tri_verts(void* mem, ManifoldMeshGL* m);
|
||||
uint32_t* manifold_meshgl_merge_from_vert(void* mem, ManifoldMeshGL* m);
|
||||
uint32_t* manifold_meshgl_merge_to_vert(void* mem, ManifoldMeshGL* m);
|
||||
uint32_t* manifold_meshgl_run_index(void* mem, ManifoldMeshGL* m);
|
||||
uint32_t* manifold_meshgl_run_original_id(void* mem, ManifoldMeshGL* m);
|
||||
float* manifold_meshgl_run_transform(void* mem, ManifoldMeshGL* m);
|
||||
uint32_t* manifold_meshgl_face_id(void* mem, ManifoldMeshGL* m);
|
||||
float* manifold_meshgl_halfedge_tangent(void* mem, ManifoldMeshGL* m);
|
||||
|
||||
size_t manifold_meshgl64_num_prop(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_num_vert(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_num_tri(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_vert_properties_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_tri_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_merge_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_run_index_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_run_original_id_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_run_transform_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_face_id_length(ManifoldMeshGL64* m);
|
||||
size_t manifold_meshgl64_tangent_length(ManifoldMeshGL64* m);
|
||||
double* manifold_meshgl64_vert_properties(void* mem, ManifoldMeshGL64* m);
|
||||
uint64_t* manifold_meshgl64_tri_verts(void* mem, ManifoldMeshGL64* m);
|
||||
uint64_t* manifold_meshgl64_merge_from_vert(void* mem, ManifoldMeshGL64* m);
|
||||
uint64_t* manifold_meshgl64_merge_to_vert(void* mem, ManifoldMeshGL64* m);
|
||||
uint64_t* manifold_meshgl64_run_index(void* mem, ManifoldMeshGL64* m);
|
||||
uint32_t* manifold_meshgl64_run_original_id(void* mem, ManifoldMeshGL64* m);
|
||||
double* manifold_meshgl64_run_transform(void* mem, ManifoldMeshGL64* m);
|
||||
uint64_t* manifold_meshgl64_face_id(void* mem, ManifoldMeshGL64* m);
|
||||
double* manifold_meshgl64_halfedge_tangent(void* mem, ManifoldMeshGL64* m);
|
||||
|
||||
// Triangulation
|
||||
|
||||
ManifoldTriangulation* manifold_triangulate(void* mem, ManifoldPolygons* ps,
|
||||
double epsilon);
|
||||
size_t manifold_triangulation_num_tri(ManifoldTriangulation* m);
|
||||
int* manifold_triangulation_tri_verts(void* mem, ManifoldTriangulation* m);
|
||||
|
||||
// memory size
|
||||
|
||||
size_t manifold_manifold_size();
|
||||
size_t manifold_manifold_vec_size();
|
||||
size_t manifold_cross_section_size();
|
||||
size_t manifold_cross_section_vec_size();
|
||||
size_t manifold_simple_polygon_size();
|
||||
size_t manifold_polygons_size();
|
||||
size_t manifold_manifold_pair_size();
|
||||
size_t manifold_meshgl_size();
|
||||
size_t manifold_meshgl64_size();
|
||||
size_t manifold_box_size();
|
||||
size_t manifold_rect_size();
|
||||
size_t manifold_triangulation_size();
|
||||
|
||||
// allocation
|
||||
|
||||
ManifoldManifold* manifold_alloc_manifold();
|
||||
ManifoldManifoldVec* manifold_alloc_manifold_vec();
|
||||
ManifoldCrossSection* manifold_alloc_cross_section();
|
||||
ManifoldCrossSectionVec* manifold_alloc_cross_section_vec();
|
||||
ManifoldSimplePolygon* manifold_alloc_simple_polygon();
|
||||
ManifoldPolygons* manifold_alloc_polygons();
|
||||
ManifoldMeshGL* manifold_alloc_meshgl();
|
||||
ManifoldMeshGL64* manifold_alloc_meshgl64();
|
||||
ManifoldBox* manifold_alloc_box();
|
||||
ManifoldRect* manifold_alloc_rect();
|
||||
ManifoldTriangulation* manifold_alloc_triangulation();
|
||||
|
||||
// destruction
|
||||
|
||||
void manifold_destruct_manifold(ManifoldManifold* m);
|
||||
void manifold_destruct_manifold_vec(ManifoldManifoldVec* ms);
|
||||
void manifold_destruct_cross_section(ManifoldCrossSection* m);
|
||||
void manifold_destruct_cross_section_vec(ManifoldCrossSectionVec* csv);
|
||||
void manifold_destruct_simple_polygon(ManifoldSimplePolygon* p);
|
||||
void manifold_destruct_polygons(ManifoldPolygons* p);
|
||||
void manifold_destruct_meshgl(ManifoldMeshGL* m);
|
||||
void manifold_destruct_meshgl64(ManifoldMeshGL64* m);
|
||||
void manifold_destruct_box(ManifoldBox* b);
|
||||
void manifold_destruct_rect(ManifoldRect* b);
|
||||
void manifold_destruct_triangulation(ManifoldTriangulation* M);
|
||||
|
||||
// pointer free + destruction
|
||||
|
||||
void manifold_delete_manifold(ManifoldManifold* m);
|
||||
void manifold_delete_manifold_vec(ManifoldManifoldVec* ms);
|
||||
void manifold_delete_cross_section(ManifoldCrossSection* cs);
|
||||
void manifold_delete_cross_section_vec(ManifoldCrossSectionVec* csv);
|
||||
void manifold_delete_simple_polygon(ManifoldSimplePolygon* p);
|
||||
void manifold_delete_polygons(ManifoldPolygons* p);
|
||||
void manifold_delete_meshgl(ManifoldMeshGL* m);
|
||||
void manifold_delete_meshgl64(ManifoldMeshGL64* m);
|
||||
void manifold_delete_box(ManifoldBox* b);
|
||||
void manifold_delete_rect(ManifoldRect* b);
|
||||
void manifold_delete_triangulation(ManifoldTriangulation* m);
|
||||
|
||||
// MeshIO / Export
|
||||
|
||||
// Import a manifold from a Wavefront obj file.
|
||||
// The obj_file parameter is the content of the obj file, not the filename,
|
||||
// and should be null-terminated.
|
||||
ManifoldManifold* manifold_read_obj(void* mem, char* obj_file);
|
||||
// Import a meshgl from a Wavefront obj file.
|
||||
// The obj_file parameter is the content of the obj file, not the filename,
|
||||
// and should be null-terminated.
|
||||
ManifoldMeshGL64* manifold_meshgl64_read_obj(void* mem, char* obj_file);
|
||||
// Export a manifold to a Wavefront obj file.
|
||||
// The callback accepts two parameters:
|
||||
// 1. Temporary null-terminated string buffer, containing the content of the
|
||||
// file. This buffer will be freed automatically after returning from the
|
||||
// callback.
|
||||
// 2. An arg value (the third parameter in the manifold_write_obj function), for
|
||||
// passing additional data into the callback.
|
||||
void manifold_write_obj(ManifoldManifold* manifold,
|
||||
void (*callback)(char*, void*), void* args);
|
||||
// Export a MeshGL64 to a Wavefront obj file.
|
||||
// The callback accepts two parameters:
|
||||
// 1. Temporary null-terminated string buffer, containing the content of the
|
||||
// file. This buffer will be freed automatically after returning from the
|
||||
// callback.
|
||||
// 2. An arg value (the third parameter in the manifold_write_obj function), for
|
||||
// passing additional data into the callback.
|
||||
void manifold_meshgl64_write_obj(ManifoldMeshGL64* mesh,
|
||||
void (*callback)(char*, void*), void* args);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// opaque pointers
|
||||
|
||||
@@ -23,15 +24,11 @@ typedef struct ManifoldCrossSection ManifoldCrossSection;
|
||||
typedef struct ManifoldCrossSectionVec ManifoldCrossSectionVec;
|
||||
typedef struct ManifoldSimplePolygon ManifoldSimplePolygon;
|
||||
typedef struct ManifoldPolygons ManifoldPolygons;
|
||||
typedef struct ManifoldMesh ManifoldMesh;
|
||||
typedef struct ManifoldMeshGL ManifoldMeshGL;
|
||||
typedef struct ManifoldMeshGL64 ManifoldMeshGL64;
|
||||
typedef struct ManifoldBox ManifoldBox;
|
||||
typedef struct ManifoldRect ManifoldRect;
|
||||
|
||||
#ifdef MANIFOLD_EXPORT
|
||||
typedef struct ManifoldMaterial ManifoldMaterial;
|
||||
typedef struct ManifoldExportOptions ManifoldExportOptions;
|
||||
#endif
|
||||
typedef struct ManifoldTriangulation ManifoldTriangulation;
|
||||
|
||||
// structs
|
||||
|
||||
@@ -41,14 +38,14 @@ typedef struct ManifoldManifoldPair {
|
||||
} ManifoldManifoldPair;
|
||||
|
||||
typedef struct ManifoldVec2 {
|
||||
float x;
|
||||
float y;
|
||||
double x;
|
||||
double y;
|
||||
} ManifoldVec2;
|
||||
|
||||
typedef struct ManifoldVec3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} ManifoldVec3;
|
||||
|
||||
typedef struct ManifoldIVec3 {
|
||||
@@ -58,17 +55,39 @@ typedef struct ManifoldIVec3 {
|
||||
} ManifoldIVec3;
|
||||
|
||||
typedef struct ManifoldVec4 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double w;
|
||||
} ManifoldVec4;
|
||||
|
||||
typedef struct ManifoldProperties {
|
||||
float surface_area;
|
||||
float volume;
|
||||
double surface_area;
|
||||
double volume;
|
||||
} ManifoldProperties;
|
||||
|
||||
typedef struct ManifoldMeshGLOptions {
|
||||
uint32_t* run_indices;
|
||||
size_t run_indices_length;
|
||||
uint32_t* run_original_ids;
|
||||
size_t run_original_ids_length;
|
||||
uint32_t* merge_from_vert;
|
||||
uint32_t* merge_to_vert;
|
||||
size_t merge_verts_length;
|
||||
float* halfedge_tangents;
|
||||
} ManifoldMeshGLOptions;
|
||||
|
||||
typedef struct ManifoldMeshGL64Options {
|
||||
uint64_t* run_indices;
|
||||
size_t run_indices_length;
|
||||
uint32_t* run_original_ids;
|
||||
size_t run_original_ids_length;
|
||||
uint64_t* merge_from_vert;
|
||||
uint64_t* merge_to_vert;
|
||||
size_t merge_verts_length;
|
||||
double* halfedge_tangents;
|
||||
} ManifoldMeshGL64Options;
|
||||
|
||||
// enums
|
||||
|
||||
typedef enum ManifoldOpType {
|
||||
@@ -90,6 +109,7 @@ typedef enum ManifoldError {
|
||||
MANIFOLD_RUN_INDEX_WRONG_LENGTH,
|
||||
MANIFOLD_FACE_ID_WRONG_LENGTH,
|
||||
MANIFOLD_INVALID_CONSTRUCTION,
|
||||
MANIFOLD_RESULT_TOO_LARGE,
|
||||
} ManifoldError;
|
||||
|
||||
typedef enum ManifoldFillRule {
|
||||
@@ -103,4 +123,8 @@ typedef enum ManifoldJoinType {
|
||||
MANIFOLD_JOIN_TYPE_SQUARE,
|
||||
MANIFOLD_JOIN_TYPE_ROUND,
|
||||
MANIFOLD_JOIN_TYPE_MITER,
|
||||
MANIFOLD_JOIN_TYPE_BEVEL,
|
||||
} ManifoldJoinType;
|
||||
|
||||
// function pointer
|
||||
typedef double (*ManifoldSdf)(double, double, double, void*);
|
||||
@@ -1,428 +0,0 @@
|
||||
// Copyright 2023 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Polygons
|
||||
|
||||
ManifoldSimplePolygon *manifold_simple_polygon(void *mem, ManifoldVec2 *ps,
|
||||
size_t length);
|
||||
ManifoldPolygons *manifold_polygons(void *mem, ManifoldSimplePolygon **ps,
|
||||
size_t length);
|
||||
size_t manifold_simple_polygon_length(ManifoldSimplePolygon *p);
|
||||
size_t manifold_polygons_length(ManifoldPolygons *ps);
|
||||
size_t manifold_polygons_simple_length(ManifoldPolygons *ps, int idx);
|
||||
ManifoldVec2 manifold_simple_polygon_get_point(ManifoldSimplePolygon *p,
|
||||
int idx);
|
||||
ManifoldSimplePolygon *manifold_polygons_get_simple(void *mem,
|
||||
ManifoldPolygons *ps,
|
||||
int idx);
|
||||
ManifoldVec2 manifold_polygons_get_point(ManifoldPolygons *ps, int simple_idx,
|
||||
int pt_idx);
|
||||
|
||||
// Mesh Construction
|
||||
|
||||
ManifoldMeshGL *manifold_meshgl(void *mem, float *vert_props, size_t n_verts,
|
||||
size_t n_props, uint32_t *tri_verts,
|
||||
size_t n_tris);
|
||||
|
||||
ManifoldMeshGL *manifold_meshgl_w_tangents(void *mem, float *vert_props,
|
||||
size_t n_verts, size_t n_props,
|
||||
uint32_t *tri_verts, size_t n_tris,
|
||||
float *halfedge_tangent);
|
||||
ManifoldMeshGL *manifold_get_meshgl(void *mem, ManifoldManifold *m);
|
||||
ManifoldMeshGL *manifold_meshgl_copy(void *mem, ManifoldMeshGL *m);
|
||||
|
||||
// SDF
|
||||
// By default, the execution policy (sequential or parallel) of
|
||||
// manifold_level_set will be chosen automatically depending on the size of the
|
||||
// job and whether Manifold has been compiled with a PAR backend. If you are
|
||||
// using these bindings from a language that has a runtime lock preventing the
|
||||
// parallel execution of closures, then you should use manifold_level_set_seq to
|
||||
// force sequential execution.
|
||||
ManifoldMeshGL *manifold_level_set(void *mem, float (*sdf)(float, float, float),
|
||||
ManifoldBox *bounds, float edge_length,
|
||||
float level);
|
||||
ManifoldMeshGL *manifold_level_set_seq(void *mem,
|
||||
float (*sdf)(float, float, float),
|
||||
ManifoldBox *bounds, float edge_length,
|
||||
float level);
|
||||
// The _context variants of manifold_level_set allow a pointer to be passed
|
||||
// back to each invocation of the sdf function pointer, for languages that
|
||||
// need additional data.
|
||||
ManifoldMeshGL *manifold_level_set_context(
|
||||
void *mem, float (*sdf)(float, float, float, void *), ManifoldBox *bounds,
|
||||
float edge_length, float level, void *ctx);
|
||||
ManifoldMeshGL *manifold_level_set_seq_context(
|
||||
void *mem, float (*sdf)(float, float, float, void *), ManifoldBox *bounds,
|
||||
float edge_length, float level, void *ctx);
|
||||
|
||||
// Manifold Vectors
|
||||
|
||||
ManifoldManifoldVec *manifold_manifold_empty_vec(void *mem);
|
||||
ManifoldManifoldVec *manifold_manifold_vec(void *mem, size_t sz);
|
||||
void manifold_manifold_vec_reserve(ManifoldManifoldVec *ms, size_t sz);
|
||||
size_t manifold_manifold_vec_length(ManifoldManifoldVec *ms);
|
||||
ManifoldManifold *manifold_manifold_vec_get(void *mem, ManifoldManifoldVec *ms,
|
||||
int idx);
|
||||
void manifold_manifold_vec_set(ManifoldManifoldVec *ms, int idx,
|
||||
ManifoldManifold *m);
|
||||
void manifold_manifold_vec_push_back(ManifoldManifoldVec *ms,
|
||||
ManifoldManifold *m);
|
||||
|
||||
// Manifold Booleans
|
||||
|
||||
ManifoldManifold *manifold_boolean(void *mem, ManifoldManifold *a,
|
||||
ManifoldManifold *b, ManifoldOpType op);
|
||||
ManifoldManifold *manifold_batch_boolean(void *mem, ManifoldManifoldVec *ms,
|
||||
ManifoldOpType op);
|
||||
ManifoldManifold *manifold_union(void *mem, ManifoldManifold *a,
|
||||
ManifoldManifold *b);
|
||||
ManifoldManifold *manifold_difference(void *mem, ManifoldManifold *a,
|
||||
ManifoldManifold *b);
|
||||
ManifoldManifold *manifold_intersection(void *mem, ManifoldManifold *a,
|
||||
ManifoldManifold *b);
|
||||
ManifoldManifoldPair manifold_split(void *mem_first, void *mem_second,
|
||||
ManifoldManifold *a, ManifoldManifold *b);
|
||||
ManifoldManifoldPair manifold_split_by_plane(void *mem_first, void *mem_second,
|
||||
ManifoldManifold *m,
|
||||
float normal_x, float normal_y,
|
||||
float normal_z, float offset);
|
||||
ManifoldManifold *manifold_trim_by_plane(void *mem, ManifoldManifold *m,
|
||||
float normal_x, float normal_y,
|
||||
float normal_z, float offset);
|
||||
|
||||
// Convex Hulls
|
||||
|
||||
ManifoldManifold *manifold_hull(void *mem, ManifoldManifold *m);
|
||||
ManifoldManifold *manifold_batch_hull(void *mem, ManifoldManifoldVec *ms);
|
||||
ManifoldManifold *manifold_hull_pts(void *mem, ManifoldVec3 *ps, size_t length);
|
||||
|
||||
// Manifold Transformations
|
||||
|
||||
ManifoldManifold *manifold_translate(void *mem, ManifoldManifold *m, float x,
|
||||
float y, float z);
|
||||
ManifoldManifold *manifold_rotate(void *mem, ManifoldManifold *m, float x,
|
||||
float y, float z);
|
||||
ManifoldManifold *manifold_scale(void *mem, ManifoldManifold *m, float x,
|
||||
float y, float z);
|
||||
ManifoldManifold *manifold_transform(void *mem, ManifoldManifold *m, float x1,
|
||||
float y1, float z1, float x2, float y2,
|
||||
float z2, float x3, float y3, float z3,
|
||||
float x4, float y4, float z4);
|
||||
ManifoldManifold *manifold_mirror(void *mem, ManifoldManifold *m, float nx,
|
||||
float ny, float nz);
|
||||
ManifoldManifold *manifold_warp(void *mem, ManifoldManifold *m,
|
||||
ManifoldVec3 (*fun)(float, float, float));
|
||||
ManifoldManifold *manifold_refine(void *mem, ManifoldManifold *m, int refine);
|
||||
|
||||
// Manifold Shapes / Constructors
|
||||
|
||||
ManifoldManifold *manifold_empty(void *mem);
|
||||
ManifoldManifold *manifold_copy(void *mem, ManifoldManifold *m);
|
||||
ManifoldManifold *manifold_tetrahedron(void *mem);
|
||||
ManifoldManifold *manifold_cube(void *mem, float x, float y, float z,
|
||||
int center);
|
||||
ManifoldManifold *manifold_cylinder(void *mem, float height, float radius_low,
|
||||
float radius_high, int circular_segments,
|
||||
int center);
|
||||
ManifoldManifold *manifold_sphere(void *mem, float radius,
|
||||
int circular_segments);
|
||||
ManifoldManifold *manifold_of_meshgl(void *mem, ManifoldMeshGL *mesh);
|
||||
ManifoldManifold *manifold_smooth(void *mem, ManifoldMeshGL *mesh,
|
||||
int *half_edges, float *smoothness,
|
||||
int n_idxs);
|
||||
ManifoldManifold *manifold_extrude(void *mem, ManifoldCrossSection *cs,
|
||||
float height, int slices,
|
||||
float twist_degrees, float scale_x,
|
||||
float scale_y);
|
||||
ManifoldManifold *manifold_revolve(void *mem, ManifoldCrossSection *cs,
|
||||
int circular_segments);
|
||||
ManifoldManifold *manifold_compose(void *mem, ManifoldManifoldVec *ms);
|
||||
ManifoldManifoldVec *manifold_decompose(void *mem, ManifoldManifold *m);
|
||||
ManifoldManifold *manifold_as_original(void *mem, ManifoldManifold *m);
|
||||
|
||||
// Manifold Info
|
||||
|
||||
int manifold_is_empty(ManifoldManifold *m);
|
||||
ManifoldError manifold_status(ManifoldManifold *m);
|
||||
int manifold_num_vert(ManifoldManifold *m);
|
||||
int manifold_num_edge(ManifoldManifold *m);
|
||||
int manifold_num_tri(ManifoldManifold *m);
|
||||
ManifoldBox *manifold_bounding_box(void *mem, ManifoldManifold *m);
|
||||
float manifold_precision(ManifoldManifold *m);
|
||||
int manifold_genus(ManifoldManifold *m);
|
||||
ManifoldProperties manifold_get_properties(ManifoldManifold *m);
|
||||
int manifold_get_circular_segments(float radius);
|
||||
int manifold_original_id(ManifoldManifold *m);
|
||||
uint32_t manifold_reserve_ids(uint32_t n);
|
||||
ManifoldManifold *manifold_set_properties(
|
||||
void *mem, ManifoldManifold *m, int num_prop,
|
||||
void (*fun)(float *new_prop, ManifoldVec3 position, const float *old_prop));
|
||||
ManifoldManifold *manifold_calculate_curvature(void *mem, ManifoldManifold *m,
|
||||
int gaussian_idx, int mean_idx);
|
||||
|
||||
// CrossSection Shapes/Constructors
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_empty(void *mem);
|
||||
ManifoldCrossSection *manifold_cross_section_copy(void *mem,
|
||||
ManifoldCrossSection *cs);
|
||||
ManifoldCrossSection *manifold_cross_section_of_simple_polygon(
|
||||
void *mem, ManifoldSimplePolygon *p, ManifoldFillRule fr);
|
||||
ManifoldCrossSection *manifold_cross_section_of_polygons(void *mem,
|
||||
ManifoldPolygons *p,
|
||||
ManifoldFillRule fr);
|
||||
ManifoldCrossSection *manifold_cross_section_square(void *mem, float x, float y,
|
||||
int center);
|
||||
ManifoldCrossSection *manifold_cross_section_circle(void *mem, float radius,
|
||||
int circular_segments);
|
||||
ManifoldCrossSection *manifold_cross_section_compose(
|
||||
void *mem, ManifoldCrossSectionVec *csv);
|
||||
ManifoldCrossSectionVec *manifold_cross_section_decompose(
|
||||
void *mem, ManifoldCrossSection *cs);
|
||||
|
||||
// CrossSection Vectors
|
||||
|
||||
ManifoldCrossSectionVec *manifold_cross_section_empty_vec(void *mem);
|
||||
ManifoldCrossSectionVec *manifold_cross_section_vec(void *mem, size_t sz);
|
||||
void manifold_cross_section_vec_reserve(ManifoldCrossSectionVec *csv,
|
||||
size_t sz);
|
||||
size_t manifold_cross_section_vec_length(ManifoldCrossSectionVec *csv);
|
||||
ManifoldCrossSection *manifold_cross_section_vec_get(
|
||||
void *mem, ManifoldCrossSectionVec *csv, int idx);
|
||||
void manifold_cross_section_vec_set(ManifoldCrossSectionVec *csv, int idx,
|
||||
ManifoldCrossSection *cs);
|
||||
void manifold_cross_section_vec_push_back(ManifoldCrossSectionVec *csv,
|
||||
ManifoldCrossSection *cs);
|
||||
|
||||
// CrossSection Booleans
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_boolean(void *mem,
|
||||
ManifoldCrossSection *a,
|
||||
ManifoldCrossSection *b,
|
||||
ManifoldOpType op);
|
||||
ManifoldCrossSection *manifold_cross_section_batch_boolean(
|
||||
void *mem, ManifoldCrossSectionVec *csv, ManifoldOpType op);
|
||||
ManifoldCrossSection *manifold_cross_section_union(void *mem,
|
||||
ManifoldCrossSection *a,
|
||||
ManifoldCrossSection *b);
|
||||
ManifoldCrossSection *manifold_cross_section_difference(
|
||||
void *mem, ManifoldCrossSection *a, ManifoldCrossSection *b);
|
||||
ManifoldCrossSection *manifold_cross_section_intersection(
|
||||
void *mem, ManifoldCrossSection *a, ManifoldCrossSection *b);
|
||||
|
||||
// CrossSection Convex Hulls
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_hull(void *mem,
|
||||
ManifoldCrossSection *cs);
|
||||
ManifoldCrossSection *manifold_cross_section_batch_hull(
|
||||
void *mem, ManifoldCrossSectionVec *css);
|
||||
ManifoldCrossSection *manifold_cross_section_hull_simple_polygon(
|
||||
void *mem, ManifoldSimplePolygon *ps);
|
||||
ManifoldCrossSection *manifold_cross_section_hull_polygons(
|
||||
void *mem, ManifoldPolygons *ps);
|
||||
|
||||
// CrossSection Transformation
|
||||
|
||||
ManifoldCrossSection *manifold_cross_section_translate(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float x, float y);
|
||||
ManifoldCrossSection *manifold_cross_section_rotate(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float deg);
|
||||
ManifoldCrossSection *manifold_cross_section_scale(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float x, float y);
|
||||
ManifoldCrossSection *manifold_cross_section_mirror(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float ax_x, float ax_y);
|
||||
ManifoldCrossSection *manifold_cross_section_transform(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3);
|
||||
ManifoldCrossSection *manifold_cross_section_warp(
|
||||
void *mem, ManifoldCrossSection *cs, ManifoldVec2 (*fun)(float, float));
|
||||
ManifoldCrossSection *manifold_cross_section_simplify(void *mem,
|
||||
ManifoldCrossSection *cs,
|
||||
double epsilon);
|
||||
ManifoldCrossSection *manifold_cross_section_offset(
|
||||
void *mem, ManifoldCrossSection *cs, double delta, ManifoldJoinType jt,
|
||||
double miter_limit, int circular_segments);
|
||||
|
||||
// CrossSection Info
|
||||
|
||||
double manifold_cross_section_area(ManifoldCrossSection *cs);
|
||||
int manifold_cross_section_num_vert(ManifoldCrossSection *cs);
|
||||
int manifold_cross_section_num_contour(ManifoldCrossSection *cs);
|
||||
int manifold_cross_section_is_empty(ManifoldCrossSection *cs);
|
||||
ManifoldRect *manifold_cross_section_bounds(void *mem,
|
||||
ManifoldCrossSection *cs);
|
||||
ManifoldPolygons *manifold_cross_section_to_polygons(void *mem,
|
||||
ManifoldCrossSection *cs);
|
||||
|
||||
// Rectangle
|
||||
|
||||
ManifoldRect *manifold_rect(void *mem, float x1, float y1, float x2, float y2);
|
||||
ManifoldVec2 manifold_rect_min(ManifoldRect *r);
|
||||
ManifoldVec2 manifold_rect_max(ManifoldRect *r);
|
||||
ManifoldVec2 manifold_rect_dimensions(ManifoldRect *r);
|
||||
ManifoldVec2 manifold_rect_center(ManifoldRect *r);
|
||||
float manifold_rect_scale(ManifoldRect *r);
|
||||
int manifold_rect_contains_pt(ManifoldRect *r, float x, float y);
|
||||
int manifold_rect_contains_rect(ManifoldRect *a, ManifoldRect *b);
|
||||
void manifold_rect_include_pt(ManifoldRect *r, float x, float y);
|
||||
ManifoldRect *manifold_rect_union(void *mem, ManifoldRect *a, ManifoldRect *b);
|
||||
ManifoldRect *manifold_rect_transform(void *mem, ManifoldRect *r, float x1,
|
||||
float y1, float x2, float y2, float x3,
|
||||
float y3);
|
||||
ManifoldRect *manifold_rect_translate(void *mem, ManifoldRect *r, float x,
|
||||
float y);
|
||||
ManifoldRect *manifold_rect_mul(void *mem, ManifoldRect *r, float x, float y);
|
||||
int manifold_rect_does_overlap_rect(ManifoldRect *a, ManifoldRect *r);
|
||||
int manifold_rect_is_empty(ManifoldRect *r);
|
||||
int manifold_rect_is_finite(ManifoldRect *r);
|
||||
|
||||
// Bounding Box
|
||||
|
||||
ManifoldBox *manifold_box(void *mem, float x1, float y1, float z1, float x2,
|
||||
float y2, float z2);
|
||||
ManifoldVec3 manifold_box_min(ManifoldBox *b);
|
||||
ManifoldVec3 manifold_box_max(ManifoldBox *b);
|
||||
ManifoldVec3 manifold_box_dimensions(ManifoldBox *b);
|
||||
ManifoldVec3 manifold_box_center(ManifoldBox *b);
|
||||
float manifold_box_scale(ManifoldBox *b);
|
||||
int manifold_box_contains_pt(ManifoldBox *b, float x, float y, float z);
|
||||
int manifold_box_contains_box(ManifoldBox *a, ManifoldBox *b);
|
||||
void manifold_box_include_pt(ManifoldBox *b, float x, float y, float z);
|
||||
ManifoldBox *manifold_box_union(void *mem, ManifoldBox *a, ManifoldBox *b);
|
||||
ManifoldBox *manifold_box_transform(void *mem, ManifoldBox *b, float x1,
|
||||
float y1, float z1, float x2, float y2,
|
||||
float z2, float x3, float y3, float z3,
|
||||
float x4, float y4, float z4);
|
||||
ManifoldBox *manifold_box_translate(void *mem, ManifoldBox *b, float x, float y,
|
||||
float z);
|
||||
ManifoldBox *manifold_box_mul(void *mem, ManifoldBox *b, float x, float y,
|
||||
float z);
|
||||
int manifold_box_does_overlap_pt(ManifoldBox *b, float x, float y, float z);
|
||||
int manifold_box_does_overlap_box(ManifoldBox *a, ManifoldBox *b);
|
||||
int manifold_box_is_finite(ManifoldBox *b);
|
||||
|
||||
// Static Quality Globals
|
||||
|
||||
void manifold_set_min_circular_angle(float degrees);
|
||||
void manifold_set_min_circular_edge_length(float length);
|
||||
void manifold_set_circular_segments(int number);
|
||||
|
||||
// Manifold Mesh Extraction
|
||||
|
||||
int manifold_meshgl_num_prop(ManifoldMeshGL *m);
|
||||
int manifold_meshgl_num_vert(ManifoldMeshGL *m);
|
||||
int manifold_meshgl_num_tri(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_vert_properties_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_tri_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_merge_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_run_index_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_run_original_id_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_run_transform_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_face_id_length(ManifoldMeshGL *m);
|
||||
size_t manifold_meshgl_tangent_length(ManifoldMeshGL *m);
|
||||
float *manifold_meshgl_vert_properties(void *mem, ManifoldMeshGL *m);
|
||||
uint32_t *manifold_meshgl_tri_verts(void *mem, ManifoldMeshGL *m);
|
||||
uint32_t *manifold_meshgl_merge_from_vert(void *mem, ManifoldMeshGL *m);
|
||||
uint32_t *manifold_meshgl_merge_to_vert(void *mem, ManifoldMeshGL *m);
|
||||
uint32_t *manifold_meshgl_run_index(void *mem, ManifoldMeshGL *m);
|
||||
uint32_t *manifold_meshgl_run_original_id(void *mem, ManifoldMeshGL *m);
|
||||
float *manifold_meshgl_run_transform(void *mem, ManifoldMeshGL *m);
|
||||
uint32_t *manifold_meshgl_face_id(void *mem, ManifoldMeshGL *m);
|
||||
float *manifold_meshgl_halfedge_tangent(void *mem, ManifoldMeshGL *m);
|
||||
|
||||
// memory size
|
||||
|
||||
size_t manifold_manifold_size();
|
||||
size_t manifold_manifold_vec_size();
|
||||
size_t manifold_cross_section_size();
|
||||
size_t manifold_cross_section_vec_size();
|
||||
size_t manifold_simple_polygon_size();
|
||||
size_t manifold_polygons_size();
|
||||
size_t manifold_manifold_pair_size();
|
||||
size_t manifold_meshgl_size();
|
||||
size_t manifold_box_size();
|
||||
size_t manifold_rect_size();
|
||||
size_t manifold_curvature_size();
|
||||
|
||||
// destruction
|
||||
|
||||
void manifold_destruct_manifold(ManifoldManifold *m);
|
||||
void manifold_destruct_manifold_vec(ManifoldManifoldVec *ms);
|
||||
void manifold_destruct_cross_section(ManifoldCrossSection *m);
|
||||
void manifold_destruct_cross_section_vec(ManifoldCrossSectionVec *csv);
|
||||
void manifold_destruct_simple_polygon(ManifoldSimplePolygon *p);
|
||||
void manifold_destruct_polygons(ManifoldPolygons *p);
|
||||
void manifold_destruct_meshgl(ManifoldMeshGL *m);
|
||||
void manifold_destruct_box(ManifoldBox *b);
|
||||
void manifold_destruct_rect(ManifoldRect *b);
|
||||
|
||||
// pointer free + destruction
|
||||
|
||||
void manifold_delete_manifold(ManifoldManifold *m);
|
||||
void manifold_delete_manifold_vec(ManifoldManifoldVec *ms);
|
||||
void manifold_delete_cross_section(ManifoldCrossSection *cs);
|
||||
void manifold_delete_cross_section_vec(ManifoldCrossSectionVec *csv);
|
||||
void manifold_delete_simple_polygon(ManifoldSimplePolygon *p);
|
||||
void manifold_delete_polygons(ManifoldPolygons *p);
|
||||
void manifold_delete_meshgl(ManifoldMeshGL *m);
|
||||
void manifold_delete_box(ManifoldBox *b);
|
||||
void manifold_delete_rect(ManifoldRect *b);
|
||||
|
||||
// MeshIO / Export
|
||||
|
||||
#ifdef MANIFOLD_EXPORT
|
||||
ManifoldMaterial *manifold_material(void *mem);
|
||||
void manifold_material_set_roughness(ManifoldMaterial *mat, float roughness);
|
||||
void manifold_material_set_metalness(ManifoldMaterial *mat, float metalness);
|
||||
void manifold_material_set_color(ManifoldMaterial *mat, ManifoldVec4 color);
|
||||
void manifold_material_set_vert_color(ManifoldMaterial *mat,
|
||||
ManifoldVec4 *vert_color, size_t n_vert);
|
||||
ManifoldExportOptions *manifold_export_options(void *mem);
|
||||
void manifold_export_options_set_faceted(ManifoldExportOptions *options,
|
||||
int faceted);
|
||||
void manifold_export_options_set_material(ManifoldExportOptions *options,
|
||||
ManifoldMaterial *mat);
|
||||
void manifold_export_meshgl(const char *filename, ManifoldMeshGL *mesh,
|
||||
ManifoldExportOptions *options);
|
||||
ManifoldMeshGL *manifold_import_meshgl(void *mem, const char *filename,
|
||||
int force_cleanup);
|
||||
|
||||
size_t manifold_material_size();
|
||||
size_t manifold_export_options_size();
|
||||
|
||||
void manifold_destruct_material(ManifoldMaterial *m);
|
||||
void manifold_destruct_export_options(ManifoldExportOptions *options);
|
||||
|
||||
void manifold_delete_material(ManifoldMaterial *m);
|
||||
void manifold_delete_export_options(ManifoldExportOptions *options);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,117 +0,0 @@
|
||||
// Copyright 2023 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "meshIO.h"
|
||||
|
||||
#include "conv.h"
|
||||
#include "types.h"
|
||||
|
||||
// C <-> C++ conversions
|
||||
|
||||
ManifoldMaterial *to_c(manifold::Material *m) {
|
||||
return reinterpret_cast<ManifoldMaterial *>(m);
|
||||
}
|
||||
|
||||
ManifoldExportOptions *to_c(manifold::ExportOptions *m) {
|
||||
return reinterpret_cast<ManifoldExportOptions *>(m);
|
||||
}
|
||||
|
||||
manifold::Material *from_c(ManifoldMaterial *mat) {
|
||||
return reinterpret_cast<manifold::Material *>(mat);
|
||||
}
|
||||
|
||||
manifold::ExportOptions *from_c(ManifoldExportOptions *options) {
|
||||
return reinterpret_cast<manifold::ExportOptions *>(options);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// material
|
||||
|
||||
ManifoldMaterial *manifold_material(void *mem) {
|
||||
return to_c(new (mem) manifold::Material());
|
||||
}
|
||||
|
||||
void manifold_material_set_roughness(ManifoldMaterial *mat, float roughness) {
|
||||
from_c(mat)->roughness = roughness;
|
||||
}
|
||||
|
||||
void manifold_material_set_metalness(ManifoldMaterial *mat, float metalness) {
|
||||
from_c(mat)->metalness = metalness;
|
||||
}
|
||||
|
||||
void manifold_material_set_color(ManifoldMaterial *mat, ManifoldVec4 color) {
|
||||
from_c(mat)->color = from_c(color);
|
||||
}
|
||||
|
||||
void manifold_material_set_vert_color(ManifoldMaterial *mat,
|
||||
ManifoldVec4 *vert_color, size_t n_vert) {
|
||||
from_c(mat)->vertColor = vector_of_vec_array(vert_color, n_vert);
|
||||
}
|
||||
|
||||
// export options
|
||||
|
||||
ManifoldExportOptions *manifold_export_options(void *mem) {
|
||||
return to_c(new (mem) manifold::ExportOptions());
|
||||
}
|
||||
|
||||
void manifold_export_options_set_faceted(ManifoldExportOptions *options,
|
||||
int faceted) {
|
||||
from_c(options)->faceted = faceted;
|
||||
}
|
||||
|
||||
void manifold_export_options_set_material(ManifoldExportOptions *options,
|
||||
ManifoldMaterial *mat) {
|
||||
from_c(options)->mat = *from_c(mat);
|
||||
}
|
||||
|
||||
// mesh IO
|
||||
|
||||
void manifold_export_meshgl(const char *filename, ManifoldMeshGL *mesh,
|
||||
ManifoldExportOptions *options) {
|
||||
manifold::ExportMesh(std::string(filename), *from_c(mesh), *from_c(options));
|
||||
}
|
||||
|
||||
ManifoldMeshGL *manifold_import_meshgl(void *mem, const char *filename,
|
||||
int force_cleanup) {
|
||||
auto m = manifold::ImportMesh(std::string(filename), force_cleanup);
|
||||
return to_c(new (mem) manifold::MeshGL(m));
|
||||
}
|
||||
|
||||
// memory size
|
||||
size_t manifold_material_size() { return sizeof(manifold::Material); }
|
||||
|
||||
size_t manifold_export_options_size() {
|
||||
return sizeof(manifold::ExportOptions);
|
||||
}
|
||||
|
||||
// memory free + destruction
|
||||
void manifold_delete_material(ManifoldMaterial *m) { delete (from_c(m)); }
|
||||
|
||||
void manifold_delete_export_options(ManifoldExportOptions *m) {
|
||||
delete (from_c(m));
|
||||
}
|
||||
|
||||
// destruction
|
||||
void manifold_destruct_material(ManifoldMaterial *m) { from_c(m)->~Material(); }
|
||||
|
||||
void manifold_destruct_export_options(ManifoldExportOptions *m) {
|
||||
from_c(m)->~ExportOptions();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -13,88 +13,92 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "conv.h"
|
||||
#include "cross_section.h"
|
||||
#include "manifold.h"
|
||||
#include "public.h"
|
||||
#include "types.h"
|
||||
#include "manifold/common.h"
|
||||
#include "manifold/types.h"
|
||||
|
||||
ManifoldRect *manifold_rect(void *mem, float x1, float y1, float x2, float y2) {
|
||||
auto p1 = glm::vec2(x1, y1);
|
||||
auto p2 = glm::vec2(x2, y2);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
ManifoldRect* manifold_rect(void* mem, double x1, double y1, double x2,
|
||||
double y2) {
|
||||
auto p1 = vec2(x1, y1);
|
||||
auto p2 = vec2(x2, y2);
|
||||
auto rect = new (mem) Rect(p1, p2);
|
||||
return to_c(rect);
|
||||
}
|
||||
|
||||
ManifoldVec2 manifold_rect_min(ManifoldRect *r) {
|
||||
ManifoldVec2 manifold_rect_min(ManifoldRect* r) {
|
||||
return to_c((*from_c(r)).min);
|
||||
}
|
||||
|
||||
ManifoldVec2 manifold_rect_max(ManifoldRect *r) {
|
||||
ManifoldVec2 manifold_rect_max(ManifoldRect* r) {
|
||||
return to_c((*from_c(r)).max);
|
||||
}
|
||||
|
||||
ManifoldVec2 manifold_rect_dimensions(ManifoldRect *r) {
|
||||
ManifoldVec2 manifold_rect_dimensions(ManifoldRect* r) {
|
||||
auto v = from_c(r)->Size();
|
||||
return {v.x, v.y};
|
||||
}
|
||||
|
||||
ManifoldVec2 manifold_rect_center(ManifoldRect *r) {
|
||||
ManifoldVec2 manifold_rect_center(ManifoldRect* r) {
|
||||
auto v = from_c(r)->Center();
|
||||
return {v.x, v.y};
|
||||
}
|
||||
|
||||
float manifold_rect_scale(ManifoldRect *r) { return from_c(r)->Scale(); }
|
||||
double manifold_rect_scale(ManifoldRect* r) { return from_c(r)->Scale(); }
|
||||
|
||||
int manifold_rect_contains_pt(ManifoldRect *r, float x, float y) {
|
||||
int manifold_rect_contains_pt(ManifoldRect* r, double x, double y) {
|
||||
auto rect = *from_c(r);
|
||||
auto p = glm::vec2(x, y);
|
||||
auto p = vec2(x, y);
|
||||
return rect.Contains(p);
|
||||
}
|
||||
|
||||
int manifold_rect_contains_rect(ManifoldRect *a, ManifoldRect *b) {
|
||||
int manifold_rect_contains_rect(ManifoldRect* a, ManifoldRect* b) {
|
||||
auto outer = *from_c(a);
|
||||
auto inner = *from_c(b);
|
||||
return outer.Contains(inner);
|
||||
}
|
||||
|
||||
void manifold_rect_include_pt(ManifoldRect *r, float x, float y) {
|
||||
void manifold_rect_include_pt(ManifoldRect* r, double x, double y) {
|
||||
auto rect = *from_c(r);
|
||||
auto p = glm::vec2(x, y);
|
||||
auto p = vec2(x, y);
|
||||
rect.Union(p);
|
||||
}
|
||||
|
||||
ManifoldRect *manifold_rect_union(void *mem, ManifoldRect *a, ManifoldRect *b) {
|
||||
ManifoldRect* manifold_rect_union(void* mem, ManifoldRect* a, ManifoldRect* b) {
|
||||
auto rect = from_c(a)->Union(*from_c(b));
|
||||
return to_c(new (mem) Rect(rect));
|
||||
}
|
||||
|
||||
ManifoldRect *manifold_rect_transform(void *mem, ManifoldRect *r, float x1,
|
||||
float y1, float x2, float y2, float x3,
|
||||
float y3) {
|
||||
auto mat = glm::mat3x2(x1, y1, x2, y2, x3, y3);
|
||||
ManifoldRect* manifold_rect_transform(void* mem, ManifoldRect* r, double x1,
|
||||
double y1, double x2, double y2,
|
||||
double x3, double y3) {
|
||||
auto mat = mat2x3({x1, y1}, {x2, y2}, {x3, y3});
|
||||
auto transformed = from_c(r)->Transform(mat);
|
||||
return to_c(new (mem) Rect(transformed));
|
||||
}
|
||||
|
||||
ManifoldRect *manifold_rect_translate(void *mem, ManifoldRect *r, float x,
|
||||
float y) {
|
||||
auto rect = *from_c(r);
|
||||
auto p = glm::vec2(x, y);
|
||||
ManifoldRect* manifold_rect_translate(void* mem, ManifoldRect* r, double x,
|
||||
double y) {
|
||||
auto p = vec2(x, y);
|
||||
auto translated = (*from_c(r)) + p;
|
||||
return to_c(new (mem) Rect(translated));
|
||||
}
|
||||
|
||||
ManifoldRect *manifold_rect_mul(void *mem, ManifoldRect *r, float x, float y) {
|
||||
auto rect = *from_c(r);
|
||||
auto p = glm::vec2(x, y);
|
||||
ManifoldRect* manifold_rect_mul(void* mem, ManifoldRect* r, double x,
|
||||
double y) {
|
||||
auto p = vec2(x, y);
|
||||
auto scaled = (*from_c(r)) * p;
|
||||
return to_c(new (mem) Rect(scaled));
|
||||
}
|
||||
|
||||
int manifold_rect_does_overlap_rect(ManifoldRect *a, ManifoldRect *r) {
|
||||
int manifold_rect_does_overlap_rect(ManifoldRect* a, ManifoldRect* r) {
|
||||
return from_c(a)->DoesOverlap(*from_c(r));
|
||||
}
|
||||
|
||||
int manifold_rect_is_empty(ManifoldRect *r) { return from_c(r)->IsEmpty(); }
|
||||
int manifold_rect_is_empty(ManifoldRect* r) { return from_c(r)->IsEmpty(); }
|
||||
|
||||
int manifold_rect_is_finite(ManifoldRect *r) { return from_c(r)->IsFinite(); }
|
||||
int manifold_rect_is_finite(ManifoldRect* r) { return from_c(r)->IsFinite(); }
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,28 +12,75 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
project(python)
|
||||
nanobind_add_module(manifold3d NB_STATIC STABLE_ABI LTO autogen_docstrings.inl
|
||||
manifold3d.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(third_party)
|
||||
nanobind_add_module(
|
||||
message(Python_EXECUTABLE = ${Python_EXECUTABLE})
|
||||
|
||||
if(MANIFOLD_PYBIND_STUBGEN)
|
||||
nanobind_add_stub(
|
||||
manifold3d_stub
|
||||
MODULE manifold3d
|
||||
OUTPUT manifold3d.pyi
|
||||
PYTHON_PATH $<TARGET_FILE_DIR:manifold3d>
|
||||
DEPENDS manifold3d
|
||||
PATTERN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/stub_pattern.txt
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET manifold3d_stub
|
||||
POST_BUILD
|
||||
COMMAND
|
||||
"${Python_EXECUTABLE}"
|
||||
"${PROJECT_SOURCE_DIR}/bindings/python/stub_postbuild.py"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/manifold3d.pyi"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(manifold3d PRIVATE manifold)
|
||||
target_compile_options(
|
||||
manifold3d
|
||||
NB_STATIC STABLE_ABI LTO
|
||||
manifold3d.cpp)
|
||||
target_link_libraries(manifold3d PRIVATE manifold sdf)
|
||||
target_compile_options(manifold3d PRIVATE ${MANIFOLD_FLAGS} -DMODULE_NAME=manifold3d)
|
||||
target_compile_features(manifold3d PUBLIC cxx_std_17)
|
||||
PRIVATE ${MANIFOLD_FLAGS} -DMODULE_NAME=manifold3d
|
||||
)
|
||||
set_target_properties(manifold3d PROPERTIES OUTPUT_NAME "manifold3d")
|
||||
|
||||
# ideally we should generate a dependency file from python...
|
||||
set(
|
||||
DOCSTRING_DEPS
|
||||
${PROJECT_SOURCE_DIR}/src/manifold.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/constructors.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/sort.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/cross_section/cross_section.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/include/manifold/common.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/gen_docs.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/docstring_override.txt
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT autogen_docstrings.inl
|
||||
DEPENDS ${DOCSTRING_DEPS}
|
||||
COMMAND ${Python_EXECUTABLE}
|
||||
ARGS ${CMAKE_CURRENT_SOURCE_DIR}/gen_docs.py
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
target_include_directories(manifold3d PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if(SKBUILD)
|
||||
install(
|
||||
TARGETS manifold3d
|
||||
LIBRARY DESTINATION ${SKBUILD_PLATLIB_DIR}
|
||||
COMPONENT bindings
|
||||
)
|
||||
set(MANIFOLD_PYBIND_LIBDIR ${SKBUILD_PLATLIB_DIR})
|
||||
else()
|
||||
set(MANIFOLD_PYBIND_LIBDIR ${Python_SITEARCH})
|
||||
endif()
|
||||
|
||||
install(
|
||||
TARGETS manifold3d
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
|
||||
COMPONENT bindings
|
||||
LIBRARY DESTINATION ${MANIFOLD_PYBIND_LIBDIR} COMPONENT bindings
|
||||
)
|
||||
if(MANIFOLD_PYBIND_STUBGEN)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/manifold3d.pyi
|
||||
DESTINATION ${MANIFOLD_PYBIND_LIBDIR}
|
||||
COMPONENT bindings
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Python Bindings
|
||||
|
||||
## Autogenerated Doc-Strings
|
||||
|
||||
Doc-strings for the python API wrapper are generated by gen_docs.py
|
||||
The script is run automatically during the build to keep python
|
||||
doc strings fully up-to-date with c++ sources.
|
||||
|
||||
It scrapes documentation comments and c++ function signatures
|
||||
from the manifold c++ sources, in order to generate a c++ header file
|
||||
exposing the comments as string variables named by function names.
|
||||
This allows python bindings to re-use the c++ comments directly.
|
||||
|
||||
Some snake-casing of params is applied for python use case.
|
||||
|
||||
---
|
||||
|
||||
When modifying the Manifold C++ sources, you may need to update
|
||||
gen_docs.py. For example, top-level free functions are white-listed,
|
||||
so if you add a new one, you will need to add it in gen_docs.py.
|
||||
|
||||
Similarly, the list of source files to parse is also white listed,
|
||||
so if you define functions in new files that need python wrappers,
|
||||
you will also need to up gen_docs.py.
|
||||
|
||||
To verify that python docs are correct after changes, you can
|
||||
run the following commends from the manifold repo root:
|
||||
```
|
||||
pip install .
|
||||
python -c 'import manifold3d; help(manifold3d)'
|
||||
```
|
||||
|
||||
Alternatively you could generate stubs with nanobind python module
|
||||
```
|
||||
pip install -m nanobind
|
||||
python -m nanobind.stubgen -m manifold3d -o manifold3d.pyi -i=. -p=bindings/python/stub_pattern.txt
|
||||
```
|
||||
It will emit some warnings and write a file `manifold3d.pyi`
|
||||
which will show all the function signatures and docstrings.
|
||||
@@ -0,0 +1,51 @@
|
||||
cross_section__warp__warp_func:
|
||||
Move the vertices of this CrossSection (creating a new one) according to
|
||||
any arbitrary input function, followed by a union operation (with a
|
||||
Positive fill rule) that ensures any introduced intersections are not
|
||||
included in the result.
|
||||
:param warp_func: A function that takes the original vertex position and
|
||||
return the new position.
|
||||
cross_section__warp_batch__warp_func:
|
||||
Same as CrossSection::warp but calls warpFunc with
|
||||
an ndarray[n, 2] instead of processing only one vertex at a time.
|
||||
:param warp_func: A function that takes multiple vertex positions as an
|
||||
ndarray[n, 2] and returns the new vertex positions.
|
||||
manifold__warp__warp_func:
|
||||
This function does not change the topology, but allows the vertices to be
|
||||
moved according to any arbitrary input function. It is easy to create a
|
||||
function that warps a geometrically valid object into one which overlaps, but
|
||||
that is not checked here, so it is up to the user to choose their function
|
||||
with discretion.
|
||||
:param warp_func: A function that takes the original vertex position and
|
||||
return the new position.
|
||||
manifold__warp_batch__warp_func:
|
||||
Same as Manifold::warp but calls warpFunc with with
|
||||
an ndarray[n, 3] instead of processing only one vertex at a time.
|
||||
:param warp_func: A function that takes multiple vertex positions as an
|
||||
ndarray[n, 3] and returns the new vertex positions. The result should have the
|
||||
same shape as the input.
|
||||
manifold__smooth__mesh_gl__sharpened_edges:
|
||||
Constructs a smooth version of the input mesh by creating tangents; this
|
||||
method will throw if you have supplied tangents with your mesh already. The
|
||||
actual triangle resolution is unchanged; use the Refine() method to
|
||||
interpolate to a higher-resolution curve.
|
||||
By default, every edge is calculated for maximum smoothness (very much
|
||||
approximately), attempting to minimize the maximum mean Curvature magnitude.
|
||||
No higher-order derivatives are considered, as the interpolation is
|
||||
independent per triangle, only sharing constraints on their boundaries.
|
||||
:param mesh: input Mesh.
|
||||
:param sharpened_edges: If desired, you can supply a vector of sharpened
|
||||
halfedges, which should in general be a small subset of all halfedges. Order
|
||||
of entries doesn't matter, as each one specifies the desired smoothness
|
||||
(between zero and one, with one the default for all unspecified halfedges)
|
||||
and the halfedge index (3 * triangle index + [0,1,2] where 0 is the edge
|
||||
between triVert 0 and 1, etc).
|
||||
:param edge_smoothness: Smoothness values associated to each halfedge defined
|
||||
in sharpened_edges. At a smoothness value of zero, a sharp crease is made. The
|
||||
smoothness is interpolated along each edge, so the specified value should be
|
||||
thought of as an average. Where exactly two sharpened edges meet at a vertex,
|
||||
their tangents are rotated to be colinear so that the sharpened edge can be
|
||||
continuous. Vertices with only one sharpened edge are completely smooth,
|
||||
allowing sharpened edges to smoothly vanish at termination. A single vertex
|
||||
can be sharpened by sharping all edges that are incident on it, allowing cones
|
||||
to be formed.
|
||||
@@ -0,0 +1,133 @@
|
||||
from manifold3d import *
|
||||
import numpy as np
|
||||
|
||||
|
||||
def all_root_level():
|
||||
set_min_circular_angle(10)
|
||||
set_min_circular_edge_length(1)
|
||||
set_circular_segments(22)
|
||||
n = get_circular_segments(1)
|
||||
assert n == 22
|
||||
poly = [[0, 0], [1, 0], [1, 1]]
|
||||
tris = triangulate([poly])
|
||||
tris = triangulate([np.array(poly)])
|
||||
|
||||
|
||||
def all_cross_section():
|
||||
poly = [[0, 0], [1, 0], [1, 1]]
|
||||
c = CrossSection([np.array(poly)])
|
||||
c = CrossSection([poly])
|
||||
c = CrossSection() + c
|
||||
a = c.area()
|
||||
c = CrossSection.batch_boolean(
|
||||
[
|
||||
CrossSection.circle(1),
|
||||
CrossSection.square((3, 3)),
|
||||
CrossSection.circle(3).translate((1, 1)),
|
||||
],
|
||||
OpType.Add,
|
||||
)
|
||||
c = CrossSection.batch_hull([c, c.translate((1, 0))])
|
||||
b = c.bounds()
|
||||
c = CrossSection.circle(1)
|
||||
c = CrossSection.compose([c, c.translate((1, 0))])
|
||||
cs = c.decompose()
|
||||
m = c.extrude(1)
|
||||
c = c.hull()
|
||||
c = CrossSection.hull_points(poly)
|
||||
c = CrossSection.hull_points(np.array(poly))
|
||||
e = c.is_empty()
|
||||
c = c.mirror((0, 1))
|
||||
n = c.num_contour()
|
||||
n = c.num_vert()
|
||||
c = c.offset(1)
|
||||
m = c.revolve()
|
||||
c = c.rotate(90)
|
||||
c = c.scale((2, 2))
|
||||
c = c.simplify()
|
||||
c = CrossSection.square((1, 1))
|
||||
p = c.to_polygons()
|
||||
c = c.transform([[1, 0, 0], [0, 1, 0]])
|
||||
c = c.translate((1, 1))
|
||||
c = c.warp(lambda p: (p[0] + 1, p[1] / 2))
|
||||
c = c.warp_batch(lambda ps: ps * [1, 0.5] + [1, 0])
|
||||
|
||||
|
||||
def all_manifold():
|
||||
mesh = Manifold.sphere(1).to_mesh()
|
||||
m = Manifold(mesh)
|
||||
m = Manifold() + m
|
||||
m = m.as_original()
|
||||
m = Manifold.batch_boolean(
|
||||
[
|
||||
Manifold.cylinder(4, 1),
|
||||
Manifold.cube((3, 2, 1)),
|
||||
Manifold.cylinder(5, 3).translate((1, 1, 1)),
|
||||
],
|
||||
OpType.Add,
|
||||
)
|
||||
m = Manifold.batch_hull([m, m.translate((0, 0, 1))])
|
||||
b = m.bounding_box()
|
||||
m = m.calculate_curvature(4, 5)
|
||||
m = m.calculate_normals(0)
|
||||
m = m.smooth_by_normals(0)
|
||||
m = Manifold.compose([m, m.translate((5, 0, 0))])
|
||||
m = Manifold.cube((1, 1, 1))
|
||||
m = Manifold.cylinder(1, 1)
|
||||
ms = m.decompose()
|
||||
m = Manifold.extrude(CrossSection.circle(1), 1)
|
||||
m = Manifold.revolve(CrossSection.circle(1))
|
||||
g = m.genus()
|
||||
a = m.surface_area()
|
||||
v = m.volume()
|
||||
m = m.hull()
|
||||
m = m.hull_points(mesh.vert_properties)
|
||||
e = m.is_empty()
|
||||
m = m.mirror((0, 0, 1))
|
||||
n = m.num_edge()
|
||||
n = m.num_prop()
|
||||
n = m.num_prop_vert()
|
||||
n = m.num_tri()
|
||||
n = m.num_vert()
|
||||
i = m.original_id()
|
||||
p = m.get_tolerance()
|
||||
pp = m.set_tolerance(0.0001)
|
||||
m = m.simplify(0.001)
|
||||
c = m.project()
|
||||
m = m.refine(2)
|
||||
m = m.refine_to_length(0.1)
|
||||
m = m.refine_to_tolerance(0.01)
|
||||
m = m.smooth_out()
|
||||
i = Manifold.reserve_ids(1)
|
||||
m = m.scale((1, 2, 3))
|
||||
m = m.set_properties(3, lambda pos, prop: pos)
|
||||
c = m.slice(0.5)
|
||||
m = Manifold.smooth(mesh, [0], [0.5])
|
||||
m = Manifold.sphere(1)
|
||||
m, n = m.split(m.translate((1, 0, 0)))
|
||||
m, n = m.split_by_plane((0, 0, 1), 0)
|
||||
e = m.status()
|
||||
m = Manifold.tetrahedron()
|
||||
mesh = m.to_mesh()
|
||||
ok = mesh.merge()
|
||||
m = m.transform([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
|
||||
m = m.translate((0, 0, 0))
|
||||
m = m.trim_by_plane((0, 0, 1), 0)
|
||||
m = m.warp(lambda p: (p[0] + 1, p[1] / 2, p[2] * 2))
|
||||
m = m.warp_batch(lambda ps: ps * 2 + [1, 0, 0])
|
||||
m = Manifold.cube()
|
||||
m2 = Manifold.cube().translate([2, 0, 0])
|
||||
d = m.min_gap(m2, 2)
|
||||
mesh2 = m.to_mesh64()
|
||||
ok = mesh.merge()
|
||||
|
||||
|
||||
def run():
|
||||
all_root_level()
|
||||
all_cross_section()
|
||||
all_manifold()
|
||||
return Manifold()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -1,18 +1,18 @@
|
||||
"""
|
||||
Copyright 2022 The Manifold Authors.
|
||||
Copyright 2022 The Manifold Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from manifold3d import Manifold
|
||||
|
||||
@@ -28,44 +28,50 @@ mortar_gap = (3 / 8) * INCHES
|
||||
|
||||
|
||||
def brick():
|
||||
return Manifold.cube(brick_length, brick_depth, brick_height)
|
||||
return Manifold.cube([brick_length, brick_depth, brick_height])
|
||||
|
||||
|
||||
def halfbrick():
|
||||
return Manifold.cube((brick_length - mortar_gap) / 2, brick_depth, brick_height)
|
||||
return Manifold.cube([(brick_length - mortar_gap) / 2, brick_depth, brick_height])
|
||||
|
||||
|
||||
def row(length):
|
||||
bricks = [
|
||||
brick().translate((brick_length + mortar_gap) * x, 0, 0) for x in range(length)
|
||||
brick().translate([(brick_length + mortar_gap) * x, 0, 0])
|
||||
for x in range(length)
|
||||
]
|
||||
return Manifold(bricks)
|
||||
return sum(bricks, Manifold())
|
||||
|
||||
|
||||
def wall(length, height, alternate=0):
|
||||
bricks = [
|
||||
row(length).translate(
|
||||
((z + alternate) % 2) * (brick_depth + mortar_gap),
|
||||
0,
|
||||
(brick_height + mortar_gap) * z,
|
||||
[
|
||||
((z + alternate) % 2) * (brick_depth + mortar_gap),
|
||||
0,
|
||||
(brick_height + mortar_gap) * z,
|
||||
]
|
||||
)
|
||||
for z in range(height)
|
||||
]
|
||||
return Manifold(bricks)
|
||||
return sum(bricks, Manifold())
|
||||
|
||||
|
||||
def walls(length, width, height):
|
||||
return Manifold(
|
||||
return sum(
|
||||
[
|
||||
wall(length, height),
|
||||
wall(width, height, 1).rotate(0, 0, 90).translate(brick_depth, 0, 0),
|
||||
wall(width, height, 1).rotate([0, 0, 90]).translate([brick_depth, 0, 0]),
|
||||
wall(length, height, 1).translate(
|
||||
0, (width) * (brick_length + mortar_gap), 0
|
||||
[0, (width) * (brick_length + mortar_gap), 0]
|
||||
),
|
||||
wall(width, height)
|
||||
.rotate(0, 0, 90)
|
||||
.translate((length + 0.5) * (brick_length + mortar_gap) - mortar_gap, 0, 0),
|
||||
]
|
||||
.rotate([0, 0, 90])
|
||||
.translate(
|
||||
[(length + 0.5) * (brick_length + mortar_gap) - mortar_gap, 0, 0]
|
||||
),
|
||||
],
|
||||
Manifold(),
|
||||
)
|
||||
|
||||
|
||||
@@ -74,21 +80,21 @@ def floor(length, width):
|
||||
if length > 1 and width > 1:
|
||||
results.append(
|
||||
floor(length - 1, width - 1).translate(
|
||||
brick_depth + mortar_gap, brick_depth + mortar_gap, 0
|
||||
[brick_depth + mortar_gap, brick_depth + mortar_gap, 0]
|
||||
)
|
||||
)
|
||||
if length == 1 and width > 1:
|
||||
results.append(row(width - 1).rotate(0, 0, 90))
|
||||
results.append(row(width - 1).rotate((0, 0, 90)))
|
||||
if width == 1 and length > 1:
|
||||
results.append(
|
||||
row(length - 1).translate(
|
||||
2 * (brick_depth + mortar_gap), brick_depth + mortar_gap, 0
|
||||
[2 * (brick_depth + mortar_gap), brick_depth + mortar_gap, 0]
|
||||
)
|
||||
)
|
||||
results.append(
|
||||
halfbrick().translate(brick_depth + mortar_gap, brick_depth + mortar_gap, 0)
|
||||
halfbrick().translate([brick_depth + mortar_gap, brick_depth + mortar_gap, 0])
|
||||
)
|
||||
return Manifold(results)
|
||||
return sum(results, Manifold())
|
||||
|
||||
|
||||
def run(width=10, length=10, height=10):
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
"""
|
||||
Copyright 2022 The Manifold Authors.
|
||||
Copyright 2022 The Manifold Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from manifold3d import Manifold
|
||||
from functools import reduce
|
||||
@@ -21,13 +21,13 @@ from functools import reduce
|
||||
|
||||
|
||||
def run(n=5, overlap=True):
|
||||
a = Manifold.cube(n, n, 0.5).translate(-0.5, -0.5, -0.5)
|
||||
a = Manifold.cube([n, n, 0.5]).translate([-0.5, -0.5, -0.5])
|
||||
|
||||
spheres = [
|
||||
Manifold.sphere(0.45 if overlap else 0.55, 50).translate(i, j, 0)
|
||||
Manifold.sphere(0.45 if overlap else 0.55, 50).translate([i, j, 0])
|
||||
for i in range(n)
|
||||
for j in range(n)
|
||||
]
|
||||
spheres = reduce(lambda a, b: a + b, spheres)
|
||||
# spheres = reduce(lambda a, b: a + b, spheres)
|
||||
|
||||
return a - spheres
|
||||
return a - sum(spheres, Manifold())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from manifold3d import CrossSection
|
||||
from manifold3d import CrossSection, Manifold
|
||||
|
||||
|
||||
def run():
|
||||
@@ -10,21 +10,21 @@ def run():
|
||||
cross_section = CrossSection(polygons_points)
|
||||
polygons = cross_section.to_polygons()
|
||||
polygon = polygons[0]
|
||||
if set(polygon) != set(polygon_points):
|
||||
if set([tuple(p) for p in polygon]) != set(polygon_points):
|
||||
raise Exception(
|
||||
f"polygon={polygon} differs from polygon_points={polygon_points}"
|
||||
)
|
||||
|
||||
# extrude a polygon to create a manifold
|
||||
extruded_polygon = cross_section.extrude(10.0)
|
||||
extruded_polygon = Manifold.extrude(cross_section, 10.0)
|
||||
eps = 0.001
|
||||
observed_volume = extruded_polygon.get_volume()
|
||||
observed_volume = extruded_polygon.volume()
|
||||
expected_volume = 10.0
|
||||
if abs(observed_volume - expected_volume) > eps:
|
||||
raise Exception(
|
||||
f"observed_volume={observed_volume} differs from expected_volume={expected_volume}"
|
||||
)
|
||||
observed_surface_area = extruded_polygon.get_surface_area()
|
||||
observed_surface_area = extruded_polygon.surface_area()
|
||||
expected_surface_area = 42.0
|
||||
if abs(observed_surface_area - expected_surface_area) > eps:
|
||||
raise Exception(
|
||||
@@ -32,7 +32,7 @@ def run():
|
||||
)
|
||||
|
||||
# get bounding box from manifold
|
||||
observed_bbox = extruded_polygon.bounding_box
|
||||
observed_bbox = extruded_polygon.bounding_box()
|
||||
expected_bbox = (0.0, 0.0, 0.0, 1.0, 1.0, 10.0)
|
||||
if observed_bbox != expected_bbox:
|
||||
raise Exception(
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
"""
|
||||
Copyright 2023 The Manifold Authors.
|
||||
Copyright 2023 The Manifold Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
from manifold3d import Mesh, Manifold
|
||||
from manifold3d import Manifold
|
||||
|
||||
|
||||
def gyroid(x, y, z):
|
||||
@@ -31,20 +31,18 @@ def gyroid(x, y, z):
|
||||
|
||||
|
||||
def gyroid_levelset(level, period, size, n):
|
||||
return Manifold.from_mesh(
|
||||
Mesh.level_set(
|
||||
gyroid,
|
||||
[-period, -period, -period, period, period, period],
|
||||
period / n,
|
||||
level,
|
||||
)
|
||||
).scale(size / period)
|
||||
return Manifold.level_set(
|
||||
gyroid,
|
||||
[-period, -period, -period, period, period, period],
|
||||
period / n,
|
||||
level,
|
||||
).scale([size / period] * 3)
|
||||
|
||||
|
||||
def rhombic_dodecahedron(size):
|
||||
box = Manifold.cube(size * math.sqrt(2.0) * np.array([1, 1, 2]), True)
|
||||
result = box.rotate(90, 45) ^ box.rotate(90, 45, 90)
|
||||
return result ^ box.rotate(0, 0, 45)
|
||||
result = box.rotate([90, 45, 0]) ^ box.rotate([90, 45, 90])
|
||||
return result ^ box.rotate([0, 0, 45])
|
||||
|
||||
|
||||
def gyroid_module(size=20, n=15):
|
||||
@@ -52,7 +50,7 @@ def gyroid_module(size=20, n=15):
|
||||
result = (
|
||||
gyroid_levelset(-0.4, period, size, n) ^ rhombic_dodecahedron(size)
|
||||
) - gyroid_levelset(0.4, period, size, n)
|
||||
return result.rotate(-45, 0, 90).translate(0, 0, size / math.sqrt(2.0))
|
||||
return result.rotate([-45, 0, 90]).translate([0, 0, size / math.sqrt(2.0)])
|
||||
|
||||
|
||||
def run(size=20, n=15):
|
||||
|
||||
@@ -4039,4 +4039,4 @@ def run():
|
||||
|
||||
ball([10, 10, 10], 0.4)
|
||||
|
||||
return Manifold.cube((n + 1) * np.array([1, 1, 1])) - Manifold(cavity)
|
||||
return Manifold.cube([n + 1] * 3) - sum(cavity, Manifold())
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import numpy as np
|
||||
from manifold3d import Manifold
|
||||
|
||||
|
||||
def run():
|
||||
small_cube = Manifold.cube([0.1, 0.1, 0.1], True)
|
||||
cube_vertices = small_cube.to_mesh().vert_properties[:, :3]
|
||||
star = Manifold.as_original(small_cube)
|
||||
for offset in [
|
||||
[[0.2, 0.0, 0.0]],
|
||||
[[-0.2, 0.0, 0.0]],
|
||||
[[0.0, 0.2, 0.0]],
|
||||
[[0.0, -0.2, 0.0]],
|
||||
[[0.0, 0.0, 0.2]],
|
||||
[[0.0, 0.0, -0.2]],
|
||||
]:
|
||||
star += Manifold.hull_points(np.concatenate((cube_vertices, offset), axis=0))
|
||||
|
||||
sphere = Manifold.sphere(0.6, 15)
|
||||
cube = Manifold.cube([1.0, 1.0, 1.0], True)
|
||||
sphereless_cube = cube - sphere
|
||||
return sphereless_cube.minkowski_sum(star)
|
||||
@@ -1,18 +1,18 @@
|
||||
"""
|
||||
Copyright 2022 The Manifold Authors.
|
||||
Copyright 2022 The Manifold Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
"""
|
||||
Copyright 2023 The Manifold Authors.
|
||||
Copyright 2023 The Manifold Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from manifold3d import Manifold, Mesh
|
||||
import numpy as np
|
||||
@@ -72,8 +72,9 @@ def run():
|
||||
blue = [0, 0, 1]
|
||||
return [(1 - b) * blue[i] + b * red[i] for i in range(3)]
|
||||
|
||||
edges, smoothing = zip(*sharpenedEdges)
|
||||
return (
|
||||
Manifold.smooth(scallop, sharpenedEdges)
|
||||
Manifold.smooth(scallop, edges, smoothing)
|
||||
.refine(n)
|
||||
.calculate_curvature(-1, 0)
|
||||
.set_properties(3, colorCurvature)
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
"""
|
||||
Copyright 2022 The Manifold Authors.
|
||||
Copyright 2022 The Manifold Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from manifold3d import Manifold
|
||||
|
||||
|
||||
def run():
|
||||
a = Manifold.cube(1.0, 1.0, 1.0)
|
||||
b = Manifold.cube(1.0, 1.0, 1.0).rotate(45.0, 45.0, 45.0)
|
||||
a = Manifold.cube([1.0, 1.0, 1.0])
|
||||
b = Manifold.cube([1.0, 1.0, 1.0]).rotate([45.0, 45.0, 45.0])
|
||||
return a.split(b)[0]
|
||||
|
||||
@@ -24,7 +24,7 @@ def fractal(holes, hole, w, position, depth, maxDepth):
|
||||
|
||||
|
||||
def posColors(pos, _):
|
||||
return [1 - p / 2 for p in pos] + [1.0]
|
||||
return [-p + 0.5 for p in pos] + [1.0]
|
||||
|
||||
|
||||
def run(n=1):
|
||||
@@ -38,4 +38,8 @@ def run(n=1):
|
||||
result -= hole.rotate([90, 0, 0])
|
||||
result -= hole.rotate([0, 90, 0])
|
||||
|
||||
return result.trim_by_plane([1, 1, 1], 0).set_properties(4, posColors).scale(100)
|
||||
return (
|
||||
result.trim_by_plane([1, 1, 1], 0)
|
||||
.set_properties(4, posColors)
|
||||
.scale([100, 100, 100])
|
||||
)
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
from manifold3d import *
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
# Creates a classic torus knot, defined as a string wrapping periodically
|
||||
# around the surface of an imaginary donut. If p and q have a common
|
||||
# factor then you will get multiple separate, interwoven knots. This is
|
||||
# an example of using the warp() method, thus avoiding any direct
|
||||
# handling of triangles.
|
||||
|
||||
|
||||
def run(warp_single=False):
|
||||
# The number of times the thread passes through the donut hole.
|
||||
p = 1
|
||||
# The number of times the thread circles the donut.
|
||||
q = 3
|
||||
# Radius of the interior of the imaginary donut.
|
||||
majorRadius = 25
|
||||
# Radius of the small cross-section of the imaginary donut.
|
||||
minorRadius = 10
|
||||
# Radius of the small cross-section of the actual object.
|
||||
threadRadius = 3.75
|
||||
# Number of linear segments making up the threadRadius circle. Default is
|
||||
# getCircularSegments(threadRadius).
|
||||
circularSegments = -1
|
||||
# Number of segments along the length of the knot. Default makes roughly
|
||||
# square facets.
|
||||
linearSegments = -1
|
||||
|
||||
# These default values recreate Matlab Knot by Emmett Lalish:
|
||||
# https://www.thingiverse.com/thing:7080
|
||||
|
||||
kLoops = np.gcd(p, q)
|
||||
pk = p / kLoops
|
||||
qk = q / kLoops
|
||||
n = (
|
||||
circularSegments
|
||||
if circularSegments > 2
|
||||
else get_circular_segments(threadRadius)
|
||||
)
|
||||
m = linearSegments if linearSegments > 2 else n * qk * majorRadius / threadRadius
|
||||
|
||||
offset = 2
|
||||
circle = CrossSection.circle(1, n).translate([offset, 0])
|
||||
|
||||
def ax_rotate(x, theta):
|
||||
a, b = (x + 1) % 3, (x + 2) % 3
|
||||
s, c = np.sin(theta), np.cos(theta)
|
||||
m = np.zeros((len(theta), 4, 4), dtype=np.float32)
|
||||
m[:, a, a], m[:, a, b] = c, s
|
||||
m[:, b, a], m[:, b, b] = -s, c
|
||||
m[:, x, x], m[:, 3, 3] = 1, 1
|
||||
return m
|
||||
|
||||
def func(pts):
|
||||
npts = pts.shape[0]
|
||||
x, y, z = pts[:, 0], pts[:, 1], pts[:, 2]
|
||||
psi = qk * np.arctan2(x, y)
|
||||
theta = psi * pk / qk
|
||||
x1 = np.sqrt(x * x + y * y)
|
||||
phi = np.arctan2(x1 - offset, z)
|
||||
|
||||
v = np.zeros((npts, 4), dtype=np.float32)
|
||||
v[:, 0] = threadRadius * np.cos(phi)
|
||||
v[:, 2] = threadRadius * np.sin(phi)
|
||||
v[:, 3] = 1
|
||||
r = majorRadius + minorRadius * np.cos(theta)
|
||||
|
||||
m1 = ax_rotate(0, -np.arctan2(pk * minorRadius, qk * r))
|
||||
m1[:, 3, 0] = minorRadius
|
||||
m2 = ax_rotate(1, theta)
|
||||
m2[:, 3, 0] = majorRadius
|
||||
m3 = ax_rotate(2, psi)
|
||||
|
||||
v = v[:, None, :] @ m1 @ m2 @ m3
|
||||
return v[:, 0, :3]
|
||||
|
||||
def func_single(v):
|
||||
pts = np.array([v])
|
||||
return func(pts)[0]
|
||||
|
||||
if warp_single:
|
||||
return Manifold.revolve(circle, int(m)).warp(func_single)
|
||||
else:
|
||||
return Manifold.revolve(circle, int(m)).warp_batch(func)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("warp_single", [True, False])
|
||||
def test_warp(warp_single):
|
||||
m = run(warp_single=warp_single)
|
||||
assert m.volume() == pytest.approx(20785.76)
|
||||
assert m.surface_area() == pytest.approx(11176.8)
|
||||
assert m.genus() == 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -4,5 +4,5 @@ from manifold3d import Manifold
|
||||
def run():
|
||||
# for some reason this causes collider error
|
||||
obj = Manifold.cube()
|
||||
obj += Manifold([Manifold.cube()]).rotate(0, 0, 45 + 180)
|
||||
obj += Manifold.cube().rotate([0, 0, 45 + 180])
|
||||
return obj
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
from os.path import dirname
|
||||
import re
|
||||
|
||||
base = dirname(dirname(dirname(__file__)))
|
||||
|
||||
|
||||
def snake_case(name):
|
||||
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", name).lower()
|
||||
|
||||
|
||||
def python_param_modifier(comment):
|
||||
# p = f":{snake_case(m[0][1:])}:"
|
||||
comment = re.sub(r"@(param \w+)", lambda m: f":{snake_case(m[1])}:", comment)
|
||||
# python API renames `MeshGL` to `Mesh`
|
||||
comment = re.sub("mesh_gl", "mesh", comment)
|
||||
comment = re.sub("MeshGL", "Mesh", comment)
|
||||
return comment
|
||||
|
||||
|
||||
def method_key(name):
|
||||
name = re.sub(r"\+", "_plus", name)
|
||||
name = re.sub(r"\-", "_minus", name)
|
||||
name = re.sub(r"\^", "_xor", name)
|
||||
name = re.sub(r"\=", "_eq", name)
|
||||
name = re.sub(r"\:", "_", name)
|
||||
name = re.sub(r"\~", "destroy_", name)
|
||||
return name
|
||||
|
||||
|
||||
parens_re = re.compile(r"[^(]+\(([^(]*(\(.*\))*[^(]*\))", flags=re.DOTALL)
|
||||
args_re = re.compile(
|
||||
r"^[^,^\(^\)]*(\(.*\))*[^,^\(^\)]*[\s\&\*]([0-9\w]+)\s*[,\)]", flags=re.DOTALL
|
||||
)
|
||||
|
||||
|
||||
def parse_args(s):
|
||||
par = parens_re.match(s)
|
||||
if not par:
|
||||
return None
|
||||
out = []
|
||||
arg_str = par[1]
|
||||
while m := re.search(args_re, arg_str):
|
||||
out += [snake_case(m[2])]
|
||||
arg_str = arg_str[m.span()[1] :]
|
||||
return out
|
||||
|
||||
|
||||
def collect(fname, matcher, param_modifier=python_param_modifier):
|
||||
comment = ""
|
||||
with open(fname) as f:
|
||||
for line in f:
|
||||
line = line.lstrip()
|
||||
if line.startswith("/**"):
|
||||
comment = ""
|
||||
elif line.startswith("*/"):
|
||||
pass
|
||||
elif line.startswith("*") and comment is not None:
|
||||
comment += line[1:].lstrip()
|
||||
elif comment and (m := matcher(line)):
|
||||
while (args := parse_args(line)) is None:
|
||||
line += next(f)
|
||||
if len(line) > 500:
|
||||
break
|
||||
|
||||
method = method_key(snake_case(m[1]))
|
||||
# comment = re.sub(param_re, param_modifier, comment)
|
||||
comment = param_modifier(comment)
|
||||
method = "__".join([method, *args])
|
||||
assert method not in comments
|
||||
comments[method] = comment
|
||||
comment = ""
|
||||
|
||||
|
||||
comments = {}
|
||||
|
||||
method_re = re.compile(r"(\w+::[\w\-\+\^\=\:]+)\(")
|
||||
function_re = re.compile(r"([\w\-\+\^\=\:]+)\(")
|
||||
|
||||
|
||||
# we don't handle inline functions in classes properly
|
||||
# so instead just white-list functions we want
|
||||
def select_functions(s):
|
||||
m = function_re.search(s)
|
||||
if m and "Triangulate" in m[0]:
|
||||
return m
|
||||
if m and "Circular" in m[0]:
|
||||
return m
|
||||
return None
|
||||
|
||||
|
||||
collect(f"{base}/src/manifold.cpp", lambda s: method_re.search(s))
|
||||
collect(f"{base}/src/constructors.cpp", lambda s: method_re.search(s))
|
||||
collect(f"{base}/src/sort.cpp", lambda s: method_re.search(s))
|
||||
collect(f"{base}/src/sdf.cpp", lambda s: method_re.search(s))
|
||||
collect(f"{base}/src/cross_section/cross_section.cpp", lambda s: method_re.search(s))
|
||||
collect(f"{base}/src/polygon.cpp", select_functions)
|
||||
collect(f"{base}/include/manifold/common.h", select_functions)
|
||||
|
||||
comments = dict(sorted(comments.items()))
|
||||
|
||||
with open(f"{base}/bindings/python/docstring_override.txt") as f:
|
||||
key = ""
|
||||
for l in f:
|
||||
if l.startswith(" "):
|
||||
comments[key] += l[2:]
|
||||
else:
|
||||
key = l[:-2]
|
||||
if key not in comments.keys():
|
||||
print(f"Error, unknown docstring override key {key}")
|
||||
exit(-1)
|
||||
comments[key] = ""
|
||||
|
||||
gen_h = "autogen_docstrings.inl"
|
||||
with open(gen_h, "w") as f:
|
||||
f.write("#pragma once\n\n")
|
||||
f.write("// --- AUTO GENERATED ---\n")
|
||||
f.write("// gen_docs.py is run by cmake build\n\n")
|
||||
f.write("namespace manifold_docstrings {\n")
|
||||
for key, doc in comments.items():
|
||||
f.write(f'const char* {key} = R"___({doc.strip()})___";\n')
|
||||
f.write("} // namespace manifold_docs")
|
||||
@@ -0,0 +1,13 @@
|
||||
manifold3d.__prefix__:
|
||||
import numpy as np
|
||||
from typing import Literal, TypeVar, Union, Any
|
||||
|
||||
N = TypeVar('N', bound=int)
|
||||
DoubleNx2 = np.ndarray[tuple[N, Literal[2]], np.dtype[np.double]]
|
||||
Doublex2 = Union[np.ndarray[tuple[Literal[2]], np.dtype[np.double]], tuple[float, float], list[float]]
|
||||
Doublex3 = Union[np.ndarray[tuple[Literal[3]], np.dtype[np.double]], tuple[float, float, float], list[float]]
|
||||
Double2x3 = np.ndarray[tuple[Literal[2], Literal[3]], np.dtype[np.double]]
|
||||
Double3x4 = np.ndarray[tuple[Literal[3], Literal[4]], np.dtype[np.double]]
|
||||
DoubleNx3 = np.ndarray[tuple[N, Literal[3]], np.dtype[np.double]]
|
||||
Intx3 = Union[np.ndarray[tuple[Literal[3]], np.dtype[np.integer]], tuple[int, int, int], list[int]]
|
||||
IntNx3 = np.ndarray[tuple[N, Literal[3]], np.dtype[np.integer]]
|
||||
@@ -0,0 +1,13 @@
|
||||
import re, sys;
|
||||
|
||||
with open(sys.argv[1], 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
content = re.sub(r"Annotated\[ArrayLike, dict\(dtype='([^']*)'.*\)\]", r"np.ndarray[Any, np.dtype[np.\1]]", content)
|
||||
|
||||
# Remove ArrayLike and Annotated import
|
||||
content = re.sub(r"\s*from numpy.typing import ArrayLike\s", r"", content)
|
||||
content = re.sub(r"from typing import Annotated, overload", r"from typing import overload", content)
|
||||
|
||||
with open(sys.argv[1], 'w') as f:
|
||||
f.write(content)
|
||||
@@ -1 +0,0 @@
|
||||
add_subdirectory(nanobind)
|
||||
@@ -0,0 +1,16 @@
|
||||
/manifold.js
|
||||
/manifold.wasm
|
||||
/manifold-3d-*.tgz
|
||||
/manifold.d.ts
|
||||
/lib/*.js
|
||||
/lib/*.js.map
|
||||
/lib/*.d.ts
|
||||
/lib/*.d.ts.map
|
||||
/test/*.js
|
||||
/test/*.js.map
|
||||
/test/*.d.ts
|
||||
/test/*.d.ts.map
|
||||
/test/results
|
||||
/coverage
|
||||
/public
|
||||
dist
|
||||
@@ -12,43 +12,43 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
project(wasm)
|
||||
|
||||
add_executable(manifoldjs bindings.cpp)
|
||||
|
||||
set_source_files_properties(bindings.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bindings.js)
|
||||
target_link_libraries(manifoldjs manifold sdf cross_section polygon)
|
||||
set_source_files_properties(
|
||||
bindings.cpp
|
||||
PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bindings.js
|
||||
)
|
||||
target_link_libraries(
|
||||
manifoldjs
|
||||
PRIVATE manifold $<$<BOOL:${MANIFOLD_PAR}>:TBB::tbb>
|
||||
)
|
||||
target_compile_options(manifoldjs PRIVATE ${MANIFOLD_FLAGS})
|
||||
target_link_options(manifoldjs PUBLIC --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/bindings.js --bind -sALLOW_TABLE_GROWTH=1
|
||||
-sEXPORTED_RUNTIME_METHODS=addFunction,removeFunction -sMODULARIZE=1 -sEXPORT_ES6=1)
|
||||
target_link_options(
|
||||
manifoldjs
|
||||
PUBLIC
|
||||
--pre-js
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bindings.js
|
||||
--bind
|
||||
-sALLOW_TABLE_GROWTH=1
|
||||
-sEXPORTED_RUNTIME_METHODS=addFunction,removeFunction
|
||||
-sMODULARIZE=1
|
||||
-sEXPORT_ES6=1
|
||||
)
|
||||
|
||||
target_compile_features(manifoldjs PUBLIC cxx_std_17)
|
||||
set_target_properties(manifoldjs PROPERTIES OUTPUT_NAME "manifold")
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/built)
|
||||
|
||||
# ensure that interface files are copied over when modified
|
||||
add_custom_target(js_deps ALL
|
||||
DEPENDS manifoldjs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/manifold*.d.ts)
|
||||
add_custom_target(
|
||||
js_deps
|
||||
ALL
|
||||
DEPENDS manifoldjs ${CMAKE_CURRENT_SOURCE_DIR}/manifold*.d.ts
|
||||
)
|
||||
|
||||
# copy WASM build back here for publishing to npm
|
||||
add_custom_command(
|
||||
TARGET js_deps POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_BINARY_DIR}/manifold.*
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# copy WASM build and TS declarations for Vite to package into ManifoldCAD.org
|
||||
add_custom_command(
|
||||
TARGET js_deps POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/manifold*
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/built/)
|
||||
|
||||
# copy TS declarations to public so they can be accessed by our editor
|
||||
add_custom_command(
|
||||
TARGET js_deps POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/manifold*.d.ts
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/public/)
|
||||
TARGET js_deps
|
||||
POST_BUILD
|
||||
# copy WASM build back here for publishing to npm
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/manifold.*
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
@@ -1,31 +1,46 @@
|
||||
[](https://codecov.io/github/elalish/manifold)
|
||||
[](https://badge.fury.io/js/manifold-3d)
|
||||
[](https://twitter.com/intent/follow?screen_name=manifoldcad)
|
||||
|
||||
[**ManifoldCAD User Guide**](https://manifoldcad.org/docs/jsuser/) | [**JS/TS/WASM API**](https://manifoldcad.org/docs/jsapi/) | [**C++ Documentation**](https://manifoldcad.org/docs/html/classmanifold_1_1_manifold.html) | [**Algorithm Documentation**](https://github.com/elalish/manifold/wiki/Manifold-Library) | [**Blog Posts**](https://elalish.blogspot.com/search/label/Manifold)
|
||||
|
||||
<!-- #region IncludeInUserGuide -->
|
||||
|
||||
A [manifold mesh](https://github.com/elalish/manifold/wiki/Manifold-Library#manifoldness) is a mesh that represents a solid object, and so is very important in manufacturing, CAD, structural analysis, etc. 'Manifold' implies that there are no gaps or tears, and that all faces are oriented outwards.
|
||||
|
||||
## Manifold Library
|
||||
|
||||
[ [Using Manifold](https://manifoldcad.org/docs/jsapi/documents/Using_Manifold.html) | [Examples](https://manifoldcad.org/docs/jsapi/documents/Manifold_Examples.html) | [Manifold WASM Developer Guide](https://manifoldcad.org/docs/jsapi/) ]
|
||||
|
||||
[Manifold](https://github.com/elalish/manifold) is a geometry library dedicated to creating and operating on manifold triangle meshes. It is available as a WASM module that runs in any modern browser.
|
||||
|
||||
Our primary goal is reliability: guaranteed manifold output without caveats or edge cases. Our secondary goal is performance: efficient algorithms that make extensive use of parallelization, or pipelining when only a single thread is available.
|
||||
|
||||
## [ManifoldCAD.org](https://manifoldcad.org)
|
||||
If you like OpenSCAD / OpenJSCAD, you might also like ManifoldCAD - our own solid modelling web app based on this package.
|
||||
|
||||

|
||||
<img alt="A metallic Menger sponge" src="https://manifoldcad.org/samples/models/mengerSponge192.png" style="float:right">
|
||||
|
||||
# Manifold
|
||||
[ [ManifoldCAD](https://manifoldcad.org) | [ManifoldCAD User Guide](https://manifoldcad.org/docs/jsuser/) ]
|
||||
|
||||
[**High-level Documentation**](https://elalish.blogspot.com/search/label/Manifold) | [**API Documentation**](https://elalish.github.io/manifold/docs/html/modules.html) | [**Algorithm Documentation**](https://github.com/elalish/manifold/wiki/Manifold-Library) | [**Web Examples**](https://elalish.github.io/manifold/model-viewer.html)
|
||||
If you like OpenSCAD / JSCAD, you might also like ManifoldCAD - our own solid modelling web app where you script in JS/TS and save a GLB or 3MF file. It contains several examples showing how to use our API to make interesting shapes. You may notice that some of these examples bare a certain resemblance to my OpenSCAD designs on [Thingiverse](https://www.thingiverse.com/emmett), which is no accident. Much as I love OpenSCAD, this library is dramatically faster and the code is more flexible.
|
||||
|
||||
[Manifold](https://github.com/elalish/manifold) is a geometry library dedicated to creating and operating on manifold triangle meshes. A [manifold mesh](https://github.com/elalish/manifold/wiki/Manifold-Library#manifoldness) is a mesh that represents a solid object, and so is very important in manufacturing, CAD, structural analysis, etc. Further information can be found on the [wiki](https://github.com/elalish/manifold/wiki/Manifold-Library).
|
||||
manifoldCAD = manifold + [TypeScript](https://www.typescriptlang.org/) + [glTF](https://www.khronos.org/gltf/)
|
||||
|
||||
## What's here
|
||||
<div style="clear:both"></div>
|
||||
|
||||
This library is fast with guaranteed manifold output. As such you need manifold meshes as input, which this library can create using constructors inspired by the OpenSCAD API, as well as more advanced features like smoothing and signed-distance function (SDF) level sets. You can also pass in your own mesh data, but you'll get an error status if the imported mesh isn't manifold. Various automated repair tools exist online for fixing non manifold models, usually for 3D printing.
|
||||
<!-- #endregion IncludeInUserGuide -->
|
||||
<!-- #region NoStlPlease -->
|
||||
|
||||
The most significant contribution here is a guaranteed-manifold [mesh Boolean](https://github.com/elalish/manifold/wiki/Manifold-Library#mesh-boolean) algorithm, which I believe is the first of its kind. If you know of another, please open a discussion - a mesh Boolean algorithm robust to edge cases has been an open problem for many years. Likewise, if the Boolean here ever fails you, please submit an issue! This Boolean forms the basis of a CAD kernel, as it allows simple shapes to be combined into more complex ones.
|
||||
## 3D Formats
|
||||
|
||||
## Note on memory management
|
||||
[ [EXT_mesh_manifold](https://manifoldcad.org/docs/jsapi/modules/manifold-gltf.html) ]
|
||||
|
||||
Since Manifold is a WASM module, it does not automatically garbage-collect like regular JavaScript. You must manually `delete()` each manifold object constructed by your scripts, see [discussion](https://github.com/elalish/manifold/discussions/256#discussioncomment-3944287).
|
||||
Please avoid saving to STL files! They are lossy and inefficient - when saving a manifold mesh to STL there is no guarantee that the re-imported mesh will still be manifold, as the topology is lost. Please consider using [3MF](https://3mf.io/) instead, as this format was designed from the beginning for manifold meshes representing solid objects.
|
||||
|
||||
## Examples
|
||||
If you use vertex properties for things like interpolated normals or texture UV coordinates, [glTF](https://www.khronos.org/Gltf) is recommended, specifically using the [`EXT_mesh_manifold`](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_manifold/README.md) extension. This allows for the lossless and efficient transmission of manifoldness even with property boundaries. Try our [make-manifold](https://manifoldcad.org/make-manifold) page to add this extension to your existing glTF/GLB models.
|
||||
|
||||
Please see our usage [examples](https://github.com/elalish/manifold/tree/master/bindings/wasm/examples) to see how to interface this library with `three.js`, `<model-viewer>`, and `glTF`. Of particular note are the included libraries for lossless roundtrip of manifold meshes through glTF files, via a new extension: [EXT_manifold](https://github.com/KhronosGroup/glTF/pull/2286).
|
||||
<!-- #endregion NoStlPlease -->
|
||||
|
||||
## About the author
|
||||
|
||||
This library was started by [Emmett Lalish](https://elalish.blogspot.com/). I am currently a Google employee and this is my 20% project, not an official Google project. At my day job I'm the maintainer of [\<model-viewer\>](https://modelviewer.dev/). I was the first employee at a 3D video startup, [Omnivor](https://www.omnivor.io/), and before that I worked on 3D printing at Microsoft, including [3D Builder](https://www.microsoft.com/en-us/p/3d-builder/9wzdncrfj3t6?activetab=pivot%3Aoverviewtab). Originally an aerospace engineer, I started at a small DARPA contractor doing seedling projects, one of which became [Sea Hunter](https://en.wikipedia.org/wiki/Sea_Hunter). I earned my doctorate from the University of Washington in control theory and published some [papers](https://www.researchgate.net/scientific-contributions/75011026_Emmett_Lalish).
|
||||
This library was started by [Emmett Lalish](https://elalish.blogspot.com/), currently a senior rendering engineer at Wētā FX. This was my 20% project when I was a Google employee, though my day job was maintaining [\<model-viewer\>](https://modelviewer.dev/). I was the first employee at a 3D video startup, [Omnivor](https://www.omnivor.io/), and before that I worked on 3D printing at Microsoft, including [3D Builder](https://www.microsoft.com/en-us/p/3d-builder/9wzdncrfj3t6?activetab=pivot%3Aoverviewtab). Originally an aerospace engineer, I started at a small DARPA contractor doing seedling projects, one of which became [Sea Hunter](https://en.wikipedia.org/wiki/Sea_Hunter). I earned my doctorate from the University of Washington in control theory and published some [papers](https://www.researchgate.net/scientific-contributions/75011026_Emmett_Lalish).
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"mainEntryPointFilePath": "./manifold-root.d.ts",
|
||||
"compiler": {
|
||||
"overrideTsconfig": {
|
||||
"include": [
|
||||
"./manifold-global-types.d.ts",
|
||||
"./manifold-encapsulated-types.d.ts",
|
||||
"./manifold-root.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
},
|
||||
"docModel": {
|
||||
"enabled": false
|
||||
},
|
||||
"dtsRollup": {
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "./manifold.d.ts"
|
||||
},
|
||||
"tsdocMetadata": {
|
||||
"enabled": false
|
||||
},
|
||||
"messages": {
|
||||
"compilerMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
}
|
||||
},
|
||||
"extractorMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
"ae-missing-release-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-unresolved-link": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-incompatible-release-tags": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-internal-missing-underscore": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
"tsdoc-malformed-html-name": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-param-tag-missing-hyphen": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-escape-right-brace": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-escape-greater-than": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-malformed-inline-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-undefined-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-reference-missing-hash": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"mainEntryPointFilePath": "./types/manifoldCAD.d.ts",
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
},
|
||||
"docModel": {
|
||||
"enabled": false
|
||||
},
|
||||
"dtsRollup": {
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "./dist/manifoldCAD.d.ts"
|
||||
},
|
||||
"tsdocMetadata": {
|
||||
"enabled": false
|
||||
},
|
||||
"messages": {
|
||||
"compilerMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
}
|
||||
},
|
||||
"extractorMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
"ae-missing-release-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-unresolved-link": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-incompatible-release-tags": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-internal-missing-underscore": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
"tsdoc-malformed-html-name": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-param-tag-missing-hyphen": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-escape-right-brace": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-escape-greater-than": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-malformed-inline-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-undefined-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-reference-missing-hash": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"mainEntryPointFilePath": "./types/manifoldCADGlobals.d.ts",
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
},
|
||||
"docModel": {
|
||||
"enabled": false
|
||||
},
|
||||
"dtsRollup": {
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "./dist/manifoldCADGlobals.d.ts"
|
||||
},
|
||||
"tsdocMetadata": {
|
||||
"enabled": false
|
||||
},
|
||||
"messages": {
|
||||
"compilerMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
}
|
||||
},
|
||||
"extractorMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
"ae-missing-release-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-unresolved-link": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-incompatible-release-tags": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-internal-missing-underscore": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
"tsdoc-malformed-html-name": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-param-tag-missing-hyphen": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-escape-right-brace": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-escape-greater-than": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-malformed-inline-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-undefined-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"tsdoc-reference-missing-hash": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2025 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {readFile} from 'node:fs/promises';
|
||||
import {Command} from 'commander';
|
||||
|
||||
import {bundleFile} from '../lib/bundler.js';
|
||||
import * as worker from '../lib/worker.js';
|
||||
import * as exportModel from '../lib/export-model.js';
|
||||
|
||||
const program = new Command();
|
||||
program.name('manifold-cad')
|
||||
.description('Compile a ManifoldCAD program into a mesh.')
|
||||
.argument('<infile.[js|ts]>', 'Input file')
|
||||
.argument('<outfile>', 'Output file')
|
||||
.option('--jscdn <string>', 'Fetch npm packages from a CDN', 'jsDelivr')
|
||||
|
||||
// True means '--bundle' is implied by default, and '--no-bundle'
|
||||
// must be specified to disable bundling.
|
||||
.option('--no-bundle', 'Do not bundle input file before building model', true)
|
||||
.action(async(infile, outfile, options) => {
|
||||
// Choose an exporter. It will throw if we cannot match the extension.
|
||||
exportModel.supports(outfile, true);
|
||||
|
||||
// Build the model.
|
||||
let bundle = '';
|
||||
if (options.bundle) {
|
||||
bundle = await bundleFile(infile, {jsCDN: options.jscdn});
|
||||
} else {
|
||||
bundle = await readFile(infile, 'utf-8');
|
||||
}
|
||||
const doc = await worker.evaluate(bundle, {doNotBundle:true});
|
||||
|
||||
// Convert it and write it to disk.
|
||||
await exportModel.writeFile(outfile, doc);
|
||||
});
|
||||
|
||||
program.parseAsync(process.argv);
|
||||
@@ -15,37 +15,55 @@
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cross_section.h"
|
||||
#include "helpers.cpp"
|
||||
#include "manifold.h"
|
||||
#include "polygon.h"
|
||||
#include "sdf.h"
|
||||
#include "manifold/cross_section.h"
|
||||
#include "manifold/manifold.h"
|
||||
|
||||
#if (MANIFOLD_PAR == 1)
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
// https://github.com/oneapi-src/oneTBB/blob/master/WASM_Support.md#limitations
|
||||
void initTBB() {
|
||||
#if (MANIFOLD_PAR == 1)
|
||||
int num_threads = tbb::this_task_arena::max_concurrency();
|
||||
std::atomic<int> barrier{num_threads};
|
||||
tbb::parallel_for(
|
||||
0, num_threads,
|
||||
[&barrier](int) {
|
||||
barrier--;
|
||||
while (barrier > 0) {
|
||||
// Send browser thread to event loop
|
||||
std::this_thread::yield();
|
||||
}
|
||||
},
|
||||
tbb::static_partitioner{});
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace emscripten;
|
||||
using namespace manifold;
|
||||
|
||||
EMSCRIPTEN_BINDINGS(whatever) {
|
||||
value_object<glm::vec2>("vec2")
|
||||
.field("x", &glm::vec2::x)
|
||||
.field("y", &glm::vec2::y);
|
||||
value_object<vec2>("vec2").field("x", &vec2::x).field("y", &vec2::y);
|
||||
|
||||
value_object<glm::ivec3>("ivec3")
|
||||
.field("0", &glm::ivec3::x)
|
||||
.field("1", &glm::ivec3::y)
|
||||
.field("2", &glm::ivec3::z);
|
||||
value_object<ivec3>("ivec3")
|
||||
.field("0", &ivec3::x)
|
||||
.field("1", &ivec3::y)
|
||||
.field("2", &ivec3::z);
|
||||
|
||||
value_object<glm::vec3>("vec3")
|
||||
.field("x", &glm::vec3::x)
|
||||
.field("y", &glm::vec3::y)
|
||||
.field("z", &glm::vec3::z);
|
||||
value_object<vec3>("vec3")
|
||||
.field("x", &vec3::x)
|
||||
.field("y", &vec3::y)
|
||||
.field("z", &vec3::z);
|
||||
|
||||
value_object<glm::vec4>("vec4")
|
||||
.field("x", &glm::vec4::x)
|
||||
.field("y", &glm::vec4::y)
|
||||
.field("z", &glm::vec4::z)
|
||||
.field("w", &glm::vec4::w);
|
||||
value_object<vec4>("vec4")
|
||||
.field("x", &vec4::x)
|
||||
.field("y", &vec4::y)
|
||||
.field("z", &vec4::z)
|
||||
.field("w", &vec4::w);
|
||||
|
||||
enum_<Manifold::Error>("status")
|
||||
.value("NoError", Manifold::Error::NoError)
|
||||
@@ -72,7 +90,8 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
enum_<CrossSection::JoinType>("jointype")
|
||||
.value("Square", CrossSection::JoinType::Square)
|
||||
.value("Round", CrossSection::JoinType::Round)
|
||||
.value("Miter", CrossSection::JoinType::Miter);
|
||||
.value("Miter", CrossSection::JoinType::Miter)
|
||||
.value("Bevel", CrossSection::JoinType::Bevel);
|
||||
|
||||
value_object<Rect>("rect").field("min", &Rect::min).field("max", &Rect::max);
|
||||
value_object<Box>("box").field("min", &Box::min).field("max", &Box::max);
|
||||
@@ -81,19 +100,15 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
.field("halfedge", &Smoothness::halfedge)
|
||||
.field("smoothness", &Smoothness::smoothness);
|
||||
|
||||
value_object<Properties>("properties")
|
||||
.field("surfaceArea", &Properties::surfaceArea)
|
||||
.field("volume", &Properties::volume);
|
||||
|
||||
register_vector<glm::ivec3>("Vector_ivec3");
|
||||
register_vector<glm::vec3>("Vector_vec3");
|
||||
register_vector<glm::vec2>("Vector_vec2");
|
||||
register_vector<std::vector<glm::vec2>>("Vector2_vec2");
|
||||
register_vector<float>("Vector_f32");
|
||||
register_vector<ivec3>("Vector_ivec3");
|
||||
register_vector<vec3>("Vector_vec3");
|
||||
register_vector<vec2>("Vector_vec2");
|
||||
register_vector<std::vector<vec2>>("Vector2_vec2");
|
||||
register_vector<double>("Vector_f64");
|
||||
register_vector<CrossSection>("Vector_crossSection");
|
||||
register_vector<Manifold>("Vector_manifold");
|
||||
register_vector<Smoothness>("Vector_smoothness");
|
||||
register_vector<glm::vec4>("Vector_vec4");
|
||||
register_vector<vec4>("Vector_vec4");
|
||||
|
||||
class_<CrossSection>("CrossSection")
|
||||
.constructor(&cross_js::OfPolygons)
|
||||
@@ -112,7 +127,7 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
.function("numVert", &CrossSection::NumVert)
|
||||
.function("numContour", &CrossSection::NumContour)
|
||||
.function("_Bounds", &CrossSection::Bounds)
|
||||
.function("simplify", &CrossSection::Simplify)
|
||||
.function("_Simplify", &CrossSection::Simplify)
|
||||
.function("_Offset", &cross_js::Offset)
|
||||
.function("_ToPolygons", &CrossSection::ToPolygons)
|
||||
.function("hull",
|
||||
@@ -126,9 +141,9 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
function("_crossSectionDifferenceN", &cross_js::DifferenceN);
|
||||
function("_crossSectionIntersectionN", &cross_js::IntersectionN);
|
||||
function("_crossSectionCollectVertices", &cross_js::CollectVertices);
|
||||
function("_crossSectionHullPoints",
|
||||
select_overload<CrossSection(std::vector<glm::vec2>)>(
|
||||
&CrossSection::Hull));
|
||||
function(
|
||||
"_crossSectionHullPoints",
|
||||
select_overload<CrossSection(std::vector<vec2>)>(&CrossSection::Hull));
|
||||
|
||||
class_<Manifold>("Manifold")
|
||||
.constructor(&man_js::FromMeshJS)
|
||||
@@ -138,9 +153,17 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
.function("_Split", &man_js::Split)
|
||||
.function("_SplitByPlane", &man_js::SplitByPlane)
|
||||
.function("_TrimByPlane", &Manifold::TrimByPlane)
|
||||
.function("minkowskiSum", &Manifold::MinkowskiSum)
|
||||
.function("minkowskiDifference", &Manifold::MinkowskiDifference)
|
||||
.function("_Slice", &Manifold::Slice)
|
||||
.function("_Project", &Manifold::Project)
|
||||
.function("hull", select_overload<Manifold() const>(&Manifold::Hull))
|
||||
.function("_GetMeshJS", &js::GetMeshJS)
|
||||
.function("refine", &Manifold::Refine)
|
||||
.function("refineToLength", &Manifold::RefineToLength)
|
||||
.function("refineToTolerance", &Manifold::RefineToTolerance)
|
||||
.function("smoothByNormals", &Manifold::SmoothByNormals)
|
||||
.function("_SmoothOut", &Manifold::SmoothOut)
|
||||
.function("_Warp", &man_js::Warp)
|
||||
.function("_SetProperties", &man_js::SetProperties)
|
||||
.function("transform", &man_js::Transform)
|
||||
@@ -151,17 +174,22 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
.function("_Decompose", select_overload<std::vector<Manifold>() const>(
|
||||
&Manifold::Decompose))
|
||||
.function("isEmpty", &Manifold::IsEmpty)
|
||||
.function("status", &Manifold::Status)
|
||||
.function("status", &man_js::Status)
|
||||
.function("numVert", &Manifold::NumVert)
|
||||
.function("numEdge", &Manifold::NumEdge)
|
||||
.function("numTri", &Manifold::NumTri)
|
||||
.function("numProp", &Manifold::NumProp)
|
||||
.function("numPropVert", &Manifold::NumPropVert)
|
||||
.function("_boundingBox", &Manifold::BoundingBox)
|
||||
.function("precision", &Manifold::Precision)
|
||||
.function("tolerance", &Manifold::GetTolerance)
|
||||
.function("setTolerance", &Manifold::SetTolerance)
|
||||
.function("_Simplify", &Manifold::Simplify)
|
||||
.function("genus", &Manifold::Genus)
|
||||
.function("getProperties", &Manifold::GetProperties)
|
||||
.function("volume", &Manifold::Volume)
|
||||
.function("surfaceArea", &Manifold::SurfaceArea)
|
||||
.function("minGap", &Manifold::MinGap)
|
||||
.function("calculateCurvature", &Manifold::CalculateCurvature)
|
||||
.function("_CalculateNormals", &Manifold::CalculateNormals)
|
||||
.function("originalID", &Manifold::OriginalID)
|
||||
.function("asOriginal", &Manifold::AsOriginal);
|
||||
|
||||
@@ -177,18 +205,21 @@ EMSCRIPTEN_BINDINGS(whatever) {
|
||||
function("_LevelSet", &man_js::LevelSet);
|
||||
function("_Merge", &js::Merge);
|
||||
function("_ReserveIDs", &Manifold::ReserveIDs);
|
||||
function("_manifoldCompose", &Manifold::Compose);
|
||||
function("_manifoldCompose", &man_js::UnionN);
|
||||
function("_manifoldUnionN", &man_js::UnionN);
|
||||
function("_manifoldDifferenceN", &man_js::DifferenceN);
|
||||
function("_manifoldIntersectionN", &man_js::IntersectionN);
|
||||
function("_manifoldCollectVertices", &man_js::CollectVertices);
|
||||
function("_manifoldHullPoints",
|
||||
select_overload<Manifold(const std::vector<glm::vec3>&)>(
|
||||
&Manifold::Hull));
|
||||
function(
|
||||
"_manifoldHullPoints",
|
||||
select_overload<Manifold(const std::vector<vec3>&)>(&Manifold::Hull));
|
||||
|
||||
// Quality Globals
|
||||
function("setMinCircularAngle", &Quality::SetMinCircularAngle);
|
||||
function("setMinCircularEdgeLength", &Quality::SetMinCircularEdgeLength);
|
||||
function("setCircularSegments", &Quality::SetCircularSegments);
|
||||
function("getCircularSegments", &Quality::GetCircularSegments);
|
||||
function("resetToCircularDefaults", &Quality::ResetToDefaults);
|
||||
|
||||
function("initTBB", &initTBB);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ Module.setup = function() {
|
||||
if (_ManifoldInitialized) return;
|
||||
_ManifoldInitialized = true;
|
||||
|
||||
// warmup tbb for emscripten, according to
|
||||
// https://github.com/oneapi-src/oneTBB/blob/master/WASM_Support.md#limitations
|
||||
Module.initTBB();
|
||||
// conversion utilities
|
||||
|
||||
function toVec(vec, list, f = x => x) {
|
||||
@@ -128,12 +131,12 @@ Module.setup = function() {
|
||||
|
||||
Module.CrossSection.prototype.warp = function(func) {
|
||||
const wasmFuncPtr = addFunction(function(vec2Ptr) {
|
||||
const x = getValue(vec2Ptr, 'float');
|
||||
const y = getValue(vec2Ptr + 4, 'float');
|
||||
const x = getValue(vec2Ptr, 'double');
|
||||
const y = getValue(vec2Ptr + 8, 'double');
|
||||
const vert = [x, y];
|
||||
func(vert);
|
||||
setValue(vec2Ptr, vert[0], 'float');
|
||||
setValue(vec2Ptr + 4, vert[1], 'float');
|
||||
setValue(vec2Ptr, vert[0], 'double');
|
||||
setValue(vec2Ptr + 8, vert[1], 'double');
|
||||
}, 'vi');
|
||||
const out = this._Warp(wasmFuncPtr);
|
||||
removeFunction(wasmFuncPtr);
|
||||
@@ -156,23 +159,28 @@ Module.setup = function() {
|
||||
};
|
||||
|
||||
Module.CrossSection.prototype.offset = function(
|
||||
delta, joinType = 'Square', miterLimit = 2.0, circularSegments = 0) {
|
||||
delta, joinType = 'Round', miterLimit = 2.0, circularSegments = 0) {
|
||||
return this._Offset(
|
||||
delta, joinTypeToInt(joinType), miterLimit, circularSegments);
|
||||
};
|
||||
|
||||
Module.CrossSection.prototype.simplify = function(epsilon = 1e-6) {
|
||||
return this._Simplify(epsilon);
|
||||
};
|
||||
|
||||
Module.CrossSection.prototype.extrude = function(
|
||||
height, nDivisions = 0, twistDegrees = 0.0, scaleTop = [1.0, 1.0],
|
||||
center = false) {
|
||||
scaleTop = vararg2vec2([scaleTop]);
|
||||
const man =
|
||||
Module._Extrude(this, height, nDivisions, twistDegrees, scaleTop);
|
||||
const man = Module._Extrude(
|
||||
this._ToPolygons(), height, nDivisions, twistDegrees, scaleTop);
|
||||
return (center ? man.translate([0., 0., -height / 2.]) : man);
|
||||
};
|
||||
|
||||
Module.CrossSection.prototype.revolve = function(
|
||||
circularSegments = 0, revolveDegrees = 360.0) {
|
||||
return Module._Revolve(this, circularSegments, revolveDegrees);
|
||||
return Module._Revolve(
|
||||
this._ToPolygons(), circularSegments, revolveDegrees);
|
||||
};
|
||||
|
||||
Module.CrossSection.prototype.add = function(other) {
|
||||
@@ -189,54 +197,64 @@ Module.setup = function() {
|
||||
|
||||
Module.CrossSection.prototype.toPolygons = function() {
|
||||
const vec = this._ToPolygons();
|
||||
const result = vec2polygons(vec);
|
||||
const result = vec2polygons(vec, v => [v.x, v.y]);
|
||||
vec.delete();
|
||||
return result;
|
||||
};
|
||||
|
||||
// Manifold methods
|
||||
|
||||
Module.Manifold.prototype.smoothOut = function(
|
||||
minSharpAngle = 60, minSmoothness = 0) {
|
||||
return this._SmoothOut(minSharpAngle, minSmoothness);
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.warp = function(func) {
|
||||
const wasmFuncPtr = addFunction(function(vec3Ptr) {
|
||||
const x = getValue(vec3Ptr, 'float');
|
||||
const y = getValue(vec3Ptr + 4, 'float');
|
||||
const z = getValue(vec3Ptr + 8, 'float');
|
||||
const x = getValue(vec3Ptr, 'double');
|
||||
const y = getValue(vec3Ptr + 8, 'double');
|
||||
const z = getValue(vec3Ptr + 16, 'double');
|
||||
const vert = [x, y, z];
|
||||
func(vert);
|
||||
setValue(vec3Ptr, vert[0], 'float');
|
||||
setValue(vec3Ptr + 4, vert[1], 'float');
|
||||
setValue(vec3Ptr + 8, vert[2], 'float');
|
||||
setValue(vec3Ptr, vert[0], 'double');
|
||||
setValue(vec3Ptr + 8, vert[1], 'double');
|
||||
setValue(vec3Ptr + 16, vert[2], 'double');
|
||||
}, 'vi');
|
||||
const out = this._Warp(wasmFuncPtr);
|
||||
removeFunction(wasmFuncPtr);
|
||||
|
||||
const status = out.status();
|
||||
if (status.value !== 0) {
|
||||
throw new Module.ManifoldError(status.value);
|
||||
if (status !== 'NoError') {
|
||||
throw new Module.ManifoldError(status);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.calculateNormals = function(
|
||||
normalIdx, minSharpAngle = 60) {
|
||||
return this._CalculateNormals(normalIdx, minSharpAngle);
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.setProperties = function(numProp, func) {
|
||||
const oldNumProp = this.numProp();
|
||||
const wasmFuncPtr = addFunction(function(newPtr, vec3Ptr, oldPtr) {
|
||||
const newProp = [];
|
||||
for (let i = 0; i < numProp; ++i) {
|
||||
newProp[i] = getValue(newPtr + 4 * i, 'float');
|
||||
newProp[i] = getValue(newPtr + 8 * i, 'double');
|
||||
}
|
||||
const pos = [];
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
pos[i] = getValue(vec3Ptr + 4 * i, 'float');
|
||||
pos[i] = getValue(vec3Ptr + 8 * i, 'double');
|
||||
}
|
||||
const oldProp = [];
|
||||
for (let i = 0; i < oldNumProp; ++i) {
|
||||
oldProp[i] = getValue(oldPtr + 4 * i, 'float');
|
||||
oldProp[i] = getValue(oldPtr + 8 * i, 'double');
|
||||
}
|
||||
|
||||
func(newProp, pos, oldProp);
|
||||
|
||||
for (let i = 0; i < numProp; ++i) {
|
||||
setValue(newPtr + 4 * i, newProp[i], 'float');
|
||||
setValue(newPtr + 8 * i, newProp[i], 'double');
|
||||
}
|
||||
}, 'viii');
|
||||
const out = this._SetProperties(numProp, wasmFuncPtr);
|
||||
@@ -248,8 +266,12 @@ Module.setup = function() {
|
||||
return this._Translate(vararg2vec3(vec));
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.rotate = function(vec) {
|
||||
return this._Rotate(...vec);
|
||||
Module.Manifold.prototype.rotate = function(xOrVec, y, z) {
|
||||
if (Array.isArray(xOrVec)) {
|
||||
return this._Rotate(...xOrVec);
|
||||
} else {
|
||||
return this._Rotate(xOrVec, y || 0, z || 0);
|
||||
}
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.scale = function(vec) {
|
||||
@@ -268,15 +290,29 @@ Module.setup = function() {
|
||||
return this._TrimByPlane(vararg2vec3([normal]), offset);
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.slice = function(height = 0.) {
|
||||
const polygonsVec = this._Slice(height);
|
||||
const result = new CrossSectionCtor(polygonsVec, fillRuleToInt('Positive'));
|
||||
disposePolygons(polygonsVec);
|
||||
return result;
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.project = function() {
|
||||
const polygonsVec = this._Project();
|
||||
const result = new CrossSectionCtor(polygonsVec, fillRuleToInt('Positive'));
|
||||
disposePolygons(polygonsVec);
|
||||
return result;
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.split = function(manifold) {
|
||||
const vec = this._split(manifold);
|
||||
const vec = this._Split(manifold);
|
||||
const result = fromVec(vec);
|
||||
vec.delete();
|
||||
return result;
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.splitByPlane = function(normal, offset = 0.) {
|
||||
const vec = this._splitByPlane(vararg2vec3([normal]), offset);
|
||||
const vec = this._SplitByPlane(vararg2vec3([normal]), offset);
|
||||
const result = fromVec(vec);
|
||||
vec.delete();
|
||||
return result;
|
||||
@@ -297,6 +333,10 @@ Module.setup = function() {
|
||||
};
|
||||
};
|
||||
|
||||
Module.Manifold.prototype.simplify = function(tolerance = 0) {
|
||||
return this._Simplify(tolerance);
|
||||
};
|
||||
|
||||
class Mesh {
|
||||
constructor({
|
||||
numProp = 3,
|
||||
@@ -308,7 +348,8 @@ Module.setup = function() {
|
||||
runOriginalID,
|
||||
faceID,
|
||||
halfedgeTangent,
|
||||
runTransform
|
||||
runTransform,
|
||||
tolerance = 0
|
||||
} = {}) {
|
||||
this.numProp = numProp;
|
||||
this.triVerts = triVerts;
|
||||
@@ -320,6 +361,7 @@ Module.setup = function() {
|
||||
this.faceID = faceID;
|
||||
this.halfedgeTangent = halfedgeTangent;
|
||||
this.runTransform = runTransform;
|
||||
this.tolerance = tolerance;
|
||||
}
|
||||
|
||||
get numTri() {
|
||||
@@ -345,12 +387,13 @@ Module.setup = function() {
|
||||
}
|
||||
|
||||
position(vert) {
|
||||
return this.vertProperties.subarray(numProp * vert, numProp * vert + 3);
|
||||
return this.vertProperties.subarray(
|
||||
this.numProp * vert, this.numProp * vert + 3);
|
||||
}
|
||||
|
||||
extras(vert) {
|
||||
return this.vertProperties.subarray(
|
||||
numProp * vert + 3, numProp * (vert + 1));
|
||||
this.numProp * vert + 3, this.numProp * (vert + 1));
|
||||
}
|
||||
|
||||
tangent(halfedge) {
|
||||
@@ -371,45 +414,43 @@ Module.setup = function() {
|
||||
|
||||
Module.Mesh = Mesh;
|
||||
|
||||
Module.Manifold.prototype.getMesh = function(normalIdx = [0, 0, 0]) {
|
||||
if (normalIdx instanceof Array)
|
||||
normalIdx = {0: normalIdx[0], 1: normalIdx[1], 2: normalIdx[2]};
|
||||
Module.Manifold.prototype.getMesh = function(normalIdx = -1) {
|
||||
return new Mesh(this._GetMeshJS(normalIdx));
|
||||
};
|
||||
|
||||
Module.ManifoldError = function ManifoldError(code, ...args) {
|
||||
let message = 'Unknown error';
|
||||
switch (code) {
|
||||
case Module.status.NonFiniteVertex.value:
|
||||
case 'NonFiniteVertex':
|
||||
message = 'Non-finite vertex';
|
||||
break;
|
||||
case Module.status.NotManifold.value:
|
||||
case 'NotManifold':
|
||||
message = 'Not manifold';
|
||||
break;
|
||||
case Module.status.VertexOutOfBounds.value:
|
||||
case 'VertexOutOfBounds':
|
||||
message = 'Vertex index out of bounds';
|
||||
break;
|
||||
case Module.status.PropertiesWrongLength.value:
|
||||
case 'PropertiesWrongLength':
|
||||
message = 'Properties have wrong length';
|
||||
break;
|
||||
case Module.status.MissingPositionProperties.value:
|
||||
case 'MissingPositionProperties':
|
||||
message = 'Less than three properties';
|
||||
break;
|
||||
case Module.status.MergeVectorsDifferentLengths.value:
|
||||
case 'MergeVectorsDifferentLengths':
|
||||
message = 'Merge vectors have different lengths';
|
||||
break;
|
||||
case Module.status.MergeIndexOutOfBounds.value:
|
||||
case 'MergeIndexOutOfBounds':
|
||||
message = 'Merge index out of bounds';
|
||||
break;
|
||||
case Module.status.TransformWrongLength.value:
|
||||
case 'TransformWrongLength':
|
||||
message = 'Transform vector has wrong length';
|
||||
break;
|
||||
case Module.status.RunIndexWrongLength.value:
|
||||
case 'RunIndexWrongLength':
|
||||
message = 'Run index vector has wrong length';
|
||||
break;
|
||||
case Module.status.FaceIDWrongLength.value:
|
||||
case 'FaceIDWrongLength':
|
||||
message = 'Face ID vector has wrong length';
|
||||
case Module.status.InvalidConstruction.value:
|
||||
case 'InvalidConstruction':
|
||||
message = 'Manifold constructed with invalid parameters';
|
||||
}
|
||||
|
||||
@@ -519,8 +560,8 @@ Module.setup = function() {
|
||||
const manifold = new ManifoldCtor(mesh);
|
||||
|
||||
const status = manifold.status();
|
||||
if (status.value !== 0) {
|
||||
throw new Module.ManifoldError(status.value);
|
||||
if (status !== 'NoError') {
|
||||
throw new Module.ManifoldError(status);
|
||||
}
|
||||
|
||||
return manifold;
|
||||
@@ -586,14 +627,6 @@ Module.setup = function() {
|
||||
return Module._ReserveIDs(n);
|
||||
};
|
||||
|
||||
Module.Manifold.compose = function(manifolds) {
|
||||
const vec = new Module.Vector_manifold();
|
||||
toVec(vec, manifolds);
|
||||
const result = Module._manifoldCompose(vec);
|
||||
vec.delete();
|
||||
return result;
|
||||
};
|
||||
|
||||
function manifoldBatchbool(name) {
|
||||
return function(...args) {
|
||||
if (args.length == 1) args = args[0];
|
||||
@@ -606,22 +639,28 @@ Module.setup = function() {
|
||||
}
|
||||
|
||||
Module.Manifold.union = manifoldBatchbool('Union');
|
||||
// Aliasing compose to union.
|
||||
// Native compose has some issues, and is deprecated.
|
||||
Module.Manifold.compose = Module.Manifold.union;
|
||||
|
||||
Module.Manifold.difference = manifoldBatchbool('Difference');
|
||||
Module.Manifold.intersection = manifoldBatchbool('Intersection');
|
||||
|
||||
Module.Manifold.levelSet = function(sdf, bounds, edgeLength, level = 0) {
|
||||
Module.Manifold.levelSet = function(
|
||||
sdf, bounds, edgeLength, level = 0, tolerance = -1) {
|
||||
const bounds2 = {
|
||||
min: {x: bounds.min[0], y: bounds.min[1], z: bounds.min[2]},
|
||||
max: {x: bounds.max[0], y: bounds.max[1], z: bounds.max[2]},
|
||||
};
|
||||
const wasmFuncPtr = addFunction(function(vec3Ptr) {
|
||||
const x = getValue(vec3Ptr, 'float');
|
||||
const y = getValue(vec3Ptr + 4, 'float');
|
||||
const z = getValue(vec3Ptr + 8, 'float');
|
||||
const x = getValue(vec3Ptr, 'double');
|
||||
const y = getValue(vec3Ptr + 8, 'double');
|
||||
const z = getValue(vec3Ptr + 16, 'double');
|
||||
const vert = [x, y, z];
|
||||
return sdf(vert);
|
||||
}, 'fi');
|
||||
const out = Module._LevelSet(wasmFuncPtr, bounds2, edgeLength, level);
|
||||
}, 'di');
|
||||
const out =
|
||||
Module._LevelSet(wasmFuncPtr, bounds2, edgeLength, level, tolerance);
|
||||
removeFunction(wasmFuncPtr);
|
||||
return out;
|
||||
};
|
||||
@@ -665,10 +704,11 @@ Module.setup = function() {
|
||||
|
||||
// Top-level functions
|
||||
|
||||
Module.triangulate = function(polygons, precision = -1) {
|
||||
Module.triangulate = function(polygons, epsilon = -1, allowConvex = true) {
|
||||
const polygonsVec = polygons2vec(polygons);
|
||||
const result = fromVec(
|
||||
Module._Triangulate(polygonsVec, precision), (x) => [x[0], x[1], x[2]]);
|
||||
Module._Triangulate(polygonsVec, epsilon, allowConvex),
|
||||
(x) => [x[0], x[1], x[2]]);
|
||||
disposePolygons(polygonsVec);
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Manifold Examples
|
||||
group: none
|
||||
---
|
||||
# Manifold Examples
|
||||
|
||||
## Interoperation with three.js
|
||||
|
||||
{@include ../examples/three/README.md#summary}
|
||||
|
||||
## <model-viewer>
|
||||
|
||||
{@include ../examples/model-viewer/README.md#summary}
|
||||
|
||||
## Manifoldness and EXT_mesh_manifold
|
||||
|
||||
{@include ../examples/make-manifold/README.md#summary}
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Using Manifold
|
||||
group: none
|
||||
---
|
||||
# Using Manifold
|
||||
|
||||
## Installation
|
||||
|
||||
In your project root folder run:
|
||||
|
||||
```bash
|
||||
npm install --save manifold-3d
|
||||
```
|
||||
|
||||
To start using Manifold, import it and initialize it:
|
||||
|
||||
```js
|
||||
import Module from 'manifold-3d';
|
||||
|
||||
const wasm = await Module();
|
||||
wasm.setup();
|
||||
const { Manifold } = wasm;
|
||||
```
|
||||
|
||||
Intro example
|
||||
|
||||
```js
|
||||
const {cube, sphere} = Manifold;
|
||||
const box = cube([100, 100, 100], true);
|
||||
const ball = sphere(60, 100);
|
||||
const result = box.subtract(ball);
|
||||
```
|
||||
|
||||
## Memory Management
|
||||
|
||||
> [!WARNING]
|
||||
> Since Manifold is a WASM module, it does not automatically garbage-collect like regular JavaScript.
|
||||
|
||||
You must manually `delete()` each object constructed by your scripts (both `Manifold` and `CrossSection`).
|
||||
See [discussion](https://github.com/elalish/manifold/discussions/256#discussioncomment-3944287).
|
||||
|
||||
## Examples
|
||||
|
||||
See [Examples](./bindings-examples.md).
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Contributing
|
||||
group: none
|
||||
category: none
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
To debug the WASM build directly in Chrome dev tools, simply build in debug mode:
|
||||
```
|
||||
emcmake cmake -DCMAKE_BUILD_TYPE=Debug .. && emmake make
|
||||
```
|
||||
and install the [DWARF](goo.gle/wasm-debugging-extension) Chrome extension.
|
||||
|
||||
When testing [ManifoldCAD.org](https://manifoldcad.org/) (either locally or the
|
||||
deployed version) note that it uses a service worker for faster loading. This
|
||||
means you need to open the page twice to see updates (the first time loads the
|
||||
old version and caches the new one, the second time loads the new version from
|
||||
cache). To see changes on each reload, open Chrome dev tools, go to the
|
||||
Application tab and check "update on reload".
|
||||
|
||||
## Documentation
|
||||
|
||||
This guide and the ManifoldCAD User Guide are built using [TypeDoc](https://typedoc.org).
|
||||
|
||||
### Building Documentation
|
||||
|
||||
Documentation can be built using NPM:
|
||||
|
||||
```bash
|
||||
cd bindings/wasm
|
||||
npm install
|
||||
npm run build
|
||||
npm run docs
|
||||
```
|
||||
|
||||
After this, the User and Developer docs will be in `docs/jsuser` and `docs/jsapi` respectively.
|
||||
|
||||
### Writing for the User Guide
|
||||
|
||||
The ManifoldCAD User Guide is generated from the declaration files present in `types/`. These mostly re-export declarations, allowing the User Guide to inherit from the Developer Guide.
|
||||
|
||||
TypeDoc reflections (comments) flagged as `@internal` will _not_ be visible in the User Guide, but will be present in the Developer Guide. Reflections tagged as `@hidden` will not be visible in either guide.
|
||||
|
||||
### WASM Bindings
|
||||
|
||||
The manifold library itself is documented in three files:
|
||||
|
||||
* `manifold-global-types.d.ts`: Defines lower level types and interfaces like {@link manifold.Vec2 | Vec2}, {@link manifold.Mat3 | Mat3}, &c.
|
||||
* `manifold-encapsulated-types.d.ts`: Declares objects and types that are implemented in C++, and compiled to WASM. Definitions of classes like {@link manifold.Manifold | Manifold} and {@link manifold.CrossSection | CrossSection} can be found here.
|
||||
* `manifold-root.d.ts`: Defines the {@link manifold.ManifoldToplevel | ManifoldToplevel} interface, and re-exports the above two files.
|
||||
|
||||
These three files are consolidated into `manifold.d.ts` using [API Extractor](https://api-extractor.com/). This is automatically run before each build as an npm lifecycle hook. It can be run manually as `npm run prebuild`.
|
||||
|
||||
### Terminology
|
||||
|
||||
These are general guidelines, not hard rules. The aim of this section is to encourage consistent documentation, not to institute brand standards.
|
||||
|
||||
* When referring to the library, manifold should generally be lowercase. Manifold can be capitalized when grammatically correct, for example at the start of a sentence. If unclear, `manifold` can be marked up as code to distinguish it from the manifold property.
|
||||
* The Manifold class should generally be capitalized. Where appropriate, it can be linked directly to the {@link manifold.Manifold | Manifold} class documentation.
|
||||
* ManifoldCAD should be capitalized. [ManifoldCAD.org](https://manifoldcad.org) should be a link.
|
||||
@@ -0,0 +1,6 @@
|
||||
@layer typedoc {
|
||||
:root {
|
||||
--light-color-background-secondary: #c0c000;
|
||||
--dark-color-background-secondary: #606000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Embedding ManifoldCAD
|
||||
group: ManifoldCAD
|
||||
---
|
||||
# Embedding ManifoldCAD
|
||||
|
||||
There are three ways to use manifold in your own projects:
|
||||
|
||||
1. Using the ManifoldCAD worker. The worker adds overhead, but it will sandbox scripts. It also makes it possible to include packages at runtime.
|
||||
1. Using ManifoldCAD libraries directly. ManifoldCAD implements importers, exporters, and garbage collection amongst other utilities. These modules are reasonably light and can be used outside of manifoldCAD.
|
||||
1. Using the [Manifold WASM module directly](./bindings.md) without any of the above.
|
||||
|
||||
## Using the ManifoldCAD worker
|
||||
|
||||
The worker is a code evaluation sandbox intended to run as a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). It will bundle a script, include any dependencies, and even fetch those dependencies from a CDN if required. At run time, it will evaluate the script as a [dynamically created function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function).
|
||||
|
||||
See:
|
||||
|
||||
* {@link lib/worker | worker API}
|
||||
* [manifold-cad](https://github.com/elalish/manifold/blob/master/bindings/wasm/bin/manifold-cad) CLI
|
||||
|
||||
### Detecting the worker
|
||||
|
||||
> [!NOTE]
|
||||
> There are slight behaviour differences between scripts running inside the manifoldCAD worker, and those outside.
|
||||
>
|
||||
> See our [import integration tests](https://github.com/elalish/manifold/blob/master/bindings/wasm/test/import.test.ts) for examples.
|
||||
|
||||
When evaluated through the worker, {@link manifoldCAD!isManifoldCAD | isManifoldCAD()} will return true. Otherwise it returns false.
|
||||
|
||||
## Using the ManifoldCAD runtime directly
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@layer typedoc {
|
||||
:root {
|
||||
--light-color-background-secondary: #A288B3;
|
||||
--dark-color-background-secondary: #675772;
|
||||
}
|
||||
/* Hide right-hand navigation bar.
|
||||
* It is redundant for such a small site.
|
||||
*/
|
||||
.tsd-page-navigation {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: Using ManifoldCAD
|
||||
---
|
||||
## Running ManifoldCAD
|
||||
|
||||
### With a Browser
|
||||
|
||||
Just go to [ManifoldCAD.org](https://manifoldcad.org), and check out the examples!
|
||||
|
||||
### On the Command Line
|
||||
|
||||
ManifoldCAD has a [command line interface](https://github.com/elalish/manifold/blob/master/bindings/wasm/bin/manifold-cad). It can be run directly as `./bin/manifold-cad`. It can also be run via `npx`. If Manifold is not already present, use `npx manifold-3d manifold-cad` or `npx manifold-3d`. If Manifold is already installed, `npx manifold-cad` will suffice.
|
||||
|
||||
```
|
||||
Usage: manifold-cad [options] <infile.js> <outfile>
|
||||
```
|
||||
|
||||
The output file can be in either `.glb` or `.3mf` format, determined by extension.
|
||||
|
||||
## Coordinate Systems
|
||||
|
||||
ManifoldCAD uses a right-handed coordinate system where '+Z' is up. Length units are assumed to be millimetres. This is slightly at odds with glTF, which also uses a right handed coordinate system, but specifies '+Y' as up, and length units are in metres.
|
||||
|
||||
ManifoldCAD will scale and rotate automatically when importing or exporting glTF models. This means that an arrow pointing in the '+Z' direction in will point in the '+Y' direction after export. However, that arrow will still point up, and will still be the same size.
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as esbuild from 'esbuild';
|
||||
|
||||
await esbuild.build({
|
||||
entryPoints: ['lib/worker.ts'],
|
||||
bundle: true,
|
||||
outfile: 'dist/worker.bundled.js',
|
||||
format: 'esm',
|
||||
target: 'esnext',
|
||||
sourcemap: 'inline',
|
||||
sourcesContent: false,
|
||||
external: [
|
||||
'node:path', 'node:url', 'node:fs', 'node:module', 'module',
|
||||
]
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
manifold*
|
||||
@@ -1,45 +0,0 @@
|
||||
# WASM/JS Examples
|
||||
|
||||
This is the home of our editor, [ManifoldCAD.org](https://manifoldcad.org/), as well as our other public examples of integrations with `three.js`, `<model-viewer>`, and `glTF`. Included are `manifold-gltf.js` and `gltf-io.js`, which are intended to be fairly general-purpose libraries for interfacing between manifolds and glTF. We should probably make them into their own npm package at some point.
|
||||
|
||||
## Local development
|
||||
|
||||
First, follow the directions in the root README to get your C++ build environment set up and working for WASM. From this directory (`bindings/wasm/examples/`) you can test the JS bindings by running:
|
||||
|
||||
```
|
||||
npm install
|
||||
npm test
|
||||
```
|
||||
|
||||
To develop the manifoldCAD.org editor as well as our other example pages, run
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
which will serve the pages, watch for changes, and automatically rebuild and refresh. This build step doesn't do TS type-checking, so to verify everything is correct (beyond VSCode's TS linting), run
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
See `package.json` for other useful scripts.
|
||||
|
||||
Note that the `emcmake` command automatically copies your WASM build into `built/`, (here, not just under the `buildWASM` directory) which is then packaged by Vite into `dist/assets/`.
|
||||
|
||||
To debug the WASM build directly in Chrome dev tools, simply build in debug mode:
|
||||
```
|
||||
emcmake cmake -DCMAKE_BUILD_TYPE=Debug .. && emmake make
|
||||
```
|
||||
and install the [DWARF](goo.gle/wasm-debugging-extension) Chrome extension.
|
||||
|
||||
When testing [ManifoldCAD.org](https://manifoldcad.org/) (either locally or the
|
||||
deployed version) note that it uses a service worker for faster loading. This
|
||||
means you need to open the page twice to see updates (the first time loads the
|
||||
old version and caches the new one, the second time loads the new version from
|
||||
cache). To see changes on each reload, open Chrome dev tools, go to the
|
||||
Application tab and check "update on reload".
|
||||
|
||||
### Note for firefox users
|
||||
|
||||
To use the manifoldCAD.org editor (`npm run dev`), you'll likely have to set
|
||||
`dom.workers.modules.enabled: true` in your `about:config`, as mentioned in the
|
||||
discussion of the
|
||||
[issue#328](https://github.com/elalish/manifold/issues/328#issuecomment-1473847102)
|
||||
of this repository.
|
||||
@@ -0,0 +1,14 @@
|
||||
## Local development
|
||||
|
||||
First, follow the directions in the root README to get your C++ build environment set up and working for WASM.
|
||||
|
||||
To develop the manifoldCAD.org editor as well as our other example pages, run
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
which will serve the pages, watch for changes, and automatically rebuild and refresh. This build step doesn't do TS type-checking, so to verify everything is correct (beyond VSCode's TS linting), run
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
See `package.json` for other useful scripts.
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import auger from '../../test/examples/auger.mjs?raw';
|
||||
import gearBearing from '../../test/examples/gear-bearing.ts?raw';
|
||||
import godelEscherBach from '../../test/examples/godel-escher-bach.ts?raw';
|
||||
import gyroidModule from '../../test/examples/gyroid-module.ts?raw';
|
||||
import heart from '../../test/examples/heart.mjs?raw';
|
||||
import importManifold from '../../test/examples/import-manifold.ts?raw';
|
||||
import intro from '../../test/examples/intro.mjs?raw';
|
||||
import involuteGearLibrary from '../../test/examples/involute-gear-library.ts?raw';
|
||||
import mengerSponge from '../../test/examples/menger-sponge.mjs?raw';
|
||||
import roundedFrame from '../../test/examples/rounded-frame.mjs?raw';
|
||||
import scallop from '../../test/examples/scallop.mjs?raw';
|
||||
import stretchyBracelet from '../../test/examples/stretchy-bracelet.mjs?raw';
|
||||
import tetrahedronPuzzle from '../../test/examples/tetrahedron-puzzle.mjs?raw';
|
||||
import torusKnot from '../../test/examples/torus-knot.mjs?raw';
|
||||
import voronoi from '../../test/examples/voronoi.mjs?raw';
|
||||
|
||||
const examples = new Map();
|
||||
examples.set('Intro', intro);
|
||||
examples.set('Auger', auger);
|
||||
examples.set('Tetrahedron Puzzle', tetrahedronPuzzle);
|
||||
examples.set('Rounded Frame', roundedFrame);
|
||||
examples.set('Heart', heart);
|
||||
examples.set('Scallop', scallop);
|
||||
examples.set('Torus Knot', torusKnot);
|
||||
examples.set('Menger Sponge', mengerSponge);
|
||||
examples.set('Stretchy Bracelet', stretchyBracelet);
|
||||
examples.set('Gyroid Module', gyroidModule);
|
||||
examples.set('Gear Bearing', gearBearing);
|
||||
examples.set('involute-gear-library', involuteGearLibrary);
|
||||
examples.set('Voronoi', voronoi);
|
||||
examples.set('Import Manifold', importManifold);
|
||||
examples.set('Gödel, Escher, Bach', godelEscherBach)
|
||||
|
||||
if (typeof self !== 'undefined') {
|
||||
self.examples = examples;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ button:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
input {
|
||||
.name {
|
||||
border: none;
|
||||
height: 36px;
|
||||
background-color: transparent;
|
||||
@@ -77,12 +77,12 @@ input {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
.name:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em;
|
||||
margin: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ model-viewer {
|
||||
|
||||
.header .margin {
|
||||
font-size: 16px;
|
||||
margin: 1em 0.5em;
|
||||
margin: 18px 8px;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
@@ -168,6 +168,29 @@ model-viewer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.top-edit {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 36px;
|
||||
top: 18px;
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.top-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 36px;
|
||||
background-size: 24px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.squish {
|
||||
margin-right: -12px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
@@ -180,6 +203,32 @@ model-viewer {
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.undo {
|
||||
background-image: url(/icons/undo.png);
|
||||
}
|
||||
|
||||
.redo {
|
||||
background-image: url(/icons/redo.png);
|
||||
}
|
||||
|
||||
.star {
|
||||
background-image: url(/icons/star.png);
|
||||
}
|
||||
|
||||
.share {
|
||||
background-image: url(/icons/share.png);
|
||||
}
|
||||
|
||||
.docs {
|
||||
background-image: url(/icons/docs.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
background-image: url(/icons/close.png);
|
||||
background-size: 20px;
|
||||
@@ -196,10 +245,22 @@ model-viewer {
|
||||
background-image: url(/icons/trash.png);
|
||||
}
|
||||
|
||||
.play {
|
||||
background-image: url(/icons/play.png);
|
||||
}
|
||||
|
||||
.pause {
|
||||
background-image: url(/icons/pause.png);
|
||||
}
|
||||
|
||||
.icon:hover {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.top-icon:hover {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.blue {
|
||||
background-color: rgb(148, 221, 255);
|
||||
}
|
||||
@@ -221,7 +282,52 @@ model-viewer {
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
#animation {
|
||||
display: none;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
#play {
|
||||
position: relative;
|
||||
background-color: #ccc;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: relative;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
margin-right: 16px;
|
||||
background: #ffffff55;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 820px) {
|
||||
.container {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
@@ -256,4 +362,4 @@ model-viewer {
|
||||
width: calc(50% - 16px);
|
||||
margin: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,20 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import ManifoldWorker from './worker?worker';
|
||||
// '?url' is vite convention to reference a static asset.
|
||||
// vite will package the asset and provide a proper URL.
|
||||
import esbuildWasmUrl from 'esbuild-wasm/esbuild.wasm?url';
|
||||
import ManifoldWorker from 'manifold-3d/lib/worker.bundled.js?worker';
|
||||
import manifoldWasmUrl from 'manifold-3d/manifold.wasm?url';
|
||||
import {AutoTypings, LocalStorageCache} from 'monaco-editor-auto-typings';
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.main';
|
||||
// '?worker' is vite convention to load a module as a web worker.
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
|
||||
|
||||
const CODE_START = '<code>';
|
||||
// Loaded globally by examples.js
|
||||
const exampleFunctions = self.examples.functionBodies;
|
||||
const exampleFunctions = self.examples;
|
||||
|
||||
if (navigator.serviceWorker) {
|
||||
navigator.serviceWorker.register(
|
||||
@@ -24,6 +34,28 @@ if (navigator.serviceWorker) {
|
||||
|
||||
let editor = undefined;
|
||||
|
||||
// Edit UI ------------------------------------------------------------
|
||||
|
||||
const undoButton = document.querySelector('#undo');
|
||||
const redoButton = document.querySelector('#redo');
|
||||
const formatButton = document.querySelector('#format');
|
||||
const shareButton = document.querySelector('#share');
|
||||
|
||||
undoButton.onclick = () => editor.trigger('ignored', 'undo');
|
||||
redoButton.onclick = () => editor.trigger('ignored', 'redo');
|
||||
formatButton.onclick = () =>
|
||||
editor.trigger('ignored', 'editor.action.formatDocument');
|
||||
shareButton.onclick = () => {
|
||||
const url = new URL(window.location.toString());
|
||||
url.hash =
|
||||
'#' +
|
||||
encodeURIComponent(
|
||||
currentFileElement.textContent + CODE_START + editor.getValue());
|
||||
navigator.clipboard.writeText(url.toString());
|
||||
console.log('Shareable link copied to clipboard!');
|
||||
console.log('Consider shortening this URL using tinyURL.com');
|
||||
};
|
||||
|
||||
// File UI ------------------------------------------------------------
|
||||
const fileButton = document.querySelector('#file');
|
||||
const currentFileElement = document.querySelector('#current');
|
||||
@@ -71,6 +103,28 @@ function nthKey(n) {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllScripts() {
|
||||
const files = {};
|
||||
for (const [name, contents] of exampleFunctions) {
|
||||
files[name] = contents;
|
||||
}
|
||||
|
||||
for (let i = 0; i < window.localStorage.length; i++) {
|
||||
const key = nthKey(i);
|
||||
if (!key || key === 'currentName' || key === 'safe') continue;
|
||||
files[key] = getScript(key)
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function getModelForScript(filename) {
|
||||
const uri = monaco.Uri.parse(`inmemory://model/${filename}.ts`);
|
||||
const model = monaco.editor.getModel(uri) ||
|
||||
monaco.editor.createModel('', 'typescript', uri);
|
||||
model.updateOptions({tabSize: 2});
|
||||
return model;
|
||||
}
|
||||
|
||||
function saveCurrent() {
|
||||
if (editor) {
|
||||
const currentName = currentFileElement.textContent;
|
||||
@@ -90,10 +144,17 @@ function switchTo(scriptName) {
|
||||
switching = true;
|
||||
currentFileElement.textContent = scriptName;
|
||||
setScript('currentName', scriptName);
|
||||
const code =
|
||||
exampleFunctions.get(scriptName) ?? getScript(scriptName) ?? '';
|
||||
isExample = exampleFunctions.get(scriptName) != null;
|
||||
editor.setValue(code);
|
||||
const code = isExample ? exampleFunctions.get(scriptName) :
|
||||
getScript(scriptName) ?? '';
|
||||
window.location.hash = '#' + scriptName;
|
||||
const model = getModelForScript(scriptName);
|
||||
editor.setModel(model);
|
||||
|
||||
// Either editor.setValue() or model.setValue() will trigger
|
||||
// onDidChangeModelContent. This will cause some UI updates, but will also
|
||||
// get monaco-editor-auto-typings to update types.
|
||||
model.setValue(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +207,7 @@ function addEdit(button) {
|
||||
const code = getScript(oldName);
|
||||
const form = document.createElement('form');
|
||||
const inputElement = document.createElement('input');
|
||||
inputElement.classList.add('name');
|
||||
inputElement.value = oldName;
|
||||
label.textContent = '';
|
||||
button.appendChild(form);
|
||||
@@ -203,16 +265,16 @@ function addEdit(button) {
|
||||
}
|
||||
|
||||
const newButton = document.querySelector('#new');
|
||||
function newItem(code) {
|
||||
const name = uniqueName('New Script');
|
||||
function newItem(code, scriptName = undefined) {
|
||||
const name = uniqueName(scriptName ?? 'New Script');
|
||||
setScript(name, code);
|
||||
const nextButton = createDropdownItem(name);
|
||||
newButton.insertAdjacentElement('afterend', nextButton.parentElement);
|
||||
addEdit(nextButton);
|
||||
nextButton.click();
|
||||
return {button: nextButton, name};
|
||||
};
|
||||
newButton.onclick = function() {
|
||||
newItem('');
|
||||
newItem('').button.click();
|
||||
};
|
||||
|
||||
const runButton = document.querySelector('#compile');
|
||||
@@ -225,58 +287,61 @@ function initializeRun() {
|
||||
if (autoExecute) {
|
||||
runButton.click();
|
||||
} else {
|
||||
poster.textContent = 'Auto-run disabled due to prior failure';
|
||||
poster.textContent = 'Auto-run disabled';
|
||||
}
|
||||
}
|
||||
|
||||
// Editor ------------------------------------------------------------
|
||||
let tsWorker = undefined;
|
||||
|
||||
async function getManifoldDTS() {
|
||||
const global = await fetch('/manifold-global-types.d.ts')
|
||||
.then(response => response.text());
|
||||
async function createEditor() {
|
||||
self.MonacoEnvironment = {
|
||||
getWorker: (_, label) => {
|
||||
if (label === 'typescript' || label === 'javascript') {
|
||||
return new tsWorker();
|
||||
} else {
|
||||
return new editorWorker();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const encapsulated = await fetch('/manifold-encapsulated-types.d.ts')
|
||||
.then(response => response.text());
|
||||
editor = monaco.editor.create(document.getElementById('editor'), {
|
||||
language: 'typescript',
|
||||
automaticLayout: true,
|
||||
});
|
||||
|
||||
return `
|
||||
${global.replaceAll('export', '')}
|
||||
${encapsulated.replace(/^import.*$/gm, '').replaceAll('export', 'declare')}
|
||||
declare interface ManifoldToplevel {
|
||||
CrossSection: typeof T.CrossSection;
|
||||
Manifold: typeof T.Manifold;
|
||||
Mesh: typeof T.Mesh;
|
||||
triangulate: typeof T.triangulate;
|
||||
setMinCircularAngle: typeof T.setMinCircularAngle;
|
||||
setMinCircularEdgeLength: typeof T.setMinCircularEdgeLength;
|
||||
setCircularSegments: typeof T.setCircularSegments;
|
||||
getCircularSegments: typeof T.getCircularSegments;
|
||||
setup: () => void;
|
||||
}
|
||||
declare const module: ManifoldToplevel;
|
||||
`;
|
||||
}
|
||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
||||
module: monaco.languages.typescript.ScriptTarget.ESNext,
|
||||
moduleResolution: monaco.languages.typescript.ScriptTarget.NodeNext,
|
||||
allowNonTsExtensions: true,
|
||||
});
|
||||
|
||||
async function getEditorDTS() {
|
||||
const global = await fetch('/editor.d.ts').then(response => response.text());
|
||||
return `${global.replace(/^import.*$/gm, '')}`;
|
||||
}
|
||||
|
||||
require.config({
|
||||
paths:
|
||||
{vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs'}
|
||||
});
|
||||
require(['vs/editor/editor.main'], async function() {
|
||||
// Make sure `manifold-3d/manifoldCAD` types are available for import.
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
await getManifoldDTS());
|
||||
await (await fetch('/manifoldCAD.d.ts')).text(),
|
||||
'inmemory://model/node_modules/manifold-3d/manifoldCAD.d.ts');
|
||||
|
||||
// Types in the global namespace for top-level scripts.
|
||||
// This could be improved in the future. API-Extractor intentionally doesn't
|
||||
// global variables, so another tool may be a better fit.
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
await getEditorDTS());
|
||||
editor = monaco.editor.create(
|
||||
document.getElementById('editor'),
|
||||
{language: 'typescript', automaticLayout: true});
|
||||
const w = await monaco.languages.typescript.getTypeScriptWorker();
|
||||
tsWorker = await w(editor.getModel().uri);
|
||||
editor.getModel().updateOptions({tabSize: 2});
|
||||
(await (await fetch('/manifoldCADGlobals.d.ts')).text())
|
||||
.replace(/^export /gm, ''));
|
||||
|
||||
// Load up all scripts so that monaco can check types of multi-file models.
|
||||
for (const [filename, content] of Object.entries(getAllScripts())) {
|
||||
getModelForScript(filename).setValue(content);
|
||||
}
|
||||
|
||||
// Initialize auto typing on monaco editor.
|
||||
self.window.typecache = new LocalStorageCache();
|
||||
const autoTypings = await AutoTypings.create(editor, {
|
||||
sourceCache: self.window.typecache,
|
||||
onError: e => {console.error(e)},
|
||||
onUpdate: (update, text) => {console.debug(text)},
|
||||
onUpdateVersions: (versions) => {
|
||||
console.debug(versions)
|
||||
}
|
||||
});
|
||||
|
||||
for (const [name] of exampleFunctions) {
|
||||
const button = createDropdownItem(name);
|
||||
@@ -298,30 +363,109 @@ require(['vs/editor/editor.main'], async function() {
|
||||
addEdit(button);
|
||||
}
|
||||
}
|
||||
switchTo(currentName);
|
||||
|
||||
if (window.location.hash.length > 0) {
|
||||
const fragment = decodeURIComponent(window.location.hash.substring(1));
|
||||
const codeIdx = fragment.indexOf(CODE_START);
|
||||
if (codeIdx != -1) {
|
||||
autoExecute = true;
|
||||
const name = fragment.substring(0, codeIdx);
|
||||
switchTo(
|
||||
newItem(fragment.substring(codeIdx + CODE_START.length), name).name);
|
||||
} else {
|
||||
if (fragment != currentName) {
|
||||
autoExecute = true;
|
||||
}
|
||||
switchTo(fragment);
|
||||
}
|
||||
} else {
|
||||
switchTo(currentName);
|
||||
}
|
||||
|
||||
if (manifoldInitialized) {
|
||||
initializeRun();
|
||||
}
|
||||
|
||||
editor.onDidChangeModelContent(e => {
|
||||
runButton.disabled = false;
|
||||
// The user switched models.
|
||||
if (switching) {
|
||||
switching = false;
|
||||
editor.setScrollTop(0);
|
||||
runButton.disabled = false;
|
||||
return;
|
||||
}
|
||||
if (isExample) {
|
||||
|
||||
// The user edited an example.
|
||||
// Copy it into a new script.
|
||||
if (isExample && exampleFunctions.get(currentName) != editor.getValue()) {
|
||||
const cursor = editor.getPosition();
|
||||
newItem(editor.getValue());
|
||||
newItem(editor.getValue()).button.click();
|
||||
editor.setPosition(cursor);
|
||||
runButton.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// monaco-editor-auto-typings loaded types. Do nothing.
|
||||
if (autoTypings.isResolving && e.changes.isFlush) {
|
||||
return;
|
||||
}
|
||||
|
||||
// And if we're here, the user made an edit.
|
||||
runButton.disabled = false;
|
||||
});
|
||||
|
||||
window.onresize = () => {
|
||||
editor.layout({});
|
||||
};
|
||||
};
|
||||
|
||||
createEditor();
|
||||
|
||||
// Animation ------------------------------------------------------------
|
||||
const mv = document.querySelector('model-viewer');
|
||||
const animationContainer = document.querySelector('#animation');
|
||||
const playButton = document.querySelector('#play');
|
||||
const scrubber = document.querySelector('#scrubber');
|
||||
let paused = false;
|
||||
|
||||
mv.addEventListener('load', () => {
|
||||
const hasAnimation = mv.availableAnimations.length > 0;
|
||||
animationContainer.style.display = hasAnimation ? 'flex' : 'none';
|
||||
if (hasAnimation) {
|
||||
play();
|
||||
}
|
||||
});
|
||||
|
||||
function play() {
|
||||
mv.play();
|
||||
playButton.classList.remove('play');
|
||||
playButton.classList.add('pause');
|
||||
paused = false;
|
||||
scrubber.classList.add('hide');
|
||||
}
|
||||
|
||||
function pause() {
|
||||
mv.pause();
|
||||
playButton.classList.remove('pause');
|
||||
playButton.classList.add('play');
|
||||
paused = true;
|
||||
scrubber.max = mv.duration;
|
||||
scrubber.value = mv.currentTime;
|
||||
scrubber.classList.remove('hide');
|
||||
}
|
||||
|
||||
playButton.onclick = function() {
|
||||
if (paused) {
|
||||
play();
|
||||
} else {
|
||||
pause();
|
||||
}
|
||||
};
|
||||
|
||||
scrubber.oninput = function() {
|
||||
mv.currentTime = scrubber.value;
|
||||
};
|
||||
|
||||
// Execution ------------------------------------------------------------
|
||||
const consoleElement = document.querySelector('#console');
|
||||
const oldLog = console.log;
|
||||
@@ -345,19 +489,13 @@ function disableCancel() {
|
||||
runButton.classList.remove('red', 'cancel');
|
||||
}
|
||||
|
||||
let t0 = performance.now();
|
||||
|
||||
function finishRun() {
|
||||
disableCancel();
|
||||
const t1 = performance.now();
|
||||
const log = consoleElement.textContent;
|
||||
// Remove "Running..."
|
||||
consoleElement.textContent = log.substring(log.indexOf('\n') + 1);
|
||||
console.log(
|
||||
`Took ${(Math.round((t1 - t0) / 10) / 100).toLocaleString()} seconds`);
|
||||
}
|
||||
|
||||
const mv = document.querySelector('model-viewer');
|
||||
const output = {
|
||||
glbURL: null,
|
||||
threeMFURL: null
|
||||
@@ -366,41 +504,70 @@ let manifoldWorker = null;
|
||||
|
||||
function createWorker() {
|
||||
manifoldWorker = new ManifoldWorker();
|
||||
manifoldWorker.onmessage = function(e) {
|
||||
if (e.data == null) {
|
||||
|
||||
manifoldWorker.onmessage = (e) => {
|
||||
const message = e.data;
|
||||
|
||||
if (message?.type === 'ready') {
|
||||
if (tsWorker != null && !manifoldInitialized) {
|
||||
initializeRun();
|
||||
}
|
||||
manifoldInitialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.log != null) {
|
||||
consoleElement.textContent += e.data.log + '\r\n';
|
||||
} else if (message?.type === 'error') {
|
||||
// Clean up.
|
||||
setScript('safe', 'false');
|
||||
finishRun();
|
||||
|
||||
// Show errors. If the stack trace makes more sense, show that.
|
||||
const errorText = `${message.name}: ${message.message}`;
|
||||
if (message.stack && message.stack.startsWith(errorText)) {
|
||||
consoleElement.textContent += message.stack + '\r\n';
|
||||
} else {
|
||||
consoleElement.textContent += errorText + '\r\n';
|
||||
}
|
||||
consoleElement.scrollTop = consoleElement.scrollHeight;
|
||||
return;
|
||||
}
|
||||
|
||||
finishRun();
|
||||
runButton.disabled = true;
|
||||
|
||||
if (output.threeMFURL != null) {
|
||||
URL.revokeObjectURL(output.threeMFURL);
|
||||
output.threeMFURL = null;
|
||||
}
|
||||
URL.revokeObjectURL(output.glbURL);
|
||||
output.glbURL = e.data.glbURL;
|
||||
output.threeMFURL = e.data.threeMFURL;
|
||||
threemfButton.disabled = output.threeMFURL == null;
|
||||
mv.src = output.glbURL;
|
||||
if (output.glbURL == null) {
|
||||
mv.showPoster();
|
||||
poster.textContent = 'Error';
|
||||
|
||||
// Clear models.
|
||||
if (output.glbURL) URL.revokeObjectURL(output.glbURL);
|
||||
if (output.threeMFURL) URL.revokeObjectURL(output.threeMFURL);
|
||||
output.glbURL = null;
|
||||
output.threeMFURL = null;
|
||||
threemfButton.disabled = true;
|
||||
|
||||
// Start all over again.
|
||||
createWorker();
|
||||
} else {
|
||||
|
||||
} else if (message?.type === 'log') {
|
||||
consoleElement.textContent += message.message + '\r\n';
|
||||
consoleElement.scrollTop = consoleElement.scrollHeight;
|
||||
|
||||
} else if (message?.type === 'done') {
|
||||
setScript('safe', 'true');
|
||||
manifoldWorker.postMessage({type: 'export', extension: 'glb'});
|
||||
manifoldWorker.postMessage({type: 'export', extension: '3mf'});
|
||||
|
||||
finishRun();
|
||||
runButton.disabled = true;
|
||||
|
||||
} else if (message?.type === 'blob') {
|
||||
if (message.extension === 'glb') {
|
||||
if (output.glbURL) URL.revokeObjectURL(output.glbURL);
|
||||
output.glbURL = message.blobURL;
|
||||
|
||||
mv.src = output.glbURL;
|
||||
} else if (message?.extension === '3mf') {
|
||||
if (output.threeMFURL) URL.revokeObjectURL(output.threeMFURL);
|
||||
output.threeMFURL = message.blobURL;
|
||||
threemfButton.disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
manifoldWorker.postMessage(
|
||||
{type: 'initialize', esbuildWasmUrl, manifoldWasmUrl});
|
||||
}
|
||||
|
||||
createWorker();
|
||||
@@ -411,9 +578,20 @@ async function run() {
|
||||
enableCancel();
|
||||
clearConsole();
|
||||
console.log('Running...');
|
||||
const output = await tsWorker.getEmitOutput(editor.getModel().uri.toString());
|
||||
manifoldWorker.postMessage(output.outputFiles[0].text);
|
||||
t0 = performance.now();
|
||||
const files = {};
|
||||
for (const [filename, contents] of Object.entries(getAllScripts())) {
|
||||
files[`./${filename}`] = contents;
|
||||
}
|
||||
const filename = currentFileElement.textContent;
|
||||
const code = editor.getValue();
|
||||
manifoldWorker.postMessage({
|
||||
type: 'evaluate',
|
||||
code,
|
||||
filename,
|
||||
files,
|
||||
jsCDN: 'jsDelivr',
|
||||
baseUrl: window.location.href
|
||||
});
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
@@ -33,13 +33,20 @@
|
||||
self.ModelViewerElement = self.ModelViewerElement || {};
|
||||
self.ModelViewerElement.modelCacheSize = 0;
|
||||
</script>
|
||||
<script type="module" src="/examples.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page">
|
||||
<div class="container header" style="background-color: #A288B3;">
|
||||
<p style="flex: 2;"><a target="_blank" href="https://github.com/elalish/manifold">Manifold</a>CAD </p>
|
||||
<p style="flex: 2;"><a target="_blank" href="https://github.com/elalish/manifold">Manifold</a>CAD
|
||||
<span class="top-edit blue">
|
||||
<button type="button" id="undo" class="top-icon undo squish"></button>
|
||||
<button type="button" id="redo" class="top-icon redo squish"></button>
|
||||
<button type="button" id="format" class="top-icon star squish"></button>
|
||||
<button type="button" id="share" class="top-icon share squish"></button>
|
||||
<a target="_blank" href="https://manifoldcad.org/docs/jsuser/" class="top-icon docs"></a>
|
||||
</span>
|
||||
</p>
|
||||
<div class="margin" id="file-margin">
|
||||
<button type="button" id="file" class="blue item"><b class="uparrow"></b> <span
|
||||
id="current">Intro</span></button>
|
||||
@@ -66,24 +73,23 @@
|
||||
<div id="editor" class="col"></div>
|
||||
<div class="col container" style="flex-direction: column;">
|
||||
<model-viewer camera-controls min-camera-orbit="auto 0deg auto" max-camera-orbit="auto 180deg auto"
|
||||
shadow-intensity="1" interaction-prompt="none" alt="Editor 3D output">
|
||||
shadow-intensity="1" tone-mapping="neutral" interaction-prompt="none" alt="Editor 3D output">
|
||||
<div class="center" slot="poster">
|
||||
<p id="poster" style="text-align: center; line-height: 36px;"> Loading... </p>
|
||||
</div>
|
||||
<div id="animation">
|
||||
<button type="button" id="play" class="icon pause"></button>
|
||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slider" id="scrubber">
|
||||
</div>
|
||||
</model-viewer>
|
||||
<div id="console"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/loader.min.js"
|
||||
integrity="sha512-6bIYsGqvLpAiEBXPdRQeFf5cueeBECtAKJjIHer3BhBZNTV3WLcLA8Tm3pDfxUwTMIS+kAZwTUvJ1IrMdX8C5w=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/editor/editor.main.min.css"
|
||||
integrity="sha512-iQEIc0rsSDujsfjtD+lfyJ1W23Bh/lbgriubKDAym6VlEIDRj9rrbSIyJRyshOrl8s0yRcQ0+gyrZfSLyjJGWQ=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer">
|
||||
<script type="module">
|
||||
import { ModelViewerElement } from '@google/model-viewer';
|
||||
</script>
|
||||
<script type="module" src="editor-examples.js"></script>
|
||||
<script type="module" src="editor.js"></script>
|
||||
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.3.0/model-viewer.min.js"></script>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "manifold-editor",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"build:watch": "vite build --watch",
|
||||
"clean": "rm -fr ./dist",
|
||||
"preview": "vite preview",
|
||||
"public": "cp -rv dist/* ../../public/"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"esbuild-wasm": "^0.27.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
||||
"@google/model-viewer": "^4.1.0",
|
||||
"manifold-3d": "file:../..",
|
||||
"monaco-editor": "^0.54.0",
|
||||
"monaco-editor-auto-typings": "^0.4.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.0.9",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "7.3.1",
|
||||
"vite-plugin-static-copy": "^3.1.5"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 539 B After Width: | Height: | Size: 539 B |
|
After Width: | Height: | Size: 330 B |
|
Before Width: | Height: | Size: 704 KiB After Width: | Height: | Size: 704 KiB |
|
Before Width: | Height: | Size: 952 KiB After Width: | Height: | Size: 952 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 240 B |
|
Before Width: | Height: | Size: 375 B After Width: | Height: | Size: 375 B |
|
After Width: | Height: | Size: 326 B |
|
After Width: | Height: | Size: 492 B |
|
After Width: | Height: | Size: 619 B |
|
After Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 471 B |
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Redirecting to the ManifoldCAD User Guide</title>
|
||||
<link rel="canonical" href="/docs/jsuser/">
|
||||
<meta http-equiv="refresh" content="0; URL=/docs/jsuser/">
|
||||
</head>
|
||||
<body><a href="/docs/jsuser/">Click here if you are not redirected automatically.</a></body>
|
||||
</html>
|
||||
@@ -0,0 +1,58 @@
|
||||
// vite.config.js
|
||||
import {resolve} from 'path'
|
||||
import {defineConfig} from 'vite'
|
||||
import {viteStaticCopy} from 'vite-plugin-static-copy'
|
||||
|
||||
export default defineConfig({
|
||||
worker: {format: 'es'},
|
||||
server: {
|
||||
// `npm run dev`
|
||||
headers: {
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
},
|
||||
fs: {allow: [resolve(__dirname, '..')]}
|
||||
},
|
||||
preview: {
|
||||
// `npm run preview`
|
||||
headers: {
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
},
|
||||
},
|
||||
plugins: [viteStaticCopy({
|
||||
targets: [
|
||||
// If type declaration files are missing, the web editor can't
|
||||
// load them, and type validation won't work for our core modules.
|
||||
{
|
||||
src: './node_modules/manifold-3d/dist/manifoldCAD.d.ts',
|
||||
dest: './', // Targets are relative to 'dist'.
|
||||
},
|
||||
{
|
||||
src: './node_modules/manifold-3d/dist/manifoldCADGlobals.d.ts',
|
||||
dest: './',
|
||||
}
|
||||
],
|
||||
})],
|
||||
resolve: {
|
||||
alias: {
|
||||
path: resolve(
|
||||
__dirname,
|
||||
'./node_modules/rollup-plugin-node-polyfills/polyfills/path.js')
|
||||
}
|
||||
},
|
||||
build: {
|
||||
target: 'esnext',
|
||||
sourcemap: 'hidden',
|
||||
rollupOptions: {
|
||||
input: {
|
||||
manifoldCAD: resolve(__dirname, 'index.html'),
|
||||
},
|
||||
output: {
|
||||
entryFileNames: `assets/[name].js`,
|
||||
chunkFileNames: `assets/[name].js`,
|
||||
assetFileNames: `assets/[name].[ext]`
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||