Skip to content

Commit

Permalink
Make runIndex easier to use (#806)
Browse files Browse the repository at this point in the history
* handled unsorted groups

* forgot types
  • Loading branch information
elalish authored May 10, 2024
1 parent 443863d commit 887f631
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 113 deletions.
194 changes: 98 additions & 96 deletions bindings/wasm/examples/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bindings/wasm/examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
"@gltf-transform/extensions": "^3.8.0",
"@gltf-transform/functions": "^3.8.0",
"@jscadui/3mf-export": "^0.5.0",
"@types/three": "^0.164.0",
"fflate": "^0.8.0",
"gl-matrix": "^3.4.3",
"simple-dropzone": "0.8.3",
"three": "0.158.0"
"three": "0.164.1"
},
"devDependencies": {
"@vitest/ui": "^0.31.1",
"@vitest/web-worker": "^0.31.1",
"@types/three": "^0.164.0",
"typescript": "5.2.2",
"vite": "^4.5.0",
"vitest": "^0.31.1"
Expand Down
24 changes: 14 additions & 10 deletions bindings/wasm/examples/three.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ cube.addGroup(18, Infinity, 1); // Rest of faces are red

const icosahedron = new IcosahedronGeometry(0.16);
icosahedron.clearGroups();
icosahedron.addGroup(30, Infinity, 2); // Last faces are blue
icosahedron.addGroup(0, 30, 0); // First 10 faces colored by normal
icosahedron.addGroup(30, Infinity, 2); // Rest of faces are blue
// The above groups are in reversed order to demonstrate the need for sorting.

// Convert Three.js input meshes to Manifolds
const manifoldCube = new Manifold(geometry2mesh(cube));
Expand Down Expand Up @@ -95,15 +96,18 @@ function geometry2mesh(geometry: BufferGeometry) {
const triVerts = geometry.index != null ?
geometry.index.array as Uint32Array :
new Uint32Array(vertProperties.length / 3).map((_, idx) => idx);
// Create a triangle run for each group (material).
const runIndex =
new Uint32Array(geometry.groups.length + 1)
.map((_, idx) => geometry.groups[idx]?.start ?? triVerts.length);
// Map the materials to ID
const runOriginalID =
new Uint32Array(geometry.groups.length)
.map((_, idx) => ids[geometry.groups[idx].materialIndex!]);

// Create a triangle run for each group (material) - akin to a draw call.
const starts = [...Array(geometry.groups.length)].map(
(_, idx) => geometry.groups[idx].start);
// Map the materials to ID.
const originalIDs = [...Array(geometry.groups.length)].map(
(_, idx) => ids[geometry.groups[idx].materialIndex!]);
// List the runs in sequence.
const indices = Array.from(starts.keys())
indices.sort((a, b) => starts[a] - starts[b])
const runIndex = new Uint32Array(indices.map(i => starts[i]));
const runOriginalID = new Uint32Array(indices.map(i => originalIDs[i]));
// Create the MeshGL for I/O with Manifold library.
const mesh =
new Mesh({numProp: 3, vertProperties, triVerts, runIndex, runOriginalID});
// Automatically merge vertices with nearly identical positions to create a
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/examples/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"target": "es2022",
"module": "es2022",
"moduleResolution": "node",
"moduleResolution": "Bundler",
"lib": [
"es2022",
"dom"
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/examples/worker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import '@vitest/web-worker';
import {WebIO} from '@gltf-transform/core';
import {expect, suite, test} from 'vitest';

import Module from './built/manifold.js';
import Module from './built/manifold';
import {readMesh, setupIO} from './gltf-io';
import {examples} from './public/examples.js';
import ManifoldWorker from './worker?worker';
Expand Down
5 changes: 4 additions & 1 deletion src/manifold/include/manifold.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ struct MeshGL {
/// Optional: Indicates runs of triangles that correspond to a particular
/// input mesh instance. The runs encompass all of triVerts and are sorted
/// by runOriginalID. Run i begins at triVerts[runIndex[i]] and ends at
/// triVerts[runIndex[i+1]]. All runIndex values are divisible by 3.
/// triVerts[runIndex[i+1]]. All runIndex values are divisible by 3. Returned
/// runIndex will always be 1 longer than runOriginalID, but same length is
/// also allowed as input: triVerts.size() will be automatically appended in
/// this case.
std::vector<uint32_t> runIndex;
/// Optional: The OriginalID of the mesh this triangle run came from. This ID
/// is ideal for reapplying materials to the output mesh. Multiple runs may
Expand Down
8 changes: 6 additions & 2 deletions src/manifold/src/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ Manifold::Impl::Impl(const MeshGL& meshGL,
}

if (!meshGL.runOriginalID.empty() && !meshGL.runIndex.empty() &&
meshGL.runOriginalID.size() + 1 != meshGL.runIndex.size()) {
meshGL.runOriginalID.size() + 1 != meshGL.runIndex.size() &&
meshGL.runOriginalID.size() != meshGL.runIndex.size()) {
MarkFailure(Error::RunIndexWrongLength);
return;
}
Expand Down Expand Up @@ -443,8 +444,11 @@ Manifold::Impl::Impl(const MeshGL& meshGL,
relation.originalID = Impl::ReserveIDs(1);
} else {
std::vector<uint32_t> runIndex = meshGL.runIndex;
const uint32_t runEnd = meshGL.triVerts.size();
if (runIndex.empty()) {
runIndex = {0, 3 * meshGL.NumTri()};
runIndex = {0, runEnd};
} else if (runIndex.size() == meshGL.runOriginalID.size()) {
runIndex.push_back(runEnd);
}
relation.triRef.resize(meshGL.NumTri());
const int startID = Impl::ReserveIDs(meshGL.runOriginalID.size());
Expand Down

0 comments on commit 887f631

Please sign in to comment.