Three.js 3Dモデルをマウスでクリック(ピッキング処理)
3Dプリンター楽しすぎです(笑)
「3Dプリンターで印刷できる3Dモデルを無料でダウンロード出来るサイト」って、ないのかな??
無いなら、つくろうかな・・・あると、便利な気がする。
今回は、「Three.jsの3Dモデル」をマウスでクリックする方法を書きます。
専門的には、「ピッキング処理」と言うのかな??
ちなみに、これはThree.jsの標準機能の一つです。
まずは、実際のソースコードから~
・クリック判定の部分(ピッキング処理)
var projector = new THREE.Projector(); //マウスのグローバル変数 var mouse = { x: 0, y: 0 }; //オブジェクト格納グローバル変数 var targetList = []; //マウスが押された時 window.onmousedown = function (ev){ if (ev.target == renderer.domElement) { //マウス座標2D変換 var rect = ev.target.getBoundingClientRect(); mouse.x = ev.clientX - rect.left; mouse.y = ev.clientY - rect.top; //マウス座標3D変換 width(横)やheight(縦)は画面サイズ mouse.x = (mouse.x / width) * 2 - 1; mouse.y = -(mouse.y / height) * 2 + 1; // マウスベクトル var vector = new THREE.Vector3( mouse.x, mouse.y ,1); // vector はスクリーン座標系なので, オブジェクトの座標系に変換 projector.unprojectVector( vector, camera ); // 始点, 向きベクトルを渡してレイを作成 var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() ); // クリック判定 var obj = ray.intersectObjects( targetList ); // クリックしていたら、alertを表示 if ( obj.length > 0 ){ alert("click!!") } } };
・「立方体」の生成の部分
//「立方体」の生成 var cube = new THREE.Mesh( //立方体の大きさ(300,300,300) new THREE.CubeGeometry(300,300,300), new THREE.MeshPhongMaterial({ color: 0x990000 //球の色 })); //sceneにcubeを追加 scene.add(cube); //targetListにcubeを入れる targetList.push(cube);
これらの実行例がコレです。(分かりやすくするため、「地面」,「立方体にテクスチャ 貼付け」,「xyz軸」,を追加しています。)
真ん中にある立方体をマウスで、クリックするとalertがでます。
画像の通り、ちゃんとalertが出ています。どの角度からクリックしても反応します。
では、詳しく見ていきます。
重要なのは、
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() ); var obj = ray.intersectObjects( targetList ); // クリックしていたら、alertを表示 if ( obj.length > 0 ){ alert("click!!") }
ここです。ここで、3Dモデルがクリックされたかの判定を行っています。
THREE.Raycasterクラスには、「intersectObjects」という交差判定を行うメソッドが用意されています。
第一引数にメッシュのリストを渡すと、全てのメッシュとの交差判定を行うことができて、交差したメッシュのみのをリストとして返してくれます。
intersectObjectsの結果のlengthが0より大きければ、衝突しています。
targetListの中には、オブジェクトを入れています。
targetList.push(cube);
このような形で、入れています。
次は、マウス座標を取得している所です。
//マウス座標2D変換① var rect = ev.target.getBoundingClientRect(); mouse.x = ev.clientX - rect.left; mouse.y = ev.clientY - rect.top; //マウス座標3D変換② mouse.x = (mouse.x / width) * 2 - 1; mouse.y = -(mouse.y / height) * 2 + 1;
①で取得したのは、マウス2D座標です。①の座標を②の部分で3D座標に変換しています。
width,heightは、画面サイズです。widthは横,heightは縦です。
「* 2 - 1」,「* 2 + 1」等で、X軸,Y軸共に「-1 ~ 1」の間に収まるように調整しています。
簡単に、マウスのクリック判定ができるので、便利です。
他にも、これを応用すると、「マウスカーソルが重なった時・・・」などのこともできます。
これで終わりです。
ご不明な点などがありましたら、遠慮なくご質問ください。
ありがとうございました!