最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - THREE.js: calling lookAt method after rendering does not work - Stack Overflow

programmeradmin2浏览0评论

The script below isn't working properly. (It just needs jquery and three.js to run). The troublesome lines are these two:

// change the view so looking at the top of the airplane
views[1].camera.position.set( 0,5,0 );
views[1].camera.lookAt(objectManager.airplane.position);

Strangely, if those two lines are mented out, it can be seen that the two similar preceeding lines below do run as expected:

views[1].camera.lookAt(objectManager.airplane.position);

and

view.camera.position.set( 5,0,0 );

For some reason it seems that the call to camera.lookAt only works the first time. After that, the camera no longer follows the airplane object. I'd be extremely grateful if someone can figure out what I'm doing wrong!

The full script is below.

Thanks

$(function(){
    var scene, renderer, viewPort, objectManager, views;

    init();
    animate();

    function init() {
        viewPort = $('body');

        scene = new THREE.Scene();

        // construct the two cameras
        initialiseViews();

        // construct airplane, lights and floor grid
        objectManager = new ObjectManager();
        objectManager.construct();
        objectManager.addToScene(scene);

        // make the second camera's position
        // stay fixed relative to the airplane
        objectManager.airplane.add(views[1].camera);

        // make the second camera stay looking
        // at the airplane
        views[1].camera.lookAt(objectManager.airplane.position);

        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();
        for (var i in views){
            views[i].render(scene, renderer);
        }
    }
    function initialiseViews(){
        views = [];

        // ----------------------------------------------------
        // Create the first view, static with respect to ground
        // ----------------------------------------------------
        views[0] = new View(viewPort, objectManager, scene);
        var view = views[0];
        view.fov = 40;
        view.proportions.height = 0.5;
        view.proportions.bottom = 0.5;
        view.init();
        view.camera.position.y = 1;
        view.camera.position.z = 4;

        // ----------------------------------------------------
        // Create the second view, which follows the airplane
        // ----------------------------------------------------

        views[1] = new View(viewPort, objectManager, scene);
        var view = views[1];

        view.fov = 20;
        view.proportions.height = 0.5;
        view.init();

        // set the initial position of the camera
        // with respect to the airplane. Views from behind
        view.camera.position.set( 5,0,0 );

        view.updateCamera = function(){

            // change the view so looking at the top of the airplane
            views[1].camera.position.set( 0,5,0 );
            views[1].camera.lookAt(objectManager.airplane.position);

            views[1].camera.updateProjectionMatrix();
        };
    }
});
function View(viewport, om, scene){
    this.scene = scene;
    this.camera;
    this.objectManager = om;
    this.viewPort = viewport;
    this.fov = 30;
    // default: full width and height
    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.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.makeCamera();
    };
    this.makeCamera = function(){
        this.camera = new THREE.PerspectiveCamera( 
                this.fov, 
                this.pixels.aspect, 
                0.1, 10000 
        );
        this.camera.updateProjectionMatrix();
        this.scene.add(this.camera);
    };
    this.render = function(scene, renderer){
        this.updateCamera();
        pixels = this.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, this.camera );
    };
    this.updateCamera = function(){};
}

function ObjectManager(){
    // manages all visible 3d objects (including lights)
    this.airplane;
    var grid;
    var ambientLight;
    var pointLight;
    this.construct = function(){
        this.constructAirplane();
        this.constructLights();
        this.constructFloorGrid();
    };
    this.constructAirplane = function(){
        this.airplane = new THREE.Object3D();
        var 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);
        var tail = newCube(
                {x: 0.15, y: 0.2, z: 0.03}, 
                {x: 0.5, y: 0.199, z: 0},
                [0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
                [0, 1, 2, 3, 4, 5]
        );
        this.airplane.add(tail);
        var wings = newCube(
                {x: 0.3, y: 0.05, z: 1},    
                {x: -0.05, y: 0, z: 0},
                [0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
                [0, 1, 2, 3, 4, 5]
        );
        this.airplane.add(wings);
    };
    this.constructLights = function(){
        ambientLight = new THREE.AmbientLight(0x808080);
        pointLight = new THREE.PointLight(0x808080);
        pointLight.position = {x: 100, y: 100, z: 100};
    };
    this.constructFloorGrid = function(){
        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 );
        }       
    };
    this.addToScene = function(scene){
        scene.add( this.airplane );
        scene.add( grid );
        scene.add( ambientLight );
        scene.add( pointLight );
    };
    this.tick = function(){
        this.airplane.rotation.x += 0.005;
        this.airplane.rotation.y += 0.01;
        this.airplane.position.x -= 0.05;
    };
};

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

The script below isn't working properly. (It just needs jquery and three.js to run). The troublesome lines are these two:

// change the view so looking at the top of the airplane
views[1].camera.position.set( 0,5,0 );
views[1].camera.lookAt(objectManager.airplane.position);

Strangely, if those two lines are mented out, it can be seen that the two similar preceeding lines below do run as expected:

views[1].camera.lookAt(objectManager.airplane.position);

and

view.camera.position.set( 5,0,0 );

For some reason it seems that the call to camera.lookAt only works the first time. After that, the camera no longer follows the airplane object. I'd be extremely grateful if someone can figure out what I'm doing wrong!

The full script is below.

Thanks

$(function(){
    var scene, renderer, viewPort, objectManager, views;

    init();
    animate();

    function init() {
        viewPort = $('body');

        scene = new THREE.Scene();

        // construct the two cameras
        initialiseViews();

        // construct airplane, lights and floor grid
        objectManager = new ObjectManager();
        objectManager.construct();
        objectManager.addToScene(scene);

        // make the second camera's position
        // stay fixed relative to the airplane
        objectManager.airplane.add(views[1].camera);

        // make the second camera stay looking
        // at the airplane
        views[1].camera.lookAt(objectManager.airplane.position);

        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();
        for (var i in views){
            views[i].render(scene, renderer);
        }
    }
    function initialiseViews(){
        views = [];

        // ----------------------------------------------------
        // Create the first view, static with respect to ground
        // ----------------------------------------------------
        views[0] = new View(viewPort, objectManager, scene);
        var view = views[0];
        view.fov = 40;
        view.proportions.height = 0.5;
        view.proportions.bottom = 0.5;
        view.init();
        view.camera.position.y = 1;
        view.camera.position.z = 4;

        // ----------------------------------------------------
        // Create the second view, which follows the airplane
        // ----------------------------------------------------

        views[1] = new View(viewPort, objectManager, scene);
        var view = views[1];

        view.fov = 20;
        view.proportions.height = 0.5;
        view.init();

        // set the initial position of the camera
        // with respect to the airplane. Views from behind
        view.camera.position.set( 5,0,0 );

        view.updateCamera = function(){

            // change the view so looking at the top of the airplane
            views[1].camera.position.set( 0,5,0 );
            views[1].camera.lookAt(objectManager.airplane.position);

            views[1].camera.updateProjectionMatrix();
        };
    }
});
function View(viewport, om, scene){
    this.scene = scene;
    this.camera;
    this.objectManager = om;
    this.viewPort = viewport;
    this.fov = 30;
    // default: full width and height
    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.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.makeCamera();
    };
    this.makeCamera = function(){
        this.camera = new THREE.PerspectiveCamera( 
                this.fov, 
                this.pixels.aspect, 
                0.1, 10000 
        );
        this.camera.updateProjectionMatrix();
        this.scene.add(this.camera);
    };
    this.render = function(scene, renderer){
        this.updateCamera();
        pixels = this.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, this.camera );
    };
    this.updateCamera = function(){};
}

function ObjectManager(){
    // manages all visible 3d objects (including lights)
    this.airplane;
    var grid;
    var ambientLight;
    var pointLight;
    this.construct = function(){
        this.constructAirplane();
        this.constructLights();
        this.constructFloorGrid();
    };
    this.constructAirplane = function(){
        this.airplane = new THREE.Object3D();
        var 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);
        var tail = newCube(
                {x: 0.15, y: 0.2, z: 0.03}, 
                {x: 0.5, y: 0.199, z: 0},
                [0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
                [0, 1, 2, 3, 4, 5]
        );
        this.airplane.add(tail);
        var wings = newCube(
                {x: 0.3, y: 0.05, z: 1},    
                {x: -0.05, y: 0, z: 0},
                [0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
                [0, 1, 2, 3, 4, 5]
        );
        this.airplane.add(wings);
    };
    this.constructLights = function(){
        ambientLight = new THREE.AmbientLight(0x808080);
        pointLight = new THREE.PointLight(0x808080);
        pointLight.position = {x: 100, y: 100, z: 100};
    };
    this.constructFloorGrid = function(){
        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 );
        }       
    };
    this.addToScene = function(scene){
        scene.add( this.airplane );
        scene.add( grid );
        scene.add( ambientLight );
        scene.add( pointLight );
    };
    this.tick = function(){
        this.airplane.rotation.x += 0.005;
        this.airplane.rotation.y += 0.01;
        this.airplane.position.x -= 0.05;
    };
};

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;
}
Share Improve this question asked Feb 8, 2013 at 12:06 JayyJayy 14.8k27 gold badges107 silver badges167 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 9 +50

You need to do this:

views[1].camera.position.set( 0, 5, 0 );
views[1].camera.lookAt( new THREE.Vector3() );

and not this:

views[1].camera.position.set( 0, 5, 0 );
views[1].camera.lookAt( objectManager.airplane.position );

Your camera is a child of the airplane. It needs to lookAt ( 0, 0, 0 ) in it's local coordinate system -- not the airplane's position in world space.

Your calls to updateProjectionMatrix() are not necessary. Copy the three.js examples.

发布评论

评论列表(0)

  1. 暂无评论