打造最美HTML5 3D機房(第二季)

寫在前面的前面

如今拍電影、搞真人秀都流行拍續集,哥今天給你們帶來的是打造最美3D機房的續集,哥的目標是成爲3D機房界的網紅。html

-------------------------------我是這個系列已經有了第三篇的分割線-------------------------------html5

前情提要

請腦補畫外音 Previously on Monolog……web

前陣子寫了一篇打造最美html5 3d機房,介紹瞭如何用html5在網頁上建立無插件的精美3d機房場景,收到不少朋友的鼓勵,深表感謝。對於索要源代碼的朋友,已經盡力郵件回覆。因爲精力所限,如未能收到的朋友請留言或給我發送郵件:tw-service@servasoft.com。最近項目第二期又要緊鑼密鼓地開始了,因此想抓緊把一些新增的內容補充上,進一步完善這個html5 3d機房的呈現效果。json

上一篇中主要介紹的是如何從最基礎的webgl封裝到建立3d物體對象,再經過3d物體對象「搭積木」式的組建整個3d機房場景。這一篇主要介紹一些如何在這個場景上進一步豐富更多的功能和呈現效果,以及實現這些功能在技術上的思路。canvas

首先咱們來看看第一季已經實現的純自然無添加無PS的HTML5 3D機房效果:
圖片描述segmentfault

已經拿到過代碼的朋友應該知道,這一場景是經過一個json文件進行組裝和加載,能夠很方便地進行修改和維護。在此基礎上,這一次我又增長了機櫃標籤、機櫃門、複雜設備、機房走線、人員軌跡等效果,下面我就把第二季的乾貨一一爲你們奉上。數組

機櫃標籤

機房中最重要的物理資源——機櫃——是機房管理、規劃、監控人員最關注的對象之一。對於規模在幾十個、上百個甚至上千個機櫃的機房,每一個機櫃必然會進行資產編號,方便檢索和管理。這個在多數資產管理系統中,都是最基本的。可是在3d場景中,如何顯示這些機櫃編號,才能讓用戶更直觀的看到每一個機櫃的位置呢?服務器

傳統的方式是用標籤顯示資產編號,例如能夠用「告警冒泡」那樣的方式顯示一個文字氣泡。不過當機櫃產生告警時,兩個氣泡會有所衝突。並且過多的氣泡會產生相互遮擋覆蓋,有點混亂,好比像這樣:
圖片描述網絡

所以我嘗試了一種不一樣的思路:把文字渲染到一個內存圖片,「溶解」到機櫃的上方貼圖中。框架

想要生成一個內存的圖片文字,能夠經過下面的函數實現:

generateAssetImage: function(text){         
        var width=512, height=256;

        var canvas = document.createElement('canvas');
        canvas.width  = width;
        canvas.height = height;

        var ctx = canvas.getContext('2d');        
        ctx.fillStyle='white';
        ctx.fillRect(0,0,width,height);
        
        ctx.font = 150+'px "Microsoft Yahei" bold';
        ctx.fillStyle = 'black';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(text, width/2,height/2);
        ctx.strokeStyle='black';
        ctx.lineWidth=15;
        ctx.strokeText(text, width/2,height/2);

        return canvas;   
    }

須要留意的是:

  1. 生成的圖片寬高數值最好是2的冪,例如12八、25六、512等,這樣在3d中渲染不容易出現閃爍和鋸齒。相關原理請查閱google。

  2. 文字繪製儘可能居中、充滿整個圖,不要過小,不然看上去比較奇怪。

  3. 空白處保持透明,沒必要填充色,方便和機櫃自己貼圖的「溶解」。

  4. 直接返回canvas對象便可,沒必要生成圖片點陣數組。

生成canvas後,能夠這樣直接貼圖使用:

var labelCanvas=demo.Default.generateAssetImage(label);
    rack.setStyle('top.m.texture.image', labelCanvas);
    rack.setStyle('top.m.specularmap.image', labelCanvas);

經過上面代碼,把貼圖做爲機櫃立方體top面的貼圖和反射映射圖。這樣出來的效果以下:
圖片描述
這樣,既不用增長3d對象,也不影響機櫃的美觀度,關鍵是看得很是清晰,在大場景中也不干擾用戶的視線:
圖片描述

機櫃門

上一篇裏,因爲時間緊迫,也考慮到呈現效率,機櫃採用了「雙擊機櫃出現設備」的方案。一個立方體的機櫃雖然簡單直接,可是沒有機櫃門,總以爲假了一點,客戶也提到了這一點,所以按照機房門的思路,增長一個機櫃門,增長雙擊開門的效果,這個比較簡單:

var rackDoor = new mono.Cube(width, height, 2);
    rackDoor.s({
        'm.type':'phong',
        'm.color': '#A5F1B5',
        'm.ambient': '#A4F4EC',
        'front.m.texture.image': 'images/rack_front_door.png',
        'back.m.texture.image': 'images/rack_door_back.png',
        'm.envmap.image': demo.Default.getEnvmap('envmap1'),
    });
    rackDoor.setParent(rack);
    rackDoor.setPosition(0, 0, depth/2+1); 
    rackDoor.setClient('animation','rotate.right.120');

上面代碼建立了一個薄薄的立方體做爲機櫃門。設置貼圖、顏色等,再設置其parent是機櫃。這樣,若是拖拽機櫃位置,機櫃也會跟着移動,簡單方便。最後,在設置一下機櫃門的動畫。經過一個字符串進行定義:rotate.right.120表示動畫是「向右側旋轉120度」,在雙擊的時候觸發。
圖片描述

複雜電信設備

第一季裏,機櫃內的設備,主要用樂服務器來表現,加入了設備彈出、告警等效果。後期根據現場和用戶的交流,用戶進一步提出要顯示機架上須要安裝更加複雜的電信設備,包括板卡、板卡的插拔動做、呈現方法等,也就是在機櫃上顯示一個有多個板卡的設備,雙擊板卡能夠彈出。

要作這個,須要把原來的一個立方體的服務器設備作一個「挖空」處理,變成一個空的設備框的樣子。而後再生成一系列的板卡對象,插入這個空框。每一個板卡應該由面板+電路板組成,能夠用兩個立方體進行拼接,添加適當的貼圖完成。代碼以下:

var parts=[{
        //card panel
        type: 'cube',
        width: width,
        height: height,
        depth: 1,
        translate: [x, y, z+1],
        rotate: rotate,
        op: '+',
        style:{
            'm.color': color,
            'm.ambient': color,
            'm.texture.image': 'images/gray.png',
            'front.m.texture.image': pic,
            'back.m.texture.image': pic,
        }
    },{
        //card body
        type: 'cube',
        width: 1,
        height: height*0.95,
        depth: depth,
        translate: [x, y, z-depth/2+1],
        rotate: rotate,
        op: '+',
        style:{
            'm.color': color,
            'm.ambient': color,
            'm.texture.image': 'images/gray.png',
            'left.m.texture.image': 'images/card_body.png',
            'right.m.texture.image': 'images/card_body.png',
            'left.m.texture.flipX': true,
            'm.transparent': true,    
        }
    }];
    
    var card=demo.Default.createCombo(parts);
    card.setClient('animation', 'pullOut.z');
    box.add(card);

上面代碼能夠生成一個板卡對象。循環重複,設置位置,便可生成整個設備。經過設置animation屬性,定義板卡動畫爲「雙擊拉出」,再次雙擊推回。效果以下圖:

圖片描述

圖片描述

固然,實際項目中,各類結構的電信設備千奇百怪,要經過代碼定義是不現實的。因此咱們還開發了一個設備編輯器,能夠經過拖拽方式快速生成設備結構圖。
圖片描述

機房線纜和走線架

除了機櫃以外,線纜的鏈接走向和鏈接關係是管理員關注的另一個焦點。機架中的電信設備或服務器設備會經過端口和線纜進行鏈接,組成必定結構的網絡。而線纜的走向在物理上經過肉眼是很難看清晰的。更多線纜會從機櫃連出,延伸到屋頂上方或地板下方的隱蔽工程中(例如走線架)固定和佈線,用肉眼更沒法觀察。此時,須要3d機房界面能清晰的顯示電纜從端口到走線架再到端口的「端到端」的物理走線,方便管理員瞭解網絡狀況和管理。

線纜

線纜,能夠用一個空間的path來定義,並設置其貼圖:

var path = demo.Default.create3DPath(json.data);
    var cable=new mono.PathNode(path, 100, 1);
    cable.s({
        'm.type': 'phong',
        'm.specularStrength': 30,
        'm.color': json.color,
        'm.ambient': json.color,         
        'm.texture.image': 'images/flow.jpg',
        'm.texture.repeat': new mono.Vec2(200, 1),
    });
    box.add(cable);

經過json定義的[x, y, z]數組來生成一個path對象,而後用它來生成一個空間的「管子」對象。流動效果能夠經過一個動畫來修改貼圖紋理的offset,讓眼睛產生貼圖不斷「移動」的效果。

圖片描述

走線架

走線架能夠經過簡單的鏤空貼圖來模擬,不須要建一個複雜的框架模型,減小對GPU的壓力。實際的走線架有不少種,例以下圖是一種典型的走線架:

圖片描述

圖片描述

咱們經過程序模擬一下:

var rail=demo.Default.createPathObject(railInfo);
    rail.s({
        'm.texture.image': 'images/rail.png',
        'm.type': 'phong',
        'm.transparent': true,
        'm.color': '#CEECF5',
        'm.ambient': '#CEECF5',
        'aside.m.visible': false,
        'zside.m.visible': false,
        'm.specularStrength': 50,
    });
    rail.setPositionY(263);
    box.add(rail);

最終走線架+線纜的效果以下:
圖片描述

路徑規劃

在3d場景中,常常須要計算規劃並顯示一個最優的空間或平面路徑,用來指示如何最快、最合理的到達目標,或經過路徑顯示一個移動物體的軌跡,方便進行監控和分析。例如,客戶提出一個實際需求:現場檢修人員手持平板進入機房,輸入設備id後,直接給出前方走動路徑,並進行實時導航引導

咱們能夠把這個需求分解爲導航路徑顯示和人員模擬兩步。

導航路徑

導航線能夠經過一個浮在地板上方的path路徑來定義。作一個簡單的顏色渲染和彎角處理,就能夠比較清晰的展現底面的走動路徑。

var path=new mono.Path();
            path.moveTo(object.getPositionX(), object.getPositionZ());
            for(var i=0;i<points.length; i++){
                path.lineTo(points[i][0], points[i][13]);
            }
            path = mono.PathNode.prototype.adjustPath(path, 20);

            var trail=new mono.PathCube(path, 10, 3);
            trail.s({
                'm.type': 'phong',
                'm.specularStrength': 30,
                'm.color': '#298A08',
                'm.ambient': '#298A08',         
                'm.texture.image': 'images/flow.jpg',
                'm.texture.repeat': new mono.Vec2(150, 1),
            });
            trail.setRotationX(Math.PI);
            //trail.setStartCap('plain');
            //trail.setEndCap('plain');
            trail.setPositionY(5);
            trail.setClient('type', 'trail');
            box.add(trail);

圖片描述

拉近後看下細節:
圖片描述

移動軌跡的顯示也有不少變化,形狀、顏色的變化,空間座標的變化,均可以產生一些不一樣的效果。例以下圖是另一個3d車庫導航系統的場景:
圖片描述

加載人物模型

接下來,要加載一我的的模型進來,放在路徑上。能夠在網上找一些3d max作的模型,並轉成obj格式的文件,這樣就能夠方便的導入場景中。Obj經過對應的mtl文件進行定義材質,須要的貼圖也須要一併涵蓋進來。經過下面幾行代碼便可完成obj模型的導入:

var obj='images/worker.obj';
        var mtl='images/worker.mtl';               
            
        var loader = new mono.OBJMTLLoader();
        loader.load(obj, mtl, {'worker': 'images/worker.png',}, function (object) {                                
            box.addByDescendant(object);
        });

效果以下圖:
圖片描述

須要留意的是,人的模型不要太大,能把人物輪廓大概渲染清晰便可。例如上面的模型也就幾百k,加載和顯示幾乎瞬間完成,不會產生卡頓。若是加載幾十兆上百兆的高清模型,則可能出現卡頓,也會拖慢場景的渲染速度。畢竟咱們的主要場景對象是3d機房,對模型選擇要有所取捨,千萬不要喧賓奪主。

讓任務沿着路徑移動,能夠經過動畫進行控制,對path中每一段路線進行平移,連續、反覆的播放,便可實現人物的移動效果。
圖片描述

固然這裏有一個缺點,人物的移動是僵硬不動的,不能像真實人物同樣邁腿一步一步的走路進行移動。若是要作,須要用到骨骼動畫等技術,相對複雜一些,目前項目緊急,就留給之後找時間研究了。固然對於3d機房這樣的企業應用來講,必要性不必定很大,畢竟不是遊戲。

經過這些技術,你們能夠輕鬆構建一個比較完整的3d機房系統,就跟咱們此次的項目同樣:
圖片描述

圖片描述

圖片描述

後記

篇幅有限,這一篇就介紹這麼多,後續找時間會繼續給你們介紹如何拖拽移動機櫃、顯示機房中的溫度雲圖、風向監控、攝像頭及視頻監控,如何建立一個大的園區和樓宇等內容。成爲一個網紅的路還很漫長,我會一步一個腳印地走,也但願對你們有所啓發和幫助。老規矩,須要相關代碼的同窗能夠發郵件到tw-service@servasoft.com,或留下郵箱,我會盡力回覆。謝謝!

相關文章
相關標籤/搜索