WebGLはHTML5の一部でしかなく、全てのイベントはHTML5(JavaScript)で管理する
three.jsではイベントを取り扱うものは全て外部ファイルで定義される
外部ファイルで定義されたクラスによって、カメラオブジェクトのパラメータが操作させる。
three.jsのリビジョンと同じリビジョンの外部ファイルを利用する必要がある
「Controls_TrackBall.html」ファイルをご覧ください
<script src="javascript/TrackballControls_r66.js"></script>
//////////////////////////////////////////////////////////////////// // カメラ初期化関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言 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; }
//トラックボールによるカメラオブジェクトのプロパティの更新 trackball.update();
マウスの操作 | カメラの動作 |
---|---|
左ボタンによるマウスドラック | カメラの位置座標と視野中心座標との距離を一定に保ちつつ、位置座標を移動(回転)する。 |
右ボタンによるマウスドラック | カメラの位置座標と視野中心座標との関係を一定に保ちつつ、位置座標と視野中心座標を平行移動する。 |
ホイール回転 | カメラの位置座標から視野中心座標へ方向を保ちつつ、距離を変更する。 |
「Controls_fly.html」ファイルをご覧ください
<script src="javascript/FlyControls_r66.js"></script>
//////////////////////////////////////////////////////////////////// // カメラ初期化関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言 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; }
var nowTime = new Date(); //現在時刻オブジェクトの取得 var delta = (nowTime - lastTime) / 1000; //1フレームあたりの経過時間 lastTime = nowTime; //基準時刻オブジェクトの更新 //フライコントロールによるカメラオブジェクトのプロパティの更新 control.update(delta);
マウスの操作 | カメラの動作 |
---|---|
マウスポインタの位置 | カメラの視野中心座標を移動する。 |
左ボタンの押し続け | カメラの位置座標が視野中心座標に向かって移動する。 |
右ボタンの押し続け | カメラの位置座標が視野中心座標の反対方向に向かって移動する。 |
キーボードの操作 | カメラの動作 |
---|---|
「↑」「→」「↓」「←」 | マウスポインタによる操作と同じ |
「D」「A」 | カメラの向きを一定に保ちながら、視野中心座標を移動する。 |
「W」「S」 | 「左ボタンの押し続け」「右ボタンの押し続け」と同じ |
「Q」「E」 | カメラの上ベクトルを回転する。 |
「Controls_PointerLock.html」ファイルをご覧ください
<script src="javascript/PointerLockControls_r66.js"></script>
//////////////////////////////////////////////////////////////////// // カメラ初期化関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言 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); }
var nowTime = new Date(); //現在時刻オブジェクトの取得 var delta = (nowTime - lastTime) / 1000; //1フレームあたりの経過時間 lastTime = nowTime; //基準時刻オブジェクトの更新 //ポインタロックコントロールによるカメラオブジェクトのプロパティの更新 control.update(delta);
マウスの操作 | カメラの動作 |
---|---|
マウスポインタの位置 | カメラの視野中心座標を移動する(マウスポインタは非表示)。 |
キーボードの操作 | カメラの動作 |
---|---|
「↑」「→」「↓」「←」 | カメラの向きを一定に保ちながら、視野中心座標を移動する。 |
「W」「D」「S」「A」 | 「↑」「→」「↓」「←」と同じ。 |
「スペース」 | ジャンプ! |
ポインタロックは「ESC」ボタンで解除
光線を発射し、貫いた3次元オブジェクトを取得する
光線が貫いたオブジェクトの3次元座標を取得できる!
「Cubes_Raycaster.html」ファイルをご覧ください
//////////////////////////////////////////////////////////////////// // オブジェクト初期化関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言 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] ); }
//////////////////////////////////////////////////////////////////// // イベント準備関数 //////////////////////////////////////////////////////////////////// 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 + ")" ); } } }
マウスドラックでオブジェクトを移動する
「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」
を適宜切り替える
カメラからの距離に応じて、
3次元オブジェクトをぼやかすための手法。
→ 大気効果
「Fog.html」ファイルをご覧ください
//////////////////////////////////////////////////////////////////// // Three.js初期化関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言(省略) function initThree() { (省略) //レンダラークリアーカラーの設定 renderer.setClearColor( 0xE1FCFF, 1.0 ); //シーンオブジェクトの生成 scene = new THREE.Scene(); //線形フォグの設定 scene.fog = new THREE.Fog( 0xE1FCFF, 10, 500 ); // 引数(フォグ色, near, far) }
//指数関数フォグの設定 scene.fog = new THREE.FogExp2(0xE1FCFF, 1.0/100); // 引数( フォグ色, density )
描画用レンダリング以外を目的としたレンダリング
テクスチャ用の画像をリアルタイムにレンダリングで生成
////////////////////////////////////////////////////////////////////
// Three.js初期化関数の定義
////////////////////////////////////////////////////////////////////
function initThree() {
(省略)
//RTTシーンオブジェクトの生成
sceneRTT = new THREE.Scene();
}
//////////////////////////////////////////////////////////////////// // オブジェクト初期化関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言(省略) 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); }
//////////////////////////////////////////////////////////////////// // 無限ループ関数の定義 //////////////////////////////////////////////////////////////////// //グローバル変数の宣言(省略) function loop() { (省略) torusKnot.rotation.set(step/50, step/70, step/90); //クリアーカラーで初期化 renderer.clear(); //レンダラークリアーカラーの設定 renderer.setClearColor(0x000000, 1.0); //RTT用テクスチャオブジェクトへのレンダリング renderer.render( sceneRTT, camera, RTTexture); (省略) }