基於 HTML5 WebGL + WebVR 的 3D 虛擬現實可視化培訓系統

前言html

2019 年VR,AR,XR,5G,工業互聯網等名詞頻繁出如今咱們的視野中,信息的分享與虛實的結合已經成爲大勢所趨,5G 是新一代信息通訊技術升級的重要方向,工業互聯網是製造業轉型升級的發展趨勢。本文所講的VR 是機械製造業與設備的又一次交流,當技術新星趕上製造潮流,無疑將成爲製造業,工控業等行業數字化轉型的重要驅動力。「5G + VR + 工業互聯網」必將成爲新的一年不變的話題,如何將當前工業中遇到的問題經過虛擬現實結合起來,讓咱們能夠更近的去交流,去感覺技術帶給咱們的變化。在今年蘋果的發佈會上,相信你們都知道蘋果的5G 手機沒有問世,說明5G 的應用和發展還處在快速發展的階段,可是手機結合AR 功能的 APP 已經早就問世,5G 的速度加上AR, VR 的身臨其境,讓咱們感覺到的不只僅是技術的革新,更是讓咱們感覺到技術在不一樣領域的實際應用場景,我相信 2020 年新的一年一定是「5G + VR + 工業互聯網」 應用的又一個新的開始,本文接下來所講的就是HT for Web 結合WebVR 開發的具體應用案例。node

系統預覽git

預覽地址:基於 HTML5 WebGL 與 WebVR 3D 虛擬現實的可視化培訓系統   http://www.hightopo.com/demo/vr-training/github

VR 拆解還原web

VR 操做json

VR 場景切換瀏覽器

PC 端拆解還原安全

PC 端考試網絡

系統介紹數據結構

該系統共分爲三個實際應用層面:

  • 三維培訓: 用戶經過 mb 端手指觸摸或者 pc 端鼠標拖拽能夠將設備拆解開來,以後能夠經過一鍵還原來將設備還原到最初的狀態,或者能夠經過拆解 or 還原按鈕查看設備自動拆解的過程以及拆解以後自動還原的過程。
  • 考試系統:這部分是考驗你對設備拆解的熟悉程度,在第一步的三維培訓以後,能夠在該系統中考覈你對拆解過程的瞭解。
  • VR 模式:該部分即是三維場景結合 WebVR 的具體實現應用,在進入 VR 以後能夠經過操做 VR 手柄,進行設備的拆解還原。

文章主要講解第三部分的VR 模式,讓咱們瞭解如何結合HT 來搭建VR 場景。下面描述了VR 中的主要操做,沒有進入VR 的時候不會出現以下所說的六個按鈕操做,在點擊進入WebVR 時,系統自動顯示出VR 場景裏的六個操做按鈕,反之退出VR 時,系統也會自動隱藏三維中的六個操做按鈕,VR 中的主要操做以下:

  • 設備切換:顧名思義,能夠經過手柄射線對準場景中左側列表,按動板機進行場景設備切換。
  • 操做切換:VR 中對設備有以下兩種操做,能夠經過右下角的模式按鈕點擊切換。
  • 平移模式:該模式下,用戶能夠對準設備而且按動板機將設備從一個位置移動到另外一個位置,而且能夠經過觸摸觸摸板來拉近和拉遠設備零件。
  • 抓取模式:該模式下,用戶能夠對準設備而且按動板機將設備抓取過來,抓取過來以後,能夠經過觸摸觸摸板來旋轉以及放大或者縮小零件。
  • 一鍵還原:將設備各部分零件還原到最初始的位置。
  • 拆解動畫:將設備的各部分零件經過以前預約好的位置按步驟一步一步拆解開來。
  • 還原動畫:該操做能夠理解爲拆解動畫的倒放,即將拆解的過程逆序還原。
  • 線框切換:HT 支持將設備節點的三角面表示出來,能夠具體的看到該設備的線框輪廓。

系統開發

三維場景
HT 支持obj 模型的導入,VR 場景所出現的設備零件均爲 obj 模型,因爲須要在以後進行設備的拆解,因此建模的時候須要分別對設備的各部分零件進行建模,而不是對設備總體進行建模,若是對設備總體建模那麼在 HT 的場景中就是一個Data 節點,從而不能對零件進行拆解,若是拆解開來,那麼在 HT 中能夠加載多個 obj 則就有多個 Data 節點,有多個零件的 Data 節點以後就能夠對設備零件進行移動或者其它旋轉操做,具體的 Data 在 HT 的含義能夠參考HT for Web 數據模型手冊

以下爲導入場景中的obj 模型:

從上圖能夠看出咱們導入obj 以後零件之間是分散的,因此須要對零件的初始位置進行調整,從而調整出一個由許多零件構成的完整設備,固然調整不可能經過代碼來調整,對應的有三維編輯器能夠調整,進行拖拖拽拽將不一樣零件拼湊起來,以下爲組合以後的設備總體:

VR 搭建
VR 場景的搭建是在第一步的基礎上進行搭建,上面所說的只在 VR 場景中顯示的按鈕也是在場景中進行搭建,在正常的場景時候咱們能夠隱藏掉對應的節點,node.s('3d.visible', false) 上面的代碼就是 HT 中在三維下面隱藏三維節點的代碼,由於進入 VR 和離開 VR 的時候,HT 內部會派發出對應的狀態告訴用戶此時已經進入 VR 或者此時已經離開 VR,相應僞代碼以下:

複製代碼

1 // graph3dView 爲 HT 中的三維場景視圖容器
2 // vr 獲取掛載在 graph3dView 上的 vr 對象
3 var vr = graph3dView.vr;
4 vr.mp(function(e) {
5 // property 對應的 vr 事件類型,detail 此時事件的狀態
6 var property = e.property;
7 var detail = e.newValue;
8 // present 表明此時進入或者離開 VR 場景
9 if (property === 'present') {
10 // 此時 detail 爲 true 表示進入 vr,false 表示離開 vr
11 if (detail) {
12 // 執行顯示 vr 場景中須要顯示的節點操做
13 } else {
14 // 執行隱藏 vr 場景中須要隱藏的節點操做
15 }
16 }
17 });

複製代碼

上面 property 在HT 總共會派發出如下幾種類型,主要是包括VR 的狀態和手柄的操做類型:

  • enable:vr 的 enable 信息發生變化
  • present:vr 的 present 信息發生變化,代表進出 vr 世界
  • gamepad.pose:手柄位置或旋轉發生變更,參數 id,position,rotation
  • gamepad.axes:手柄中間的轉盤觸摸點位變更,參數 id,axes;其中 axes 格式形如:[ 0.2, 0.7 ],分辨表示橫縱百分比
  • gamepad.button.thumbpad:thumbpad 按鍵被按下,參數 id,state,其中 state 包含 down 跟 up 兩種
  • gamepad.button.trigger:trigger 按鍵被按下,參數 id,state,其中 state 包含 down 跟 up 兩種
  • gamepad.button.grips:grips 按鍵被按下,參數 id,state,其中 state 包含 down 跟 up 兩種
  • gamepad.button.menu:menu 按鍵被按下,參數 id,state,其中 state 包含 down 跟 up 兩種

VR 中有一個關鍵的配置就是比例尺,由於 VR 裏面的單位是和現實中的長度單位是一致的,咱們戴着頭盔往前走 1m 那麼對應在 HT 三維場景中須要往前走多遠這須要一個對應關係,HT 提供的 VR 插件中會提供一個measureOflength 的配置項,以下:

1 var vr_config = {
2 measureOflength: 0.01,
3 }

上面 0.01 表明的意思就是 HT 場景中的單位長度 1 表明現實場景的 0.01 米,因此若是此時現實場景你戴着頭盔往前移動 1m,那麼 HT 中對應的視角會往前移動 100 個單位,因此若是須要搭建 VR 場景要注意場景的模型建模比例和現實世界是相差多少,按照統一的比例來建模,否則在 VR 場景中會出現設備大小不一的問題,致使出現錯覺,以下對比圖,左側是 0.01 的比例,射線的小點很小,右側是是 0.001 的比例致使射線的小點變大。

HT 中已經對瀏覽器提供的WebVR 相關接口的 API 進行了封裝,包括獲取設備navigator.getVRDisplays() 這是進入 VR 世界的第一步,若是此時執行此代碼返回的結果爲空表明獲取 VR 設備失敗,那麼以後更不用說了,以及獲取手柄信息navigator.getGamepads(),用戶能夠經過在瀏覽器控制檯敲入上面兩行代碼,查看瀏覽器是否已經獲取到了 VR 設備信息和 VR 手柄信息,若是返回爲空則說明獲取失敗。HT 只要經過執行graph3dView.vr.enable = true 就能夠開啓VR,固然用戶不用執行該代碼,HT 提供的VR 插件也會提供對應的配置項vrEnable: true 來表明開啓 VR,對應的配置也掛在在上面的vr_config 對象內,以下:

1 var vr_config = {
2 measureOflength: 0.01,
3 vrEnable: true, // 表明開啓 VR
4 }

在該展現的系統中有直接在VR 中切換場景的功能,因爲每一個場景的vr_config 中的配置項值可能會有差異,例如第一個場景的measureOflength 比例尺的大小爲 0.01,可能第二個場景的比例尺大小measureOflength 就變成了 0.02,因此 VR 插件提供一個銷燬的功能,用來銷燬上一個場景的資源,銷燬場景的資源包括清空上一個場景的全部節點,因此在加載新的場景時,不須要再執行清空場景節點的操做,即不須要執行 dataModel.clear(),由於 VR 提供的銷燬功能已經都清空了,手柄和射線都是場景中的一個 Data 節點,因此在新的場景不須要額外的清除手柄和射線這兩個節點,故插件幫你管理場景的節點。在調用銷燬功能以後,能夠調用graph3dView 的序列化函數graph3dView.deserialize('場景資源json地址') 來序列化新的場景 json 文件,在序列化完成的回調函數中,能夠根據新的場景修改此時vr_config 的值,而後再次調用graph3dView.initVRForScene() 來再次初始化VR 場景。相關的步驟僞代碼以下:

複製代碼

1 // window.GVR 是在調用 graph3dView.initVRForScene() 以後初始化的一個全局 VR 插件變量 用於用戶獲取插件對象
2 window.GVR.destory();
3 // 執行新的場景序列化操做
4 graph3dView.deserialize('場景資源json地址',
5 function(json, dm, g3d, datas) {
6 // 修改新的場景比例尺爲 0.02
7 window.vr_config.measureOflength = 0.02;
8 // 修改新的 VR 場景初始化視角
9 window.vr_config.vrEye = ht.Default.clone(g3d.getEye());;
10 // 再次初始化 VR 場景
11 graph3dView.initVRForScene()
12 });

複製代碼

固然 HT 提供的 VR 插件還有不少的配置項,方便用戶更好的調整 VR 場景,包括刷地形,場景移動方式,場景操做方式均可以經過配置進行配置,利用 HT 進行 VR 搭建主要流程以下流程圖所示:

經過上面的流程圖,咱們大致能夠了解配合 HT 提供的 VR 插件如何進行快速的搭建 VR 場景。

目前谷歌瀏覽器和火狐瀏覽器都很友好的支持 VR,能夠經過火狐官網提供的WebVR Demo 在線感覺下官方提供的 VR 場景。

拆解規則
從文章前面的部分效果圖能夠看到咱們每一個場景的設備都有拆解,而且每一個設備的零件數量,零件位置,零件拆解的方向,偏移的長短都是不一致的,因此不可能經過代碼來將上面的偏移長短,偏移方向寫死,須要制定一套拆解規則來幫助咱們能夠更方便製做每一個場景的拆解動畫,這樣只須要設計師根據與程序約定好的拆解規則進行配置就能夠配置出不一樣場景不一樣設備的拆解動畫。該系統的拆解分爲兩種狀況:

  • 單體移動:單個設備零件沿着父節點位置和該節點位置的鏈接線方向移動
  • 組合移動:多個設備零件的組合沿着某個方向移動,組合移動以後,設備零件能夠在組合移動以後的位置進行再沿着某個方向進行移動,能夠無限進行嵌套,即組合以後還能夠組合移動,或者單體移動

單體移動示意圖以下:

組合移動示意圖以下:

在 HT 中能夠經過data.setDisplayName('名稱') 來給節點設置名稱,這裏約定經過不一樣設備的名稱,來獲取到不一樣設備的偏移信息,例如data.setDisplayName('1-0.5-1000') 該名稱就是和設計師約定好的配置規則,1 表明拆解步驟的第一步執行,固然場景中能夠有多個 1,即第一步同時拆解這些零件 0.5 表明朝着父節點的方向偏移本身位置和父節點位置鏈接線長度的50%1000 表明偏移的過程持續1000 毫秒,固然以後能夠約定旋轉以及旋轉的角度等信息。設計師知道這些配置規則以後即可以經過可視化編輯器進行不一樣零件的配置,這樣程序方面只須要寫一套通用的邏輯就能夠對不一樣的設備進行拆解和還原。

系統中維護了一個隊列和一個隊列用來記錄拆解順序用來記錄還原順序。拆解的過程經過配置的序號,按順序推動隊列,採用隊列的數據結構即是由於隊列先進先出的特色,第一個壓入隊列的零件則第一個執行,最後壓入隊列的零件最後一個執行拆解順序。拆解出隊列的零件則同時壓入棧,採用記錄還原順序是由於先進後出的特色,即第一個執行完拆解的零件,在還原的時候倒是最後一個執行還原的動做。因此上述採用的不一樣數據結構即是爲了更好的記錄數據。如下爲相關 js 僞代碼:

複製代碼

1 // 記錄拆解順序
2 const queue = [];
3 // 記錄還原順序
4 const stack = [];
5 // each 循環中用來記錄拆解隊列 queue 順序
6 dataModel.each((node) = >{
7 const displayName = node.getDisplayName();
8 if (displayName) {
9 const[index, distancePer, during] = displayName.split('-');
10 if (index !== void 0) {
11 if (queue[index]) {
12 if (queue[index] instanceof Array) {
13 queue[index].push(node);
14 } else {
15 const tempNode = queue[index];
16 queue[index] = [tempNode, node];
17 }
18 } else {
19 queue[index] = node;
20 }
21 }
22 }
23 });

複製代碼

相關邏輯以下流程圖:

經過上面的約定,設計師可使用可視化編輯器來配置不一樣零件的移動規則,大大提升了動畫的製做效率。

代碼分析
該部分主要對拆解還原動畫的代碼進行分析,主要採用向量和部分三角函數的概念來計算不一樣零件在三維空間的位置,初始的時候須要記錄下每一個零件在前面全部組合移動以後的初始移動位置向量,以及零件沒有組合移動以前的初始位置向量,獲取這兩個位置向量目的是一是爲了零件拆解在前面所說組合以後移動,和零件在拆解以後恢復到一整個設備形態的初始位置,兩個位置向量都有重要的做用,如下爲相關僞代碼:

複製代碼

1 // Vector3 爲 HT 封裝的三維向量
2 const Vector3 = ht.Math.Vector3;
3 // 記錄第一個重要位置向量
4 node.a('relativeP3Vec', new Vector3(node.p3()));
5 // node 當前零件節點
6 // moveQueue 爲移動順序在 node 以前的,而且爲 node 節點的祖先節點
7 for (let i = 0, l = moveQueue.length; i < l; i++) {
8 const moveNode = moveQueue[i],
9 parentMoveNode = moveNode.getParent();
10 if (parentMoveNode) {
11 const[, distancePer] = moveNode.getDisplayName().split('-');
12 moveNode.a('defP3', moveNode.p3()) moveNode.p3(new Vector3().lerpVectors(new Vector3(moveNode.p3()), new Vector3(parentMoveNode.p3()), distancePer).toArray());
13 }
14 }
15 // 記錄組合節點移動以後的第二個重要相對位置向量
16 node.a('relativeP3Vec', new Vector3(node.p3()));
17 // 逆序還原組合的父節點位置
18 for (let i = moveQueue.length - 1; i >= 0; i--) {
19 const moveNode = moveQueue[i];
20 moveNode.p3(moveNode.a('defP3'));
21 moveNode.a('defP3', undefined);
22 }

複製代碼

因爲在場景拆解過程當中須要設置設備零件節點不可選擇,因此須要記錄下不可選擇以前的零件是否可選擇狀態,用來恢復節點初始狀態,相關僞代碼以下:

1 dm3d.each((node) = >{
2 node.a('defSelectable', node.s('3d.selectable'));
3 });

文中所示的線框效果爲 HT 核心包支持的線框模式,能夠經過以下代碼進行配置:

複製代碼

dm3d.each((data) = >{

if (data.s('shape3d') && data.s('shape3d').startsWith('models/')) {
    data.s({
        'shape3d.transparent': true,
        'shape3d.opacity': 0, // 目的爲隱藏本來的模型
        'wf.geometry': true, // 開啓線框模式
        'wf.combineTriangle': 2, // 線框三角面合併類型
        'wf.color': 'rgba(96,172,252,0.3)' // 線框顏色
    });
}

});

複製代碼

上述wf.combineTriangle 主要包括

  • false,0:不合並三角形
  • true,1: 合併相鄰三角爲四邊面,原來的效果
  • 2:融合全部聯通的共面三角面
  • 3:根據法線信息融合全部平滑三角面

VR 軟件以及硬件安裝

本系統採用的VR 硬件設備爲HTC VIVE 接下來說的是安裝 HTC VIVE 的過程和步驟。

第一步:撮合 HTC VIVE 和電腦主機

HTC 官網找到鏈接指南,而後按照步驟安裝便可,咱們只需看如下截圖部分的目錄便可。

第二步:下載軟件

Steam 官網下載 Steam,下載完 Steam 能夠在 Steam 中下載 Stream VR。

第三步:打開 Stream VR 檢查設備狀態

打開 Stream VR,會出現如下畫面,這是用來表示 HTC VIVE 頭顯的工做狀態的,經過圖標咱們便可查看頭顯、手柄控制器和定位器等配件的工做狀況。

第四步:選擇房間設置模式

若是您的房間位置比較大能夠選擇第一項,我選擇的模式爲第二項,站立模式。建議選擇一種房間規模,能夠完整的進行設置。

第五步:將頭盔、兩個手柄控制器放置在兩個定位器可視範圍內,創建定位

第六步:校準頭盔中心點

該步爲設置頭盔默認的朝向。

第七步:定位地面

將兩個手柄控制器放置在定位器可視範圍內,而後點擊電腦屏幕上的按鈕「校準地面」,等待系統校準

第八步:進入 Steam VR 自帶房間進行測試

設置完畢以後能夠進入 Steam VR 自帶的房間進行體驗。

總結
當人們談起5G 時代的新應用,VR、AR 老是一大熱門話題。4G 時代移動網絡已經足以承載起高清視頻,那麼 5G 時代理所固然就能傳輸數據量更大的沉浸式 VR、AR 影像。所以,很多人將 5G 視爲 VR、AR 崛起的踏板,隨時隨地身臨天涯海角,彷佛並不是是高不可攀的夢。當前 4G 網絡應用在 VR/AR 上會帶來大約 70ms 的時延,這個時延會致使體驗者存在眩暈感,而 5G 數據傳輸的延遲可達到毫秒級,能夠有效解決數據時延帶來的眩暈感,有助於 VR/AR 的大規模應用。目前隨着 5G 網絡的逐漸普及,VR/AR 產業正逐步走向復甦,市場熱情在逐漸升溫,虛擬現實遊戲、虛擬現實現場直播等都是 5G 在 VR/AR 上的具體應用。在科技進步的今天,安全也是一個重要的話題,VR 結合仿真的應用也是大勢所趨,仿真可讓用戶真實切身感覺,例如消防預警管道預警,可讓用戶在 VR 世界中體驗消防滅火等消防員的操做,讓用戶沉浸在 VR 世界中感覺到火災來臨時怎麼進行實際操做。因此 VR 帶來的應用遠遠不止仿真,模擬等體驗,更多帶來的是能爲人們提供真實的實際做用,而不是噱頭。

程序手機端運行截圖:

相關文章
相關標籤/搜索