bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

three.jsとdat.guiで遊ぶ

テスト的なものを作ってみた。
カメラは制約付きで球上を動きます。
http://dl.dropbox.com/u/67579260/sample.html

コードはサンプルの改造程度のもの。

<!doctype html>
<html lang="en">
	<head>
		<title>three.js, dat.GUI</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: Monospace;
				background-color: #f0f0f0;
				margin: 10px;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		
		<script src="mrdoob-three.js-a4088b8/build/Three.js"></script>
		<script src="mrdoob-three.js-a4088b8/examples/js/Stats.js"></script>
		<script src="dat/dat.gui.min.js"></script>
		
		<script>
			
			var CameraController = function(theta, phi, radius)
			{
				this.name = "Camera Controller";
				this.theta = theta;
				this.phi = phi;
				this.radius = radius;
				
				this.update = function(refCamera)
				{
					refCamera.position.x = this.radius*Math.sin(this.theta*Math.PI/180.0)*Math.cos(this.phi*Math.PI/180.0);
					refCamera.position.y = this.radius*Math.cos(this.theta*Math.PI/180.0);
					refCamera.position.z = this.radius*Math.sin(this.theta*Math.PI/180.0)*Math.sin(this.phi*Math.PI/180.0);
					refCamera.lookAt({x:0, y:0, z:0});
				};
			}
			
			var targetRotation = 0;
			var targetRotationOnMouseDown = 0;
			var mouseX = 0;
			var mouseXOnMouseDown = 0;
			var windowHalfX = window.innerWidth / 2;
			var windowHalfY = window.innerHeight / 2;
			init();
			animate();
			
			var container;
			function initContainer()
			{
				container = document.createElement( 'div' );
				document.body.appendChild( container );
				
				var info = document.createElement( 'div' );
				info.style.position = 'absolute';
				info.style.top = '10px';
				info.style.width = '100%';
				info.style.textAlign = 'center';
				info.innerHTML = 'Drag to spin the cube';
				container.appendChild( info );
			}
			
			var camera, cameraController, scene;
			function initScene()
			{
				scene = new THREE.Scene();
				
				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
				camera.position.x = 500;
				camera.position.y = 500;
				camera.position.z = 500;
				camera.lookAt(new THREE.Vector3(0,0,0));
				scene.add( camera );
				cameraController = new CameraController(45, 45, 1000);
				
				initObjects();
			}
			
			var cube, plane;
			function initObjects()
			{
				// AxisX
				var axisX = new THREE.Geometry();
				axisX.vertices.push(new THREE.Vertex(new THREE.Vector3(0,0,0)));
				axisX.vertices.push(new THREE.Vertex(new THREE.Vector3(10000,0,0)));
				scene.add(new THREE.Line(axisX, new THREE.LineBasicMaterial({color:0xff0000, opacity:1.0})));
				// AxisY
				var axisY = new THREE.Geometry();
				axisY.vertices.push(new THREE.Vertex(new THREE.Vector3(0,0,0)));
				axisY.vertices.push(new THREE.Vertex(new THREE.Vector3(0,10000,0)));
				scene.add(new THREE.Line(axisY, new THREE.LineBasicMaterial({color:0x00ff00, opacity:1.0})));
				var axisZ = new THREE.Geometry();
				axisZ.vertices.push(new THREE.Vertex(new THREE.Vector3(0,0,0)));
				axisZ.vertices.push(new THREE.Vertex(new THREE.Vector3(0,0,10000)));
				scene.add(new THREE.Line(axisZ, new THREE.LineBasicMaterial({color:0x0000ff, opacity:1.0})));
				
				// Cube
				var materials = [];
				for ( var i = 0; i < 6; i ++ ) 
				{
					materials.push( new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) );
				}
				cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200, 1, 1, 1, materials ), new THREE.MeshFaceMaterial() );
				scene.add( cube );
			}
			
			var renderer;
			function initRenderer()
			{
				renderer = new THREE.CanvasRenderer();
				renderer.setSize( window.innerWidth, window.innerHeight );
				container.appendChild( renderer.domElement );
			}
			
			var stats;
			function initStats()
			{
				stats = new Stats();
				stats.domElement.style.position = 'absolute';
				stats.domElement.style.top = '0px';
				container.appendChild( stats.domElement );
			}
			
			function initDAT()
			{
				var gui = new dat.GUI();
				gui.add(cameraController, 'name');
				gui.add(cameraController, 'theta', 10.0, 170.0, 0.1);
				gui.add(cameraController, 'phi', 0, 359, 0.1);
				gui.add(cameraController, 'radius', 1000, 3000, 10);
			}
			
			function initEventListener()
			{
				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
			}
			
			function init()
			{
				initContainer();
				initScene();
				initRenderer();
				initStats();
				initDAT();
				initEventListener();
			}
			
			//
			
			function onDocumentMouseDown( event )
			{
				event.preventDefault();
				
				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
				document.addEventListener( 'mouseup', onDocumentMouseUp, false );
				document.addEventListener( 'mouseout', onDocumentMouseOut, false );
				
				mouseXOnMouseDown = event.clientX - windowHalfX;
				targetRotationOnMouseDown = targetRotation;
			}

			function onDocumentMouseMove( event )
			{
				mouseX = event.clientX - windowHalfX;
				targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
			}

			function onDocumentMouseUp( event )
			{
				document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
				document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
				document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
			}

			function onDocumentMouseOut( event )
			{
				document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
				document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
				document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
			}

			function onDocumentTouchStart( event )
			{
				if ( event.touches.length == 1 ) {
					event.preventDefault();
					mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
					targetRotationOnMouseDown = targetRotation;
				}
			}

			function onDocumentTouchMove( event )
			{
				if ( event.touches.length == 1 ) {
					event.preventDefault();
					mouseX = event.touches[ 0 ].pageX - windowHalfX;
					targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
				}
			}

			//

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

			function render() {
				//plane.rotation.z = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05;
				cameraController.update( camera );
				renderer.render( scene, camera );
			}

		</script>

	</body>
</html>