热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

HTML5WebG的3D网络拓扑结构图-

本文主要和大家分享HTML5WebG的3D网络拓扑结构图,我们会从3D网络拓扑结构介绍及图文进行详解介绍,希望能帮助到大家。
本文主要和大家分享HTML5 WebG 的3D网络拓扑结构图,我们会从3D网络拓扑结构介绍及图文进行详解介绍,希望能帮助到大家。

现在,3D 模型已经用于各种不同的领域。在医疗行业使用它们制作器官的精确模型;电影行业将它们用于活动的人物、物体以及现实电影;视频游戏产业将它们作为计算机与视频游戏中的资源;在科学领域将它们作为化合物的精确模型;建筑业将它们用来展示提议的建筑物或者风景表现;工程界将它们用于设计新设备、交通工具、结构以及其它应用领域;在最近几十年,地球科学领域开始构建三维地质模型,而且 3D 模型经常做成动画,例如,在故事片电影以及计算机与视频游戏中大量地应用三维模型。它们可以在三维建模工具中使用或者单独使用。为了容易形成动画,通常在模型中加入一些额外的数据,例如,一些人类或者动物的三维模型中有完整的骨骼系统,这样运动时看起来会更加真实,并且可以通过关节与骨骼控制运动。

这些种种都让我们前端开发者觉得如果我们可以不用学习 unity3d 或者其他游戏开发工具就能实现 3D 效果,而且能够精准的靠代码来控制移动或者方向就好了。。。于是我利用 HT For Web 中的 3D组件 来实现了一个小例子,用了 HT 中 3D组件 的大部分功能,做这个例子就是想把 3D 组件好好的掌握,尽量放进一个例子中,到时候别人有需要就可以参考了。

先来看看整体实现的效果图:

用 HT for Web,现有的 3d 模板创建三层底板不是问题,问题是要如何将图中第一层的“电脑”和“机柜组件”放上去?我是在网上 down 下来的 obj 格式的文件,然后我利用 HT 中的 ht.Default.loadObj(objUrl, mtlUrl, params) 函数将模型加载进去,其中的 params 部分可以参考 http://www.hightopo.com/guide...,代码如下:

ht.Default.loadObj('obj/机柜组件1.obj', 'obj/机柜组件1.mtl', {  //加载 obj 文件
    cube: true,  //是否将模型缩放到单位1的尺寸范围内,默认为false
    center: true,  //模型是否居中,默认为false,设置为true则会移动模型位置使其内容居中
    shape3d: 'box',  //如果指定了shape3d名称,则HT将自动将加载解析后的所有材质模型构建成数组的方式,以该名称进行注册
    finishFunc: function(modelMap, array, 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);  
      }  
    }  
});

其中 finishiFunc 函数中的三个参数定义如下:

  • modelMap:调用 ht.Default.parseObj 解析后的返回值,若加载或解析失败则返回值为空

  • array:所有材质模型组成的数组

  • rawS3:包含所有模型的原始尺寸

一般在实际应用中我们都会将图元的大小设置为模型的原始尺寸。

“电脑”上方有个红色的立体能旋转的“警告”,是依靠 ht.Default.setShape3dModel 函数(HT for Web 建模手册 http://www.hightopo.com/guide... 3d 模型,在 ht 中,封装好的建模函数有很多,比较基础的就是球体,圆柱,立方体等等,这边我用的是构造环形的方法 createRingModel 来生成“警告”最外面的环,感叹号的上部分就是用的 createSmoothSphereModel 构造的球体,感叹号的下部分就是用 createSmoothCylinderModel 来构造的圆柱。我一开始直接使用了 3d 模型中封装好的函数,导致后来根本不知道函数中使用的参数是做什么用的,而且也不明白 3d 模型是怎么构成的,然后自己又重新看了前面的“模型基础”,才知道原来 3d 模型采用的一个面,最基础的是三角面,之后复杂的面也是由多个三角面来形成的,然后绕着一根特定的轴旋转之后形成的,当然,这个轴是你来决定的,不同的轴可以生成不同的形状,对于颜色等风格方面的设置可以参考 HT for Web 风格手册(http://www.hightopo.com/guide...。至于如何让这个 3d 模型旋转起来,ht 中封装了 addScheduleTask(Task) 方法,我在第三层 Task 中调用了 ht 封装的一个旋转函数 setRotation 来设置旋转的顺序和方向,并且指定了旋转的对象。以下是自定义“警告”的 3d 模型的方法(注意:因为本例的模型是自定义组合的,如果要设置整体模型的颜色要用 “all.blend” style 属性):

function createAlarm(device, formPane) {
    var ringModel = ht.Default.createRingModel([ 8, 1, 10, 1, 10, -1, 8, -1, 8, 1 ], null, null, false, false, 100);//根据xy平面的曲线,环绕一周形成3D模型。
    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 alarmArr = [//组合模型 由三个模型ringModel、sphereModel、cylinderModel组合而成
        {
          shape3d: ringModel,//定义模型类型
          r3: [Math.PI/2, 0, 0],//设置旋转角度
          color: {//设置模型颜色
            func: 'style@all.blend',//数据绑定style样式中的all.blend属性,可通过data.s()获取和设置这个属性
          }
        },{
          shape3d: sphereModel,
          t3: [0, 4, 0],
          color: {
            func: 'style@all.blend',
          }
        },{
          shape3d: cylinderModel,
          t3: [0, -3, 0],
          color: {
            func: 'style@all.blend',
          }
        }
    ];
    ht.Default.setShape3dModel('alarm', {//注册自定义3D模型
      shape3d: alarmArr
    });

    var alarmTip = createNode('alarm', device);//创建shape3d为alarm的节点
    alarmTip.s3([2, 2, 2]);//设置节点大小
    alarmTip.p3(device.p3()[0], device.p3()[1]+60, device.p3()[2]);
    alarmTip.s('all.blend', 'red');//改变此属性可改变模型的颜色,因为模型创建的时候已经数据绑定了

    return alarmTip;
}

接下来看看怎么让这个“告警”节点“闪烁”,我是直接将这个动画跟节点绑定,这样可以直接通过节点来控制动画。所以在上面我们创建 alarm 的模型时就可以直接将动画绑在节点上:

if(formPane){
    alarmNode.scaleFunc = function() {//设置大小变化动画
        var size = alarmNode.s3();//获取节点的大小
        if (size[0] === 2 && size[1] === 2 && size[2] === 2) alarmNode.s3([1, 1, 1]);
        else alarmNode.s3([2, 2, 2]);
        alarmNode.scaleTimer = setTimeout(alarmNode.scaleFunc, formPane.v('scaleInterval'));//设置动画
    }
    alarmNode.blinkFunc = function(){//设置闪烁的动画
        var color = alarmNode.s('all.blend');//获取节点的style样式
        if (color === 'red') alarmNode.s({'all.blend': 'yellow'});//如果节点颜色为红色,那么设置为黄色
        else alarmNode.s({'all.blend': 'red'});
        alarmNode.blinkTimer = setTimeout(alarmNode.blinkFunc, formPane.v('blinkInterval'));
    }
    alarmNode.rotateFunc = function() {//设置旋转动画
        alarmNode.setRotation(alarmNode.getRotation() + Math.PI/20);//获取节点当前的旋转角度,在这个旋转角度之上添加 Math.PI/20 个角度
        alarmNode.rotateTimer = setTimeout(alarmNode.rotateFunc, formPane.v('rotInterval'));
    }
}

上面的动画我设置了可以通过 form 表单面板上的属性来控制节点闪烁的速度,以及闪烁节点的动画等等,主要说一下这个功能在 form 表单上的实现:

formPane.addRow([//向form表单面板上添加一行元素
    {
        checkBox: {//复选框
            label: 'Enable Blink',//复选框对应的文本内容
            selected: true,//设置选中复选框
            onValueChanged: function(){//复选框值变化时回调的函数
                var data = dataModel.getDataByTag('colorAlarm');//通过tag标签获取节点
                if (this.getValue()) {//获取复选框当前值true/false
                    data.blinkTimer = setTimeout(data.blinkFunc, formPane.v('blinkInterval'));//直接通过设置节点的blinkTimer来设置动画
                }
                else {
                    clearTimeout(data.blinkTimer);//清除动画
                }
            }
        }
    },
    {
        id: 'blinkInterval',//form可以通过getValue(简写为v)来获取这个item的值
        slider: {//设置了该属性后HT将根据属性值自动构建ht.widget.Slider对象,并保存在element属性上
            min: 0,//滑动条最小值
            max: 1000,//滑动条最大值
            step: 50,//滑动条步进
            value: 500,//当前滑动条的值
        }
    }
], [0.1, 0.1]);//设置这行的两个item元素的宽度小于1的值为比例

最后来说说 3D 管线上的小球流动的部分,这个功能确实非常实用,而且做出来的效果也确实不错,跟大家分享~

首先,创建一条连线连接起始节点和结束节点并设置这个连线的样式,用 ht.Edge 可以将连线吸附在起始节点和结束节点上,这样移动这两个节点中的任意一个节点连线都会跟着节点移动的位置变化,非常方便:

var polyline = new ht.Edge(source, target);//创建连线
dataModel.add(polyline);//将连线添加进数据容器中
polyline.s({
    'edge.width': 5,//连线宽度
    'edge.type': 'points',//连线类型 为points时连线走向将由edge.points属性决定,用于绘制折线
    'edge.points': [//可设置类型为ht.List的{x:100, y:100}格式的点对象数组,当edge.type为points时起作用
        {x: source.getPosition3d()[0]+200, y: source.getPosition3d()[2], e: source.getPosition3d()[1]},
        {x: target.getPosition3d()[0]+400, y: target.getPosition3d()[2], e: target.getPosition3d()[1]}
    ],
    'edge.segments': [1, 4],//用于描述点连接样式,数组元素为整型值
    'shape3d': 'cylinder',//圆柱
    'shape3d.color': 'rgba(242, 200, 40, 0.4)',
    'shape3d.resolution': 30,//微分段数,可以决定曲线的平滑度
    'edge.source.t3': [20, 0, 0],//连线source端偏移,[tx, ty, tz]格式,默认为空
    'edge.target.t3': [20, 0, 0]//连线target端偏移,[tx, ty, tz]格式,默认为空
});

因为我们在创建连线的时候设置的 points 仅为曲线上的两个点,所以如果要获取曲线目前形成的点,是缺少 source 和 target 两个点的,我们重新设置一个数组,将这两个点添加进去,后面获取曲线上所有点时会用上:

var list = new ht.List();
list.push({x: source.getPosition3d()[0], y: source.getPosition3d()[2], e: source.getPosition3d()[1]});//向数组中添加source点
polyline.s('edge.points').each(function(item){//添加style属性中已设置的两个点
    list.push(item);
});
list.push({x: target.getPosition3d()[0], y: target.getPosition3d()[2], e: target.getPosition3d()[1]});//添加target点

然后创建一个在管线上滑动的小球节点,这是仅是设置节点,真正添加进数据容器 dataModel 中需要设置完小球的坐标时再添加,如果没有给节点设置位置就将节点添加进数据容器中,节点的初始位置就是 3D 场景的正中心 [0, 0, 0] 的位置。小球滑动的动画代码如下:

var ball = new ht.Node();//创建小球节点
ball.s({//设置小球节点的样式
    'shape3d': 'sphere',//设置小球的3d模型为球形
    'shape3d.color': 'rgba(40, 90, 240, 0.4)'//设置3d模型的颜色
});

var delta = 10, flag = 0;
setInterval(function(){
    flag++;
    var length = (polyline.a('total') || 0) % polyline.a('length') + delta;//小球当前走过的曲线长度
    var cache = ht.Default.getLineCacheInfo(list, polyline.s('edge.segments'));//获取曲线上的点的信息
    var lineLength = ht.Default.getLineLength(cache);//获取曲线的总长度
    polyline.a('length', lineLength - 50);//因为我设置了edge的t3(相当于2d中的offset),所以线段长度实际没有那么长
    var offset = ht.Default.getLineOffset(cache, length);//曲线根据曲线上点的信息的偏移量
    ball.setPosition3d(offset.point.x + 10, offset.point.y, offset.point.z);//设置节点的坐标
    polyline.a('total', length);
    if(flag === 1) dataModel.add(ball);//这时候节点已经有了坐标了,可以添加进数据容器中了
}, 10);

我们还可以看到第二层上有两个特殊的多边形“平行四边形”和“梯形”,平行四边形是靠 createParallelogramModel 模型函数,这个函数比较简单,createExtrusionModel(array, segments, top, bottom, resolution, repeatUVLength, tall, elevation),array 是你要形成的图形的坐标点,这边只是针对于 xz 轴上画的平面图形,segments 指的是如何连接这几个坐标点,可参考 HT for Web 形状手册(http://hightopo.com/guide/gui...),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);  
});


推荐阅读
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了一种图片处理应用,通过固定容器来实现缩略图的功能。该方法可以实现等比例缩略、扩容填充和裁剪等操作。详细的实现步骤和代码示例在正文中给出。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • C++语言入门:数组的基本知识和应用领域
    本文介绍了C++语言的基本知识和应用领域,包括C++语言与Python语言的区别、C++语言的结构化特点、关键字和控制语句的使用、运算符的种类和表达式的灵活性、各种数据类型的运算以及指针概念的引入。同时,还探讨了C++语言在代码效率方面的优势和与汇编语言的比较。对于想要学习C++语言的初学者来说,本文提供了一个简洁而全面的入门指南。 ... [详细]
  • 本文介绍了Python函数的定义与调用的方法,以及函数的作用,包括增强代码的可读性和重用性。文章详细解释了函数的定义与调用的语法和规则,以及函数的参数和返回值的用法。同时,还介绍了函数返回值的多种情况和多个值的返回方式。通过学习本文,读者可以更好地理解和使用Python函数,提高代码的可读性和重用性。 ... [详细]
author-avatar
手机用户2602910773
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有