【第4部】
様々なテクニック

  • 1. マウスによるカメラ操作
  • 2. マウスによるオブジェクトの操作
  • 3. フォグ効果
  • 4. オフスクリーンレンダリング

three.js におけるイベントの取り扱い

WebGLはHTML5の一部でしかなく、全てのイベントはHTML5(JavaScript)で管理する

three.jsではイベントを取り扱うものは全て外部ファイルで定義される

マウスによるカメラの操作

外部ファイルで定義されたクラスによって、カメラオブジェクトのパラメータが操作させる。

外部ファイル

  • トラックボールコントロール:TrackballControls.js
  • フライコントロール:FlyControls.js
  • ポインタロックコントロール:PointerLockControls.js

注意点

three.jsのリビジョンと同じリビジョンの外部ファイルを利用する必要がある

トラックボールの実装手順

Controls_TrackBall.html」ファイルをご覧ください

1.トラックボール用のライブラリの読み込み

<script src="javascript/TrackballControls_r66.js"></script>

2.トラックボールオブジェクトの用意

////////////////////////////////////////////////////////////////////
				// カメラ初期化関数の定義
				////////////////////////////////////////////////////////////////////
				//グローバル変数の宣言
				var camera;		//カメラオブジェクト
				var trackball; //トラックボールオブジェクト
				function initCamera() {
					(省略:カメラの準備)

					//トラックボールオブジェクトの宣言
					trackball = new THREE.TrackballControls(camera, canvasFrame);
					//トラックボール動作範囲のサイズとオフセットの設定
					trackball.screen.width = canvasFrame.clientWidth;											//横幅
					trackball.screen.height = canvasFrame.clientHeight;											//縦幅
					trackball.screen.offsetLeft = canvasFrame.getBoundingClientRect().left;	//左オフセット
					trackball.screen.offsetTop = canvasFrame.getBoundingClientRect().top;		//右オフセット

					//トラックボールの回転無効化と回転速度の設定
					trackball.noRotate = false;
					trackball.rotateSpeed = 3.0;  //<----------------------------------------------(※1)

					//トラックボールの拡大無効化と拡大速度の設定
					trackball.noZoom = false;
					trackball.zoomSpeed = 2.0;  //<------------------------------------------------(※2)

					//トラックボールのカメラ中心移動の無効化と中心速度の設定
					trackball.noPan = false;
					trackball.panSpeed = 0.5;  //<-------------------------------------------------(※3)
					trackball.target = new THREE.Vector3(0, 0, 0);

					//トラックボールのスタティックムーブの有効化
					trackball.staticMoving = true;
					//トラックボールのダイナミックムーブ時の減衰定数
					trackball.dynamicDampingFactor = 0.3;
				}

3.無限ループ関数内で情報の更新

					//トラックボールによるカメラオブジェクトのプロパティの更新
					trackball.update();
				

トラックボールコントロール

マウスの操作 カメラの動作
左ボタンによるマウスドラック カメラの位置座標と視野中心座標との距離を一定に保ちつつ、位置座標を移動(回転)する。
右ボタンによるマウスドラック カメラの位置座標と視野中心座標との関係を一定に保ちつつ、位置座標と視野中心座標を平行移動する。
ホイール回転 カメラの位置座標から視野中心座標へ方向を保ちつつ、距離を変更する。

フライコントロールの実装手順

Controls_fly.html」ファイルをご覧ください

1.フライコントロール用のライブラリの読み込み

<script src="javascript/FlyControls_r66.js"></script>

2.フライコントロールオブジェクトの用意

				////////////////////////////////////////////////////////////////////
				// カメラ初期化関数の定義
				////////////////////////////////////////////////////////////////////
				//グローバル変数の宣言
				var camera;	//カメラオブジェクト
				var control; //コントロールオブジェクト
				function initCamera() {
					(省略:カメラの準備)

					//フライコントロールオブジェクトの宣言
					control = new THREE.FlyControls(camera, canvasFrame);
					
					//カメラ座標の前進・後退速度	
					control.movementSpeed = 100.0;  //<----------------------------------------------(※1)
					//カメラ座標の回転速度
					control.rollSpeed = Math.PI / 6;  //<------------------------------------------------(※2)

					//自動前進の有無
					control.autoForward = false;  //<-------------------------------------------------(※3)

					//マウスドラックによるカメラの回転
					control.dragToLook = false;

				}
				

3.無限ループ関数内で情報の更新

				var nowTime = new Date();								//現在時刻オブジェクトの取得
				var delta = (nowTime - lastTime) / 1000;	//1フレームあたりの経過時間
				lastTime = nowTime;											//基準時刻オブジェクトの更新
				//フライコントロールによるカメラオブジェクトのプロパティの更新
				control.update(delta);
				

フライコントロールによる操作

マウスの操作 カメラの動作
マウスポインタの位置 カメラの視野中心座標を移動する。
左ボタンの押し続け カメラの位置座標が視野中心座標に向かって移動する。
右ボタンの押し続け カメラの位置座標が視野中心座標の反対方向に向かって移動する。
キーボードの操作 カメラの動作
「↑」「→」「↓」「←」 マウスポインタによる操作と同じ
「D」「A」 カメラの向きを一定に保ちながら、視野中心座標を移動する。
「W」「S」 「左ボタンの押し続け」「右ボタンの押し続け」と同じ
「Q」「E」 カメラの上ベクトルを回転する。

ポインタロックコントロールの実装手順

Controls_PointerLock.html」ファイルをご覧ください

1.ポインタロックコントロール用のライブラリの読み込み

				<script src="javascript/PointerLockControls_r66.js"></script>

2.ポインタロックコントロールオブジェクトの用意

				////////////////////////////////////////////////////////////////////
				// カメラ初期化関数の定義
				////////////////////////////////////////////////////////////////////
				//グローバル変数の宣言
				var camera;	//カメラオブジェクト
				var control; //コントロールオブジェクト
				function initCamera() {
					(省略:カメラの準備)

					//ポインタロックコントロールオブジェクトの宣言
					control = new THREE.PointerLockControls(camera);
					scene.add( control.getObject() );

					//ポインタロックイベントの追加  //<----------------------------------------------(※1)
					document.addEventListener('pointerlockchange', pointerlockchange);
					document.addEventListener('webkitpointerlockchange', pointerlockchange);

					//ポインタロックの変更時に呼び出される関数  //<------------------------------------(※2)
					function pointerlockchange( event ) {
						if (document.pointerLockElement === document.body || document.webkitPointerLockElement === document.body) {
							control.enabled = true;
						} else {
							control.enabled = false;
						}
					}
					//キャンバスフレーム要素をクリックしたときのイベント登録  //<----------------------------(※3)
					canvasFrame.addEventListener('click', function (event) {
						//ポインタロック用メソッドを再定義
						document.body.requestPointerLock = document.body.requestPointerLock || document.body.webkitRequestPointerLock;
						//ポインタロックを有効
						document.body.requestPointerLock();
					}, false);
				}
				

3.無限ループ関数内で情報の更新

					var nowTime = new Date();                   //現在時刻オブジェクトの取得
					var delta = (nowTime - lastTime) / 1000;	//1フレームあたりの経過時間
					lastTime = nowTime;							//基準時刻オブジェクトの更新
					//ポインタロックコントロールによるカメラオブジェクトのプロパティの更新
					control.update(delta);
				

ポインタロックコントロールによる操作

マウスの操作 カメラの動作
マウスポインタの位置 カメラの視野中心座標を移動する(マウスポインタは非表示)。
キーボードの操作 カメラの動作
「↑」「→」「↓」「←」 カメラの向きを一定に保ちながら、視野中心座標を移動する。
「W」「D」「S」「A」 「↑」「→」「↓」「←」と同じ。
「スペース」 ジャンプ!

ポインタロックは「ESC」ボタンで解除

  • 1. マウスによるカメラ操作
  • 2. マウスによるオブジェクトの操作
  • 3. フォグ効果
  • 4. オフスクリーンレンダリング

マウスポインタによる
3次元空間内オブジェクトの選択

光線を発射し、貫いた3次元オブジェクトを取得する

光線が貫いたオブジェクトの3次元座標を取得できる!

実装手順

Cubes_Raycaster.html」ファイルをご覧ください

1.対象となるオブジェクトの登録

				////////////////////////////////////////////////////////////////////
				// オブジェクト初期化関数の定義
				////////////////////////////////////////////////////////////////////
				//グローバル変数の宣言
				var axis;				//軸オブジェクト
				var cubes = [];	//立方体オブジェクト
				var rayReceiveObjects = []; //光線を受けるオブジェクト配列
				function initObject() {
				(省略:立方体の準備)

				//光線受信判定用
				cubes[0].name = "箱1";
				cubes[1].name = "箱2";
				cubes[2].name = "箱3";
				//光線受信オブジェクト配列へ追加
				rayReceiveObjects.push( cubes[0] );  //<----この配列に格納されたオブジェクトのみを対象とする
				rayReceiveObjects.push( cubes[1] );
				rayReceiveObjects.push( cubes[2] );
				}
				

2.クリックイベントを定義

				////////////////////////////////////////////////////////////////////
				// イベント準備関数
				////////////////////////////////////////////////////////////////////
				function initEvent() {
					//マウスダウンイベント
					canvasFrame.addEventListener( 'mousedown', onDocumentMouseDown, false );
					function onDocumentMouseDown( event ) {
						//イベントの伝播の無効化
						event.preventDefault();
						//マウスポインタの位置座標の取得  //<--------------- x:[-1, 1], y:[-1, 1] の座標系として取得
						var mx = (event.clientX / canvasFrame.clientWidth) * 2 - 1;
						var my = -(event.clientY / canvasFrame.clientHeight) * 2 + 1;
						var vector = new THREE.Vector3(mx, my, 0);

						//プロジェクターオブジェクトの生成
						var projector = new THREE.Projector();
						//逆投影変換を行うことで仮想空間内のベクトルへと変換する
						vector = projector.unprojectVector( vector, camera );
						//カメラ位置座標を起点として規格化を行う
						vector = vector.sub( camera.position ).normalize();
						//カメラ位置座標から光線を発射
						var raycaster = new THREE.Raycaster( camera.position, vector );
						//光線と交わるオブジェクトを収集
						var intersects = raycaster.intersectObjects( rayReceiveObjects );
						//交わるオブジェクトが1個以上の場合
						if ( intersects.length > 0 ) {
							//最も近いオブジェクトの名前をアラート表示する
							alert(intersects[0].object.name + "がクリックされました!");
							console.log("カメラ位置座標からの距離:" + intersects[0].distance);
							console.log("光線との交差座標(" + intersects[0].point.x + ", " + intersects[0].point.y + ", " + intersects[0].point.z + ")" );
						}
					}
				}
				

マウスポインタによる
3次元空間内オブジェクトの移動

マウスドラックでオブジェクトを移動する

オブジェクト移動までの概要

1.マウスオーバーした(光線が貫いた)オブジェクトの稼働域を取得する

2.マウスドラック中は平面オブジェクトと光線との交点座標をオブジェクトの座標とする

オブジェクト移動までの概要

Cubes_Raycaster_draggablecubes.html
ファイルをご覧ください

				////////////////////////////////////////////////////////////////////
				// イベント準備関数
				////////////////////////////////////////////////////////////////////
				function initEvent() {
					canvasFrame.addEventListener('mousemove', onDocumentMouseMove, false);
					canvasFrame.addEventListener('mousedown', onDocumentMouseDown, false);
					canvasFrame.addEventListener('mouseup'	, onDocumentMouseUp,	false);

					//マウスクリック時の選択したオブジェクト中心からのマウスポインタのズレ
					var offset = new THREE.Vector3();
					var INTERSECTED; //マウスポインタが指しているオブジェクト 
					var SELECTED;		//マウスドラック中のオブジェクト
					function onDocumentMouseMove(event) {
						//マウスポインタの位置座標の取得
						var mx = (event.clientX / canvasFrame.clientWidth) * 2 - 1;
						var my = -(event.clientY / canvasFrame.clientHeight) * 2 + 1;
						var vector = new THREE.Vector3(mx, my, 0.5);
						//プロジェクターオブジェクトの生成
						var projector = new THREE.Projector();
						//逆投影変換を行うことで仮想空間内のベクトルへと変換する
						vector = projector.unprojectVector( vector, camera );
						//カメラ位置座標を起点として規格化を行う
						vector = vector.sub( camera.position ).normalize();
						//カメラ位置座標から光線を発射
						var raycaster = new THREE.Raycaster( camera.position, vector );

						//オブジェクトがマウスドラックされている時
						if (SELECTED) {
							//光線と交わる平面オブジェクトオブジェクトを収集
							var intersects = raycaster.intersectObject(plane);
							//マウスドラック時のマウスポインタの指している平面オブジェクトの3次元空間中の位置座標
							var vec3 = intersects[0].point;
							//マウスドラックされているオブジェクトを移動
							SELECTED.position.copy(vec3.sub(offset));
							return;
						}
						//光線と交わるオブジェクトを収集
						var intersects = raycaster.intersectObjects( rayReceiveObjects )
						//マウスポインタがオブジェクト上にある場合
						if (intersects.length > 0) {
							if (INTERSECTED != intersects[0].object) {
								//マウスポインタが指しているオブジェクトが登録されていなければ、一番手前のオブジェクトを「INTERSECTED」に登録
								INTERSECTED = intersects[0].object;
								//平面オブジェクトの位置座標を「INTERSECTED」に登録されたオブジェクトと同じ位置座標とする
								plane.position.copy(INTERSECTED.position);
								//平面オブジェクトの上ベクトルをカメラの位置座標の方向へ向ける
								plane.lookAt(camera.position);
							}
							//マウスポインタのカーソルを変更
							canvasFrame.style.cursor = 'pointer';
						} else {
							//マウスポインタがオブジェクトから離れている場合
							INTERSECTED = null;
							//マウスポインタのカーソルを変更
							canvasFrame.style.cursor = 'auto';
						}
					}

					function onDocumentMouseDown(event) {
						//マウスポインタの位置座標の取得
						var mx = (event.clientX / canvasFrame.clientWidth) * 2 - 1;
						var my = -(event.clientY / canvasFrame.clientHeight) * 2 + 1;
						var vector = new THREE.Vector3(mx, my, 0.5);
						//プロジェクターオブジェクトの生成
						var projector = new THREE.Projector();
						//逆投影変換を行うことで仮想空間内のベクトルへと変換する
						vector = projector.unprojectVector( vector, camera );
						//カメラ位置座標を起点として規格化を行う
						vector = vector.sub( camera.position ).normalize();
						//カメラ位置座標から光線を発射
						var raycaster = new THREE.Raycaster( camera.position, vector );
						//光線と交わるオブジェクトを収集
						var intersects = raycaster.intersectObjects( rayReceiveObjects );
						//交わるオブジェクトが1個以上の場合
						if (intersects.length > 0) {
							//クリックされたオブジェクトを「SELECTED」に登録
							SELECTED = intersects[0].object;

							//光線と交わる平面オブジェクトオブジェクトを収集
							var intersects = raycaster.intersectObject(plane);
							//クリック時のマウスポインタの指した平面オブジェクトの3次元空間中の位置座標
							var vec3 = intersects[0].point;
							//平面オブジェクトの中心から見た相対的な位置座標
							offset.copy(vec3).sub(plane.position);
							//マウスポインタのカーソルを変更
							canvasFrame.style.cursor = 'move';
						}
					}
					function onDocumentMouseUp(event) {
						//マウスアップ時にマウスポインタがオブジェクト上にある場合
						if (INTERSECTED) {
							//平面オブジェクトの位置座標をオブジェクトの位置座標に合わせる
							plane.position.copy(INTERSECTED.position);
							//マウスドラックの解除
							SELECTED = null;
						}
						//マウスポインタのカーソルを変更
						canvasFrame.style.cursor = 'auto';
					}
				}
				

+トラックボールコントロール

Cubes_Raycaster_draggablecubes_tracball.html
ファイルをご覧ください

trackball.enabled = 「true」 or 「false」
を適宜切り替える

  • 1. マウスによるカメラ操作
  • 2. マウスによるオブジェクトの操作
  • 3. フォグ効果
  • 4. オフスクリーンレンダリング

フォグとは

カメラからの距離に応じて、
3次元オブジェクトをぼやかすための手法。 → 大気効果

フォグなしの場合

フォグの種類

1.線形関数フォグ:距離に比例した効果(実装結果

2.指数関数フォグ:距離に指数関数的な効果(実装結果

フォグの実装方法

Fog.html」ファイルをご覧ください

1.線形関数フォグ:距離に比例した効果(実装結果

				////////////////////////////////////////////////////////////////////
				// Three.js初期化関数の定義
				////////////////////////////////////////////////////////////////////
				//グローバル変数の宣言(省略)
				function initThree() {
				(省略)
					//レンダラークリアーカラーの設定
					renderer.setClearColor( 0xE1FCFF, 1.0 );
					//シーンオブジェクトの生成
					scene = new THREE.Scene();
					//線形フォグの設定
					scene.fog = new THREE.Fog( 0xE1FCFF, 10, 500 );	// 引数(フォグ色, near, far)
				}
				

2.指数関数フォグ:距離に指数関数的な効果(実装結果

					//指数関数フォグの設定
					scene.fog = new THREE.FogExp2(0xE1FCFF, 1.0/100); // 引数( フォグ色, density )
				
  • 1. マウスによるカメラ操作
  • 2. マウスによるオブジェクトの操作
  • 3. フォグ効果
  • 4. オフスクリーンレンダリング

オフスクリーンレンダリングとは?

描画用レンダリング以外を目的としたレンダリング

主な用途:RTT(Real Time Texturing)

テクスチャ用の画像をリアルタイムにレンダリングで生成

実装方法 (RTT.html)

1.RTT用シーンオブジェクトの追加

				////////////////////////////////////////////////////////////////////
				// Three.js初期化関数の定義
				////////////////////////////////////////////////////////////////////
				 function initThree() {
					(省略)
					//RTTシーンオブジェクトの生成
					sceneRTT = new THREE.Scene();
				}
				

2.RTT用シーンの追加

			////////////////////////////////////////////////////////////////////
			// オブジェクト初期化関数の定義
			////////////////////////////////////////////////////////////////////
			//グローバル変数の宣言(省略)
			function initObject() {
				(省略)
				//形状オブジェクトの宣言と生成
				var geometry = new THREE.TorusKnotGeometry(40, 5, 200, 200, 2, 3, 2);
				//材質オブジェクトの宣言と生成
				var material = new THREE.MeshNormalMaterial({ shading: THREE.SmoothShading });
				//トーラスオブジェクトの生成
				torusKnot = new THREE.Mesh(geometry, material);
				//トーラスオブジェクトのシーンへの追加
				sceneRTT.add( torusKnot );

				//RTT用テクスチャオブジェクトの生成
				RTTexture = new THREE.WebGLRenderTarget(256, 256);
				//形状オブジェクトの宣言と生成
				var geometry = new THREE.PlaneGeometry(100, 100);
				//材質オブジェクトの宣言と生成
				var material = new THREE.MeshBasicMaterial({color:0xffffff, map: RTTexture});
				//平面オブジェクトの生成
				plane = new THREE.Mesh(geometry, material);
				//平面オブジェクトのシーンへの追加
				scene.add(plane);
			}

3.RTT用レンダリングの実行

			////////////////////////////////////////////////////////////////////
			// 無限ループ関数の定義
			////////////////////////////////////////////////////////////////////
			//グローバル変数の宣言(省略)
			function loop() {
			(省略)
				torusKnot.rotation.set(step/50, step/70, step/90);
				//クリアーカラーで初期化
				renderer.clear();
				//レンダラークリアーカラーの設定
				renderer.setClearColor(0x000000, 1.0);
				//RTT用テクスチャオブジェクトへのレンダリング
				renderer.render( sceneRTT, camera, RTTexture);
				(省略)
			}

【第4部】
様々なテクニック
終了

three.jsの始め方