使用三个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      更新时间:2023-09-26

我正在做一个小项目,我正在尝试使用三个js在点云可视化中显示NSF OpenTopography数据。我能够创建点云,但在相机设置和相机导航方面遇到严重问题。我尝试过使用各种控件(OrbitControls.js, TrackballControls.js和FirstPersonControls.js),但都出现了不足。下面是一个链接,我在哪里可视化工作副本。我的目标是能够绘制点云数据,并使用鼠标或箭头键来导航场景。

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

请让我知道是否需要额外的代码和/或示例。上面的例子只是让某些东西工作的众多尝试中的一个。

请指教。

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

问题似乎是轨道控制无法处理你疯狂的场景大小。当相机的position设置为如此高的值时,旋转速度和变焦适应(它移动得更快)。但是你的视觉数据的一般边界框不是那么大,所以我猜它会立即移出观看空间。

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