工業機械產品大多體積龐大、運輸成本高,在參加行業展會或向海外客戶銷售時,若是沒有實物展現,僅憑靜態、簡單的圖片說明書介紹,沒法讓客戶全面瞭解產品,不只工做人員製做麻煩,客戶看得也費力。若是能在 Web 上作 3D 設備展現,銷售人員能夠不限平臺隨時給客戶介紹演示。還能夠不受現實條件限制,演示設備拆分和組裝的過程,展現產品內部結構和動態運做時的效果,讓客戶更直觀瞭解產品的部件組成,更準確、全面地瞭解產品的功能和特色,大大下降了溝通成本。爲了解決這些行業痛點,本篇文章採用 Hightopo 的 HT for Web 產品實現了一個發動機設備 3D 可視化案例。html
預覽地址:基於 HTML5 WebGL 的發動機 3D 可視化系統(http://www.hightopo.com/demo/engine/)node
發動機模型是設計師經過 3ds Max 建模,而後導出 obj 與 mtl 文件,在 HT 中解析 obj 與 mtl 文件生成 3D 場景中可用的模型(可參考 obj 手冊《經過JSON加載》章節),由於各個部件須要單獨操做,因此設備模型拆分爲多個 obj 文件後導入。json
2D 面板部分則是經過 HT 的矢量繪製,咱們須要建立 ht.graph.GraphView 和 ht.graph3d.Graph3dView 來呈現 2D 和 3D 的內容。相關代碼以下:ide
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 緩動效果,代碼以下:ui
// 圓環動畫 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); };
設備部件的拆解動畫,是經過改變節點的座標和旋轉角度來實現的,代碼以下:spa
// 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 方法實現,代碼以下:3d
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 虛擬現實可視化培訓系統》。