基於 HTML5 WebGL 的發動機 3D 視覺化系統
前言
工業機械產品大多體積龐大、運輸成本高,在參加行業展會或向海外客戶銷售時,如果沒有實物展示,僅憑靜態、簡單的圖片說明書介紹,無法讓客戶全面瞭解產品,不僅工作人員製作麻煩,客戶看得也費力。如果能在 Web 上做 3D 裝置展示,銷售人員可以不限平臺隨時給客戶介紹演示。還可以不受現實條件限制,演示裝置拆分和組裝的過程,展示產品內部結構和動態運作時的效果,讓客戶更直觀瞭解產品的部件組成,更準確、全面地瞭解產品的功能和特點,大大降低了溝通成本。為了解決這些行業痛點,本篇文章採用 Hightopo 的 HT for Web 產品實現了一個發動機裝置 3D 視覺化案例。
系統預覽
預覽地址:基於 HTML5 WebGL 的發動機 3D 視覺化系統(http://www.hightopo.com/demo/engine/)
場景搭建
發動機模型是設計師通過 3ds Max 建模,然後匯出 obj 與 mtl 檔案,在 HT 中解析 obj 與 mtl 檔案生成 3D 場景中可用的模型(可參考 obj 手冊《通過JSON載入》章節),因為各個部件需要單獨操作,所以裝置模型拆分為多個 obj 檔案後匯入。
2D 皮膚部分則是通過 HT 的向量繪製,我們需要建立 ht.graph.GraphView 和 ht.graph3d.Graph3dView 來呈現 2D 和 3D 的內容。相關程式碼如下:
var g2d = new ht.graph.GraphView();
var g3d = new ht.graph3d.Graph3dView();
// 將 3D 元件加入到 body 下
g3d.addToDOM();
// 將 2D 元件加入到 3D 元件的根 div 下
g2d.addToDOM(g3d.getView());
功能實現
裝置拆解動畫
當我們點選“展開”按鈕時,給各個動畫設定不同的延遲,使動畫錯開執行,以達到更好的視覺效果,讓2D圖紙和3D場景更好地聯動起來。
如果我們的每個動畫都勻速執行,那看起來難免有些單調。於是我給不同動畫加上了不同的 Easing 函式,Easing 函式通過定義不同曲線的資料公式方式,來描述每一幀回撥時需要改變圖形引數屬性的幅度,從而達到均勻、先快後慢、先慢後快,甚至先超出起始值和結束值再慢慢恢復的各種動畫特效。這裡還有個例子可以幫助我們更直觀的感受不同 Easing 函式的效果:《From Easing》。
例如圖紙中心的跟隨部件拆解旋轉放大的圓環,我給它設定了 Easing.backBoth 緩動效果,程式碼如下:
// 圓環動畫
animCenter(data) {
ht.Default.startAnim({
duration: 4500,
// 設定緩動函式
easing: Easing.backBoth,
// 延遲一秒執行動畫
delay: 1000,
action: function (v, t) {
// 修改圖元縮放值
data.setScale(1 + v \* 0.9, 1 + v \* 0.9);
// 修改圖元旋轉角度
data.setRotation(Math.PI \* v);
},
});
}
// 緩動函式
Easing.easeOutStrong = function (t) {
var BACK\_CONST = 1.70158;
if ((t \*= 2) < 1) {
return .5 \* (t \* t \* (((BACK\_CONST \*= (1.525)) + 1) \* t - BACK\_CONST));
}
return .5 \* ((t -= 2) \* t \* (((BACK\_CONST \*= (1.525)) + 1) \* t + BACK\_CONST) + 2);
};
裝置部件的拆解動畫,是通過改變節點的座標和旋轉角度來實現的,程式碼如下:
// targetP3 為拆解後的座標,p3為當前座標
var p3 = node.p3();
var offset = [targetP3[0] - p3[0], targetP3[1] - p3[1], targetP3[2] - p3[2]];
// targetR3 為拆解後的旋轉角度,r3為當前旋轉角度
var r3 = node.r3();
var offset = [targetR3[0] - r3[0], targetR3[1] - r3[1], targetR3[2] - r3[2]];
// 拆解動畫
ht.Default.startAnim({
duration: 2000,
// 設定緩動函式
easing: Easing.easeOutStrong,
delay: 1000,
action: function (v, t) {
// 修改節點座標
node.p3(p3[0] + offset[0] * v, p3[1] + offset[1] * v, p3[2] + offset[2] * v);
// 修改節點旋轉角度
node.r3(r3[0] + offset[0] * v, r3[1] + offset[1] * v, r3[2] + offset[2] * v);
},
});
// 緩動函式
Easing.easeOutStrong = function (t) {
return 1 - (--t) * t * t * t;
};
還有圖紙兩側的皮膚,可以通過設定它的裁剪方向和裁剪比例實現隱藏效果,程式碼如下:
// 設定圖元裁剪方向為從右到左
node.s('clip.direction', 'left');
// 裁剪動畫
ht.Default.startAnim({
duration: 1800,
easing: Easing.easeOutStrong,
action: function (v, t) {
// 修改圖元裁剪比例
node.s('clip.percentage', 1 - v);
}
});
// 緩動函式
Easing.easeOutStrong = function (t) {
return 1 - (--t) \* t \* t \* t;
};
裝置內部運作動畫
接下來我們實現視角變化動畫來觀察裝置不同部件構造,3D 場景中的視角是由 Graph3dView 提供的 center(目標點座標)和 eye(攝像機座標)兩個引數決定的,所以視角動畫只要動態改變這兩個引數,這裡用了 HT 提供的 moveCamera 方法實現,程式碼如下:
g3d.moveCamera([-466, 93, -280], [40, -40, -40], {
duration: 2500,
easing: function (t) {
return 1 - (--t) * t * t * t;
},
});
裝置中一些小的部件吸附在大部件上,會跟隨大部件移動旋轉。比如這個液壓桿,當我們要實現小部件的運動動畫時,如果用修改座標的方式計算起來比較麻煩,所以我們用修改錨點的方式來實現,錨點影響著節點的位置,錨點也是旋轉和縮放的中心點。這裡通過修改液壓桿的 Y 軸錨點實現動畫,效果如下:
相關程式碼如下:
ht.Default.startAnim({
duration: 800,
action: function (v, t) {
// 修改節點 Y 軸錨點
node.setAnchor3d(0.5,v,0.5);
},
};
點選流動按鈕後,我們可以看到管道內有液體流動的動畫。要實現流動效果,首先我們需要一張二方連續貼圖(左右或上下可以無縫銜接的貼圖),然後我們再通過程式碼驅動 UV 向 U 軸的正值方向偏移一個象限,並無限迴圈這一動作,效果如下:
程式碼如下:
ht.Default.startAnim({
duration: 2000,
action: function (v, t) {
// 修改貼圖uv值
node.s('shape3d.uv.offset', [v, 0]);
},
};
裝置復原動畫
滑鼠移入效果
為了能透過外殼清楚的觀察到裝置內部結構,所以當滑鼠懸停在部件上時,我調整了外殼模型透明度並設定模型高亮模式,相關程式碼如下:
// 設定高亮顏色
ht.Style['highlight.color'] = 'rgba(255,255,255,0.6)';
// 設定當前高亮的模式
g3d.setHighlightMode('mouseover');
// 節點啟用高亮效果
data.s('highlight.visible', true);
// 節點設定為可互動
data.s('interactive', true);
// 節點開啟互動後,不阻止場景上預設的互動行為
data.s('preventDefaultWhenInteractive', false);
// 監聽互動事件
g3d.mi(function (e) {
// 滑鼠移入事件
if (e.kind === 'onEnter') {
// 節點開啟透明
data.s('shape3d.transparent', true);
// 設定節點透明度
data.s('shape3d.opacity', 0.25);
}
// 滑鼠移出事件
if (e.kind === 'onLeave') {
data.s('shape3d.transparent', false);
}
});
場景視角限制
最後,我們再對整個場景的視角範圍做下限制,程式碼如下:
// 設定最大角度
ht.Default.graph3dViewMaxPhi = Math.PI \* 1 / 2;
// 設定最小角度
ht.Default.graph3dViewMinPhi = Math.PI \* 1 / 4;
總結
通過案例我們可以感受到,相較於傳統方式,裝置的三維展示具有更靈活的表現形式和更直觀生動的效果,對於出口型企業,生動的演示動畫能讓外商更快了解產品的工作原理和優勢,還能避免因語言誤差而造成誤解。而且比起普通的工業動畫,Web 上的視覺化系統展示內容更豐富、自由度更高,後續需求更改也更為靈活、成本更低。
本文使用的裝置模型是設計師虛構的核動力發動機,更注重於模型的展示效果,如果應用於實際產品中,還可以製作更還原實際的裝置拆解流程,通過線上的 3D 產品操作演練,對工作人員進行產品組裝、拆分、維修培訓。有興趣可以參考我們另一個案例《基於 HTML5 WebGL + WebVR 的 3D 虛擬現實視覺化培訓系統》。
相關文章
- 基於 HTML5 WebGL 的 3D 風機視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 + WebGL 的無人機 3D 視覺化系統HTMLWeb無人機3D視覺化
- 基於 WebGL 的 HTML5 3D 工控隧道視覺化系統WebHTML3D視覺化
- 基於 HTML5 + WebGL 的太陽系 3D 視覺化系統HTMLWeb3D視覺化
- 基於 WebGl HTML5 的 3D 視覺化機房WebHTML3D視覺化
- 基於 HTML5 + WebGL 的 3D 風力發電場視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 的 WebGL 3D 地鐵站視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的地鐵站 3D 視覺化系統HTMLWeb3D視覺化
- 基於 WebGL 3D 的 HTML5檔案館視覺化管理系統Web3DHTML視覺化
- 基於 HTML5 的 WebGL 3D 檔案館視覺化管理系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的挖掘機 3D 視覺化應用HTMLWeb3D視覺化
- 基於 HTML5 WebGL + WebVR 的 3D 虛實現實視覺化培訓系統HTMLWebVR3D視覺化
- 基於 HTML5 WebGL 的加油站 3D 視覺化監控HTMLWeb3D視覺化
- 基於 WebGL 的 HTML5 樓宇自控 3D 視覺化監控WebHTML3D視覺化
- 基於 HTML5 的 WebGL 樓宇自控 3D 視覺化監控HTMLWeb3D視覺化
- 基於HTML5的WebGL呈現A星演算法的3D視覺化HTMLWeb演算法3D視覺化
- WebGL入門之基於WebGL的3D視覺化引擎介紹Web3D視覺化
- 基於 WebGL 的 HTML5 3D 工控裙房系統WebHTML3D
- 基於 HTML5 WebGL 的 3D 工控裙房系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 挖掘機HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 機房HTMLWeb3D
- 基於 HTML5 + WebGL 的太陽系 3D 展示系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 倉儲管理系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 科幻風機HTMLWeb3D
- 基於 HTML5 的 3D 機房視覺化實景監控HTML3D視覺化
- 基於 WebGL 的 HTML5 3D 棉花加工監控系統WebHTML3D
- 基於 WebGL 的 HTML5 3D SCADA 主站系統WebHTML3D
- 基於 HTML5 WebGL 的 3D SCADA 主站系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 棉花加工監控系統HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 智慧樓宇監控系統WebHTML3D
- 基於 HTML5 的 WebGL 3D 智慧樓宇監控系統HTMLWeb3D
- 基於 HTML5 WebGL 的計量站三維視覺化監控系統 Web 組態工控應用HTMLWeb視覺化
- 基於 HTML5 + WebGL 的 3D 風力發電場HTMLWeb3D
- 基於 HTML5 WebGL 與 GIS 的智慧機場大資料視覺化分析HTMLWeb大資料視覺化
- 基於 HTML5 和 VR 技術的 3D 機房資料中心視覺化HTMLVR3D視覺化
- 基於 HTML5 WebGL 的垃圾分類系統HTMLWeb
- 基於 HTML5 WebGL 的 3D 渲染引擎構建工廠運作系統HTMLWeb3D
- 基於顯揚科技3D機器視覺的驅動輪抓取上料系統3D視覺