UNPKG

@jonobr1/force-directed-graph

Version:

GPU supercharged attraction-graph visualizations for the web built on top of Three.js

106 lines (93 loc) 2.97 kB
import { BufferAttribute, DoubleSide, InstancedBufferAttribute, InstancedBufferGeometry, Mesh, ShaderMaterial, UniformsLib, } from 'three'; import { each } from './math.js'; import shader from './shaders/links.js'; const vertices = new Float32Array([-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0]); const indices = [0, 1, 2, 2, 1, 3]; class Links extends Mesh { constructor(geometry, uniforms) { const material = new ShaderMaterial({ uniforms: { ...UniformsLib['fog'], ...{ frustumSize: uniforms.frustumSize, is2D: uniforms.is2D, inheritColors: uniforms.linksInheritColor, linecap: uniforms.linecap, linewidth: uniforms.linewidth, opacity: uniforms.opacity, pixelRatio: uniforms.pixelRatio, resolution: uniforms.resolution, sizeAttenuation: uniforms.sizeAttenuation, texturePositions: { value: null }, uColor: uniforms.linkColor, uBeginning: uniforms.uBeginning, uEnding: uniforms.uEnding, uNodeAmount: uniforms.uNodeAmount, }, }, vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, transparent: true, fog: true, side: DoubleSide, }); super(geometry, material); this.frustumCulled = false; } static parse(points, data) { const geometry = new InstancedBufferGeometry(); const sources = []; const targets = []; const sourceColors = []; const targetColors = []; const v = points.geometry.attributes.position.array; const c = points.geometry.attributes.color.array; geometry.setAttribute('position', new BufferAttribute(vertices, 3)); geometry.setIndex(indices); return each(data.links, (_, i) => { const link = data.links[i]; const sourceIndex = 3 * link.sourceIndex; const targetIndex = 3 * link.targetIndex; sources.push(v[sourceIndex + 0], v[sourceIndex + 1], v[sourceIndex + 2]); targets.push(v[targetIndex + 0], v[targetIndex + 1], v[targetIndex + 2]); sourceColors.push( c[sourceIndex + 0], c[sourceIndex + 1], c[sourceIndex + 2], ); targetColors.push( c[targetIndex + 0], c[targetIndex + 1], c[targetIndex + 2], ); }).then(() => { geometry.setAttribute( 'source', new InstancedBufferAttribute(new Float32Array(sources), 3), ); geometry.setAttribute( 'target', new InstancedBufferAttribute(new Float32Array(targets), 3), ); geometry.setAttribute( 'sourceColor', new InstancedBufferAttribute(new Float32Array(sourceColors), 3), ); geometry.setAttribute( 'targetColor', new InstancedBufferAttribute(new Float32Array(targetColors), 3), ); geometry.instanceCount = data.links.length; return geometry; }); } } export { Links };