如今,3D模型已经用于各类不一样的领域。在医疗行业使用它们制做器官的精确模型;电影行业将它们用于活动的人物、物体以及现实电影;视频游戏产业将它们做为计算机与视频游戏中的资源;在科学领域将它们做为化合物的精确模型;建筑业将它们用来展现提议的建筑物或者风景表现;工程界将它们用于设计新设备、交通工具、结构以及其它应用领域;在最近几十年,地球科学领域开始构建三维地质模型,并且3D模型常常作成动画,例如,在故事片电影以及计算机与视频游戏中大量地应用三维模型。它们能够在三维建模工具中使用或者单独使用。为了容易造成动画,一般在模型中加入一些额外的数据,例如,一些人类或者动物的三维模型中有完整的骨骼系统,这样运动时看起来会更加真实,而且能够经过关节与骨骼控制运动。html
这些种种都让咱们前端开发者以为若是咱们能够不用学习unity3d或者其余游戏开发工具就能实现3D效果,并且可以精准的靠代码来控制移动或者方向就行了。。。因而我利用HT For Web中的3D组件来实现了一个小例子,用了HT中3D组件的大部分功能,作这个例子就是想把3D组件好好的掌握,尽可能放进一个例子中,到时候别人有须要就能够参考了,可是由于以前历来没有实现过3D的效果,再加上如今手册没有很完整,因此这个例子对我来讲仍是有点难度的。前端
本例位置:http://www.hightopo.com/demo/...
先来看看总体实现的效果图:
用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', { 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属性):json
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 形状手册。app
想让2d图片在3d管线上移动则是使用g3d.toViewPosition(position)来获取3d模型的二维坐标,这个函数中的参数就是三维模型的3d坐标,咱们能够直接将polyline管线上的点传入toViewPosition函数中,这边获取管线上的点在ht中已经封装好三个函数getLineCacheInfo、getLineLength、getLineOffset,这样就能够直接获取到二维坐标,而后将img的坐标设置上去便可,如下是img图片在管道上移动的代码:ide
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); });