博客
关于我
分享 HT 实用技巧:实现指南针和 3D 魔方导航
阅读量:464 次
发布时间:2019-03-06

本文共 3376 字,大约阅读时间需要 11 分钟。

三维场景中常需要一个方位标识,用以确定场景所处的方向。常见的表现形式包括指南针和方位魔方。参考百度百科中的maya界面,可以看到右上角有一个标识方位的小盒子,这就是方位指示工具。

Hightopo的HT for Web产品能够方便地构建轻量化的3D可视化场景。在web端,我们可以利用HT 2D引擎和3D渲染引擎来实现这个功能,搭建一个简易的maya操作界面。预览地址已移除。

在这个界面中,我们使用了一个二维场景和两个三维场景,具体效果如下:

页面布局如下:指南针通过在ht.graph.GraphView中设置一个事先绘制好的图标来实现,只需将它放置在图纸的左上角即可。方位魔方通过在一个小场景(ht.graph3d.Graph3dView)中放置魔方模型来实现,然后将这个小场景放置在图纸的右上角即可。主三维场景作为背景放置在整个二维页面的下方。

代码示例如下:

const g3d = new ht.graph3d.Graph3dView();g3d.setOriginAxisVisible(true);g3d.setGridVisible(true);g3d.addToDOM();const g2d = new ht.graph.GraphView();g2d.deserialize('displays/test.json', json => {    g2d.addToDOM(g3d.getView());});

位置关系:Z轴负半轴为北方,Z轴正半轴为南方,X轴正半轴为东方,X轴负半轴为西方。

指南针同步:首先约定方位,Z轴负半轴为北方,Z轴正半轴为南方,X轴正半轴为东方,X轴负半轴为西方。由于指南针的目的是用于指示鸟瞰图中的方位,我们可以将整个计算过程放在二维空间中进行。

代码示例:

const eye = this.g3d.getEye();const center = this.g3d.getCenter();const v = new ht.Math.Vector2(eye[0], eye[2]);const v2 = new ht.Math.Vector2(center[0], center[2]);const angle = v.sub(v2).angle() - Math.PI / 2;compass.setRotation(-angle);compass.a('angle', angle);compass.a('angle2', angle);

在这段代码中,我们用eye(相机)和center(观测点)构建两个二维向量(ht.Math.Vector2),舍弃掉Y轴的分量。利用向量减法,求得从center指向eye的向量并存入变量v中。角度由angle()方法获取,与x正半轴的夹角(弧度制)相减Math.PI / 2是因为计算的方向与Z轴负半轴(北方)对应。

指南针的旋转角度通过setRotation()方法设置。由于视线的逆时针旋转与指南针的相对运动方向是顺时针旋转,故取负值。

通过HT 2D引擎提供的数据绑定功能,轮盘图标和角度图标的旋转角度可以通过设置compass节点的属性值来实时动态改变。每次视线变化时,需要执行上述计算和设置,可以通过在三维场景组件中增加属性监听器来实现:

graph3dView.addPropertyChangeListener(e => {    if (e.property === 'eye' || e.property === 'center') {        changeCompass();        //...    }});

方位魔方同步:方位魔方用于呈现三维空间中的视线方位。与指南针不同,它也是一个可交互的方位操纵杆,可以方便快捷地将当前视角变为顶视图、侧视图等。

视线改变触发魔方变换:代码示例如下:

graph3dView.addPropertyChangeListener(e => {    if (e.property === 'eye') {        const newValue = e.newValue;        const vEye = new ht.Math.Vector3(newValue[0], newValue[1], newValue[2]).normalize();        graph3dView2.setEye([300 * vEye.x, 300 * vEye.y, 300 * vEye.z]);    }});

在上述代码中,我们通过监听主三维场景(graph3dView)中的eye属性变化来动态改变小场景(graph3dView2)中的eye位置,实现联动效果。e.newValue获取场景视点改变后的值,构建三维向量并归一化,乘以300使距离合适。

点击魔方改变场景视角:要实现点击魔方改变主场景中的视线,需要知道鼠标点击的小魔方哪个面。利用graph3dView.intersectObject(event, data)方法获取点击位置信息,world属性描述点击位置的世界坐标。

代码示例:

graph3dView2.addInteractorListener(event => {    if (event.kind === 'clickData') {        const obj = graph3dView2.intersectObject(event.event, event.data);        if (obj) {            const world = obj.world;            const x = world.x;            const y = world.y;            const z = world.z;            if (Math.abs(x) - Math.abs(y) > 0 && Math.abs(x) - Math.abs(z) > 0) {                if (x > 0) {                    graph3dView2.setEye([300, 0, 0]);                    graph3dView.setEye([this._distance, 0, 0]);                    graph3dView2.setCenter([0, 0, 0]);                    this._g3d.setCenter([0, 0, 0]);                } else {                    graph3dView2.setEye([-300, 0, 0]);                    graph3dView.setEye([-this._distance, 0, 0]);                    graph3dView2.setCenter([0, 0, 0]);                    graph3dView.setCenter([0, 0, 0]);                }            } else if (Math.abs(y) - Math.abs(x) > 0 && Math.abs(y) - Math.abs(z) > 0) {                //...            }        }    }});

点击魔方各个面效果演示:

通过上述方法,点击魔方的不同面会改变主场景的视线方向。点击后,小方块颜色可以通过以下代码禁用选中效果:

const sm = graph3dView2.dm().getSelectionModel();sm.setSelection(null);

总结:直观的方位指示在室内定位、GIS、车站、机场等场景中有广泛应用。利用HT引擎可以轻松实现web 3D的可视化场景。

转载地址:http://whcbz.baihongyu.com/

你可能感兴趣的文章
Nacos配置中心集群原理及源码分析
查看>>
nacos配置自动刷新源码解析
查看>>
Nacos集群搭建
查看>>
nacos集群搭建
查看>>
Navicat for MySQL 查看BLOB字段内容
查看>>
Neo4j电影关系图Cypher
查看>>
Neo4j的安装与使用
查看>>
Neo4j(2):环境搭建
查看>>
Neo私链
查看>>
nessus快速安装使用指南(非常详细)零基础入门到精通,收藏这一篇就够了
查看>>
Nessus漏洞扫描教程之配置Nessus
查看>>
Nest.js 6.0.0 正式版发布,基于 TypeScript 的 Node.js 框架
查看>>
NetApp凭借领先的混合云数据与服务把握数字化转型机遇
查看>>
NetBeans IDE8.0需要JDK1.7及以上版本
查看>>
netcat的端口转发功能的实现
查看>>
netfilter应用场景
查看>>
netlink2.6.32内核实现源码
查看>>
Netpas:不一样的SD-WAN+ 保障网络通讯品质
查看>>
NetScaler的常用配置
查看>>
netsh advfirewall
查看>>