HTML5 WebGL 在三維中的應用,已經發展的如火如荼,使其在三維組態(工業控制)方面也變得簡單易行! 三維組態軟件提升了工業控制的管理效率,讓工業控制的資源管理、風險管控獲得很大的改善。前端
傳統的三維組態通常都是本地應用, 該案例使用的是基於瀏覽器B/S架構下的三維組態的應用。node
該案例模擬的是一個油田簡單的工業控制場景, 模型大體包括
油井、分離器、 加熱爐、自然氣、外輸泵。
還包括管路流動、流動方向。 描述了採油、加工、 輸出的全過程。程序員
第一步要作的就是建模,設計組使用3D建模工具 3d max或者c4d 進行油田設備模型的建模。建模後導出後綴爲obj或者gltf格式文件,這兩種格式是咱們三維渲染引擎支持最好的文件格式。後端
建模後的全部模型文件,最終會放到後端的模型庫,模型庫的管理目錄,以下圖所示:
瀏覽器
須要製做的模型包括油井、分離器、加熱爐、自然氣、外輸泵,以下圖所示,架構
加載模型可以使用引擎模型的加載函數,進行模型加載,如obj模型加載,以下代碼所示:app
new mono.OBJMTLLoader().load( 'youjing.obj', 'youjing.mtl', '', (node)=> { node.type = 'obj'; box.addByDescendant(node); }, );
如加載一個油井模型,由於加載模型是一個異步的過程,因此會有一個回調函數,加載完成以後,在回調函數中,把模型文件生成的三維對象,加入到場景容器box之中,加入以後場景中就會顯示咱們的三維對象,以下圖所示:異步
建立Network3D對象,便可以建立三維場景對象,以下代碼所示:ide
const box = new mono.DataBox(); const network = new TopoNetwork(box, null, 'monoCanvas'); network.mode = 'editor'; window.network = network; // todo this.network = network; network.bindApp(this); network.setRenderSelectFunction(() => false); make.Default.path = './static/myModellib/'; network.setClearColor(0, 0, 0); network.setClearAlpha(0); const directionalLight = new mono.DirectionalLight(0x333333, 0.3); directionalLight.setDirection(new mono.Vec3(0, 1, 1)); box.add(directionalLight); let pointLight = new mono.PointLight(0xeae5e1, 0.3); pointLight.setPosition(2000, 2000, 2000); box.add(pointLight); pointLight = new mono.PointLight(0xeae5e1, 0.4); pointLight.setPosition(-2000, 2000, 2000); box.add(pointLight); pointLight = new mono.PointLight(0xeae5e1, 0.3); pointLight.setPosition(2000, 2000, -2000); box.add(pointLight); pointLight = new mono.PointLight(0xeae5e1, 0.4); pointLight.setPosition(-2000, 2000, -2000); box.add(pointLight); box.add(new mono.AmbientLight(0x888888)); mono.Utils.autoAdjustNetworkBounds( network, document.querySelector('.app'), 'clientWidth', 'clientHeight', );
從模型列表,把模型拖拽到三維場景對象上,便可以建立模型對象,以下圖所示:
函數
在模型按鈕上,須要監聽drag 或者dragstart事件,這個被封裝到一個獨立的類Dragger.js裏面,在該類中專門處理了dragstart事件:
addDragger(parent, subClass, option) { parent.addEventListener('dragstart', (e) => { let target = null; // 拿到冒泡的全部元素 const path = eventPath(e); for (let i = 0; i < path.length; i += 1) { if (path[i].classList && path[i].classList.contains(subClass)) { target = path[i]; break; } } ... }
在三維場景中,能夠直接經過打點的方式建立三維管道,以下代碼所示:
let path = new mono.Path(pipePoints); path = mono.PathNode.prototype.adjustPath(path, 2, 2); const node = new mono.PathNode(path, 10, 3, 20); node.s({ 'm.type': 'phong', 'm.side': 'both', 'm.normalType': mono.NormalTypeSmooth, 'm.color': '#E35944', 'm.ambient': '#E35944', }); this.network.getDataBox().addByDescendant(node);
其中pipePoints是打點記錄下的三維頂點。
管路動畫是經過管路貼圖的offset屬性,不斷變化造成的動態流動效果,以下代碼所示:
node.animate = new mono.Animate({ from: pipeDirection === 'forward' ? 0 : 1, to: pipeDirection === 'forward' ? 1 : 0, dur: 1000, reverse: false, repeat: Number.POSITIVE_INFINITY, onUpdate(value) { node.setStyle('m.texture.offset', new mono.Vec2(value, 0)); }, });
最終效果以下圖:
經過研發編輯,最終的顯示效果大體以下:
還有更多效果本文並無凸顯出來, 有興趣獲取demo的,請發郵件到:
terry.tan@servasoft.com
歡迎關注公衆號「ITman彪叔」。彪叔,擁有10多年開發經驗,現任公司系統架構師、技術總監、技術培訓師、職業規劃師。在計算機圖形學、WebGL、前端可視化方面有深刻研究。對程序員思惟能力訓練和培訓、程序員職業規劃有濃厚興趣。