javascript - 使用三个js和NSF OpenTopography数据的点云: How do you set up the camera and a controls library to navigate the data?

标签 javascript three.js point-clouds

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

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

最佳答案

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

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

关于javascript - 使用三个js和NSF OpenTopography数据的点云: How do you set up the camera and a controls library to navigate the data?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32489928/

相关文章:

three.js - 如何在 THREE.PointCloudMaterial 中使用大小?

javascript - Three.js如何获取具有全局位置的PointCloud顶点

javascript - What happens to an HTML5 web worker thread when the tab is closed while it's running?

javascript - 未捕获的引用 $ 未定义

javascript - 我想用javascript在控制台中显示匹配的记录

javascript - 纹理在视口(viewport) Three.js 中显示不清晰

javascript - html5 3d, Canvas ,three.js

javascript - 优先级-web-sdk : Implementing a DATE8 field

three.js - 为什么附加到组后顶点没有更新?

C++ 查找一个点集位于两个点集之间的位置