From 67348bce31469d20f734b19f9c6d6a966abd969a Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Sat, 15 Nov 2025 16:31:45 +1100 Subject: [PATCH] The problem is with the flipping logic - I haven't fixed it yet but I'm getting there --- linktest.js | 46 +++++++++++++++++++++++++++----------- taperedLink.js | 60 +++++++++++++++++++++++++------------------------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/linktest.js b/linktest.js index 756cd37..7a9ff86 100644 --- a/linktest.js +++ b/linktest.js @@ -5,7 +5,6 @@ import { GUI } from 'lil-gui'; import { TaperedLink } from './taperedLink.js'; - const FACE_OPACITY = 0.3; const CAMERA_K = 5; @@ -39,15 +38,24 @@ renderer.localClippingEnabled = true; document.body.appendChild( renderer.domElement ); const NODEC = 0x3293a9; +const LINKC = 0x00ff88; const BACKGROUNDC = 0xd4d4d4; scene.background = new THREE.Color(BACKGROUNDC); -const material = new THREE.MeshStandardMaterial({ color: NODEC }); +const material = new THREE.MeshStandardMaterial({ color: LINKC }); +material.transparent = true; +material.opacity = 0.5; + +const node_mat = new THREE.MeshStandardMaterial({ color: NODEC }); + +node_mat.transparent = true; +node_mat.opacity = 0.1; const params = { r1: 0.5, r2: 0.6, + sync: false, l: 3, }; @@ -55,34 +63,46 @@ const gui = new GUI(); gui.add(params, "r1", 0.01, 1.5); gui.add(params, "r2", 0.01, 1.5); +gui.add(params, "sync"); gui.add(params, "l", 0, 4); function makeNode(material, pos, r) { const geometry = new THREE.SphereGeometry(1); const sphere = new THREE.Mesh(geometry, material); - updateNode(sphere, pos, r); - return sphere; + const node = { + v3: pos, + object: sphere + }; + updateNode(node, pos, r); + return node; } function updateNode(node, pos, r) { - node.scale.copy(new THREE.Vector3(r, r, r)); - node.position.copy(pos); + node.v3 = pos; + node.object.scale.copy(new THREE.Vector3(r, r, r)); + node.object.position.copy(pos); } -const n1 = makeNode(material, new THREE.Vector3(-0.5 * params["l"], 0, 0), params["r1"]); -const n2 = makeNode(material, new THREE.Vector3(0.5 * params["l"], 0, 0), params["r2"]) +const n1 = makeNode(node_mat, new THREE.Vector3(-0.5 * params["l"], 0, 0), params["r1"]); +const n2 = makeNode(node_mat, new THREE.Vector3(0.5 * params["l"], 0, 0), params["r2"]); -//const tl = new TaperedLink( +const tl = new TaperedLink(material, n1, n2, params["r1"], params["r2"]); -scene.add(n1); -scene.add(n2); +scene.add(n1.object); +scene.add(n2.object); + +scene.add(tl); function animate() { requestAnimationFrame(animate); - updateNode(n1, new THREE.Vector3(-0.5 * params["l"], 0, 0), params["r1"]); - updateNode(n2, new THREE.Vector3(0.5 * params["l"], 0, 0), params["r2"]); + const r1 = params["r1"]; + const r2 = params["sync"] ? r1 : params["r2"] + + updateNode(n1, new THREE.Vector3(-0.5 * params["l"], 0, 0), r1); + updateNode(n2, new THREE.Vector3(0.5 * params["l"], 0, 0), r2); + tl.update(n1, n2, r1, r2); renderer.render(scene, camera); } animate(); diff --git a/taperedLink.js b/taperedLink.js index 153b9f9..3f5e965 100644 --- a/taperedLink.js +++ b/taperedLink.js @@ -2,22 +2,24 @@ import * as THREE from 'three'; // really stupid idea: add a cylinder as well! +const EPSILON = 0.01; + class TaperedLink extends THREE.Group { constructor(baseMaterial, n1, n2, r1, r2) { super(); - const cone = new THREE.ConeGeometry( 0.75, 1, 32, true ); + const cone = new THREE.ConeGeometry( 1, 1, 32, true ); const cplane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0.5); const material = baseMaterial.clone(); - material.clippingPlanes = [ cplane ]; +// material.clippingPlanes = [ cplane ]; this.cone = new THREE.Mesh( cone, material ); this.add( this.cone ); - const cylinder = new THREE.CylinderGeometry(1, 1, 1, 16, 1, true); - const cyl_material = baseMaterial.clone(); - cyl_material.color = new THREE.Color(0xff0000); - this.cylinder = new THREE.Mesh(cylinder, cyl_material); - this.add( this.cylinder ); - this.update(n1, n2, r1, r2); +// const cylinder = new THREE.CylinderGeometry(1, 1, 1, 16, 1, true); +// const cyl_material = baseMaterial.clone(); +// cyl_material.color = new THREE.Color(0xff0000); +// this.cylinder = new THREE.Mesh(cylinder, cyl_material); +// this.add( this.cylinder ); + // this.update(n1, n2, r1, r2); } update(n1, n2, r1, r2) { @@ -41,33 +43,31 @@ class TaperedLink extends THREE.Group { } const l = nbase.distanceTo(napex); - const h = l * rbase / k; + const lapex = l * rapex / k; + const h = l + lapex; + this.cone.scale.copy(new THREE.Vector3(rbase, h, rbase)); const h_offset = 0.5 * h / l; const pos = new THREE.Vector3(); - if( l > 0 ) { - pos.lerpVectors(nbase, napex, h_offset); - } - const rmean = 0.5 * (r1 + r2); - if( h_offset < 1 ) { - this.cone.scale.copy(new THREE.Vector3(rbase, h, rbase)); - this.cylinder.scale.copy(new THREE.Vector3(rmean, l, rmean)); - } else { - // you're on the other side of napex so flip the cone - this.cone.scale.copy(new THREE.Vector3(rbase, -h, rbase)); - this.cylinder.scale.copy(new THREE.Vector3(rmean, -l, rmean)); - } + pos.lerpVectors(nbase, napex, h_offset); + + + //if( h_offset > 1 ) { + // this.cone.scale.copy(new THREE.Vector3(rbase, -h, rbase)); + //} { + // this.cone.scale.copy(new THREE.Vector3(rbase, h, rbase)); + //} this.lookAt(napex); // the group, not the cone!! this.position.copy(pos); // the group, not the cone!! this.cone.rotation.x = Math.PI / 2.0; - this.cylinder.rotation.x = Math.PI / 2.0; - const clipnorm = new THREE.Vector3(); - clipnorm.copy(napex); - clipnorm.sub(nbase); - clipnorm.negate(); - clipnorm.normalize(); - this.cone.material.clippingPlanes[0].setFromNormalAndCoplanarPoint( - clipnorm, napex - ); +// this.cylinder.rotation.x = Math.PI / 2.0; +// const clipnorm = new THREE.Vector3(); +// clipnorm.copy(napex); + // clipnorm.sub(nbase); + // clipnorm.negate(); + // clipnorm.normalize(); + // this.cone.material.clippingPlanes[0].setFromNormalAndCoplanarPoint( + // clipnorm, napex + // ); }