基於HT for Web矢量實現3D葉輪旋轉

在上一篇《基於HT for Web矢量實現2D葉輪旋轉》中講述了葉輪旋轉在2D上的應用,今天咱們就來說講葉輪旋轉在3D上的應用。php

3D拓撲上能夠建立各類各樣的圖元,在HT for Web系統中提供了一些常規的3D模型,可是對於那些比較複雜的模型,好比汽車、人物等模型就無能爲力了,那再項目中須要用到這樣的模型該腫麼辦呢?這時候就須要藉助專業的3ds Max工具來建模了,而後經過3ds Max工具將模型導出成obj文件,而後再項目中引用導出的obj文件,這樣就能成功的使用上覆雜的圖元了。html

在《HT圖形組件設計之道(四)》一文中有說起HT for Web引入obj文件的介紹,在這裏我就不作重複介紹了,咱們先來看看今天做爲演示的Demo模型長什麼樣:數組

 

嘿嘿,是否是感受今天的模型有些大材小用了,沒辦法,怪只怪本身不懂3ds Max工具,只能先用這個你們熟悉的模型來作Demo演示了。app

首先咱們須要有3ds Max工具將模型導出成obj及mtl文件,而後調用HT for Web的ht.Default.loadObj()方法讀取並解析模型文件,在解析完成後,經過調用ht.Default.setShape3dModel()方法將模型註冊到系統中,如此在後續的代碼中就可以應用到該模型了,模型文件的讀取及註冊具體代碼以下:函數

ht.Default.loadObj('plane.obj', 'plane.mtl', {                    
    center: true,
    r3: [0, -Math.PI/2, 0], // make plane face right
    s3: [0.15, 0.15, 0.15], // make plane smaller
    finishFunc: function(modelMap, array, rawS3){
        if(modelMap){  
            ht.Default.setShape3dModel('plane', array);

            var plane = new ht.Node();
            plane.s3(rawS3);
            plane.s({
                'shape3d': 'plane',
                'shape3d.scaleable': false,
                'wf.visible': true,
                'wf.color': 'white',
                'wf.short': true
            });
            dataModel.add(plane);
        }
    }
});

註冊完3D模型後,咱們立刻建立了一個3D圖元,並將其添加到了dataModel容器中,這時咱們須要一個3D拓撲來顯示這個3D圖元,具體的建立代碼以下:工具

var dataModel = new ht.DataModel();
var g3d = new ht.graph3d.Graph3dView(dataModel);
g3d.setEye(200, 50, 300);
g3d.setDashDisabled(false);
g3d.getView().style.background = '#4C7BBB';
g3d.addToDOM();

3D拓撲上作了些簡單的屬性設置,讓拓撲看起來舒服些,如此咱們就能夠看到咱們建立出來的飛機模型到底長什麼樣了動畫

怎麼樣,建立一個複雜模型好像並無想象中的複雜(複雜的東西都讓美工作完了)。ui

咱們仔細觀察飛機會發現,飛機前面的螺旋槳顏色和機身同樣,一眼看去不太容易注意到它的存在,那可否將其顏色改掉呢?咱們能夠查看下mtl文件,看飛機的螺旋槳是否分離機身獨立成一個材質,mtl文件的內容以下:spa

newmtl body
    Ns 10.0000
    Ni 1.5000
    d 1.0000
    Tr 0.0000
    Tf 1.0000 1.0000 1.0000 
    illum 2
    Ka 0.3608 0.4353 0.2549
    Kd 0.3608 0.4353 0.2549
    Ks 0.0000 0.0000 0.0000
    Ke 0.0000 0.0000 0.0000

newmtl propeller
    Ns 10.0000
    Ni 1.5000
    d 1.0000
    Tr 0.0000
    Tf 1.0000 1.0000 1.0000 
    illum 2
    Ka 0.3608 0.4353 0.2549
    Kd 0.3608 0.4353 0.2549
    Ks 0.0000 0.0000 0.0000
    Ke 0.0000 0.0000 0.0000

正如咱們所想,飛機模型的機身和螺旋槳是分開了兩個獨立的材質,並將螺旋槳的材質名字定義爲propeller,所以咱們能夠獨立控制機身及螺旋槳,那麼咱們就來修改下螺旋槳的顏色吧,在loadObj()方法中的finishFunc回調函數中添加上以下代碼便可:scala

modelMap.propeller.s3 = [1, 1.2, 1.2];
modelMap.propeller.color = ‘yellow';

 

在代碼中,咱們不只改變了螺旋槳的顏色,咱們還對螺旋槳作了縮放處理,令螺旋槳的寬度和長度變大一點。

到這裏,模型就算完成了,接下來要作的就是讓螺旋槳動起來,和2D葉輪旋轉相似,在3D模型上也能夠作數據綁定,要想讓螺旋槳旋轉起來,咱們就須要設置螺旋槳的rotation屬性,和3D上的圖元不一樣的是,設置3D圖元的rotation屬性須要設置一個數組,定義3D上三個方向的旋轉值。

咱們先來嘗試下讓螺旋槳沿着x軸旋轉45度試下:

modelMap.propeller.r3 = [Math.PI / 4, 0, 0];

果真能夠,那麼接下來咱們就能夠爲螺旋槳的rotation屬性作數據綁定的處理了:

modelMap.propeller.r3 = {
    func: function(data){
        return [data.a('angle'), 0, 0];
    }
};

咱們將螺旋槳的x軸上的旋轉角度綁定到圖元的angle自定義屬性上,咱們能夠經過改變angle屬性值令螺旋槳沿着x軸轉動起來,那麼接下來咱們就經過定時器來動態改變angle屬性吧,看看螺旋槳是否是真的能夠動起來:

window.setInterval(function() {
    var rotation = plane.a('angle') + Math.PI / 10;
    if (rotation > Math.PI * 2) {
        rotation -= Math.PI * 2;
    }
    plane.a('angle', rotation);
}, 40);

 

螺旋槳果真動起來了,這個定時器讓螺旋槳作勻速運動,可是飛機的螺旋槳在起飛和降落的時候其旋轉速度都不是勻速,咱們要模擬飛機起飛和降落時螺旋槳的旋轉速度該如何處理呢?這個時候咱們能夠考慮用HT for Web中的動畫來解決這個問題,關於動畫的內容因爲比較複雜,在這裏就不深刻探討,等之後有機會再和你們分享動畫的相關內容,今天就先講訴下動畫的基本用法,簡單實現螺旋槳模擬起飛和降落的效果,具體的代碼以下:

var params = {
    delay: 1500,
    duration: 20000,
    easing: function(t){
        return (t *= 2) < 1 ? 0.5 * t * t : 0.5 * (1 - (--t) * (t - 2));
    },
    action: function(v, t){
        plane.a('angle', v*Math.PI*120);
    },
    finishFunc: function(){
        ht.Default.startAnim(params);
    }
};

ht.Default.startAnim(params);

咱們來分析下代碼:

1. delay屬性:定義動畫播放前的停頓時間;

2. duration屬性:定義動畫持續時間;

3. easing函數:定義動畫緩動函數;

4. action函數:action函數必須提供,實現動畫過程當中的屬性變化,在這裏設置angle屬性;

5. finishFunc函數:動畫結束後調用的函數,在這裏又啓動了動畫,讓螺旋槳不斷的旋轉。 

運行代碼,你會發現螺旋槳在1.5秒後進入旋轉狀態,而且旋轉速度由慢變快,再變慢直至中止,而後再過1.5秒後繼續旋轉,如此周而復始。 

好了,今天的內容到這裏就結束了,整個Demo的運行效果能夠經過下面的視頻查看,最後再附上本次Demo的全部代碼。

http://v.youku.com/v_show/id_XMTI5NDI5MzYyOA==.html

<!DOCTYPE html>
<html>
    <head>
        <title>HT for Web - Plane</title>
        <meta charset="UTF-8" name="viewport" content="user-scalable=yes, width=600">
        <script src="../../../build/ht-debug.js"></script>
        <script src="../../../build/ht-obj-debug.js"></script>
        <script>
            function init(){
                var dataModel = new ht.DataModel();
                var g3d = new ht.graph3d.Graph3dView(dataModel);
                g3d.setEye(200, 50, 300);
                g3d.setDashDisabled(false);
                g3d.getView().style.background = '#4C7BBB';
                g3d.addToDOM();
                
                ht.Default.loadObj('plane.obj', 'plane.mtl', {
                    center: true,
                    r3: [0, -Math.PI/2, 0], // make plane face right
                    s3: [0.15, 0.15, 0.15], // make plane smaller
                    finishFunc: function(modelMap, array, rawS3){
                        if(modelMap){
                            modelMap.propeller.r3 = {
                                func: function(data){
                                    return [data.a('angle'), 0, 0];
                                }
                            };
                            // make propeller a litter bigger
                            modelMap.propeller.s3 = [1, 1.2, 1.2];
                            modelMap.propeller.color = 'yellow';
                
                            ht.Default.setShape3dModel('plane', array);
                
                            var plane = new ht.Node();
                            plane.s3(rawS3);
                            plane.s({
                                'shape3d': 'plane',
                                'shape3d.scaleable': false,
                                'wf.visible': true,
                                'wf.color': 'white',
                                'wf.short': true
                            });
                            dataModel.add(plane);
                
                            var params = {
                                delay: 1500,
                                duration: 20000,
                                easing: function(t){
                                    return (t *= 2) < 1 ? 0.5 * t * t : 0.5 * (1 - (--t) * (t - 2));
                                },
                                action: function(v, t){
                                    plane.a('angle', v*Math.PI*120);
                                },
                                finishFunc: function(){
                                    ht.Default.startAnim(params);
                                }
                            };
                            
                            ht.Default.startAnim(params);
                
                            /*window.setInterval(function() {
                                var rotation = plane.a('angle') + Math.PI / 10;
                                if (rotation > Math.PI * 2) {
                                    rotation -= Math.PI * 2;
                                }
                                plane.a('angle', rotation);
                            }, 40);*/
                        }
                    }
                });
            }
        </script>
    </head>
    <body onload="init();">                         
    </body>
</html>
相關文章
相關標籤/搜索