前阵子写了一篇无插件纯Web 3D机房,介绍了如何用html5在网页上建立无插件的精美3d机房场景。这两个月以来,陆续收到不少朋友的鼓(膝)励(盖),受宠若惊之余,对索要源代码的朋友都已经尽力邮件回复。因为精力所限,未能收到的朋友请留言或给我发送邮件:tw-service@servasoft.com。最近项目第二期又要紧锣密鼓地开始了,因此想抓紧把一些新增的内容补充上,进一步完善这个html5 3d机房的呈现效果。html
上一篇中主要介绍的是如何从最基础的webgl封装到建立3d物体对象,再经过3d物体对象“搭积木”式的组建整个3d机房场景。这一篇主要介绍一些如何在这个场景上进一步丰富更多的功能和呈现效果,以及实现这些功能在技术上的思路。html5
首先咱们来看看第一季已经实现的纯自然无添加无PS的HTML5 3D机房效果:
web
已经拿到过代码的朋友应该知道,这一场景是经过一个json文件进行组装和加载,能够很方便地进行修改和维护。在此基础上,这一次我又增长了机柜标签、机柜门、复杂设备、机房走线、人员轨迹等效果,下面我就把第二季的干货一一为你们奉上。json
机房中最重要的物理资源——机柜——是机房管理、规划、监控人员最关注的对象之一。对于规模在几十个、上百个甚至上千个机柜的机房,每一个机柜必然会进行资产编号,方便检索和管理。这个在多数资产管理系统中,都是最基本的。可是在3d场景中,如何显示这些机柜编号,才能让用户更直观的看到每一个机柜的位置呢?canvas
传统的方式是用标签显示资产编号,例如能够用“告警冒泡”那样的方式显示一个文字气泡。不过当机柜产生告警时,两个气泡会有所冲突。并且过多的气泡会产生相互遮挡覆盖,有点混乱,好比像这样:
数组
所以我尝试了一种不一样的思路:把文字渲染到一个内存图片,“溶解”到机柜的上方贴图中。服务器
想要生成一个内存的图片文字,能够经过下面的函数实现:网络
generateAssetImage: function(text){ var width=512, height=256; var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; var ctx = canvas.getContext('2d'); ctx.fillStyle='white'; ctx.fillRect(0,0,width,height); ctx.font = 150+'px "Microsoft Yahei" bold'; ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, width/2,height/2); ctx.strokeStyle='black'; ctx.lineWidth=15; ctx.strokeText(text, width/2,height/2); return canvas; }
须要留意的是:框架
- 生成的图片宽高数值最好是2的幂,例如12八、25六、512等,这样在3d中渲染不容易出现闪烁和锯齿。相关原理请查阅google。
- 文字绘制尽可能居中、充满整个图,不要过小,不然看上去比较奇怪。
- 空白处保持透明,没必要填充色,方便和机柜自己贴图的“溶解”。
- 直接返回canvas对象便可,没必要生成图片点阵数组。
生成canvas后,能够这样直接贴图使用:编辑器
var labelCanvas=demo.Default.generateAssetImage(label); rack.setStyle('top.m.texture.image', labelCanvas); rack.setStyle('top.m.specularmap.image', labelCanvas);
经过上面代码,把贴图做为机柜立方体top面的贴图和反射映射图。这样出来的效果以下:
这样,既不用增长3d对象,也不影响机柜的美观度,关键是看得很是清晰,在大场景中也不干扰用户的视线:
上一篇里,因为时间紧迫,也考虑到呈现效率,机柜采用了“双击机柜出现设备”的方案。一个立方体的机柜虽然简单直接,可是没有机柜门,总以为假了一点,客户也提到了这一点,所以按照机房门的思路,增长一个机柜门,增长双击开门的效果,这个比较简单:
var rackDoor = new mono.Cube(width, height, 2); rackDoor.s({ 'm.type':'phong', 'm.color': '#A5F1B5', 'm.ambient': '#A4F4EC', 'front.m.texture.image': 'images/rack_front_door.png', 'back.m.texture.image': 'images/rack_door_back.png', 'm.envmap.image': demo.Default.getEnvmap('envmap1'), }); rackDoor.setParent(rack); rackDoor.setPosition(0, 0, depth/2+1); rackDoor.setClient('animation','rotate.right.120');
上面代码建立了一个薄薄的立方体做为机柜门。设置贴图、颜色等,再设置其parent
是机柜。这样,若是拖拽机柜位置,机柜也会跟着移动,简单方便。最后,在设置一下机柜门的动画。经过一个字符串进行定义:rotate.right.120
表示动画是“向右侧旋转120度”,在双击的时候触发。
第一季里,机柜内的设备,主要用乐服务器来表现,加入了设备弹出、告警等效果。后期根据现场和用户的交流,用户进一步提出要显示机架上须要安装更加复杂的电信设备,包括板卡、板卡的插拔动做、呈现方法等,也就是在机柜上显示一个有多个板卡的设备,双击板卡能够弹出。
要作这个,须要把原来的一个立方体的服务器设备作一个“挖空”处理,变成一个空的设备框的样子。而后再生成一系列的板卡对象,插入这个空框。每一个板卡应该由面板+电路板组成,能够用两个立方体进行拼接,添加适当的贴图完成。代码以下:
var parts=[{ //card panel type: 'cube', width: width, height: height, depth: 1, translate: [x, y, z+1], rotate: rotate, op: '+', style:{ 'm.color': color, 'm.ambient': color, 'm.texture.image': 'images/gray.png', 'front.m.texture.image': pic, 'back.m.texture.image': pic, } },{ //card body type: 'cube', width: 1, height: height*0.95, depth: depth, translate: [x, y, z-depth/2+1], rotate: rotate, op: '+', style:{ 'm.color': color, 'm.ambient': color, 'm.texture.image': 'images/gray.png', 'left.m.texture.image': 'images/card_body.png', 'right.m.texture.image': 'images/card_body.png', 'left.m.texture.flipX': true, 'm.transparent': true, } }]; var card=demo.Default.createCombo(parts); card.setClient('animation', 'pullOut.z'); box.add(card);
上面代码能够生成一个板卡对象。循环重复,设置位置,便可生成整个设备。经过设置animation
属性,定义板卡动画为“双击拉出”,再次双击推回。效果以下图:
固然,实际项目中,各类结构的电信设备千奇百怪,要经过代码定义是不现实的。因此咱们还开发了一个设备编辑器,能够经过拖拽方式快速生成设备结构图。
除了机柜以外,线缆的链接走向和链接关系是管理员关注的另一个焦点。机架中的电信设备或服务器设备会经过端口和线缆进行链接,组成必定结构的网络。而线缆的走向在物理上经过肉眼是很难看清晰的。更多线缆会从机柜连出,延伸到屋顶上方或地板下方的隐蔽工程中(例如走线架)固定和布线,用肉眼更没法观察。此时,须要3d机房界面能清晰的显示电缆从端口到走线架再到端口的“端到端”的物理走线,方便管理员了解网络状况和管理。
线缆,能够用一个空间的path
来定义,并设置其贴图:
var path = demo.Default.create3DPath(json.data); var cable=new mono.PathNode(path, 100, 1); cable.s({ 'm.type': 'phong', 'm.specularStrength': 30, 'm.color': json.color, 'm.ambient': json.color, 'm.texture.image': 'images/flow.jpg', 'm.texture.repeat': new mono.Vec2(200, 1), }); box.add(cable);
经过json定义的[x, y, z]数组来生成一个path
对象,而后用它来生成一个空间的“管子”对象。流动效果能够经过一个动画来修改贴图纹理的offset,让眼睛产生贴图不断“移动”的效果。
走线架能够经过简单的镂空贴图来模拟,不须要建一个复杂的框架模型,减小对GPU的压力。实际的走线架有不少种,例以下图是一种典型的走线架:
咱们经过程序模拟一下:
var rail=demo.Default.createPathObject(railInfo); rail.s({ 'm.texture.image': 'images/rail.png', 'm.type': 'phong', 'm.transparent': true, 'm.color': '#CEECF5', 'm.ambient': '#CEECF5', 'aside.m.visible': false, 'zside.m.visible': false, 'm.specularStrength': 50, }); rail.setPositionY(263); box.add(rail);
最终走线架+线缆的效果以下:
在3d场景中,常常须要计算规划并显示一个最优的空间或平面路径,用来指示如何最快、最合理的到达目标,或经过路径显示一个移动物体的轨迹,方便进行监控和分析。例如,客户提出一个实际需求:现场检修人员手持平板进入机房,输入设备id后,直接给出前方走动路径,并进行实时导航引导。
咱们能够把这个需求分解为导航路径显示和人员模拟两步。
导航路径
--
导航线能够经过一个浮在地板上方的path路径来定义。作一个简单的颜色渲染和弯角处理,就能够比较清晰的展现底面的走动路径。
var path=new mono.Path(); path.moveTo(object.getPositionX(), object.getPositionZ()); for(var i=0;i<points.length; i++){ path.lineTo(points[i][0], points[i][13]); } path = mono.PathNode.prototype.adjustPath(path, 20); var trail=new mono.PathCube(path, 10, 3); trail.s({ 'm.type': 'phong', 'm.specularStrength': 30, 'm.color': '#298A08', 'm.ambient': '#298A08', 'm.texture.image': 'images/flow.jpg', 'm.texture.repeat': new mono.Vec2(150, 1), }); trail.setRotationX(Math.PI); //trail.setStartCap('plain'); //trail.setEndCap('plain'); trail.setPositionY(5); trail.setClient('type', 'trail'); box.add(trail);
拉近后看下细节:
移动轨迹的显示也有不少变化,形状、颜色的变化,空间坐标的变化,均可以产生一些不一样的效果。例以下图是另一个3d车库导航系统的场景:
接下来,要加载一我的的模型进来,放在路径上。能够在网上找一些3d max作的模型,并转成obj格式的文件,这样就能够方便的导入场景中。Obj经过对应的mtl文件进行定义材质,须要的贴图也须要一并涵盖进来。经过下面几行代码便可完成obj模型的导入:
var obj='images/worker.obj'; var mtl='images/worker.mtl'; var loader = new mono.OBJMTLLoader(); loader.load(obj, mtl, {'worker': 'images/worker.png',}, function (object) { box.addByDescendant(object); });
效果以下图:
须要留意的是,人的模型不要太大,能把人物轮廓大概渲染清晰便可。例如上面的模型也就几百k,加载和显示几乎瞬间完成,不会产生卡顿。若是加载几十兆上百兆的高清模型,则可能出现卡顿,也会拖慢场景的渲染速度。毕竟咱们的主要场景对象是3d机房,对模型选择要有所取舍,千万不要喧宾夺主。
让任务沿着路径移动,能够经过动画进行控制,对path中每一段路线进行平移,连续、反复的播放,便可实现人物的移动效果。
固然这里有一个缺点,人物的移动是僵硬不动的,不能像真实人物同样迈腿一步一步的走路进行移动。若是要作,须要用到骨骼动画等技术,相对复杂一些,目前项目紧急,就留给之后找时间研究了。固然对于3d机房这样的企业应用来讲,必要性不必定很大,毕竟不是游戏。
经过这些技术,你们能够轻松构建一个比较完整的3d机房系统,就跟咱们此次的项目同样:
篇幅有限,这一篇就介绍这么多,但愿对你们有所启发和帮助,后续找时间会继续给你们介绍如何拖拽移动机柜、显示机房中的温度云图、风向监控、摄像头及视频监控,如何建立一个大的园区和楼宇等内容。你们有什么好的想法和意见,或须要相关代码的同窗能够发邮件到:tw-service@servasoft.com,或留下邮箱,我会尽力回复。谢谢!