2017-04-14 61 views
0

我正在试着在three.js中呈现d3力图,我使用带有照片纹理的标准Line和BoxGeometry。在力图表更新我叫画功能,这也叫上当相机在三个j中移动时线会消失

controls.addEventListener('change',() => {this.redraw()});

,但是当我移动相机,一些线路disapear,当 我更近,似乎最坏的,除了它不看就像有任何规则,即使当我接近图表时,它看起来像是随机选择disapear的线条。

有线是

enter image description here

这是,如果我移动相机有点角度

enter image description here

这是从图中的一侧:

enter image description here

这是当其他:

enter image description here

I tried to scale down units

And also frustum = false

整个代码:

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) 
    } 
} 

回答

1

我无法得到它的工作使用Line对象,但如果我使用LineSegments并推送所有p顶点到一个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

(1)在一个单一的绘图调用呈现所有段显然是一种改进。 (2)对于你的问题可能的解释是,当你更新几何的顶点时,你应该调用'geometry.computeBoundingSphere()'。渲染器会在第一次渲染调用中为您调用它,但在此之后,如果修改了顶点,则边界球不再正确,您需要更新它。或者,您可以设置'mesh.frustumCulled = false'; – WestLangley

相关问题