【BIM】BIMFACE中创建疏散效果

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【BIM 】BIMFACE 中创建疏散效果
背景
在BIM 运维中,消防疏散是不可或缺的⼀环,当发⽣⽕警的时候,触发烟感器发⽣报警,同时启动消防疏散,指导现场⼯作⼈员进⾏疏散,及时准确地显⽰出疏散路线对争取疏散时间尤为重要。

我将介绍如何在中建⽴消防疏散指⽰动画效果。

思路第⼀种⽅式就是通过⾃带的材质对象,结合requestAnimationFrame 函数实现,具体地址见官⽹的。

这种⽅式存在弊端,⾸先代码量相对来说⽐较⼤,要配置各种对象的参数;其次对构件有强依赖性,也就是说这种⽅式是对构件进⾏材质重写来实现的;此外这种⽅式的贴图是通过UV 贴图实现,贴图缩放⽐例不好确定,需要摸索试探地确定⽐较合适的参数,第⼆种⽅式是直接通过threejs 来实现,相对于第⼀种⽅式⽽⾔,⽆需太多的代码,直奔主题,最重要的是不依赖构件(实际上是⾃⼰创建了Mesh ),也就是说没有构件同样可以实现上述效果,最重要的是不⽤再摸着⽯头贴图了,⾃⼰能够掌握贴图的规律。

本⽂中采⽤第⼆种⽅式来实现疏散效果,其实思路很简单,⽆⾮是创建Mesh ,然后给Mesh 贴上带箭头的图⽚,完成贴图后动态地修改贴图的偏移量(offset ),就实现了箭头动画效果。

实践⾸先来制作材质,因为路线由若⼲个PlaneBufferGeometry 组成,所以每⼀个都要进⾏贴图操作,其实除了图⽚在PlaneBufferGeometry 上的分布个数不⼀致,其他的参数都是⼀致的,所以要结合图⽚的⼤⼩和PlaneBufferGeometry 的长度来动态计算每个PlaneBufferGeometry 上材质需要重复的次数。

将创建的材质放⼊集合中是为了后续在执⾏动画时,可以针对每⼀个材质进⾏偏移量的修改,代码如下:
//声明存储材质的集合var textureCollection = [];function generateMaterial(repeat) { var basicMaterial = new THREE.MeshBasicMaterial(); texture = new THREE.TextureLoader().load('images/icon_arrow_right_pow.png', function (map) { basicMaterial.map = map; basicMaterial.wireframe = false; basicMaterial.needsUpdate = true; basicMaterial.transparent = true; basicMaterial.side = THREE.DoubleSide; }); texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping; texture.repeat.x = repeat; textureCollection.push(texture); return basicMaterial;
}有了材质,还需要创建若⼲个Mesh ,因为疏散路线是由⼀个⼀个的长条矩形组成,所以选择⽤平⾯PlaneBufferGeometry 来制作,材质使⽤箭头图⽚进⾏贴图。

代码如下:/**
* @param {若⼲Mesh 的集合,每个Mesh 结构如下} planeArray *
* @param {构件最⼩点世界坐标} min_position
* @param {构件最⼤点世界坐标} max_position
* @param {构件⽅向,上下左右以此对应(1,-1,2,0)} direction */function loadPlane(planeArray) {
// 标准宽度 const statndardWidth = 500;
// ⽤于计算标准图⽚重复个数
const statndardRepeat = 600;
###
// 指定默认⾓度
const rotate = Math.PI / 2;
var planeGroup = new THREE.Group();
// 思路⼀:仅⽤最⼤点进⾏定位(⽬前采⽤)
// 思路⼆:⽤最⼤点和最⼩点进⾏定位
for (let k = 0, l = planeArray.length; k < l; k++) {
let l = position_x = position_y = 0;
//区分横向和纵向
if (planeArray[k].direction === 1 || planeArray[k].direction === -1) {
l = Math.floor(planeArray[k].max_position.y - planeArray[k].min_position.y);
position_x = planeArray[k].max_position.x - (statndardWidth / 2);
position_y = planeArray[k].max_position.y - (l / 2);
} else {
l = Math.floor(planeArray[k].max_position.x - planeArray[k].min_position.x);
position_x = planeArray[k].max_position.x - (l / 2);
position_y = planeArray[k].max_position.y - (statndardWidth / 2);
}
let _material = generateMaterial(Math.floor(l / statndardRepeat));
let planeGeometry = new THREE.PlaneBufferGeometry(l, statndardWidth, 100, 50);
let plane = new THREE.Mesh(planeGeometry, _material);
plane.position.x = position_x;
plane.position.y = position_y;
plane.position.z = planeArray[k].max_position.z + 10;
plane.rotation.z = rotate * planeArray[k].direction;
planeGroup.add(plane);
}
viewer.addExternalObject("planeGroup", planeGroup);
viewer.render();
}
⽬前形状和材质都已经建⽴完成,整个场景还是静态的,由箭头组成的平⾯形状集合,下⼀步是让这些箭头跑起来,思路就是在渲染的时候动态修改材质的offset,代码如下:
function animate() {
animationId = requestAnimationFrame(animate);
for (let m = 0, len = textureCollection.length; m < len; m++) {
textureCollection[m].offset.x += 0.005;
}
viewer.render();
}
使⽤⽅式,只需要将mesh对应的包围盒最⼤点和最⼩点(⽤于确定位置)以及箭头⽅向(⽤于确定箭头流向)的参数放在数组中传⼊loadPlane函数,然后调⽤animate函数即可实现疏散效果,代码如下:
let planeArray = [];
const UP = 1;
const DOWN = -1;
const LEFT = 2;
const RIGHT = 0;
let a = { min_position: { x: -10432.83984375, y: 20233.87109375, z: 15 }, max_position: { x: -9932.83984375, y: 26744.16796875, z: 40 }, direction: UP }; let b = { min_position: { x: -14117.83984375, y: 28943.8671875, z: 15 }, max_position: { x: -12812.83984375, y: 29443.8671875, z: 50 }, direction: RIGHT }; let c = { min_position: { x: -7591.01171875, y: 27244.16796875, z: 15 }, max_position: { x: -7091.01171875, y: 33333.8671875, z: 20 }, direction: UP };
planeArray.push(a);
planeArray.push(b); planeArray.push(c);
loadPlane(planeArray);
animate();
#
效果
以下是结合真实模型的疏散路线效果如有描述不当之处,还请不吝赐教。

相关文档
最新文档