Three.js 選擇拾取對象學習總結

Three.js 選擇對象的本質是從點擊位置發射光線,但屏幕座標系與webgl座標系是不同的,而把屏幕的二維座標轉化爲三維座標就是關鍵,做一步換算後交由Raycaster的setFromCamera方法即可。
所以思路如下:
1.獲取屏幕座標(x, y)
2.換算至webgl座標中的(x2,y2),此時長度仍爲像素單位下的長度
3.由於webgl座標軸的範圍爲(-1,1),做個比值,稱爲標準化
4.Raycaster.setFromCamera(mouse, camera)發射射線
5.Raycaster.intersectObjects獲取射得的所有對象,再按需要操作

先對比下各座標軸,再按代碼分析步驟

代碼中使用了我封裝的方法,threeConf對象包含three.js的基本組件,但不影響拾取對象的邏輯,拾取的代碼於此

一、座標軸

1.屏幕座標軸

即我們的屏幕的二維座標,矩形爲我們的屏幕,左上角就是(0, 0)

clipboard.png

2.世界座標系

即webgl中的座標系,屏幕中心爲(0, 0, 0),第三個座標爲從屏幕指向我們的z軸。三個座標的大小範圍爲(-1,1),如圖

clipboard.png

這裏其實還有個相機座標系,因爲還沒有學習webgl或者opengl怕胡說八道,我覺得一篇很棒的blog貼於文末
但是我們實現選擇拾取功能時,但單純從three.js角度來看可以不需要相關知識

二、代碼思路

代碼較長,這裏截取部分代碼按思路來,全部代碼請看GitHub

1.座標標準化

//1.獲取屏幕座標(x, y)
//2.換算至webgl座標中的(x2,y2),此時長度單位仍爲像素
//3.由於webgl座標軸的範圍爲(-1,1),做個比值,稱爲標準化
//這三步後化簡的式子如下,這裏我們three.js的窗口爲整個瀏覽器
let rayRaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();
function onMouseMove(event) {
    mouse.x = (event.clientX/window.innerWidth) * 2 - 1;
    mouse.y =  1 -(event.clientY/window.innerHeight) * 2 ;
}
window.addEventListener('mousemove', onMouseMove, false);

x1 = event.clientX,y1 = event.clientY,即點擊位置,換算過程如下(這裏默認畫布寬高爲瀏覽器寬高)
圖片描述
根據式子帶入x1與y1即可得到代碼中相同的式子

2.發射射線,獲取對象

這裏截取射線代碼

function render() {
    //射線射出
    rayRaster.setFromCamera(mouse, threeConf.camera);
    //射線上的物體
    let intersects = rayRaster.intersectObjects(threeConf.scene.children);
    //選中另一物體的情況,仍爲同一物體則不更新,這裏我們只拿第一個物體
    if(selectedObj !== intersects[0]){
        selectedObj && selectedObj.object.material.color.set(0x87CEEB); //復原
        intersects.length && intersects[0].object.material.color.set(0xff0000);
        selectedObj = intersects[0];
        document.body.style.cursor = "pointer";
    }
    //未選中物體情況
    if(intersects[0] === undefined){
        document.body.style.cursor = "auto";
    }
    threeConf.stats.update();
    threeConf.renderer.render(threeConf.scene, threeConf.camera);
    requestAnimationFrame(render);
}

即可

三、參考資料
ThreeJS中的點擊與交互——Raycaster的用法
https://segmentfault.com/a/11...

OpenGL.座標系統的介紹與座標變換的實現(此篇blog包含相機座標軸)
https://blog.csdn.net/stringN...

Three.js Raycaster官方文檔
https://threejs.org/docs/#api...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章