Day 11 的檢視器能載入、旋轉、復位。今天加上「點選零件」,讓它從「一個整體的模型」變成「一組可以個別互動的零件」。
概念:從鏡頭出發、穿過滑鼠(或手指)的位置,朝場景裡射一條看不見的線,碰到的最近的東西就是被點到的目標。three.js 內建 Raycaster 做這件事。
步驟:
這裡看得出 Day 03、07 的伏筆:點選之所以可行,是因為零件樹被保住了。如果前面把所有零件合併成一整塊網格,射線只會打到「一整台機器」,永遠分不出是哪個零件。
被選中的零件要看得出來,做法有兩層:
| 做法 | 缺點 | |
|---|---|---|
| ① 自發光(emissive) | 讓被選零件的材質微微發藍光 | 一樣要通過「深度測試」(前面的東西擋住後面的),被外殼擋住的內部零件,光就畫不出來 |
| ② 穿透疊層 | 複製被選零件的形狀,蓋一層半透明的藍色,關閉深度測試,並設定最後才畫 | 這層永遠畫在最上面,即使零件在外殼裡面,也能在外殼表面看到它的輪廓 |
兩層一起用:沒被擋住時,①讓零件有自然的光澤;被擋住時,②讓你仍看得到它。
一個容易踩的坑:第一版的疊層只畫「正面」,選箱體內部的齒輪時畫面完全沒變。原因是從外面往內看,看到的是內部零件三角形的背面(法線背對鏡頭),預設會被自動略過(背面剔除)。改成雙面都畫(DoubleSide)就解決了。
右側的列表從已載入模型的結構「長」出來:走訪整棵節點樹,只收「有形狀(mesh)、有名字」的節點;像 Input_Stage 這種只是歸類用的容器節點沒有形狀,自然被濾掉。所以不需要另外維護一份「哪些算零件」的清單,這份清單是 CAD 結構自己帶來的。
part:select 事件,外部(例如之後的導覽員)可以聽到。到目前為止,viewer 靠 GLB 的節點名認零件(也就是 Day 07 保住的 CAD 名稱)。資料約定(契約)已經升級到 v0.2.1:節點名改成零件編號(如 p_0004),原本的 CAD 名稱放在節點的 extras.name,給人看的名稱寫在場景的 parts 清單裡,標籤依序取 display_name、extras.name、節點名。這樣同名零件不會認錯,也能有中文顯示名稱。viewer 端的列表怎麼顯示這些標籤,仍在接上,所以這篇先講不受影響的機制。
爆炸圖、剖切、量測(L3)。下一篇:熱點與導覽。