HTML5 WebGL 实现民航客机飞行监控系统

2020-04-25 07:41:39易采站长站整理

视角限制的话一般是限制 g3d 的 eye 和 center ,不太了解的朋友可以去看 hightopo 官网中的 3d 手册,里面有详细的说明,这里我就不再赘述了;因为视角范围的关系,所以我决定固定 center 的位置,代码如下:
 


g3d.addPropertyChangeListener(e => {
// 固定中心点
if (e.property === 'center') {
e.newValue[0] = center[0];
e.newValue[1] = center[1];
e.newValue[2] = center[2];
}
}

然后再把 eye 限制在某一个范围内就大功告成了,然而这里却并不是那么简单,最开始我把 eye 限制在一个立方体的空间内,但交互效果很不理想,考虑到 g3d 默认交互中,鼠标拖拽平移视角变换时,实际上 eye 是在一个以 center 为球心的球面上运动的,所以我决定从这个球中挖出来一块作为 eye 的限制空间,也就是球扇形,不太理解的朋友可以参考这个图:


 

球扇形视角限制,一共需要三个参数,分别是中心参考轴、中心轴和外边所成角度、所在球限制半径,其中中心参考轴可根据初始 eye 和 center 的连接延长线确定,所在球限制半径又分最大限制和最小限制,代码如下:

 


function limitEye(g3d, eye, center, options) {
var limitMaxL = options.limitMaxL,
limitMinL = options.limitMinL,
limitA = options.limitA;

g3d.addPropertyChangeListener(e => {
// 固定中心点
if (e.property === 'center') {
e.newValue[0] = center[0];
e.newValue[1] = center[1];
e.newValue[2] = center[2];
}
// 限制视角
if (e.property === 'eye') {
var newEyeV = new ht.Math.Vector3(e.newValue),
centerV = new ht.Math.Vector3(center),
refEyeV = new ht.Math.Vector3(eye),
refVector = refEyeV.clone().sub(centerV),
newVector = newEyeV.clone().sub(centerV);

if (centerV.distanceTo(newEyeV) > limitMaxL) {
newVector.setLength(limitMaxL);
e.newValue[0] = newVector.x;
e.newValue[1] = newVector.y;
e.newValue[2] = newVector.z;
}
if (centerV.distanceTo(newEyeV) < limitMinL) {
newVector.setLength(limitMinL);
e.newValue[0] = newVector.x;
e.newValue[1] = newVector.y;
e.newValue[2] = newVector.z;
}
if (newVector.angleTo(refVector) > limitA) {
var oldLength = newVector.length(),
oldAngle = newVector.angleTo(refVector),
refLength = oldLength * Math.cos(oldAngle),
vertVector,
realVector,
realEye;

refVector.setLength(refLength);

newEyeV = newVector.clone().add(centerV);
refEyeV = refVector.clone().add(centerV);
vertVector = newEyeV.clone().sub(refEyeV);
vertLength = refLength * Math.tan(limitA);

vertVector.setLength(vertLength);

realVector = vertVector.clone().add(refEyeV).sub(centerV);