javascript - examples - three.js tutorial
THREE.js: llamar al método lookAt una vez que la representación no funciona (1)
El script a continuación no funciona correctamente. (Solo necesita jquery y three.js para ejecutar). Las líneas problemáticas son estas dos:
// 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);
Extrañamente, si esas dos líneas están comentadas, se puede ver que las dos líneas anteriores similares se ejecutan como se esperaba:
views[1].camera.lookAt(objectManager.airplane.position);
y
view.camera.position.set( 5,0,0 );
Por alguna razón, parece que la llamada a camera.lookAt solo funciona la primera vez. Después de eso, la cámara ya no sigue el objeto del avión. ¡Estaría extremadamente agradecido si alguien puede descubrir lo que estoy haciendo mal!
El guion completo está abajo.
Gracias
$(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;
}
Usted necesita hacer ésto:
views[1].camera.position.set( 0, 5, 0 );
views[1].camera.lookAt( new THREE.Vector3() );
y no esto:
views[1].camera.position.set( 0, 5, 0 );
views[1].camera.lookAt( objectManager.airplane.position );
Tu cámara es hija del avión. Necesita mirar A ( 0, 0, 0 )
en su sistema de coordenadas local, no la position
del avión en el espacio mundial.
Sus llamadas a updateProjectionMatrix()
no son necesarias. Copie los ejemplos de three.js.