117 lines
3.4 KiB
HTML
117 lines
3.4 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<title>Manifold - three.js Example</title>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="shortcut icon" type="image/png" href="https://elalish.github.io/manifold/samples/models/favicon.png" />
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
background-color: #f7f7f7;
|
|
font-family: 'Rubik', sans-serif;
|
|
font-size: 16px;
|
|
line-height: 24px;
|
|
color: rgba(0, 0, 0, .87);
|
|
font-weight: 400;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
p {
|
|
max-width: 700px;
|
|
margin: 1em;
|
|
text-align: left;
|
|
}
|
|
|
|
canvas {
|
|
display: block;
|
|
width: 100vw;
|
|
height: 100vw;
|
|
max-width: 600px;
|
|
max-height: 600px;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<p>This demonstrates the minimum code to connect Manifold to a three.js rendering. A slightly more complex example
|
|
involving GLTF export and <model-viewer> can be found <a href="model-viewer.html">here</a>. </p>
|
|
<select>
|
|
<option value="difference" selected>Difference</option>
|
|
<option value="intersection">Intersection</option>
|
|
<option value="union">Union</option>
|
|
</select><br />
|
|
<canvas id="output"></canvas>
|
|
</body>
|
|
<script type="module">
|
|
import * as THREE from 'three';
|
|
import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
|
|
import Module from './built/manifold.js';
|
|
|
|
const wasm = await Module();
|
|
wasm.setup();
|
|
|
|
const { Manifold, Mesh } = wasm;
|
|
|
|
// we have manifold module, let's do some three.js
|
|
const camera = new THREE.PerspectiveCamera(30, 1, 0.01, 10);
|
|
camera.position.z = 1;
|
|
|
|
const scene = new THREE.Scene();
|
|
const mesh = new THREE.Mesh(undefined, new THREE.MeshNormalMaterial({
|
|
flatShading: true
|
|
}));
|
|
scene.add(mesh);
|
|
|
|
const icosahedron = simplify(new THREE.IcosahedronGeometry(0.16));
|
|
|
|
const manifold_1 = Manifold.cube([0.2, 0.2, 0.2], true);
|
|
const manifold_2 = new Manifold(geometry2mesh(icosahedron));
|
|
|
|
const csg = function (operation) {
|
|
mesh.geometry?.dispose();
|
|
mesh.geometry = mesh2geometry(Manifold[operation](manifold_1, manifold_2).getMesh());
|
|
};
|
|
|
|
document.querySelector('select').onchange = function (event) {
|
|
csg(event.target.value);
|
|
};
|
|
|
|
csg('difference');
|
|
|
|
const output = document.querySelector("#output");
|
|
const renderer = new THREE.WebGLRenderer({ canvas: output, antialias: true });
|
|
const dim = output.getBoundingClientRect();
|
|
renderer.setSize(dim.width, dim.height);
|
|
renderer.setAnimationLoop(function (time) {
|
|
mesh.rotation.x = time / 2000;
|
|
mesh.rotation.y = time / 1000;
|
|
renderer.render(scene, camera);
|
|
});
|
|
|
|
// functions to convert between three.js and wasm
|
|
function geometry2mesh(geometry) {
|
|
const vertProperties = geometry.attributes.position.array;
|
|
const triVerts = geometry.index.array;
|
|
return new Mesh({ numProp: 3, vertProperties, triVerts });
|
|
}
|
|
|
|
function mesh2geometry(mesh) {
|
|
const geometry = new THREE.BufferGeometry();
|
|
geometry.setAttribute('position', new THREE.BufferAttribute(mesh.vertProperties, 3));
|
|
geometry.setIndex(new THREE.BufferAttribute(mesh.triVerts, 1));
|
|
return geometry;
|
|
}
|
|
|
|
// most of three.js geometries aren't manifolds, so...
|
|
function simplify(geometry) {
|
|
delete geometry.attributes.normal;
|
|
delete geometry.attributes.uv;
|
|
const simplified = mergeVertices(geometry);
|
|
simplified.computeVertexNormals();
|
|
return simplified;
|
|
}
|
|
</script>
|
|
|
|
</html> |