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


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

## カメラ自動回転

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


```javascript: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: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 );
}

```