Skip to content

Commit

Permalink
updated tet puzzle example (#625)
Browse files Browse the repository at this point in the history
* updated tet puzzle example

* updated description
  • Loading branch information
elalish authored Nov 20, 2023
1 parent e273f6b commit 6e1629d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 17 deletions.
39 changes: 24 additions & 15 deletions bindings/wasm/examples/public/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ export const examples = {

TetrahedronPuzzle: function() {
// A tetrahedron cut into two identical halves that can screw together as
// a puzzle. This only outputs one of the halves. This demonstrates how
// redundant points along a polygon can be used to make twisted extrusions
// smoother. Based on the screw puzzle by George Hart:
// a puzzle. This demonstrates how redundant points along a polygon can be
// used to make twisted extrusions smoother. It also showcases animated
// assemblies. Based on the screw puzzle by George Hart:
// https://www.thingiverse.com/thing:186372

const edgeLength = 50; // Length of each edge of the overall tetrahedron.
Expand All @@ -61,19 +61,21 @@ export const examples = {

const scale = edgeLength / (2 * Math.sqrt(2));

const tet = Manifold.tetrahedron().scale(scale);
const tet = Manifold.tetrahedron().intersect(
Manifold.tetrahedron().rotate([0, 0, 90]).scale(2.5));

const box = [];
box.push([1, -1], [1, 1]);
box.push([2, -2], [2, 2]);
for (let i = 0; i <= nDivisions; ++i) {
box.push([gap / (4 * scale), 1 - i * 2 / nDivisions]);
box.push([gap / (2 * scale), 2 - i * 4 / nDivisions]);
}

const cyan = [0, 1, 1];
const magenta = [1, 0, 1];
const fade = (color, pos) => {
for (let i = 0; i < 3; ++i) {
color[i] = cyan[i] * pos[2] + magenta[i] * (1 - pos[2]);
const x = pos[2] / 2;
color[i] = cyan[i] * x + magenta[i] * (1 - x);
}
};

Expand All @@ -82,35 +84,42 @@ export const examples = {
// channels as colors, and sets the factor to white, since our default is
// yellow.
const screw = setMaterial(
Manifold.extrude(box, 1, nDivisions, 270).setProperties(3, fade),
Manifold.extrude(box, 2, nDivisions, 270).setProperties(3, fade),
{baseColorFactor: [1, 1, 1], attributes: ['COLOR_0']});

const result = tet.intersect(
screw.rotate([0, 0, -45]).translate([0, 0, -0.5]).scale(2 * scale));
const result =
tet.intersect(screw.rotate([0, 0, -45]).translate([0, 0, -1]))
.scale(scale);

// Assigned materials are only applied to a GLTFNode. Note that material
// definitions cascade, applying recursively to all child surfaces, but
// overridden by any materials defined lower down. The default material
// properties, as well as animation parameters can be set via
// globalDefaults.

const node = new GLTFNode();
node.rotation = [45, -Math.atan(1 / Math.sqrt(2)) * 180 / Math.PI, 120];
const layFlat = new GLTFNode();
layFlat.rotation =
[45, -Math.atan(1 / Math.sqrt(2)) * 180 / Math.PI, 120];
layFlat.translation = [0, 0, scale * Math.sqrt(3) / 3];

const fixed = new GLTFNode(node);
const fixed = new GLTFNode(layFlat);
fixed.manifold = result;
fixed.rotation = [0, 0, 180];

const moving = new GLTFNode(node);
// For 3MF export, only top-level objects are independently arrangeable.
const layFlat2 = layFlat.clone();

const moving = new GLTFNode(layFlat2);
moving.manifold = result;
// Use functions to create animation, which runs from t=0 to t=1.
moving.translation = (t) => {
const a = 1 - t;
const x = a > 0.5 ? scale * 2 * (0.5 - a) : 0;
return [x, x, -2 * x + scale * 4 * (0.5 - Math.abs(0.5 - a))];
};
moving.rotation = (t) => [0, 0, 270 * 2 * (1 - t)];

globalDefaults.animationLength = 10;
globalDefaults.animationLength = 10; // seconds
globalDefaults.animationMode = 'ping-pong';
return result;
},
Expand Down
4 changes: 2 additions & 2 deletions bindings/wasm/examples/worker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ suite('Examples', () => {
test('Tetrahedron Puzzle', async () => {
const result = await runExample('Tetrahedron Puzzle');
expect(result.genus).to.equal(0, 'Genus');
expect(result.volume).to.be.closeTo(7297, 1, 'Volume');
expect(result.surfaceArea).to.be.closeTo(3303, 1, 'Surface Area');
expect(result.volume).to.be.closeTo(7240, 1, 'Volume');
expect(result.surfaceArea).to.be.closeTo(3235, 1, 'Surface Area');
});

test('Rounded Frame', async () => {
Expand Down

0 comments on commit 6e1629d

Please sign in to comment.