zoukankan      html  css  js  c++  java
  • ThingJS适合js工程师快速开发爆炸图动效

    全选所有物体(别选摄影机和灯)。转换为多边形或者网格,然后选中一个网格,附加其他所有物体,这个就叫塌陷。3DMAX的模型导入ThingJS之后,塌陷后的模型数据更小,适合js工程师快速开发爆炸图动效。

    今天来讲讲如何基于js语法来开发一个物体模型拆解展开的效果,专业名称叫“物体爆炸图”,标准ThingJS体系模型出于互动模型性能考虑,都要求在模型上传前做塌陷,这种建模细节对于提升3D开发效率很有必要,目的是减少模型对内存的占用。

    在3D开发之前,模型本身会重叠很多命令,占用很大一部分内存和CPU,拖慢电脑,所以针对模型进行塌陷后(指的是把很多个物体合并成一个,转换为一个命令可编辑多边形或可编辑网格),就会去除这些多余的命令参数,不再花时间记录和存储,从而加快运行速度。

    制作物体模型时,根据爆炸图中各个零件的拆分需要,针对子模型或子节点定义并命名物体子对象,在3DMAX等建模软件里就能创建子对象。这些子对象在ThingJS在线开发中可作为模型子节点来控制,能够像单独模型对象物体一样进行移动、添加事件等操作。

    拆分后磨性子节点如果有多材质或点数超过上限,那在ThingJS开发中会继续拆分,并在子节点中被命名成组,组内继续拆分“01”、“02”等对象。例如:3dmax命名, 一个子节点名字为“box”,由于该子节点使用了多种材质,该子节点在在线开发中会被命名成组,组内会被拆分并命名为“box_0”,“box_1”等对象。

    注意经塌陷的模型不再有子节点保留,只有上述分项控制模型局部要求,保留已命名的子对象信息,最大程度上提高开发性能,又满足模型拆分的特殊需要。

    官方示例请各位看官参考:

    // 加载场景代码 
    var app = new THING.App({ 
        url: '/api/scene/406e419fae9000a47a4a8899'
    });
    
    // 发电机模型节点数据
    var nodeObjData = {
        '1': {name: '机座', offset: [0, 0, -1]},
        '2': {name: '保护装置', offset: [0, -1, 0]},
        '3': {name: '电瓶', offset: [0, -1, 0]},
        '4': {name: '排气口', offset: [0, 0, 1]},
        '5_0': {name: '过滤器', offset: [0, 0, 1]},
        '5_1': {name: '过滤网', offset: [0.5, 0, 1]},
        '6': {name: '供给装置', offset: [0, 0, 1]},
        '7': {name: '烟囱', offset: [-1, 0, 0]},
        '8': {name: '发电机'},
        '9': {name: '控制器', offset: [0, 1, 0]}
    }
    // 发电机模型节点对象
    var nodeJsonData = null;
    // 发电机对象
    var generatorObj = null;
    // 发电机展开状态
    var expandState = false;
    // 发电机展开次数
    var expandCount = 0;
    
    // 场景加载完成后执行
    app.on('load', function (ev) {
        // 查询发电机对象
        generatorObj = app.query('#generator')[0]
        // 获取发电机模型节点对象
        nodeJsonData = getNode(generatorObj);
    
        // 创建测试按钮
        new THING.widget.Button('展开', expandObj);
        new THING.widget.Button('还原', unexpandObj);
        new THING.widget.Button('顶牌显示', createAllPanel);
        new THING.widget.Button('顶牌隐藏', hiddenAllPanel);
    })
    
    /**
     * 说明:显示所有顶牌
     */
    function createAllPanel(){
        for (let key in nodeObjData) {
            nodeJsonData[key].name = nodeObjData[key].name;
            createPanel(nodeJsonData[key]);
        }
    }
    
    /**
     * 说明:隐藏所有顶牌
     */
    function hiddenAllPanel(){
        for (let key in nodeObjData) {
            hiddenPanel(nodeJsonData[key]);
        }
    }
    
    /**
     * 说明:展开物体
     */
    function expandObj() {
        // 防止发电机在执行一次展开过程中多次点击
        if (expandState) {
            return;
        }
        expandState = true;
        expandCount++;
        for (let key in nodeObjData) {
            // 各子节点进行偏移
            objOffset(nodeJsonData[key], nodeObjData[key].offset);
        }
    }
    
    /**
     * 说明:还原物体
     */
    function unexpandObj() {
        // 展开次数为0,代表未展开
        if (expandCount == 0) {
            return;
        }
        for (let key in nodeObjData) {
            if(nodeObjData[key].offset){
                // 计算还原时子节点需要进行的偏移量,数值为 -1 * 展开次数 * nodeObjData中定义的该子节点对应的偏移量
                let offsetValue = [-1 * expandCount * nodeObjData[key].offset[0], -1 * expandCount * nodeObjData[key].offset[1], -1 * expandCount * nodeObjData[key].offset[2]]
                objOffset(nodeJsonData[key], offsetValue);
            }
        }
        expandCount = 0;
    }
    
    /**
     * 说明:获取节点对象
     */
    function getNode(obj) {
        let nodeJson = {};
        // obj.subNodes 即可获取到一个物体的所有子节点
        for (let i = 0; i < obj.subNodes.length; i++) {
            let subnode = obj.subNodes[i];
            // 获取物体子节点对象中node属性的type值,只有当type值为Mesh时,才能对物体添加事件
            let type = subnode.node.type;
            if(type == 'Mesh'){
                nodeJson[subnode.name] = subnode;
            }
        }
        return nodeJson;
    }
    
    /**
     * 说明:物体偏移
     */
    function objOffset(obj, value) {
        if (!value) {
            return;
        }
        // 物体移动
        obj.moveTo({
            offsetPosition: value,  // 自身坐标系下的相对位置
            time: 500,  // 移动完成需要的时间
            complete: function () {
                expandState = false;
            }
        });
    }
    
    /**
     * 说明:创建面板
     */
    function createPanel(obj) {
        // 判断是否已经创建过面板,如果已创建,显示,否则创建面板
        var panel = obj.getAttribute('panel');
        if (panel != null) {
            panel.visible = true;
            return;
        }
        // 创建panel
        panel = new THING.widget.Panel({
            // 设置面板宽度
             '100px',
            // 没有角标 none ,没有线的角标 noline ,折线角标 polyline
            cornerType: 'polyline'
    
        })
        // 绑定物体身上相应的属性数据
        panel.addString(obj, 'name').caption('');
        // 创建UIAnchor面板
        var uiAnchor = app.create({
            // 类型
            type: 'UIAnchor',
            // 设置父物体
            parent: obj,
            // 要绑定的dom元素对象
            element: panel.domElement,
            // 设置 localPosition 为 [0, 0, 0]
            localPosition: [0, 0, 0],
            // 相对于面板左上角的偏移像素值,当前用值是角标的中心点
            pivotPixel: [-16, 109]
        });
        // 更改面板文本样式
        $('.ThingJS_wrap .main .ThingJS_UI .ThingJS_string-value').css('text-align', 'center');
        obj.setAttribute('panel', uiAnchor);
    }
    
    /**
     * 说明:隐藏面板
     */
    function hiddenPanel(obj) {
        var panel = obj.getAttribute('panel');
        if (panel != null) {
            panel.visible = false;
        }
    }
    

    爆炸图的基础动效新鲜出炉,ThingJS教程简单,支持JS工程师快速入门3D开发!

  • 相关阅读:
    五月一日工作感悟
    Loadrunner 性能指标
    tcp ,http .udp
    Loadrunner 面试常见问题
    抓包不求人
    性能测试自动化测试平台
    jmeter 控制器
    转:java中String使用equals和==比较的区别
    转:Java对象及对象引用变量
    排序算法小结
  • 原文地址:https://www.cnblogs.com/thingjs/p/13675268.html
Copyright © 2011-2022 走看看