当前位置: 首页 > Web前端 > HTML5

基于HTML5WebGL的3D机房数据中心可视化展示

时间:2023-04-05 17:34:24 HTML5

前言在3D机房数据中心可视化应用中,随着视频监控联网系统的不断普及和发展,网络摄像机在监控系统中的应用越来越多,尤其是在监控系统中。高清时代物联网的到来加速了网络摄像机的发展和应用。在监控摄像头数量不断增加的同时,监控系统面临着严峻的现实问题:海量视频分散、孤立、视角不完整、位置不清晰等问题始终围绕在用户身边。因此,如何更直观、更清晰地管理摄像机和控制视频动态成为提升视频应用价值的重要课题。因此,本项目就是从解决这一现状的角度出发的。着眼于如何改进、管理和有效利用前端设备采集的海量信息服务于公共安全,特别是在技术融合的大趋势下,如何结合当前先进的视频融合、虚拟现实融合、3D动态等实现3D场景实时动态可视化监控的技术,对海量数据进行更有效的识别、分析和挖掘,以提供有效的信息服务公共应用,已成为视频监控平台可视化发展的趋势和方向。目前在监控行业,海康威视、大华等监控行业的龙头企业可以基于此方法规划公共场所、公园的摄像机布局,并通过海康威视、大华等摄像机品牌的摄像机参数进行系统调整.中间是摄像机模型的可视范围和监控方向,更方便人们直观的了解摄像机的监控区域和监控角度。以下是项目地址:基于HTML5的WebGL自定义3D摄像头监控模型效果预览整体场景-摄像头渲染局部场景-摄像头渲染代码生成摄像头模型及场景项目中使用的摄像头模型是通过3dMax建模生成的。建模工具可以导出obj和mtl文件,通过在HT中解析obj和mtl文件生成3D场景中的相机模型。项目中的场景由HT的3d编辑器搭建而成。场景中有的模型是用HT建模的,有的是用3dMax建模的,然后导入到HT中。场景中地面上的白光是由HT的3d编辑器制作的。地面纹理呈现的效果。圆锥造型3D模型由最基本的三角形面组成。例如,一个长方形可以由2个三角形组成,一个立方体可以由6个面或12个三角形组成。以此类推,更复杂的模型可以由许多小三角形组合而成。因此,3D模型的定义就是对构成模型的所有三角形的描述,每个三角形由三个顶点vertex组成。顶点构造三角形面的前面。在HT中,函数ht.Default.setShape3dModel(name,model)可用于注册自定义3D模型。摄像机前面生成的锥体就是通过这种方法生成的。圆锥体可以看作由5个顶点和6个三角形组成。具体图如下:ht.Default.setShape3dModel(name,model)name为模型名称,如果名称与预定义的相同,则替换预定义的模型model是一个JSON类型的对象,其中vs代表顶点坐标数组,_is_代表索引数组,_uv_代表纹理坐标数组。如果要单独定义一个面,可以使用bottom_vs、bottom_is、bottom_uv、top_vs、top_is、top_uv_等定义,然后可以通过_shape3d.top.、shape3d.bottom.等单独控制某个面。下面是我的模型定义的代码:;)//camera是当前cameraprimitive//fovy是camera的张角tan值的一半varsetRangeModel=function(camera,fovy){varfovyVal=0.5*fovy;varpointArr=\[0,0,0,-fovyVal,fovyVal,0.5,fovyVal,fovyVal,0.5,fovyVal,-fovyVal,0.5,-fovyVal,-fovyVal,0.5\];ht.Default.setShape3dModel(camera.getTag(),\[{vs:pointArr,是:\[2,1,0,4,1,0,4,3,0,3,2,0\],from_vs:pointArr.slice(3,15),from_is:\[3,1,0,3,2,1\],from_uv:\[0,0,1,0,1,1,0,1\]}\]);};)我使用当前相机的标签值作为模型名称。tag标签在HT中用于唯一标识一个图元,用户可以自定义tag值。使用pointArr记录当前五面体五个顶点的坐标信息。代码中使用from_vs、from_is、from_uv分别构造五面体的底面,用于显示当前相机呈现的图像。圆锥样式对象的wf.geometry属性在代码中设置。通过该属性可以将模型的线框添加到圆锥体中,增强模型的三维效果,线框的颜色可以通过wf.color、wf.width等参数调整粗细等设置相关模型的style属性的代码如下:;)1rangeNode.s({2'shape3d':cameraName,3//相机模型名称4'shape3d.color':'rgba(52,148,252,0.3)',5//圆锥模型的颜色??6'shape3d.reverse.flip':true,7//圆锥模型的反面是否显示正面的内容8'shape3d.light':false,9//圆锥模型是否受光影响10'shape3d.transparent':true,11//圆锥模型是否透明12'3d.movable':false,13//圆锥模型是否透明movable14'wf.geometry':true//是否显示圆锥模型Wireframe15});;)相机图像生成原理透视投影透视投影是一种在二维纸或画布平面上按顺序绘制或渲染的方法获得接近真实三维物体的视觉效果,也称为透视图。透视使远的物体变小,近的物体变大,平行线会先相交,更接近人眼观察到的视觉效果。如上图所示,透视投影最终在屏幕上只显示截锥体(ViewFrustum)的内容,所以Graph3dView提供了eye、center、up、far、near、fovy和aspect参数来控制截锥体具体体的范围。具体透视投影请参考HTforWeb的3D手册。根据上图的描述,在本项目中,初始化相机后,可以缓存眼睛的位置和当前3d场景的中心,然后可以设置眼睛和3d场景的中心到摄像头中心点的位置,然后在获取当前3D场景此时的截图,也就是当前摄像头的监控画面,然后将3D场景的中心和眼睛设置到positions一开始缓存的眼睛和中心。该方法可以实现任意位置的3D场景抓拍,从而实现摄像机监控图像的实时生成。相关伪代码如下:;)1functiongetFrontImg(camera,rangeNode){2varoldEye=g3d.getEye();3varoldCenter=g3d.getCenter();4varoldFovy=g3d.getFovy();5g3d.setEye(相机位置);6g3d.setCenter(相机方向);7g3d.setFovy(摄像机角度);8g3d.setAspect(相机纵横比);9g3d.validateImp();10g3d.toDataURL();11g3d.setEye(oldEye);;12g3d.setCenter(oldCenter);13g3d.setFovy(oldFovy);14g3d.setAspect(undefined);15g3d.validateImp();16};)经过测试,通过该方法获取图片会导致页面卡顿,因为是获取当前3d场景的整体截图。由于现在的3d场景比较大,通过toDataURL获取图像信息很慢,所以我采用了离屏的方式。具体获取图像的方法如下:1.新建一个3d场景,将当前场景的宽高设置为200px,当前3d场景的内容与主屏相同。在HT中,使用新的ht。graph3d.Graph3dView(dataModel)创建新场景,其中dataModel为当前场景的所有图元,因此主屏和离屏3d场景共享同一个dataModel,保证了场景的一致性。2.将新建场景的位置设置到屏幕上看不到的地方,并添加到dom中。3、将之前在主屏上获取图像的操作改为在屏外获取图像的操作。此时离屏图像的尺寸比之前在主屏上获取的图像要小很多,离屏获取不需要保存原来的眼睛位置和中心位置,因为我们没有改变眼睛的位置和主屏幕的中心位置,因此切换带来的开销也减少了,相机获取图像的速度也大大提高了。下面是该方法实现的代码:;)1functiongetFrontImg(camera,rangeNode){2//捕捉当前图像时隐藏相机所属的五面体3rangeNode.s('shape3d.from.visible',错误的);4rangeNode.s('shape3d.visible',false);5rangeNode.s('wf.geometry',false);6varcameraP3=camera.p3();7varcameraR3=camera.r3();8varcameraS3=camera.s3();9varupdateScreen=function(){10demoUtil.Canvas2dRender(camera,outScreenG3d.getCanvas());11rangeNode.s({12'shape3d.from.image':camera.a('canvas')13});14rangeNode.s('shape3d.from.visible',true);15rangeNode.s('shape3d.visible',true);16rangeNode.s('wf.geometry',true);17};1819//Currentconestartposition20varrealP3=[cameraP3[0],cameraP3[1]+cameraS3[1]/2,cameraP3[2]+cameraS3[2]/2];21//围绕起始点旋转当前眼睛位置相机的位置以获得正确的眼睛位置22varrealEye=demoUtil.getCenter(cameraP3,realP3,cameraR3);2324outScreenG3d.setEye(realEye);25outScreenG3d.setCenter(demoUtil.getCenter(realEye,[realEye[0],realEye[1],realEye[2]+5],cameraR3));26outScreenG3d.setFovy(camera.a('fovy'));27outScreenG3d.validate();28updateScreen();29};)上面代码中有一个getCenter方法,用于获取A点在3d场景中绕B点旋转一个角度得到的3d场景中的位置场景。该方法使用了HT封装的ht.Math的如下方法,代码如下:;)1//pointA是围绕pointB的旋转点2//pointB是要旋转的点3//r3是旋转角度array[xAngle,yAngle,zAngle]分别为绕x,y,z轴旋转的角度4vargetCenter=function(pointA,pointB,r3){5varmtrx=newht.Math.Matrix4();6vareuler=新的ht.Math。欧拉();7varv1=newht.Math.Vector3();8varv2=newht.Math.Vector3();910mtrx.makeRotationFromEuler(euler.set(r3[0],r3[1],r3[2]));1112v1.fromArray(pointB).sub(v2.fromArray(pointA));13v2.copy(v1).applyMatrix4(mtrx);14v2.sub(v1);1516返回[pointB[0]+v2.x,pointB[1]+v2.y,pointB[2]+v2.z];17};;)这里应用到vector的部分知识如下:OA+OB=OC方法分为以下几步求解:varmtrx=newht.Math.Matrix4()创建一个变换矩阵,通过mtrx.makeRotationFromEuler(euler.set(r3[0],r3[1],r3[2]))围绕r3[0],r3[1],r3[2]得到的是x轴,y轴和z轴旋转的旋转矩阵。2.通过newht.Math.Vector3()创建两个向量v1和v2。3.v1.fromArray(pointB)是创建一个从原点到pointB的向量。v2.fromArray(pointA)是创建一个从原点到pointA的向量。v1.fromArray(pointB).sub(v2.fromArray(pointA))是向量OB-OA,此时得到的向量是AB,此时v1就变成了向量AB。v2.copy(v1)v2向量复制v1向量,然后通过v2.copy(v1).applyMatrix4(mtrx)将旋转矩阵应用于v2向量。变换后,v1向量绕pointA旋转后成为向量v2。7、此时通过v2.sub(v1),起点为pointB,终点为pointB旋转后的点组成的向量。向量现在是v2。8、向量公式得到旋转后的点为[pointB[0]+v2.x,pointB[1]+v2.y,pointB[2]+v2.z]。项目中的3D场景实例,其实就是海拓近期贵州数博会的VR实例,HT上的工业互联网展台。大众对VR/AR抱有很高的期望,但这条路还是要一步一步走,即使已经融资23亿,MagicLeap的首款产品也只能是FullofShit。这个话题稍后会展开。以下是上段场景的视频照片:2D图像粘贴到3D模型。通过上一步的介绍,我们可以得到当前相机位置的截图。那么如何将当前图像粘贴到之前构建的五面体的底部呢?最下面的矩形是由from_vs、from_is构造的,所以在HT中可以将五面体样式中的shape3d.from.image属性设置为当前图像,其中from_uv数组用于定义贴图的位置,如下图所示:定义纹理位置的代码from_uv:1from_uv:[0,0,1,0,1,1,0,1]from_uv是定义纹理的位置数组。根据上图的解释,可以将2d图像从face粘贴到3d模型中。在控制面板HT中,使用newht.widget.Panel()生成如下图所示的面板:面板中的每个摄像头都有一个模块来呈现当前的监控画面。其实这个地方也是一个canvas,就是场景中锥体前面的监控图像是同一个canvas,每个摄像头都有自己的canvas来保存当前摄像头的实时监控图像,这样画布可以粘贴到任何地方,将画布添加到面板的代码如下:1formPane.addRow([{2element:camera.a('canvas')3}],240,240);代码中将canvas节点存放在camera图元的attr属性下,然后可以通过camera.a('canvas')获取当前的camera图像。面板中的每个控制节点都是通过formPane.addRow添加的。详见HTforWeb的表单手册。然后通过ht.widget.Panel将表单面板formPane添加到面板面板中。详见HTforWeb面板手册。部分控制代码如下:;)1formPane.addRow(['rotateY',{2slider:{3min:-Math.PI,4max:Math.PI,5value:r3[1],6onValueChanged:function(){7varcameraR3=camera.r3();8camera.r3([cameraR3[0],this.getValue(),cameraR3[2]]);9rangeNode.r3([cameraR3[0],this.getValue(),cameraR3[2]]);10getFrontImg(camera,rangeNode);11}12}13}],[0.1,0.15]);;)控制面板使用addRow添加控制元素,上面的代码是添加相机左右控制沿y轴的旋转。onValueChanged在滑块的值改变时被调用。此时通过camera.r3()获取当前相机的旋转参数。由于它绕着y轴旋转,所以x轴和z轴的夹角是不同的。变化的是y轴的旋转角度,所以通过camera.r3([cameraR3[0],this.getValue(),cameraR3[2]])和rangeNode.r3([cameraR3[0],this.getValue(),cameraR3[2]])设置摄像头前方圆锥体的旋转角度,然后调用之前封装的getFrontImg函数获取旋转下的实时图像信息此时的角度。项目中可以通过Panel面板的配置参数titleBackground:rgba(230,230,230,0.4)将标题背景设置为带透明度的背景,其他类似的标题参数如titleColor,titleHeight等可以通过separatorColor、separatorWidth等进行配置。split参数可以设置内面板之间的分割线的颜色、宽度等。最后panel通过panel.setPositionRelativeTo('rightTop')设置panel的位置为右上角,通过document.body.appendChild(panel.getView())将panel的最外层div添加到页面中,panel.getView()用于获取面板最外层的dom节点。具体初始化面板代码如下:;)1functioninitPanel(){2varpanel=newht.widget.Panel();3varconfig={4title:"CameraControlPanel",5titleBackground:'rgba(230,230,230,0.4)',6titleColor:'rgb(0,0,0)',7titleHeight:30,8separatorColor:'rgb(67,175,241)',9separatorWidth:1,10exclusive:true,11items:[]12};13cameraArr.forEach(function(data,num){14varcamera=data['camera'];15varrangeNode=data['rangeNode'];16varformPane=newht.widget.FormPane();17initFormPane(formPane,camera,rangeNode);18config.items.push({19title:"相机"+(num+1),20titleBackground:'rgba(230,230,230,0.4)',21titleColor:'rgb(0,0,0)',22titleHeight:30,23separatorColor:'rgb(67,175,241)',24separatorWidth:1,25content:formPane,26flowLayout:true,27contentHeight:400,28width:250,29expanded:num===030});31});32panel.setConfig(config);33panel.setPositionRelativeTo('rightTop');34document.body.appendChild(panel.getView());35window.addEventListener("resize",36function(){37panel.invalidate();38});39};)在控制面板中,摄像头的方向可以调整后,摄像头监测到摄像头的辐射范围,摄像头前方锥体的长度等,实时生成摄像头的图像,下面是运行截图:如下是本项目使用的3D场景结合HTforWeb的VR技术的操作: