From 0fa6f8fcdd63b4b49d10e5e1cea295dde880dbae Mon Sep 17 00:00:00 2001 From: Emmett Lalish Date: Tue, 9 May 2023 12:35:01 -0700 Subject: [PATCH 1/7] make-manifold working --- bindings/wasm/examples/gltf-io.js | 107 ++++++++----- bindings/wasm/examples/make-manifold.html | 140 ++++++++++++++++++ .../wasm/manifold-encapsulated-types.d.ts | 1 + 3 files changed, 212 insertions(+), 36 deletions(-) create mode 100644 bindings/wasm/examples/make-manifold.html diff --git a/bindings/wasm/examples/gltf-io.js b/bindings/wasm/examples/gltf-io.js index faed21c33..6d936a56d 100644 --- a/bindings/wasm/examples/gltf-io.js +++ b/bindings/wasm/examples/gltf-io.js @@ -32,23 +32,17 @@ export function setupIO(io) { return io.registerExtensions([EXTManifold]); } -export function readMesh(mesh, attributes, materials) { - if (attributes.length < 1 || attributes[0] !== 'POSITION') - throw new Error('First attribute must be "POSITION".'); - - const primitives = mesh.listPrimitives(); - if (primitives.length === 0) { - return {}; - } - - const numProp = attributes.map((def) => attributeDefs[def].components) - .reduce((a, b) => a + b); - const position = primitives[0].getAttribute('POSITION'); - const numVert = position.getCount() - const vertProperties = new Float32Array(numProp * numVert); +function readPrimitive(primitive, numProp, attributes) { + const position = primitive.getAttribute('POSITION'); + const numVert = position.getCount(); + const vertProperties = []; let offset = 0; for (const attribute of attributes) { - const accessor = primitives[0].getAttribute(attribute); + if (attribute === 'SKIP') { + offset += attributeDefs[attribute].components; + continue; + } + const accessor = primitive.getAttribute(attribute); const array = accessor.getArray(); const size = accessor.getElementSize(); for (let i = 0; i < numVert; ++i) { @@ -58,37 +52,78 @@ export function readMesh(mesh, attributes, materials) { } offset += size; } + return vertProperties; +} + +export function readMesh(mesh, attributes, materials) { + const primitives = mesh.listPrimitives(); + if (primitives.length === 0) { + return {}; + } + if (attributes.length === 0) { + const attributeSet = new Set(); + for (const primitive of primitives) { + const semantics = primitive.listSemantics(); + for (const semantic of semantics) { + attributeSet.add(semantic); + } + } + for (const semantic in attributeDefs) { + if (attributeSet.has(semantic)) { + attributes.push(semantic); + attributeSet.delete(semantic); + } + } + for (const semantic of attributeSet.keys()) { + attributes.push(semantic); + } + } + + if (attributes.length < 1 || attributes[0] !== 'POSITION') + throw new Error('First attribute must be "POSITION".'); + + const numProp = attributes.map((def) => attributeDefs[def].components) + .reduce((a, b) => a + b); + + const manifoldPrimitive = mesh.getExtension('EXT_manifold'); + + const vertPropArray = []; const triVertArray = []; - const runIndexArray = [0]; - for (const primitive of primitives) { - if (primitive.getAttribute('POSITION') === position) { + const runIndexArray = []; + const mergeFromVert = []; + const mergeToVert = []; + if (manifoldPrimitive != null) { + runIndexArray.push(0); + vertPropArray.push(...readPrimitive(primitives[0], numProp, attributes)); + for (const primitive of primitives) { triVertArray.push(...primitive.getIndices().getArray()); runIndexArray.push(triVertArray.length); materials.push(primitive.getMaterial()); - } else { - console.log('primitives do not share accessors!'); + } + const mergeTriVert = manifoldPrimitive.getMergeIndices()?.getArray() ?? []; + const mergeTo = manifoldPrimitive.getMergeValues()?.getArray() ?? []; + const vert2merge = new Map(); + for (const [i, idx] of mergeTriVert.entries()) { + vert2merge.set(triVertArray[idx], mergeTo[i]); + } + for (const [from, to] of vert2merge.entries()) { + mergeFromVert.push(from); + mergeToVert.push(to); + } + } else { + for (const primitive of primitives) { + const numVert = vertPropArray.length / numProp; + vertPropArray.push(...readPrimitive(primitive, numProp, attributes)); + triVertArray.push( + ...primitive.getIndices().getArray().map((i) => i + numVert)); + materials.push(primitive.getMaterial()); } } + const vertProperties = new Float32Array(vertPropArray); const triVerts = new Uint32Array(triVertArray); const runIndex = new Uint32Array(runIndexArray); - const manifoldPrimitive = mesh.getExtension('EXT_manifold'); - const mergeTriVert = - manifoldPrimitive ? manifoldPrimitive.getMergeIndices().getArray() : []; - const mergeTo = - manifoldPrimitive ? manifoldPrimitive.getMergeValues().getArray() : []; - const vert2merge = new Map(); - for (const [i, idx] of mergeTriVert.entries()) { - vert2merge.set(triVerts[idx], mergeTo[i]); - } - const mergeFromVert = []; - const mergeToVert = []; - for (const [from, to] of vert2merge.entries()) { - mergeFromVert.push(from); - mergeToVert.push(to); - } - return { numProp, triVerts, diff --git a/bindings/wasm/examples/make-manifold.html b/bindings/wasm/examples/make-manifold.html new file mode 100644 index 000000000..e382ff090 --- /dev/null +++ b/bindings/wasm/examples/make-manifold.html @@ -0,0 +1,140 @@ + + + + + Make manifold glTF + + + + + + + +

Load a glTF/GLB model and our Manifold library will attempt to + merge it into a set of manifold objects. You can download the new GLB which will have our EXT_manifold extension, thus preserving the manifold + data without losing any mesh properties.

+ + + + Drop a GLB here + + + + + + + \ No newline at end of file diff --git a/bindings/wasm/manifold-encapsulated-types.d.ts b/bindings/wasm/manifold-encapsulated-types.d.ts index 351c20f27..b4afd92b8 100644 --- a/bindings/wasm/manifold-encapsulated-types.d.ts +++ b/bindings/wasm/manifold-encapsulated-types.d.ts @@ -435,6 +435,7 @@ export class Mesh { get numTri(): number; get numVert(): number; get numRun(): number; + merge(): boolean; verts(tri: number): SealedUint32Array<3>; position(vert: number): SealedFloat32Array<3>; extras(vert: number): Float32Array; From d1b0e27406e28fb2938cda5db26f70922942e52b Mon Sep 17 00:00:00 2001 From: Emmett Lalish Date: Tue, 9 May 2023 13:00:26 -0700 Subject: [PATCH 2/7] prettier --- bindings/wasm/examples/make-manifold.html | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/bindings/wasm/examples/make-manifold.html b/bindings/wasm/examples/make-manifold.html index e382ff090..52e326461 100644 --- a/bindings/wasm/examples/make-manifold.html +++ b/bindings/wasm/examples/make-manifold.html @@ -8,7 +8,6 @@ @@ -41,15 +49,16 @@ data without losing any mesh properties.

- - Drop a GLB here + + Drop a GLB here @@ -57,11 +66,13 @@