2.3.10.1 摄像机高级设置
本教程中,我们将介绍一些摄像机的高级设置方法。
添加摄像机事件的语法
下面的代码中,通过 on() 方法添加事件。
app.on(THING.EventType.name, function (ev) {
});
其中,name 为 camera 事件的名称。
关于 camera 相关事件类型,可以点击查看 EventType。
摄像机相关事件示例
可以通过以下脚本对摄像机添加相关事件,可以按照自己的需求进行具体选择。
// 设置摄像机俯仰角度范围[最小值, 最大值]
app.camera.xAngleLimitRange = [30, 60];
// 摄像机位置变动开始触发
app.on(THING.EventType.CameraChangeStart, function (ev) {
console.log('CameraChangeStart ');
console.log('pos:' + ev.position + ' target:' + ev.target);
});
// 摄像机位置变动结束触发
app.on(THING.EventType.CameraChangeEnd, function (ev) {
console.log('CameraChangeEnd ');
console.log('pos:' + ev.position + ' target:' + ev.target);
})
// 摄像机位置变动中触发
app.on(THING.EventType.CameraChange, function (ev) {
console.log(' CameraChange ');
console.log('pos:' + ev.position + ' target:' + ev.target);
})
// 摄像机位置缩放后触发
app.on(THING.EventType.CameraZoom,function(ev){
console.log('CameraZoom ');
console.log(ev.delta);
})
// 改变摄像机观察模式后触发
app.on(THING.EventType.CameraViewChange, function (ev) {
console.log('CameraViewChange ');
console.log(ev.view);
})
摄像机的投影方式
我们看到的 3D 画面其实是计算机把三维空间中的物体从世界坐标系通过各种复杂的计算投影到屏幕坐标系,并显示在视口中。
而投影的方式有透视投影和正射投影两种:
透视投影:即离视点近的物体大,离视点远的物体小。
正射投影:又叫平行投影。它的特点是无论物体距离相机多远,投影后的物体大小尺寸不变。
在 ThingJS 中可通过 app.camera.porjectionType 设置摄像机的投影类型,参考脚本如下:
//透视投影
app.camera.projectionType= THING.CameraProjectionType.Perspective;
//正射投影
app.camera.projectionType= THING.CameraProjectionType.Orthographic;
视锥体
视锥体为可以观看投影物体的可视区域,由近平面,远平面,左,上,右,下各面组成。 只有在可视区域内才可见,区域外会被裁剪。
在 ThingJS 中可以设置 camera 的远剪裁面 far 、近剪裁面 near 和 fov 来设置可视区域范围。
FOV(视场角)即 Field of View,类似于摄影中的焦距,值越大,画面显示的内容就越多,但也越扭曲。
//设置近裁剪面的距离,比这个距离近的物体将不会被渲染
app.camera.near = 10;//默认值0.1
//设置远裁剪面的距离,比这个距离远的物体将不会被渲染
app.camera.far= 100; //默认值1000
//设置摄像机FOV
app.camera.fov = 30;//默认值60
可通过 isInView() 判断场景中某个物体是否在可视范围内。
// 根据物体包围盒检测是某物体否在摄相机视锥范围内
app.camera.isInView(obj);
屏幕坐标与 3D 世界坐标转换
可通过 worldToScreen() , screenToWorld() 进行 3D 世界坐标和 2D 屏幕坐标的相互转换。
注意事项
2D 屏幕坐标系以左上角为原点,向右为 X 正向,向下为 Y 正向
坐标转换脚本如下:
//世界坐标系下3D坐标转换成2D屏幕坐标
app.camera.worldToScreen(obj.position);
//屏幕坐标转3D世界坐标
app.camera.screenToWorld([200,200]);
屏幕坐标转 3D 世界坐标返回的为经过摄像机 position , target 两点的直线与三维世界坐标系下平面的交点,见下图:
关于“最佳看点”
当摄像机看向目标物体时,一般将物体中心点作为 “看点” 的 target 位置。
我们可以通过相对于目标物体的坐标系下 x 轴旋转角度、 y 轴旋转角度以及距目标物体“中心”的距离来确定一个位置,作为“看点”的 position 位置。
我们将物体 包围盒 的中心点作为“最佳看点”的 target 位置。
如果用户需自定义 fit() 物体的摄像机位置,可控制以下参数来进行设置:
app.camera.fit({
'object': obj,
'xAngle': 60, //绕物体自身X轴旋转角度
'yAngle': 30, //绕物体自身Y轴旋转角度
'radiusFactor':3, //物体包围球半径的倍数
});
通过摄像机的 lookAt() 方法,也可以让摄像机一直“盯着”某个位置或物体看,示例脚本如下:
//摄像机一直“盯着”[0,0,0]点看
app.camera.lookAt([0, 0, 0]); //
//摄像机一直“盯着”某物体看
var obj = app.query("car01")[0];
app.camera.lookAt(obj);
//取消摄像机一直盯着物体看
app.camera.lookAt(null);