基于HTML5及WebGL的工控SCADA模拟飞机飞行
昨天看到一篇文章说是学习如何开飞机的,然后我就想,如果我也可以开飞机那就好玩了,每个人小时候都想做飞行员!中国飞行员太难当了,再说也不轻易让你开飞机!后来我就想如果能用 HT 开飞机那就是真的有趣了,哈哈,这个实现的效果还是很不错的,可以让你满足一下开飞机的虚荣心
Demo 地址: http://hightopo.com/guide/guide/plugin/obj/examples/example_path.html
来看下具体实现的效果:
这个例子基本上完全模拟了飞机的飞行模式,包括起飞跑道,包括飞机的移动路径,螺旋桨的旋转,机尾的指示灯等部分。
首先,最重要的是我们的飞机模型,前面有文章写到过,HT 内部封装了一个方法 ht.Default.loadObj 来加载 OBJ 文件:
ht.Default.loadObj('obj/plane.obj', 'obj/plane.mtl', {
center: true,
r3: [0, -Math.PI/2, 0], // make plane face right
s3: [0.15, 0.15, 0.15], // make plane smaller
finishFunc: function(modelMap, array, rawS3){
if(modelMap){
modelMap.propeller.r3 = {//propeller 螺旋桨
func: function(data){
return [data.a('angle'), 0, 0];
}
};
// make propeller a litter bigger
modelMap.propeller.s3 = [1, 1.2, 1.2];
modelMap.propeller.color = 'yellow';
}
});
这里面的 modelMap.propeller 是 OBJ 文件中定义好的 modelMap 对象中的 propeller 对象,你可以试着打印 modelMap 看看输出结果。
这个方法里的 finishFunc(modelMap, array, rawS3) 用于加载后的回调处理,具体查阅 HT for Web OBJ 手册,我们还添加了一个在 OBJ 模型中没有的飞机尾部的“红色闪烁指示灯”,这里用到的是组合模型 array(所有材质组成的数组,里面有至少一个模型),我们在 array中加入一个新的球模型:
// add a sphere model as an indicator light 指示灯
array.push({
shape3d: ht.Default.createSmoothSphereModel(),
t3: [-40, 10, 0],
s3: [6, 6, 6],
color: {
func: function(data){
return data.a('light') ? 'red': 'black';
}
}
});
这里的 shape3d 是 HT 封装的一个属性名,通过 setShape3dModel(name, model) 函数注册的或者是通过 getShape3dModel(name) 函数返回的注册过的 3D 模型,如何注册 3D 模型可查阅 HT for Web 建模手册。
color 属性名对应了一个对象,这边的定义是这样的,color 直接通过 data.getAttr('a') 获取 data.setAttr(‘a’, value) 中的值,这样做有两个好处,一是可以不污染 HT 的常用属性操作,所以 HT 专门定义了这个 attr 属性类型,是 HT 预留给用户存储业务数据的;二是这样也很方便数据绑定,我们可以通过在需要更改属性的地方调用 setAttr 方法,非常方便。
接着我们通过 ht.Default.setShape3dModel(name, model) 来将我们刚刚组合好的模型 array 注册成我们要的“plane”模型:
ht.Default.setShape3dModel('plane', array);
注册好模型后肯定是要调用这个模型,我们可以通过 shape3d 属性来调用这个模型,并且在这个模型中自定义上面代码中出现过的 light 属性和 angle 属性:
plane = new ht.Node();
plane.s3(200, 200, 200);
plane.s3(rawS3);
plane.s({
'shape3d': 'plane',
'shape3d.scaleable': false,
'wf.visible': true,//线框是否可见
'wf.color': 'white',
'wf.short': true //是否显示封闭的线框,true为不封闭的短线框
});
plane.a({
'angle': 0,
'light': false
});
因为飞机还有螺旋桨、指示灯两个功能,我们还得对这两个模型做动画效果,可查阅 HT for Web 动画手册,通过用户在 form 表单上选择的结果来决定飞机飞行持续时间、看飞机的视角、飞机沿着“航线”飞行所要旋转的角度、机尾指示灯的“闪烁”功能等等,最后别忘了飞机停止飞行时,如果要让飞机继续飞行,就得回调这个动画,并且设置灯不再闪烁,别忘了要启动动画:
params = {
delay: 1500,
duration: 20000,
easing: function(t){
return (t *= 2) < 1 ? 0.5 * t * t : 0.5 * (1 - (--t) * (t - 2));
},
action: function(v, t){
var length = g3d.getLineLength(polyline),
offset = g3d.getLineOffset(polyline, length*v),
point = offset.point,
px = point.x,
py = point.y,
pz = point.z,
tangent = offset.tangent,
tx = tangent.x,
ty = tangent.y,
tz = tangent.z;
plane.p3(px, py, pz);
plane.lookAt([px + tx, py + ty, pz + tz], 'right'); var camera = formPane.v('Camera');
if(camera === 'Look At'){
g3d.setCenter(px, py, pz);
}
else if(camera === 'First Person'){
g3d.setEye(px - tx * 400, py - ty * 400 + 30, pz - tz * 400);
g3d.setCenter(px, py, pz);
} plane.a('angle', v*Math.PI*120);
if(this.duration * t % 1000 > 500){
plane.a('light', false);
}else{
plane.a('light', true);
}
},
finishFunc: function(){
animation = ht.Default.startAnim(params);
plane.a('light', false);
}
}; animation = ht.Default.startAnim(params);
其实最让我们好奇的是描绘的路径跟飞机本身的飞行并没有关系,还有那么多左拐右拐的,要如何做才能做到呢?
接下来我们来描绘路径,首先这个路径是由 ht.Polyline 作为基础来描绘的:
polyline = new ht.Polyline();
polyline.setThickness(2);
polyline.s({
'shape.border.pattern': [16, 16],
'shape.border.color': 'red',
'shape.border.gradient.color': 'yellow',
'shape3d.resolution': 300,
'3d.selectable': false
});
dataModel.add(polyline);
上面的代码只是向 datamodel 数据模型中添加了一个 polyline 管线而已,不会显示任何东西,要显示“航道”首先就要设置航道所在的点,我们先设置航道的初始点:
points = [{ x: 0, y: 0, e: 0 }];
segments = [1];
这个 points 和 segments 是 HT for Web Shape 手册中定义的,points 是 ht.List 类型数组的定点信息,顶点为 { x: 100, y: 200 } 格式的对象;segments 是 ht.List 类型的线段数组信息,代表 points 数组中的顶点按数组顺序的连接方式。
图中“航道”左侧的多个圆形轨道也是通过设置 points 和 segments 来设置的:
for(var k=0; k<count+1; k++){
var angle = k * Math.PI * 2 * round / count;
points.push({
x: cx + radius * Math.cos(angle),
y: cy + radius * Math.sin(angle),
e: k * height / count
});
segments.push(2);
}
接下来几个拐点也是这种方法来实现的,这里就不赘述了,如果你还没看手册的话,这里标明一点,segments 只能取值 1~5,1 代表一个新路径的起点;2 代表从上次最后点连接到该点;3 占用两个点信息,第一个点作为曲线控制点,第二个点作为曲线结束点;4 占用3个点信息,第一和第二个点作为曲线控制点,第三个点作为曲线结束点;5 不占用点信息,代表本次绘制路径结束,并闭合到路径的起始点:
points.push({ x: cx+radius, y: 0, e: height/2 });
points.push({ x: 0, y: 0, e: height/2 });
segments.push(3); points.push({ x: radius, y: -radius, e: height/2*0.7 });
points.push({ x: radius*2, y: radius, e: height/2*0.3 });
points.push({ x: radius*3, y: 0, e: 0 });
segments.push(4); points.push({ x: 0, y: 0, e: 0 });
segments.push(2);
我们已经把路径上的点都添加进“航道”中了,接下来要把点都设置到管道上去才会显示在界面上:
polyline.setPoints(points);
polyline.setSegments(segments);
“跑道”就比较简单了,只是一个 Node 节点然后设置基础效果而已,没什么特别的:
runway = new ht.Node();
runway.s3(-cx+radius*3, 1, 200);
runway.p3(cx+runway.getWidth()/2, -22, 0);
runway.s({
'all.color': '#FAFAFA',
'all.transparent': true,
'all.reverse.cull': true,
'all.opacity': 0.8,
'3d.selectable': false
});
dataModel.add(runway);
最后,在界面上添加一个 formPane 表单面板,定义好之后可以直接添加到 body 上,这样就不会跟 graph3dView 有显示的联系了。
formPane 可以用 formPane.addRow 方法动态添加行,这个方法中可以直接对动态变化的数据进行交互,例如本例中的是否有动画 Animation,我们利用 checkBox 来记录选中或者非选中的状态:
{
checkBox: {
label: 'Animation',
selected: true,
onValueChanged: function(){
if(this.isSelected()){
animation.resume();
}else{
animation.pause();
}
}
}
}
也可以通过设置“id”来记录动态改变的值,然后 formPane就会通过调用 formPane.v(id) 来获取当前值。
至此,整个 Demo 的解释到此为止,如果还有不懂的可以先查阅我们官网 HT for Web,之后还有不懂的可以私信我,但还是希望你们能仔细阅读,不然很浪费我们双方的时间,谢谢~
基于HTML5及WebGL的工控SCADA模拟飞机飞行的更多相关文章
- 基于HTML5 Canvas的工控SCADA模拟飞机飞行
昨天看到一篇文章说是学习如何开飞机的,然后我就想,如果我也可以开飞机那就好玩了,每个人小时候都想做飞行员!中国飞行员太难当了,再说也不轻易让你开飞机!后来我就想如果能用 HT 开飞机那就是真的有趣了, ...
- 基于HTML5 Canvas 实现矢量工控风机叶轮旋转
之前在拓扑上的应用都是些静态的图元,今天我们将在拓扑上设计一个会动的图元--叶轮旋转. 先看看最后我们实现的效果:http://www.hightopo.com/demo/fan/index.html ...
- 基于 HTML5 的 WebGL 楼宇自控 3D 可视化监控
前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...
- 基于 HTML5 的 WebGL 和 VR 技术的 3D 机房数据中心可视化
前言 在 3D 机房数据中心可视化应用中,随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的 ...
- 基于 HTML5 的 WebGL 自定义 3D 摄像头监控模型
前言 随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的同时,在监控系统中面临着严峻的现状问 ...
- 基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块
基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块 前言 最近学习了 HT for Web flow 插件,除了正常的 flow 效果,其中还有两个十分好用的两个接口 getPercen ...
- 基于 HTML5 和 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于HTML5的WebGL电信网管3D机房监控应用
先上段视频,不是在玩游戏哦,是规规矩矩的电信网管企业应用,嗯,全键盘的漫游3D机房: http://www.hightopo.com/guide/guide/core/3d/examples/exam ...
- 基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测
为了实现一个基于HTML5的场景小游戏,我采用了HT for Web来实现,短短200行代码,我就能实现用“第一人称”来操作前进后退上下左右,并且实现了碰撞检测. 先来看下实现的效果:http://h ...
随机推荐
- log4j的基本使用和参数设定
1.简介 apache的一个开放源代码项目. 精确控制日志的输出,包括输出的格式,输出的目的地,输出的过滤(不同级别日志的输出)等. 配置简单,不需要在代码中配置环境,支持两种配置文件格式,XML和J ...
- [UIKit学习]00.关于前置知识(storyboard,UIViewController,类扩展,项目属性)
storyboard文件的认识 用来描述软件界面 默认情况下,程序一启动就会加载Main.storyboard 加载storyboard时,会首先创建和显示箭头所指的控制器界面 IBAction和IB ...
- PHP实现页面静态化
1.通过buffer来实现 需要用file_put_contents ob_get_clean()等内置函数 ob_start (); include "filterpost.htm ...
- RMQ-ST算法的理解与实现(C++)
RMQ-ST的含义 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返 ...
- DotNetCore跨平台~linux上还原自主nuget包需要注意的问题
问题的产生的背景 由于我们使用了jenkins进行部署(jenkins~集群分发功能和职责处理),而对于.net core项目来说又是跨平台的,所以对它的项目拉取,包的还原,项目的编译和项目的发布都是 ...
- Symbol
ES5 的对象属性名都是字符串,这容易造成属性名的冲突.比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突.如果有一种机制,保证 ...
- 从Thread.start()方法看Thread源码,多次start一个线程会怎么样
这篇文章作为Thread类源码剖析的补充,从一个侧面来看Thread源码.也解答了面试高频问题:"多次start一个线程会怎么样?" 答案是:java.lang.IllegalTh ...
- JAVA设计模式总结之23种设计模式
上一篇总结了设计模式的六大原则<JAVA设计模式总结之六大设计原则>,这一篇,正式进入到介绍23种设计模式的归纳总结. 一.什么是设计模式 ...
- windows下实现linux的远程访问以及linux上文件的上传和下载
在网络性能.安全性.可管理性上,Linux有着其他系统无法比拟的强大优势,而服务器对这些方面要求特别高,因此Linux常常被用来做服务器使用.而当我们需要维护linux服务器的时候,就需要远程访问li ...
- C# 7.0 新特性:本地方法
C# 7.0:本地方法 VS 2017 的 C# 7.0 中引入了本地方法,本地方法是一种语法糖,允许我们在方法内定义本地方法.更加类似于函数式语言,但是,本质上还是基于面向对象实现的. 1. 本地方 ...