简体   繁体   English

将相机WRT 3d对象放置在three.js中

[英]Placing camera W.R.T 3d object in three.js

I have an object that moves and rotates, and I want the camera to stay a certain distance behind it. 我有一个可移动和旋转的对象,并且我希望相机在它后面保持一定距离。 To be clear, I'm drawing an airplane and want the camera to always be looking at its rear. 为了清楚起见,我正在绘制一架飞机,并希望相机始终向后看。 (Unless the user drags the mouse, for example to look at the top of the airplane as it flies). (除非用户拖动鼠标,例如,以观察飞机飞行时的顶部)。

So say I have set the position and rotation of the airplane (instance of THREE.Object3D): 假设我已经设置了飞机的位置和旋转(例如THREE.Object3D):

airplane.position = {x: 1, y:2, z: 3};
airplane.rotation = {x: Math.PI/4, y:1.2, z: 0};

And say, when the rotation and positions are (0,0,0) the camera is at (5, 0, 0), (ie 5 units behind the airplane's center), what would be the simplest way of finding the position vector to set the camera at? 并说,当旋转和位置为(0,0,0)时,相机位于(5,0,0)(即飞机中心后5个单位),找到位置向量的最简单方法就是将相机放在?

Thanks 谢谢

Sorry for the sprawled code, I'm hacking it to death. 抱歉,代码过多,我将其砍死了。 I'd make a jsfiddle for it, but haven't got a server to host three.js on... 我会为此做一个jsfiddle,但是还没有服务器来托管Three.js。

$(function(){
    var camera1, camera2, scene, renderer, viewPort;
    var objectManager;
    var views = [];
    var vpWidth, vpHeight;
    init();
    animate();
    updateSize();
    function updateSize(){
        vpWidth = viewPort.innerWidth();
        vpHeight = viewPort.innerHeight();
    }
    function init() {
        viewPort = $('#viewPort');
        objectManager = new ObjectManager();

        views[0] = new View(viewPort, objectManager);
        var view = views[0];
        view.fov = 20;
        view.proportions.height = 0.5;
        view.proportions.bottom = 0.5;
        view.init();
        views[1] = new View(viewPort, objectManager);
        var view = views[1];
        view.fov = 10;
        view.proportions.height = 0.5;
        view.init();
        view.updateCamera = function(){

            //-----------------------------------------------------
            // when the user drags the mouse, (not yet implemented)
            // the following camera position numbers would change
            // so that he could view for example the top of the
            // airplane as it flies
            //-----------------------------------------------------
            this.camera.position.set( 5,5,5 );

            //-----------------------------------------------------
            // This line does not work as expected: the airplane
            // does not stay in the center of the view but follows
            // some sort of curved path with respect to the camera
            //-----------------------------------------------------
            this.camera.lookAt(objectManager.airplane.position);

            this.camera.updateProjectionMatrix();
        };
        scene = new THREE.Scene();
        objectManager.addTo(scene);

        objectManager.airplane.add(views[1].camera);

        //-----------------------------------------------
        // The following two lines *do* work correctly //
        //-----------------------------------------------
        views[1].camera.position.set( 0,0,5 );
        views[1].camera.lookAt(objectManager.airplane.position);

        var ambientLight = new THREE.AmbientLight(0x808080);
        scene.add(ambientLight);        

        var pointLight = new THREE.PointLight(0x808080);
        pointLight.position = {x: 100, y: 100, z: 100};
        scene.add(pointLight);      

        renderer = new THREE.WebGLRenderer();
        renderer.setClearColorHex(0x000000, 1);
        renderer.setSize( viewPort.innerWidth(), viewPort.innerHeight() );
        viewPort.get(0).appendChild(renderer.domElement);
    }

    function animate() {
        requestAnimationFrame( animate );
        render();
    }
    function render() {
        objectManager.tick();
        var view;
        for (var i in views){
            view = views[i];
            view.updateCamera();
            pixels = view.pixels;
            renderer.setViewport(pixels.left, pixels.bottom, pixels.width, pixels.height);
            renderer.setScissor(pixels.left, pixels.bottom, pixels.width, pixels.height);
            renderer.enableScissorTest(true);
            renderer.render( scene, view.camera );
        }
    }
});
function View(vp, om){
    this.objectManager = om;
    this.viewPort = vp;
    this.fov = 30;
    this.proportions = { left: 0, bottom: 0, height: 1, width: 1 };
    this.pixels = { left: 0, bottom: 0, height: 0, width: 0, aspect: 0 };
    this.aspect;
    this.init = function(){
        this.camera = new THREE.PerspectiveCamera( 
                this.fov, 
                this.viewPort.innerWidth() / this.viewPort.innerHeight(), 
                0.1, 10000 
        );
        this.pixels.left = Math.floor(this.proportions.left * this.viewPort.innerWidth()); 
        this.pixels.width = Math.floor(this.proportions.width * this.viewPort.innerWidth()); 
        this.pixels.bottom = Math.floor(this.proportions.bottom * this.viewPort.innerHeight()); 
        this.pixels.height = Math.floor(this.proportions.height * this.viewPort.innerHeight()); 
        this.pixels.aspect = this.pixels.width / this.pixels.height;
        this.camera.position.y = 0;
        this.camera.position.z = 10;
        this.camera.aspect = this.pixels.aspect;
        this.camera.updateProjectionMatrix();
    };
    this.updateCamera = function(){};
}

function newCube(dims, pos, cols, colAss){
    var mesh;
    var geometry;
    var materials = [];
    geometry = new THREE.CubeGeometry( dims.x, dims.y, dims.z );
    for (var i in cols){
        materials[i] = new THREE.MeshLambertMaterial( { color: cols[i], ambient: cols[i], overdraw: true } );
    }
    geometry.materials = materials;
    for (var i in colAss){
        geometry.faces[i].materialIndex = colAss[i];
    }
    mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
    mesh.position = pos;
    return mesh;
}
function ObjectManager(){
    this.airplane;
    var fuselage;
    var tail;
    var grid;
    this.addTo = function(scene){
        this.airplane = new THREE.Object3D();
        fuselage = newCube(
                {x: 1, y: 0.1, z: 0.1}, 
                {x: 0, y: 0, z: 0},
                [0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
                [0, 1, 2, 3, 4, 5]
        );
        this.airplane.add(fuselage);
        tail = newCube(
                {x: 0.15, y: 0.2, z: 0.05}, 
                {x: 0.5, y: 0.199, z: 0},
                [0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
                [0, 1, 2, 3, 4, 5]
        );
        this.airplane.add(tail);
        scene.add( this.airplane );

        grid = new THREE.Object3D();

        var geometry = new THREE.Geometry();
        geometry.vertices.push(new THREE.Vector3( - 200, 0, 0 ) );
        geometry.vertices.push(new THREE.Vector3( 200, 0, 0 ) );

        linesMaterial = new THREE.LineBasicMaterial( { color: 0x00ff00, opacity: 1, linewidth: .1 } );

        for ( var i = 0; i <= 200; i ++ ) {

            var line = new THREE.Line( geometry, linesMaterial );
            line.position.z = ( i * 2 ) - 200;
            grid.add( line );

            var line = new THREE.Line( geometry, linesMaterial );
            line.position.x = ( i * 2 ) - 200;
            line.rotation.y = 90 * Math.PI / 180;
            grid.add( line );
        }       
        scene.add( grid );

    };
    this.tick = function(){
        this.airplane.rotation.x += 0.005;
        this.airplane.rotation.y += 0.01;
        this.airplane.position.x += 0.01;
    };
};

Add the camera as a child of the airplane, instead. 而是将相机添加为飞机的子代。

airplane.add( camera );
camera.position.set( 5, 0, 0 );
camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );

Now, when you rotate/move the airplane, the camera will follow automatically. 现在,当您旋转/移动飞机时,相机将自动跟随。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM