我正在尝试在three.js中渲染d3力图,我正在使用带有照片纹理的标准Line和BoxGeometry。在强制图更新时,我调用绘制函数,该函数也在
中调用 controls.addEventListener('change', () => {this.redraw()});
但是当我移动相机时,有些线条消失了 我更接近,看起来最糟糕,除了它看起来没有任何规则, 即使我接近图形,它看起来像是随意选择消失的线条。
有线是
这就是我将镜头移动了一点角度
这是图表的一侧:
这是来自其他人的时间:
整个代码:
import {
WebGLRenderer,
Scene,
PerspectiveCamera,
Texture,
MeshBasicMaterial,
SphereGeometry,
Mesh,
Geometry,
Vector3,
LineBasicMaterial,
Line,
LineSegments,
BoxGeometry,
TextureLoader
} from 'three';
import * as three from 'three';
import { ViewModel, Link, Node } from './Model';
import { event } from 'd3-selection';
import * as selection from 'd3-selection';
import { drag } from 'd3-drag';
// Old module syntax
declare function require(name:String);
let OrbitControls = require('./../../../node_modules/three-orbit-controls/index')(three);
interface IView {
render():void;
}
class ViewNode {
public vector:Vector3;
public mesh:Mesh;
public node:Node;
}
export class Full3DView implements IView {
private canvas: Element;
private renderer: WebGLRenderer;
private scene: Scene;
private lineMaterial: LineBasicMaterial;
private camera: PerspectiveCamera;
private controls: any;
private nodes:ViewNode[] = [];
private lines:Geometry[] = [];
constructor(private model:ViewModel) {
this.canvas = document.querySelector('#view3d2');
this.model.onChange(() => {this.render()});
}
render(): void {
this.buildScene();
this.model.simulation.on('tick', () => this.redraw());
this.model.linkForce.distance(40);
this.model.collideForce.radius(30);
}
private buildScene() {
this.scene = new Scene();
this.camera = new PerspectiveCamera( 90, window.innerWidth/window.innerHeight, 1, 20000 );
this.renderer = new WebGLRenderer();
this.renderer.setSize( this.canvas.clientWidth, this.canvas.clientHeight );
this.canvas.appendChild( this.renderer.domElement );
this.controls = new OrbitControls( this.camera, this.renderer.domElement);
this.controls.addEventListener('change', () => {this.redraw()});
this.lineMaterial = new LineBasicMaterial({ color: 0xccff00, linewidth: 3});
let vectorIndex:Map<String, Vector3> = new Map();
let textureLoader = new TextureLoader();
this.model.nodes.forEach((node:Node) => {
this.buildNode(vectorIndex, textureLoader, node);
});
this.model.links.forEach((link:Link) => {
this.buildEdge(vectorIndex, link);
});
this.camera.position.z = 5000;
}
private buildNode(vectorIndex:Map<String, Vector3>, textureLoader:TextureLoader, node:Node) {
let material = new MeshBasicMaterial();
let geometry = new BoxGeometry( 30, 30, 30);
let mesh = new Mesh( geometry, material );
mesh.lookAt(this.camera.position);
this.scene.add( mesh );
mesh.position.set(node.x, node.y, 0);
mesh.rotation.x += 1;
vectorIndex.set(node.index, mesh.position);
this.nodes.push({
vector: mesh.position,
mesh: mesh,
node: node
});
textureLoader.load('/data/images/' + node.id + '.jpg', (texture:Texture) => {
material.map = texture;
material.needsUpdate = true;
});
}
private buildEdge(vectorIndex:Map<String, Vector3>, link:Link) {
let geometry = new Geometry();
geometry.vertices.push(
vectorIndex.get(link.source.index).copy(vectorIndex.get(link.source.index).setZ(0)),
vectorIndex.get(link.target.index).copy(vectorIndex.get(link.target.index).setZ(0))
);
geometry.computeLineDistances();
this.lines.push(geometry);
let line = new Line(geometry, this.lineMaterial);
this.scene.add(line);
}
private redraw() {
this.nodes.forEach((node:ViewNode) => {
node.vector.setX(node.node.x * 10);
node.vector.setY(node.node.y * 10);
node.mesh.lookAt(this.camera.position);
node.mesh.frustumCulled = false;
});
this.lines.forEach((line:Geometry) => {
line.verticesNeedUpdate = true;
});
this.renderer.render(this.scene, this.camera)
}
}
答案 0 :(得分:1)
我无法使用Line
对象进行操作,但如果我使用LineSegments
并将所有顶点对推到一个Geometry
,则效果很好。
所以在函数buildScene
中我使用而不是
this.lineMaterial = new LineBasicMaterial({ color: 0xccff00, linewidth: 3});
行
this.linesGeometry = new Geometry();
this.scene.add(new LineSegments(this.linesGeometry, new LineBasicMaterial({ color: 0xccff00, linewidth: 3})));
然后buildEdge
的内容是
this.linesGeometry.vertices.push(
vectorIndex.get(link.source.index).copy(vectorIndex.get(link.source.index).setZ(0)),
vectorIndex.get(link.target.index).copy(vectorIndex.get(link.target.index).setZ(0))
);
并且在redraw
函数中我只是做
this.linesGeometry.verticesNeedUpdate = true;
而不是
this.lines.forEach((line:Geometry) => {
line.verticesNeedUpdate = true;
});
答案 1 :(得分:0)