1. 程式人生 > >基於HTML5和WebGL的3D網絡拓撲結構圖

基於HTML5和WebGL的3D網絡拓撲結構圖

bsp 針對 對象 如何使用 別人 做成 segments end ges

現在,3D模型已經用於各種不同的領域。在醫療行業使用它們制作器官的精確模型;電影行業將它們用於活動的人物、物體以及現實電影;視頻遊戲產業將它們作為計算機與視頻遊戲中的資源;在科學領域將它們作為化合物的精確模型;建築業將它們用來展示提議的建築物或者風景表現;工程界將它們用於設計新設備、交通工具、結構以及其它應用領域;在最近幾十年,地球科學領域開始構建三維地質模型,而且3D模型經常做成動畫,例如,在故事片電影以及計算機與視頻遊戲中大量地應用三維模型。它們可以在三維建模工具中使用或者單獨使用。為了容易形成動畫,通常在模型中加入一些額外的數據,例如,一些人類或者動物的三維模型中有完整的骨骼系統,這樣運動時看起來會更加真實,並且可以通過關節與骨骼控制運動。

這些種種都讓我們前端開發者覺得如果我們可以不用學習unity3d或者其他遊戲開發工具就能實現3D效果,而且能夠精準的靠代碼來控制移動或者方向就好了。。。於是我利用HT For Web中的3D組件來實現了一個小例子,用了HT中3D組件的大部分功能,做這個例子就是想把3D組件好好的掌握,盡量放進一個例子中,到時候別人有需要就可以參考了,但是因為之前從來沒有實現過3D的效果,再加上現在手冊沒有很完整,所以這個例子對我來說還是有點難度的。

本例位置:http://www.hightopo.com/demo/3DTopology/index.html

先來看看整體實現的效果圖:

技術分享

用HT for Web,現有的3d模板創建三層底板不是問題,問題是要如何將圖中第一層的“電腦”和“機櫃組件”放上去?我是在網上down下來的obj格式的文件,然後我利用HT中的ht.Default.loadObj(objUrl, mtlUrl, params)函數將模型加載進去,其中的params部分可以參考http://www.hightopo.com/guide/guide/plugin/obj/ht-obj-guide.html,代碼如下:

ht.Default.loadObj(‘obj/機櫃組件1.obj‘, ‘obj/機櫃組件1.mtl‘, {  
    cube: true,  
    center: true,  
    shape3d: ‘box‘,  
    finishFunc: function(modelMap, array, rawS3){  
        window.rawS3 = rawS3;  
      if(modelMap){  
        device2 = createNode(‘box‘, floor1);  
    device2.p3([x1-120, y1+13, z1+60]);  
    device2.s3(rawS3);  
    createEdge(device1, device2);  
    device3 
= createNode(‘box‘, floor1);     device3.s3(rawS3);     device3.p3([x1+120, y1+13, z1+60]);     createEdge(device1, device3);   } } });

“電腦”上方有個紅色的立體能旋轉的“警告”,是依靠ht.Default.setShape3dModel函數(HT for Web 建模手冊)註冊的一個3d模型,在ht中,封裝好的建模函數有很多,比較基礎的就是球體,圓柱,立方體等等,這邊我用的是構造環形的方法createRingModel來生成“警告”最外面的環,感嘆號的上部分就是用的createSmoothSphereModel構造的球體,感嘆號的下部分就是用createSmoothCylinderModel來構造的圓柱。我一開始直接使用了3d模型中封裝好的函數,導致後來根本不知道函數中使用的參數是做什麽用的,而且也不明白3d模型是怎麽構成的,然後自己又重新看了前面的“模型基礎”,才知道原來3d模型采用的一個面,最基礎的是三角面,之後復雜的面也是由多個三角面來形成的,然後繞著一根特定的軸旋轉之後形成的,當然,這個軸是你來決定的,不同的軸可以生成不同的形狀,對於顏色等風格方面的設置可以參考HT for Web 風格手冊。至於如何讓這個3d模型旋轉起來,ht中封裝了addScheduleTask(Task)方法,我在第三層Task中調用了ht封裝的一個旋轉函數setRotation來設置旋轉的順序和方向,並且指定了旋轉的對象。以下是自定義“警告”的3d模型的方法(註意:因為本例的模型是自定義組合的,如果要設置整體模型的顏色要用“all.blend”style屬性):

var ringModel = ht.Default.createRingModel([8, 1, 10, 1, 10, -1, 8, -1, 8, 1], null, null, false, false, 100);  
var sphereModel = ht.Default.createSmoothSphereModel(8, 8, 0, Math.PI*2, 0, Math.PI, 2);  
var cylinderModel = ht.Default.createSmoothCylinderModel(8, true, true, 1, 2, 0, Math.PI*2, 8);  
var arr = [  
    {  
        r3: [Math.PI/2, 0, 0],  
        color: ‘red‘  
    },{  
        shape3d: sphereModel,  
        t3: [0, 4, 0],  
        color: ‘red‘  
    },{  
        shape3d: cylinderModel,  
        t3: [0, -3, 0],  
        color: ‘red‘  
    }  
];  
ht.Default.setShape3dModel(‘alarm‘, {  
    shape3d: arr  
}); 

要實現3D界面上展現2d圖片,只要按照平常的路走就行,因為ht中的Graph3dView和其他的組件的根部都是div,在div上生成圖片用的就是原生js,new Image(),再將image的src和大小賦值,並且加到3d面板上就行了,註意這裏是加到3d的底層div上,要用g3d.getView().appendChild來添加,我們還可以看到管線上有虛線流動的痕跡,這是通過不斷改變“shape3d.uv.offset”參數實現管道流動的特殊效果,詳情請參考HT for Web 形狀手冊。

想讓2d圖片在3d管線上移動則是使用g3d.toViewPosition(position)來獲取3d模型的二維坐標,這個函數中的參數就是三維模型的3d坐標,我們可以直接將polyline管線上的點傳入toViewPosition函數中,這邊獲取管線上的點在ht中已經封裝好三個函數getLineCacheInfo、getLineLength、getLineOffset,這樣就可以直接獲取到二維坐標,然後將img的坐標設置上去即可,以下是img圖片在管道上移動的代碼:

var delta = 10;  
params = {  
    frames: Infinity,  
    interval: 50,  
    action: function(v, t){  
        var length = (polyline.a(‘total‘) || 0) % polyline.a(‘length‘) + delta;  
        var cache = ht.Default.getLineCacheInfo(polyline.getPoints(), polyline.getSegments());  
        var lineLength = ht.Default.getLineLength(cache);  
        var offset = ht.Default.getLineOffset(cache, length);  
        arr = [offset.point.x, offset.point.y, offset.point.z];  
        var position = g3d.toViewPosition(arr);  
            img.style.left = (position.x - 5) + ‘px‘;  
            img.style.top = (position.y - 5) + ‘px‘;  
            polyline.a(‘total‘, length);  
    }  
};  
anim = ht.Default.startAnim(params);  

可以看到圖中第二層中的立方體上有“SDH”的字樣,我是通過設置shape3d.top.img: imgURL來實現的,這邊的imgURL可以是圖片的相對路徑,也可以是ht中用ht.Default.setImage聲明的img的名稱,還可以是json格式構造的圖片。在ht中,2D文字顯現在3D上,則字體周圍會出現“鋸齒”,這個時候只要設置“label.transparent: true”即可。

我們還可以看到第二層上有兩個特殊的多邊形“平行四邊形”和“梯形”,因為之前有客戶說不知道如何使用createExtrusionModel這個模型函數(HT for Web 建模手冊),我索性就寫了一下,平行四邊形是靠createParallelogramModel模型函數,這個函數比較簡單,createExtrusionModel(array, segments, top, bottom, resolution, repeatUVLength, tall, elevation),array是你要形成的圖形的坐標點,這邊只是針對於xz軸上畫的平面圖形,segments指的是如何連接這幾個坐標點,可參考HT for Web 形狀手冊,top和bottom就是讓你選擇是否有頂部或者底部,resolution微分段數,我們描繪一段曲線的時候可能只要確認幾個個別的點然後在每兩個點之間的連線上把它分成多個段,這樣這條線段就會變得平滑,ht為了用戶能夠輕松操作這些線段,就封裝了這一個參數,repeatUVLength默認為空,設置值後頂部和底部的貼圖將根據制定長度值進行重復,tall模型的高度,默認為5,elevation模型中心的y軸位置,默認值為0,設置這個值可以使xz上的平面繞著y軸旋轉。

底層的一個環形的效果是通過一個算法來實現的,環形得確認這個環形上有多少個元素,然後算每兩個之間的角度,在通過sin、cos來計算每一個元素的位置,得出了如下代碼:

names = [‘設備2‘, ‘設備3‘, ‘設備4‘, ‘設備5‘, ‘設備6‘, ‘設備7‘, ‘設備8‘, ‘設備9‘];  
names.forEach(function(name, index) {  
    x = 400, y = 200, angle = 45, r = 120;  
    x = x3 + Math.sin((2 * Math.PI / 360) * angle * index) * r;  
    y = z3 + Math.cos((2 * Math.PI / 360) * angle * index) * r;  
    device = createRect([x, y3 + 15, y], [w * 0.1, 15, h * 0.1], ‘‘, ‘‘, floor3);  
    createEdge(device5, device);  
}); 

基於HTML5和WebGL的3D網絡拓撲結構圖