zoukankan      html  css  js  c++  java
  • 基于HT for Web矢量实现3D叶轮旋转

    在上一篇《基于HT for Web矢量实现2D叶轮旋转》中讲述了叶轮旋转在2D上的应用,今天我们就来讲讲叶轮旋转在3D上的应用。

    3D拓扑上能够创建各种各样的图元,在HT for Web系统中提供了一些常规的3D模型,可是对于那些比較复杂的模型,比方汽车、人物等模型就无能为力了,那再项目中须要用到这种模型该肿么办呢?这时候就须要借助专业的3ds Max工具来建模了。然后通过3ds Max工具将模型导出成obj文件。然后再项目中引用导出的obj文件,这样就能成功的使用上复杂的图元了。

    在《HT图形组件设计之道(四)》一文中有提及HT for Web引入obj文件的介绍,在这里我就不做反复介绍了,我们先来看看今天作为演示的Demo模型长什么样:

     

    嘿嘿,是不是感觉今天的模型有些大材小用了,没办法。怪仅仅怪自己不懂3ds Max工具,仅仅能先用这个大家熟悉的模型来做Demo演示了。

    首先我们须要有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拓扑上做了些简单的属性设置,让拓扑看起来舒服些,如此我们就能够看到我们创建出来的飞机模型究竟长什么样了

    怎么样,创建一个复杂模型好像并没有想象中的复杂(复杂的东西都让美工做完了)。

    我们细致观察飞机会发现,飞机前面的螺旋桨颜色和机身一样,一眼看去不太easy注意到它的存在。那是否能将其颜色改掉呢?我们能够查看下mtl文件,看飞机的螺旋桨是否分离机身独立成一个材质,mtl文件的内容例如以下:

    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回调函数中加入上例如以下代码就可以:

    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>

     

     

  • 相关阅读:
    ListCtrl中垂直滚动条自动滚动
    auth组件
    母版的继承
    mysql数据备份和恢复
    部署MHA
    安装mysql
    yum源优化
    存储过程
    redis哨兵、集群
    redis主从同步
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6831216.html
Copyright © 2011-2022 走看看