Skip to content

Commit

Permalink
EXT_manifold for glTF (elalish#420)
Browse files Browse the repository at this point in the history
* extension export works

* reading GLBs

* trying to merge documents

* add await

* removed extra materials

* added builds

* several fixes

* fix versions

* move to built

* fixed test.js

* updated README

* disable nix JS test for now

* fix codecov timeout

* fix test
  • Loading branch information
elalish committed May 5, 2023
1 parent aa05560 commit 0fe257c
Show file tree
Hide file tree
Showing 22 changed files with 1,125 additions and 197 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
workflow_conclusion: completed
pr: ${{github.event.pull_request.number}}
name: wasm
path: ./public
path: ./public/built

- name: Deploy to Github Pages
uses: peaceiris/actions-gh-pages@v3
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/manifold.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:

jobs:
build:
timeout-minutes: 30
timeout-minutes: 45
strategy:
matrix:
cuda_support: [ON, OFF]
Expand All @@ -32,13 +32,15 @@ jobs:
submodules: recursive
- uses: jwlawson/actions-setup-cmake@v1.12
- name: Build ${{matrix.backend}}
if: matrix.parallel_backend != 'NONE' || matrix.cuda_support != '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}} -DMANIFOLD_USE_CUDA=${{matrix.cuda_support}} .. && make
- name: Test ${{matrix.parallel_backend}} with CUDA ${{matrix.cuda_support}}
# note that the test for CUDA backend does not really test CUDA, as we
# don't have CUDA GPU on GitHub Action
if: matrix.parallel_backend != 'NONE' || matrix.cuda_support != 'OFF'
run: |
export PYTHONPATH=$PYTHONPATH:$(pwd)/build/bindings/python
cd build/test
Expand All @@ -51,6 +53,7 @@ jobs:
# perhaps issue related to invalid memory access?
if: matrix.parallel_backend == 'NONE' && matrix.cuda_support == 'OFF'
run: |
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DMANIFOLD_PAR=${{matrix.parallel_backend}} -DMANIFOLD_USE_CUDA=${{matrix.cuda_support}} -DCODE_COVERAGE=ON .. && make
lcov --capture --initial --directory . --output-file ./code_coverage_init.info
Expand Down Expand Up @@ -219,7 +222,7 @@ jobs:
timeout-minutes: 30
strategy:
matrix:
variant: [none, omp, tbb, none-cuda, omp-cuda, tbb-cuda, js]
variant: [none, omp, tbb, none-cuda, omp-cuda, tbb-cuda]
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/manifold.*
${CMAKE_CURRENT_BINARY_DIR}/manifold-*.d.ts
${CMAKE_CURRENT_BINARY_DIR}/examples/)
${CMAKE_CURRENT_SOURCE_DIR}/examples/built/)
19 changes: 18 additions & 1 deletion bindings/wasm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,24 @@ The most significant contribution here is a guaranteed-manifold [mesh Boolean](h

## Note on memory management

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 https://github.com/elalish/manifold/discussions/256#discussioncomment-3944287.
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).

## 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/`) you can test the JS bindings by running:

```
npm install
npm test
```

You can also test the manifoldCAD.org editor as well as our other example pages by serving from `bindings/wasm/examples/` with e.g. `npx http-server`.

Note that the `emcmake` command automatically copies your WASM build into `examples/built/` - these are checked into our repo in order to make sharing repro cases much easier. Note that you can test manifoldCAD.org on anyone's branch by simply going to: `https://raw.githack.com/<user>/manifold/<branch>/bindings/wasm/examples/index.html` e.g. https://raw.githack.com/elalish/manifold/glTFextension/bindings/wasm/examples/index.html

Of course these built files may easily end up with conflicts, but there's no need to address them; simply overwrite them with your newer build. These files are also not used for our deployed pages, as the deployment process overwrites them with current builds. Never edit anything in the `built` directory by hand.

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".

## About the author

Expand Down
18 changes: 16 additions & 2 deletions bindings/wasm/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ std::vector<SimplePolygon> ToPolygon(
return simplePolygons;
}

val GetMeshJS(const Manifold& manifold, const glm::ivec3& normalIdx) {
MeshGL mesh = manifold.GetMeshGL(normalIdx);
val MeshGL2JS(const MeshGL& mesh) {
val meshJS = val::object();

meshJS.set("numProp", mesh.numProp);
Expand Down Expand Up @@ -129,6 +128,20 @@ MeshGL MeshJS2GL(const val& mesh) {
return out;
}

val GetMeshJS(const Manifold& manifold, const glm::ivec3& normalIdx) {
MeshGL mesh = manifold.GetMeshGL(normalIdx);
return MeshGL2JS(mesh);
}

val Merge(const val& mesh) {
val out = val::object();
MeshGL meshGL = MeshJS2GL(mesh);
bool changed = meshGL.Merge();
out.set("changed", changed);
out.set("mesh", changed ? MeshGL2JS(meshGL) : mesh);
return out;
}

Manifold FromMeshJS(const val& mesh) { return Manifold(MeshJS2GL(mesh)); }

Manifold Smooth(const val& mesh,
Expand Down Expand Up @@ -270,6 +283,7 @@ EMSCRIPTEN_BINDINGS(whatever) {
function("_Triangulate", &Triangulate);
function("_Revolve", &Revolve);
function("_LevelSet", &LevelSetJs);
function("_Merge", &Merge);

function("_unionN", &UnionN);
function("_differenceN", &DifferenceN);
Expand Down
11 changes: 9 additions & 2 deletions bindings/wasm/bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ Module.setup = function() {
return this.runOriginalID.length;
}

merge() {
const {changed, mesh} = Module._Merge(this);
Object.assign(this, {...mesh});
return changed;
}

verts(tri) {
return this.triVerts.subarray(3 * tri, 3 * (tri + 1));
}
Expand Down Expand Up @@ -304,10 +310,11 @@ Module.setup = function() {

Module.triangulate = function(polygons, precision = -1) {
const polygonsVec = polygons2vec(polygons);
const result = fromVec(Module._Triangulate(polygonsVec, precision), (x) => [x[0], x[1], x[2]]);
const result = fromVec(
Module._Triangulate(polygonsVec, precision), (x) => [x[0], x[1], x[2]]);
disposePolygons(polygonsVec);
return result;
}
};

Module.revolve = function(polygons, circularSegments = 0) {
const polygonsVec = polygons2vec(polygons);
Expand Down
Loading

0 comments on commit 0fe257c

Please sign in to comment.