使用三个 js 和 NSF OpenTopography 数据的点云:如何设置相机和控件库来导航数据?

Point cloud using three js and NSF OpenTopography data : How do you set up the camera and a controls library to navigate the data?

我正在做一个小项目,我试图使用三个 js 在点云可视化中显示 NSF OpenTopography 数据。我能够创建点云,但 运行 相机设置和相机导航存在严重问题。我尝试过使用各种控件(OrbitControls.js、TrackballControls.js 和 FirstPersonControls.js),但都不够用。下面是一个 link 到我在可视化中所处位置的工作副本。我的目标是能够绘制点云数据并使用鼠标或箭头键在场景中导航。

http://jsfiddle.net/mcroteau/ycg1hqu0/

如果需要其他代码和/或示例,请告诉我。上面的 jsfiddle 只是许多尝试中的一种尝试。

任何指导将不胜感激。

Javascript

var container, scene, 
    camera, renderer, 
    controls, stats,
    geometry, material;

var SCREEN_WIDTH = window.innerWidth, 
    SCREEN_HEIGHT = window.innerHeight;

var VIEW_ANGLE = 45, 
    ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, 
    NEAR = 0.1, 
    FAR = 20000;

var POINT_SIZE = 1;

var BACKGROUND_COLOR = 0xefefef,
    POINT_COLOR = 0x4466B0;

var maxX = maxY = maxZ = 0;
var minX = minY = minZ = 0;
var midX = midY = midZ = 0;

var step = 1;
var lookZ = lookX = 0;


init();
animate();


function init() {

    scene = new THREE.Scene();

    container = document.createElement('div');
    document.body.appendChild( container );

    if ( Detector.webgl ){
        renderer = new THREE.WebGLRenderer({ antialias: true });
    }else{
        renderer = new THREE.CanvasRenderer(); 
    }

    renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    renderer.setClearColor( BACKGROUND_COLOR, 1);

    container.appendChild( renderer.domElement );


    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.bottom = '0px';
    stats.domElement.style.zIndex = 100;
    container.appendChild( stats.domElement );


    geometry = new THREE.Geometry();

    for (var i = 0; i < data.length; i ++ ) {
        var vertex = new THREE.Vector3();

        /** 
        correct x, y, z values 
        camera seems really out of position when using these values
        **/
        //var x = data[i][0];
        //var y = data[i][1];
        //var z = data[i][2];

        var x = data[i][1];
        var y = data[i][2];
        var z = data[i][0];


        vertex.x = x;
        vertex.y = y;
        vertex.z = z;
        geometry.vertices.push(vertex);

        if(i < 10){
            console.log([x, y, z]);
        }
        checkSetMaxValues(x, y, z, i);
    }

    setMedians()

    camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
    camera.position.x = minX  - 20
    camera.position.y = maxY + 20
    camera.position.z = minZ - 20

    scene.position.x = midX
    scene.position.y = minY
    scene.position.z = midZ

    scene.add(camera);
    camera.lookAt(scene.position);

    //controls = new THREE.OrbitControls( camera, renderer.domElement );

    lookZ = camera.position.z
    lookX = camera.position.x


    material = new THREE.PointCloudMaterial( { size: POINT_SIZE, color : POINT_COLOR } );
    particles = new THREE.PointCloud( geometry, material );
    scene.add( particles );

    window.addEventListener( 'resize', onWindowResize, false );

}

function setMedians(){
    midX = (maxX + minX) / 2;
    midY = (maxY + minY) / 2;
    midZ = (maxZ + minZ) / 2;
    console.info('mid', midX, midY, midZ);
}


function checkSetMaxValues(x, y, z, i){
    if(x > maxX || maxX === 0)maxX = x
    if(x < minX || minX === 0)minX = x
    if(y > maxY || maxY === 0)maxY = y
    if(y < minY || minY === 0)minY = y
    if(z > maxZ || maxZ === 0)maxZ = z
    if(z < minZ || minZ === 0)minZ = z

    if(data.length == i + 1){
        console.log('max:', maxX, maxY, maxZ)
        console.log('min:', minX, minY, minZ)
    }
}


function onWindowResize() {
    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );
}


function animate() {
    render();       
    update();
    requestAnimationFrame( animate );
}



function update(){
    stats.update();
    updateCamera();
    //would like to use a controls library
    //controls.update()
}



function updateCamera(){

    if(lookZ < maxZ){
        camera.position.z = camera.position.z + 0.20;
        lookZ = camera.position.z
    }

    if(lookZ >= maxZ){
        if(lookX < maxX){
            camera.position.x = camera.position.x + 0.20;
            lookX = camera.position.x
        }
    }

    camera.lookAt(scene.position)
}


function render() {
    renderer.render( scene, camera );
}

问题似乎是 Orbit Controls 无法处理您疯狂的场景大小。当相机 position 设置为如此高的值时,旋转速度和缩放会适应(移动速度更快)。但是您的视觉数据的一般边界框并没有那么大,所以我猜它会立即移出视图 space。

我通过使用 geometry.center(); 重新居中几何而不修改 scene.position 解决了这个问题。这是结果:http://jsfiddle.net/ycg1hqu0/9/