Three.js進階篇之6 - 碰撞檢測
最近在試著用Three.js做一個簡單的賽車遊戲,裡面有一個需要解決的問題是如何判斷兩個物體發生了碰撞,比如賽車是否碰上了障礙物或者獲得了獎勵物品。
示例
我找了一些資料,發現了兩個示例程式:第一個示例、 第二個示例 。
以上兩個程式都是用 THREE.Raycaster
類來解決問題的。
Raycaster類
Raycaster 應該翻譯為“光線投射”,顧名思義,就是投射出去的一束光線。
Raycaster的建構函式如下
Raycaster( origin, direction, near, far ) {
origin — 射線的起點向量。
direction — 射線的方向向量,應該歸一化。
near — 所有返回的結果應該比 near 遠。Near不能為負,預設值為0。
far — 所有返回的結果應該比 far 近。Far 不能小於 near,預設值為無窮大。
使用Raycaster進行碰撞檢測
用Raycaster來檢測碰撞的原理很簡單,我們需要以物體的中心為起點,向各個頂點(vertices)發出射線,然後檢查射線是否與其它的物體相交。如果出現了相交的情況,檢查最近的一個交點與射線起點間的距離,如果這個距離比射線起點至物體頂點間的距離要小,則說明發生了碰撞。
這個方法有一個 缺點 ,當物體的中心在另一個物體內部時,是不能夠檢測到碰撞的。而且當兩個物體能夠互相穿過,且有較大部分重合時,檢測效果也不理想。
還有需要 注意 的一點是:在Three.js中建立物體時,它的頂點(veritces)數目是與它的分段數目相關的,分段越多,頂點數目越多。為了檢測過程中的準確度考慮,需要適當增加物體的分段。
檢測光線是否與物體相交使用的是 intersectObject
或 intersectObjects
方法:
.intersectObject ( object, recursive )
object — 檢測該物體是否與射線相交。
recursive — 如果設定,則會檢測物體所有的子代。
相交的結果會以一個陣列的形式返回,其中的元素依照距離排序,越近的排在越前:
[ { distance, point, face, faceIndex, indices, object }, ... ]
這樣通過對陣列中的元素進行處理,就能得出想要的結果。
intersectObjects
與 intersectObject
類似,除了傳入的引數是一個陣列之外,並無大的差別。
檢測碰撞的程式碼片段
/**
* 功能:檢測 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());
// 檢測射線與多個物體的相交情況
var collisionResults = ray.intersectObjects(collideMeshList);
// 如果返回結果不為空,且交點與射線起點的距離小於物體中心至頂點的距離,則發生了碰撞
if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
crash = true; // crash 是一個標記變數
}
}
在Three.js中是使用矩陣來記錄3D轉換的,每一個Object3D的例項都有一個矩陣,儲存了位置position,旋轉rotation和伸縮scale。
var globalVertex = localVertex.applyMatrix4(movingCube.matrix);
這一句程式碼將物體的本地座標乘以變換矩陣,得到了這個物體在世界座標系中的值,處理之後的值才是我們所需要的。
我的示例程式碼
Online Demo 按方向鍵移動方塊,點選滑鼠左鍵並拖動更改視角。
相關文章
- Three.js 進階之旅:物理效果-碰撞和聲音 ?JS
- Three.js進階篇之5 - 粒子系統JS
- 測開之函式進階· 第6篇《閉包》函式
- Three.js中實現對InstanceMesh的碰撞檢測JS
- Three.js進階篇之7 - 3D宇宙特效JS3D特效
- 碰撞檢測
- Three.js進階篇之9 - 紋理對映和UV對映JS
- 介面測試進階篇
- [ ES6 ] 進階篇(一) —— PromisePromise
- WPF 2D 碰撞檢測
- javascript矩形碰撞檢測程式碼JavaScript
- 測開之函式進階· 第2篇《純函式》函式
- 測開之函式進階· 第4篇《匿名函式》函式
- 測開之函式進階· 第5篇《偏函式》函式
- go 單元測試進階篇Go
- 學習 PixiJS — 碰撞檢測JS
- 測開之函式進階· 第1篇《遞迴函式》函式遞迴
- 華為車輛碰撞檢測專利公佈,可檢測車輛能否碰撞潛在障礙物
- Three.js 進階之旅:頁面平滑滾動-王國之淚 ?JS
- python如何檢測pygame中的碰撞PythonGAM
- 簡單前端——圓與圓碰撞檢測前端
- Java多執行緒之進階篇Java執行緒
- Membership三步曲之進階篇
- Java進階篇 設計模式之十四 ----- 總結篇Java設計模式
- 使用四叉樹優化碰撞檢測優化
- JS寫的不咋地的碰撞檢測JS
- Html5 Canvas動畫基礎(碰撞檢測)HTMLCanvas動畫
- javascript圓形區域碰撞檢測程式碼JavaScript
- Three.js 進階之旅:全景漫遊-高階版線上看房 ?JS
- Linux ACL 許可權之進階篇Linux
- Asp.Net MVC 系列--進階篇之FilterASP.NETMVCFilter
- Three.js 進階之旅:新春特典-Rabbit craft go ?JSRaftGo
- C 實現射線檢測多邊形碰撞
- ElasticSearch進階檢索Elasticsearch
- Three.js入門篇之1 - WebGL on HTMLJSWebHTML
- 【webpack 系列】進階篇Web
- React進階篇1React
- React進階篇2React