From 6f4d4cc633c4c43d28027273e661fbead746f8e6 Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Fri, 26 Apr 2024 11:42:37 +1000 Subject: [PATCH] Link foreshortening works, but updating the geometry of every edge is making large objects like the 120-cell noticeably stuttery --- fourDShape.js | 17 ++++++++++------ gui.js | 4 ++-- polytopes.js | 56 --------------------------------------------------- 3 files changed, 13 insertions(+), 64 deletions(-) diff --git a/fourDShape.js b/fourDShape.js index 7716066..9d5dcd7 100644 --- a/fourDShape.js +++ b/fourDShape.js @@ -2,7 +2,7 @@ import * as THREE from 'three'; const HYPERPLANE = 2.0; -const NODE_FORESHORTENING = 0.4; +const W_FORESHORTENING = 0.4; class FourDShape extends THREE.Group { @@ -15,9 +15,10 @@ class FourDShape extends THREE.Group { this.nodes3 = {}; this.links = structure.links; this.faces = ( "faces" in structure ) ? structure.faces : []; - this.node_scale = structure.geometry.node_size; - this.link_scale = structure.geometry.link_size; + this.node_scale = 1; + this.link_scale = 1; this.hyperplane = HYPERPLANE; + this.foreshortening = W_FORESHORTENING; this.initShapes(); } @@ -69,7 +70,11 @@ class FourDShape extends THREE.Group { const length = n1.v3.distanceTo(n2.v3); const centre = new THREE.Vector3(); centre.lerpVectors(n1.v3, n2.v3, 0.5); - link.object.scale.copy(new THREE.Vector3(this.link_scale * s2, this.link_scale * s1, length)); + // is this really the only way to do this? + const geometry = new THREE.CylinderGeometry(this.link_scale * s2, this.link_scale * s1, 1); + link.object.children[0].geometry.dispose(); + link.object.children[0].geometry = geometry; + link.object.scale.copy(new THREE.Vector3(1, 1, length)); link.object.position.copy(centre); link.object.lookAt(n2.v3); link.object.children[0].rotation.x = Math.PI / 2.0; @@ -157,10 +162,10 @@ class FourDShape extends THREE.Group { const v4 = this.fourDrotate(n.x, n.y, n.z, n.w, rotations); const k = this.fourDscale(v4.w); const v3 = new THREE.Vector3(v4.x * k, v4.y * k, v4.z * k); - const s4 = k * this.node_scale * NODE_FORESHORTENING; + const s4 = k * this.node_scale * this.foreshortening; const s3 = new THREE.Vector3(s4, s4, s4); this.nodes3[n.id].v3 = v3; - this.nodes3[n.id].scale = k; + this.nodes3[n.id].scale = k * this.foreshortening; this.nodes3[n.id].object.position.copy(v3); this.nodes3[n.id].object.scale.copy(s3); this.nodes3[n.id].object.visible = ( !nodes_show || n.label in nodes_show ); diff --git a/gui.js b/gui.js index effa87e..db46041 100644 --- a/gui.js +++ b/gui.js @@ -67,14 +67,14 @@ class FourDGUI { }); this.gui.add(this.params, 'hyperplane', 0.5, 1 / 0.8); this.gui.add(this.params, 'zoom', 0.1, 2.0); - this.gui.add(this.params, 'thickness', 0, 1); + this.gui.add(this.params, 'thickness', 0, 0.1); this.gui.add(this.params, 'linkopacity', 0, 1).onChange( (v) => setLinkOpacity(v, true) ); this.gui.add(this.params, 'link2opacity', 0, 1).onChange( (v) => setLinkOpacity(v, false) ); - this.gui.add(this.params, 'nodesize', 0, 1); + this.gui.add(this.params, 'nodesize', 0, 0.1); this.gui.addColor(this.params, 'color').onChange(setColor); this.gui.addColor(this.params, 'background').onChange(setBackground); this.gui.add(this.params, 'xRotate', [ 'YW', 'YZ', 'ZW' ]); diff --git a/polytopes.js b/polytopes.js index b7011a8..91816c2 100644 --- a/polytopes.js +++ b/polytopes.js @@ -80,10 +80,6 @@ export const cell5 = () => { { id:9, source:3, target: 5}, { id:10, source:4, target: 5}, ], - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: '--' }], description: `Five tetrahedra joined at ten faces with three tetrahedra around each edge. The 5-cell is the simplest regular @@ -115,10 +111,6 @@ export const cell16 = () => { name: '16-cell', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: '--' }], description: `Sixteen tetrahedra joined at 32 faces with four tetrahedra around each edge. The 16-cell is the four-dimensional @@ -157,10 +149,6 @@ export const tesseract = () => { name: 'Tesseract', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: 'none', links: [ 0 ] }, { name: 'one 16-cell', links: [ 0, 1 ] }, @@ -221,10 +209,6 @@ export const cell24 = () => { name: '24-cell', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, base: {}, options: [ { name: 'none', links: [ 0 ] }, @@ -412,10 +396,6 @@ export const cell120_layered = (max) => { name: '120-cell layered', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, nolink2opacity: true, options: options, description: `This version of the 120-cell lets you explore its @@ -447,10 +427,6 @@ export const cell120_inscribed = () => { name: '120-cell', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: "none", links: [ 0 ]}, { name: "one inscribed 600-cell", links: [ 0, 1 ] }, @@ -582,10 +558,6 @@ export const cell600 = () => { name: '600-cell', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: "none", links: [ 0 ]}, { name: "one 24-cell", links: [ 0, 1 ] }, @@ -635,10 +607,6 @@ export const cell600_layered = () => { name: '600-cell layered', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, nolink2opacity: true, options: options, description: `This version of the 600-cell lets you explore its @@ -666,10 +634,6 @@ export const snub24cell = () => { name: 'Snub 24-cell', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: "--" } ], description: `The snub 24-cell is a semiregular polytope which connects the 24-cell with the 600-cell. It consists of 24 icosahedra @@ -736,10 +700,6 @@ export const dodecahedron = () => { name: 'Dodecahedron', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: "none", links: [ 0 ]}, { name: "one tetrahedron", links: [ 0, 1 ] }, @@ -774,10 +734,6 @@ export const tetrahedron = () => { { id:5, source:2, target: 4}, { id:6, source:3, target: 4}, ], - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: '--' }], description: `The simplest three-dimensional polytope, consisting of four triangles joined at six edges. The 5-cell is its four-dimensional analogue.`, }; @@ -811,10 +767,6 @@ export const octahedron = () => { name: 'Octahedron', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: '--' }], description: `The three-dimensional cross-polytope, the 16-cell is its four-dimensional analogue.`, }; @@ -839,10 +791,6 @@ export const cube = () => { name: 'Cube', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: '--' }], description: `The three-dimensional measure polytope, the tesseract is its four-dimensional analogue.`, }; @@ -885,10 +833,6 @@ export const icosahedron = () => { name: 'Icosahedron', nodes: nodes, links: links, - geometry: { - node_size: 0.02, - link_size: 0.02 - }, options: [ { name: "--"}, ],