用Raycaster來檢測碰撞的原理很簡單,咱們須要以物體的中心爲起點,向各個頂點(vertices)發出射線,而後檢查射線是否與其它的物體相交。若是出現了相交的狀況,檢查最近的一個交點與射線起點間的距離,若是這個距離比射線起點至物體頂點間的距離要小,則說明發生了碰撞。數組
這個方法有一個 缺點 ,當物體的中心在另外一個物體內部時,是不可以檢測到碰撞的。並且當兩個物體可以互相穿過,且有較大部分重合時,檢測效果也不理想。併發
還有須要 注意 的一點是:在Three.js中建立物體時,它的頂點(veritces)數目是與它的分段數目相關的,分段越多,頂點數目越多。爲了檢測過程當中的準確度考慮,須要適當增長物體的分段。app
Raycaster( origin, direction, near, far ) { } origin — 射線的起點向量。 direction — 射線的方向向量,應該歸一化。 near — 全部返回的結果應該比 near 遠。Near不能爲負,默認值爲0。 far — 全部返回的結果應該比 far 近。Far 不能小於 near,默認值爲無窮大。
檢測碰撞的代碼片斷ide
/** * 功能:檢測 movingCube 是否與數組 collideMeshList 中的元素髮生了碰撞 * */ // 獲取物體中心點座標 var originPoint = movingCube.position.clone(); for (var vertexIndex = 0; vertexIndex < movingCube.geometry.vertices.length; vertexIndex++) { // 頂點原始座標 var localVertex = movingCube.geometry.vertices[vertexIndex].clone(); // 頂點通過變換後的座標 var globalVertex = localVertex.applyMatrix4(movingCube.matrix); // 得到由中心指向頂點的向量 var directionVector = globalVertex.sub(movingCube.position); // 將方向向量初始化,併發射光線 var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize()); // 檢測射線與多個物體的相交狀況 // 若是爲true,它還檢查全部後代。不然只檢查該對象自己。缺省值爲false var collisionResults = ray.intersectObjects(collideMeshList, true); // 若是返回結果不爲空,且交點與射線起點的距離小於物體中心至頂點的距離,則發生了碰撞 if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) { crash = true; // crash 是一個標記變量 } }
六步:
一、獲取物體中心點座標:
二、獲取物體頂點座標:
三、頂點通過變換後的座標:
四、得到由中心指向頂點的向量:
五、用 THREE.Raycaster 對象從屏幕上的點擊位置向場景中發射一束光線:
六、用 intersectObjects 來判斷指定對象有沒有被這束光線擊中,返回被擊中對象的信息,相交的結果會以一個數組的形式返回,其中的元素依照距離排序,越近的排在越前code
在Three.js中是使用矩陣來記錄3D轉換的,每個Object3D的實例都有一個矩陣,存儲了位置position,旋轉rotation和伸縮scale。orm
var globalVertex = localVertex.applyMatrix4(movingCube.matrix);
這一句代碼將物體的本地座標乘以變換矩陣,獲得了這個物體在世界座標系中的值,處理以後的值纔是咱們所須要的。對象