three.jsのサンプルをいじってカメラの動きを確認してみた

More than 1 year has passed since last update.

カメラ位置を自動で動かすなら、OrbitControlsは使えない

カメラ位置を自動で動かさないなら、OrbitControlsを使える


カメラ自動回転

render()部分のカメラの自動回転に着目。


javascript

// Detector.js webgl使えないブラウザへのサポート

// http://gupuru.hatenablog.jp/entry/2014/01/05/224813
if ( ! Detector.webgl ) {
Detector.addGetWebGLMessage();
document.getElementById( 'container' ).innerHTML = "";
}

var container, stats;
var camera, controls, scene, renderer;
var sphere;
var parameters = {
width: 2000,
height: 2000,
widthSegments: 250,
heightSegments: 250,
depth: 1500,
param: 4,
filterparam: 1
};
var waterNormals;

var clock = new THREE.Clock();

init();
animate();

function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );

renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 10000, 2000 );

scene.add( new THREE.AmbientLight( 0x444444 ) );

// 球の上のライト
var light = new THREE.DirectionalLight( 0xffffbb, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );

// 水面
waterNormals = new THREE.TextureLoader().load( 'img/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;

water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );

// 水面反射
mirrorMesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.material
);

mirrorMesh.add( water );
mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );

// load skybox 環境マッピング
// http://www.atmarkit.co.jp/ait/articles/1210/04/news142_3.html
var cubeMap = new THREE.CubeTexture( [] );
cubeMap.format = THREE.RGBFormat;

var loader = new THREE.ImageLoader();
loader.load( 'img/skyboxsun25degtest.png', function ( image ) {

var getSide = function ( x, y ) {

var size = 1024;

var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;

var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );

return canvas;

};

cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
cubeMap.needsUpdate = true;

} );

var cubeShader = THREE.ShaderLib[ 'cube' ];
cubeShader.uniforms[ 'tCube' ].value = cubeMap;

var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
var skyBox = new THREE.Mesh(
new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );

// 球体をつくる
// http://threejs.org/docs/#Reference/Extras.Geometries/IcosahedronGeometry
var geometry = new THREE.IcosahedronGeometry( 800, 1 );

// 一面づつ色を変える
for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
}

var material = new THREE.MeshPhongMaterial( {
vertexColors: THREE.FaceColors,
shininess: 100,
envMap: cubeMap
} );

sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );

// stats.js FPSを表示する
// http://tmlife.net/programming/javascript/lasted-stats-js-usage.html
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );

window.addEventListener( 'resize', onWindowResize, false );
}

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );
}

function animate() {
stats.update();
render();

requestAnimationFrame( animate );
}

function render() {
// カメラ回転
var theta = clock.getElapsedTime();
camera.position.x = 10000 * Math.sin(theta);
camera.position.y = 3000 * Math.cos(theta) + 3100; // 水面下に入らないように+100
camera.position.z = 10000 * Math.cos(theta);
camera.lookAt(new THREE.Vector3(0, 0, 0));

// 球
var time = performance.now() * 0.002; // 球のスピード
sphere.position.y = Math.sin( time ) * 1000 + 500;
sphere.rotation.x = time * 0.5;
sphere.rotation.z = time * 0.51;

// 海
water.material.uniforms.time.value += 50.0 / 60.0; // 波のスピード
water.render();

renderer.render( scene, camera );
}



カメラ手動回転

OrbitControlsの記述に着目。


javascript

if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

var stats;
var camera, controls, scene, renderer;

init();
animate();

function init() {

scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xB7B5DA, 0.002 );

renderer = new THREE.WebGLRenderer();
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );

var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );

camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;

// OrbitControls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enablePan = true;
controls.enableZoom = true;
controls.minDistance = -500.0;
controls.maxDistance = 800.0;
controls.target.set( 0, 0, 0 );
controls.maxPolarAngle = Math.PI * 1; // 0.5なら下からのぞき込めなくなる

// world
var geometry = new THREE.BoxGeometry(10, 25, 0);
var texture = new THREE.TextureLoader().load( 'img/hat.png' );
var material = new THREE.MeshPhongMaterial( { map: texture, transparent: true, side: THREE. BackSide } );

// ばらばらに配置
for ( var i = 0; i < 2000; i ++ ) {
mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
scene.add( mesh );
}

// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );

light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );

light = new THREE.AmbientLight( 0x222222 );
scene.add( light );

// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );

window.addEventListener( 'resize', onWindowResize, false );
}

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}

function animate() {
requestAnimationFrame( animate );
controls.update();
stats.update();
render();
}

function render() {
renderer.render( scene, camera );
}