Skip to content

Commit

Permalink
Fix web examples (#254)
Browse files Browse the repository at this point in the history
* fixed three.js examples

* add link and fix spelling
  • Loading branch information
elalish authored Oct 21, 2022
1 parent 066aec0 commit 0fb4769
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 33 deletions.
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
[![codecov](https://codecov.io/github/elalish/manifold/branch/master/graph/badge.svg?token=IIA8G5HVS7)](https://codecov.io/github/elalish/manifold)

## [ManifoldCAD.org](https://manifoldcad.org)

If you like OpenSCAD / OpenJSCAD, you might also like ManifoldCAD - our own solid modelling web app. The operations are not GPU-accelerated, but it's still pretty fast and a good way to test out our Manifold library.

![A metallic Menger sponge](https://elalish.github.io/manifold/samples/models/mengerSponge3.webp "A metallic Menger sponge")

# Manifold
Expand All @@ -14,15 +18,15 @@ This is a modern C++ library that Github's CI verifies builds and runs on a vari

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.

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 alorithm 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.
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 CUDA, OMP 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 for CUDA, the code will still run without a GPU, falling back to the serial version of the algorithms. 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.

## Building

Only CMake and a C++ compiler 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.
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.

Build and test (Ubuntu or similar):
```
Expand All @@ -46,6 +50,13 @@ The build instructions used by our CI are in [manifold.yml](https://github.com/e

### WASM
To build the JS WASM library, first install NodeJS and set up emscripten:

(on Mac):
```
brew install nodejs
brew install emscripten
```
(on Linux):
```
sudo apt install nodejs
git clone https://github.com/emscripten-core/emsdk.git
Expand All @@ -57,11 +68,10 @@ source ./emsdk/emsdk_env.sh
Then build:
```
cd manifold
mkdir build
cd build
mkdir buildWASM
cd buildWASM
emcmake cmake -DCMAKE_BUILD_TYPE=Release .. && emmake make
cd build/test
node ./manifold_test.js
node test/manifold_test.js
```

### Python
Expand Down
14 changes: 7 additions & 7 deletions bindings/wasm/bindings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ declare class Manifold {
translate(v: Vec3): Manifold;

/**
* Applys an Euler angle rotation to the manifold, first about the X axis,
* Applies an Euler angle rotation to the manifold, first about the X axis,
* then Y, then Z, in degrees. We use degrees so that we can minimize rounding
* error, and elimiate it completely for any multiples of 90 degrees.
* Addtionally, more efficient code paths are used to update the manifold when
* error, and eliminate it completely for any multiples of 90 degrees.
* Additionally, more efficient code paths are used to update the manifold when
* the transforms only rotate by multiples of 90 degrees. This operation can
* be chained. Transforms are combined and applied lazily.
*
Expand Down Expand Up @@ -207,7 +207,7 @@ declare class Manifold {
getMesh(): Mesh;

/**
* Gets the relationship to the previous meshes, for the purpose of assinging
* Gets the relationship to the previous meshes, for the purpose of assigning
* properties like texture coordinates. The triBary vector is the same length
* as Mesh.triVerts: BaryRef.originalID indicates the source mesh and
* BaryRef.tri is that mesh's triangle index to which these barycentric
Expand All @@ -226,7 +226,7 @@ declare class Manifold {
/**
* If you copy a manifold, but you want this new copy to have new properties
* (e.g. a different UV mapping), you can reset its meshIDs to a new original,
* meaning it will now be referenced by its descendents instead of the meshes
* meaning it will now be referenced by its descendants instead of the meshes
* it was built from, allowing you to differentiate the copies when applying
* your properties to the final result.
*
Expand Down Expand Up @@ -328,7 +328,7 @@ declare function tetrahedron(): Manifold;
* @param crossSection A set of non-overlapping polygons to extrude.
* @param height Z-extent of extrusion.
* @param nDivisions Number of extra copies of the crossSection to insert into
* the shape vertically; especially useful in combnation with twistDegrees to
* the shape vertically; especially useful in combination with twistDegrees to
* avoid interpolation artifacts. Default is none.
* @param twistDegrees Amount to twist the top crossSection relative to the
* bottom, interpolated linearly for the divisions in between.
Expand Down Expand Up @@ -398,7 +398,7 @@ declare function levelSet(
* default on construction. If circularSegments is specified, it takes
* precedence. If it is zero, then instead the minimum is used of the segments
* calculated based on edge length and angle, rounded up to the nearest
* multiple of four. To get numbers not divisible by four, circularSegements
* multiple of four. To get numbers not divisible by four, circularSegments
* must be specified.
*/
///@{
Expand Down
4 changes: 2 additions & 2 deletions bindings/wasm/examples/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const exampleFunctions = {

Heart: function () {
// Smooth, complex manifolds can be created using the warp() function. This
// example recreates the Expoitable Heart by Emmett Lalish:
// example recreates the Exploitable Heart by Emmett Lalish:
// https://www.thingiverse.com/thing:6190

const func = (v) => {
Expand Down Expand Up @@ -181,7 +181,7 @@ const exampleFunctions = {
},

TorusKnot: function () {
// Creates a classic torus knot, defined as a string wrapping peroidically
// 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.
Expand Down
14 changes: 7 additions & 7 deletions bindings/wasm/examples/model-viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,20 @@
function mesh2geometry(mesh) {
const geometry = new THREE.BufferGeometry();

const numVert = mesh.vertPos.size();
const numVert = mesh.vertPos.length;
const vert = new Float32Array(3 * numVert);
for (let i = 0; i < numVert; i++) {
const v = mesh.vertPos.get(i);
const v = mesh.vertPos[i];
const idx = 3 * i;
vert[idx] = v.x;
vert[idx + 1] = v.y;
vert[idx + 2] = v.z;
vert[idx] = v[0];
vert[idx + 1] = v[1];
vert[idx + 2] = v[2];
}

const numTri = mesh.triVerts.size();
const numTri = mesh.triVerts.length;
const tri = new Uint32Array(3 * numTri);
for (let i = 0; i < numTri; i++) {
const v = mesh.triVerts.get(i);
const v = mesh.triVerts[i];
const idx = 3 * i;
tri[idx] = v[0];
tri[idx + 1] = v[1];
Expand Down
22 changes: 11 additions & 11 deletions bindings/wasm/examples/three.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,25 +122,25 @@
function mesh2geometry(mesh) {
const geometry = new THREE.BufferGeometry();

const numVert = mesh.vertPos.size();
const numVert = mesh.vertPos.length;
const vert = new Float32Array(3 * numVert);
const norm = new Float32Array(3 * numVert);
for (let i = 0; i < numVert; i++) {
const v = mesh.vertPos.get(i);
const n = mesh.vertNormal.get(i);
const v = mesh.vertPos[i];
const n = mesh.vertNormal[i];
const idx = 3 * i;
vert[idx] = v.x;
vert[idx + 1] = v.y;
vert[idx + 2] = v.z;
norm[idx] = n.x;
norm[idx + 1] = n.y;
norm[idx + 2] = n.z;
vert[idx] = v[0];
vert[idx + 1] = v[1];
vert[idx + 2] = v[2];
norm[idx] = n[0];
norm[idx + 1] = n[1];
norm[idx + 2] = n[2];
}

const numTri = mesh.triVerts.size();
const numTri = mesh.triVerts.length;
const tri = new Uint32Array(3 * numTri);
for (let i = 0; i < numTri; i++) {
const v = mesh.triVerts.get(i);
const v = mesh.triVerts[i];
const idx = 3 * i;
tri[idx] = v[0];
tri[idx + 1] = v[1];
Expand Down

0 comments on commit 0fb4769

Please sign in to comment.