import * as THREE from 'three'; // really stupid idea: add a cylinder as well! class TaperedLink extends THREE.Group { constructor(baseMaterial, n1, n2, r1, r2) { super(); const cone = new THREE.ConeGeometry( 0.75, 1, 32, true ); const cplane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0.5); const material = baseMaterial.clone(); 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); } update(n1, n2, r1, r2) { this.update_cone(n1, n2, r1, r2); } update_cone(n1, n2, r1, r2) { const kraw = r1 - r2; let k = ( kraw == 0 ) ? 0.001 : kraw; let nbase = n1.v3; let napex = n2.v3; let rbase = r1; let rapex = r2; if( k < 0 ) { nbase = n2.v3; napex = n1.v3; rbase = r2; rapex = r1; k = -k; } const l = nbase.distanceTo(napex); const h = l * rbase / k; 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)); } 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 ); } update_cylinder_busted(n1, n2, r1, r2) { const length = n1.v3.distanceTo(n2.v3); const centre = new THREE.Vector3(); centre.lerpVectors(n1.v3, n2.v3, 0.5); const link_mean = (r1 + r2) * 0.5; this.cylinder.scale.copy(new THREE.Vector3(link_mean, link_mean, length)); this.cylinder.position.copy(centre); //this.cylinder.lookAt(n2.v3); this.cylinder.rotation.x = Math.PI / 2.0; } } export { TaperedLink };