【BIM】BIMFACE中实现构件呼吸灯效果

背景

实现报警呼吸灯效果,目前产品中报警设备仅仅是做了高亮处理,并没有明显的动画效果来提示用户该设备正在报警,bimface中也提供了构件闪烁的接口,但是看起来比较生硬,查看代码发现是通过定时器实现,比较占用CPU资源,而呼吸灯报警效果是采用着色器程序编写,通过GPU执行,性能和效果均优于定时器。

思路

首先,获取到报警设备的包围盒,根据包围盒计算出创建立方体的参数,可以让立方体的尺寸稍微比报警设备大一些,避免因共面而引起花屏的问题,然后通过着色器程序渲染立方体,在requestAnimationFrame中不停地修改着色器中的统一变量,以实现呼吸灯效果。核心代码如下:

<script type="x-vertexShader" id="vertex">
void main(){
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script>

<script type="x-fragmentShader" id="fragment">
uniform float time;
void main(){
  gl_FragColor = vec4(0.65,0.0,0.0,abs(sin(time) * 0.85));
}
</script>
var uniform = {
    time: {
        value: 0.0
    }
}
//获取着色器程序
let vertexShader = document.getElementById('vertex').textContent;
let fragmentShader = document.getElementById('fragment').textContent;
//获取报警设备包围盒信息
let max = {
    x: 48267.05078125,
    y: 145279.40625,
    z: 4566.999938964844
};
let min = {
    x: 47267.050842285156,
    y: 143739.40625,
    z: 3833
};
//偏移量
let offset = 100, segment = 2.0;
let width = (max.x - min.x + offset), height = (max.y - min.y + offset), depth = (max.z - min.z + offset);
let targetPos = {
    x: (max.x + min.x + offset / segment) / segment,
    y: (max.y + min.y + offset / segment) / segment,
    z: (max.z + min.z + offset / segment) / segment
};
let boundingBoxGeometry = new THREE.BoxBufferGeometry(width, height, depth);
let boundingBoxMaterial = new THREE.ShaderMaterial({
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        transparent: true,
        uniforms: uniform
    });
let boundingBoxMesh = new THREE.Mesh(boundingBoxGeometry, boundingBoxMaterial);
boundingBoxMesh.position.set(targetPos.x, targetPos.y, targetPos.z);
viewer.addExternalObject("boundingBox", boundingBoxMesh);

//执行动画
function animation() {
    uniform.time.value += 0.075;
    requestAnimationFrame(animation);
    viewer.render();
}
animation();

效果

呼吸灯

posted @ 2020-07-15 16:28  悠扬的牧笛  阅读(562)  评论(0编辑  收藏  举报