Camera

Android Camera系列(一):SurfaceView+Camera 本文介绍了Camera+SurfaceView的基本操作及关键代码,但是你如果看github中代码会发现和文中出入很大。其原因在于文章我想用一种简单的方式让没有做过自定义Camera的人也能明白。而github中的项目我已经进行了多次重构、抽象。其中包括对Camera的抽象,定义ICameraManager接口。对预览的View的重构,定义BaseCameraView接口,以及预览视图的众多超类。 阅读详情

CesiumJS 中的相机控制场景的视图。 有很多操作相机的方法,例如旋转,缩放,平移和飞到目的地。 CesiumJS 具有鼠标和触摸事件处理程序以与相机进行交互,并具有以编程方式操作相机的API。 了解如何使用 Camera API 和自定义相机控件。


Default camera behavior

在 Sandcastle 中打开 Hello World 示例,以浏览默认的相机控件。 默认值为:

Mouse Action3D2DColumbus View
Left click + dragRotate around the globeTranslate over the mapTranslate over the map
Right click + dragZoom in and outZoom in and outZoom in and out
Middle wheel scrollingZoom in and outZoom in and outZoom in and out
Middle click + dragTilt the globeNo actionTilt the map

使用 setView 功能以编程方式设置摄像机的位置和方向。 destination 可以是 Cartesian3 或 Rectangle ,方向可以是航向/俯仰/滚动或方向/向上。 航向角,俯仰角和横滚角以弧度定义。 航向是从局部北向旋转,其中正角向东增加。 俯仰是从本地东西向平面的旋转。 正俯仰角在平面上方。 负俯仰角在平面下方。 横摇是绕局部东轴应用的第一次旋转。

camera.setView({
    destination : new Cesium.Cartesian3(x, y, z),
    orientation: {
        heading : headingAngle,
        pitch : pitchAngle,
        roll : rollAngle
    }
});
viewer.camera.setView({
    destination : Cesium.Rectangle.fromDegrees(west, south, east, north),
    orientation: {
        heading : headingAngle,
        pitch : pitchAngle,
        roll : rollAngle
    }
});

所有参数都是可选的。 如果未指定,则参数值将默认为当前摄像机的位置和方向。

使用以下方法,将摄像机的位置设置为朝北,并垂直向下看地球:

camera.setView({
    destination : Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
    orientation: {
        heading : 0.0,
        pitch : -Cesium.Math.PI_OVER_TWO,
        roll : 0.0
    }
});

Custom camera mouse or keyboard events

让我们创建自己的事件处理程序,使相机朝着鼠标的方向看,并在按键时向前,向后,向左,向右,向上和向下移动。 首先禁用默认事件处理程序。 添加以下代码(在var viewer = …之后):

var scene = viewer.scene;
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.onclick = function() {
    canvas.focus();
};
var ellipsoid = viewer.scene.globe.ellipsoid;

// disable the default event handlers
scene.screenSpaceCameraController.enableRotate = false;
scene.screenSpaceCameraController.enableTranslate = false;
scene.screenSpaceCameraController.enableZoom = false;
scene.screenSpaceCameraController.enableTilt = false;
scene.screenSpaceCameraController.enableLook = false;

创建变量以记录当前鼠标位置,并创建标记以跟踪相机的移动方式:

var startMousePosition;
var mousePosition;
var flags = {
    looking : false,
    moveForward : false,
    moveBackward : false,
    moveUp : false,
    moveDown : false,
    moveLeft : false,
    moveRight : false
};

添加事件处理程序以在单击鼠标左键时设置标志并记录当前鼠标位置:

var handler = new Cesium.ScreenSpaceEventHandler(canvas);

handler.setInputAction(function(movement) {
    flags.looking = true;
    mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

handler.setInputAction(function(movement) {
    mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

handler.setInputAction(function(position) {
    flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

创建键盘事件处理程序以切换标志以进行摄像机移动。 我们将为以下键和行为设置标志:

  • w 将向前移动相机。
  • s 将向后移动相机。
  • a 将相机移至左侧。
  • d 将相机移至右侧。
  • q 将向上移动相机。
  • e 将向下移动相机。
function getFlagForKeyCode(keyCode) {
    switch (keyCode) {
    case 'W'.charCodeAt(0):
        return 'moveForward';
    case 'S'.charCodeAt(0):
        return 'moveBackward';
    case 'Q'.charCodeAt(0):
        return 'moveUp';
    case 'E'.charCodeAt(0):
        return 'moveDown';
    case 'D'.charCodeAt(0):
        return 'moveRight';
    case 'A'.charCodeAt(0):
        return 'moveLeft';
    default:
        return undefined;
    }
}

document.addEventListener('keydown', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = true;
    }
}, false);

document.addEventListener('keyup', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = false;
    }
}, false);

现在,当指示事件发生的标志为true时,我们想更新摄像机。 我们可以在时钟上向onTick事件添加一个侦听器,其中包含以下代码:

viewer.clock.onTick.addEventListener(function(clock) {
    var camera = viewer.camera;
});

接下来,使相机朝着鼠标光标的方向看。 将此代码添加到变量声明下的事件侦听器函数中:

if (flags.looking) {
    var width = canvas.clientWidth;
    var height = canvas.clientHeight;

    // Coordinate (0.0, 0.0) will be where the mouse was clicked.
    var x = (mousePosition.x - startMousePosition.x) / width;
    var y = -(mousePosition.y - startMousePosition.y) / height;

    var lookFactor = 0.05;
    camera.lookRight(x * lookFactor);
    camera.lookUp(y * lookFactor);
}

lookRight 和 lookUp 方法采用一个以弧度为单位的参数,即旋转角度。 我们将鼠标坐标转换为(-1.0,1.0)范围,将坐标(0.0,0.0)转换为画布的中心。 鼠标与中心的距离决定了转弯的速度。 靠近中心的位置会使照相机移动得较慢,而离中心较远的位置会使照相机移动得更快。

最后,添加代码以移动相机的位置。 还将其添加到事件监听器函数中:

// Change movement speed based on the distance of the camera to the surface of the ellipsoid.
var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
var moveRate = cameraHeight / 100.0;

if (flags.moveForward) {
    camera.moveForward(moveRate);
}
if (flags.moveBackward) {
    camera.moveBackward(moveRate);
}
if (flags.moveUp) {
    camera.moveUp(moveRate);
}
if (flags.moveDown) {
    camera.moveDown(moveRate);
}
if (flags.moveLeft) {
    camera.moveLeft(moveRate);
}
if (flags.moveRight) {
    camera.moveRight(moveRate);
}

moveForward , moveBackward ,moveUp, moveDown , moveLeft 和 moveRight 方法采用以米为单位的单个参数来移动照相机。照相机将在其上移动的距离 每次按键操作都会随着相机到椭圆表面的距离的变化而变化,相机越靠近表面,每次按键移动的速度就越慢。

完整的代码如下:

var viewer = new Cesium.Viewer('cesiumContainer');

var scene = viewer.scene;
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.onclick = function() {
    canvas.focus();
};
var ellipsoid = viewer.scene.globe.ellipsoid;

// disable the default event handlers
scene.screenSpaceCameraController.enableRotate = false;
scene.screenSpaceCameraController.enableTranslate = false;
scene.screenSpaceCameraController.enableZoom = false;
scene.screenSpaceCameraController.enableTilt = false;
scene.screenSpaceCameraController.enableLook = false;

var startMousePosition;
var mousePosition;
var flags = {
    looking : false,
    moveForward : false,
    moveBackward : false,
    moveUp : false,
    moveDown : false,
    moveLeft : false,
    moveRight : false
};

var handler = new Cesium.ScreenSpaceEventHandler(canvas);

handler.setInputAction(function(movement) {
    flags.looking = true;
    mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

handler.setInputAction(function(movement) {
    mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

handler.setInputAction(function(position) {
    flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

function getFlagForKeyCode(keyCode) {
    switch (keyCode) {
    case 'W'.charCodeAt(0):
        return 'moveForward';
    case 'S'.charCodeAt(0):
        return 'moveBackward';
    case 'Q'.charCodeAt(0):
        return 'moveUp';
    case 'E'.charCodeAt(0):
        return 'moveDown';
    case 'D'.charCodeAt(0):
        return 'moveRight';
    case 'A'.charCodeAt(0):
        return 'moveLeft';
    default:
        return undefined;
    }
}

document.addEventListener('keydown', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = true;
    }
}, false);

document.addEventListener('keyup', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = false;
    }
}, false);

viewer.clock.onTick.addEventListener(function(clock) {
    var camera = viewer.camera;

    if (flags.looking) {
        var width = canvas.clientWidth;
        var height = canvas.clientHeight;

        // Coordinate (0.0, 0.0) will be where the mouse was clicked.
        var x = (mousePosition.x - startMousePosition.x) / width;
        var y = -(mousePosition.y - startMousePosition.y) / height;

        var lookFactor = 0.05;
        camera.lookRight(x * lookFactor);
        camera.lookUp(y * lookFactor);
    }

    // Change movement speed based on the distance of the camera to the surface of the ellipsoid.
    var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
    var moveRate = cameraHeight / 100.0;

    if (flags.moveForward) {
        camera.moveForward(moveRate);
    }
    if (flags.moveBackward) {
        camera.moveBackward(moveRate);
    }
    if (flags.moveUp) {
        camera.moveUp(moveRate);
    }
    if (flags.moveDown) {
        camera.moveDown(moveRate);
    }
    if (flags.moveLeft) {
        camera.moveLeft(moveRate);
    }
    if (flags.moveRight) {
        camera.moveRight(moveRate);
    }
});

Camera

Camera 代表摄影机当前位置,方向,参考系和视锥的状态。 上面的摄像机矢量在每个帧中都是正交的。

move* 和 zoom* 功能沿其方向或给定的向量平移相机的位置。 方向保持固定。

look* 和 twist* 函数围绕方向,向上或向右向量旋转方向。 该职位保持固定。

rotate* 函数围绕给定矢量旋转位置和方向。

用于在给定范围或位置和目标的情况下设置摄像机位置和方向的功能。 例如:

var west = Cesium.Math.toRadians(-77.0);
var south = Cesium.Math.toRadians(38.0);
var east = Cesium.Math.toRadians(-72.0);
var north = Cesium.Math.toRadians(42.0);
var extent = new Cesium.Extent(west, south, east, north);
camera.viewExtent(extent, Cesium.Ellipsoid.WGS84);

用于从相机位置到像素创建光线的功能。 这对于选择很有用,例如:

// find intersection of the pixel picked and an ellipsoid
var ray = camera.getPickRay(mousePosition);
var intersection = Cesium.IntersectionTests.rayEllipsoid(ray, Cesium.Ellipsoid.WGS84);

Screen space camera controller

ScreenSpaceCameraController 将用户输入(例如鼠标和触摸)从窗口坐标转换为相机运动。 它包含用于启用和禁用不同类型的输入,修改惯量以及最小和最大缩放距离的属性。


Resources

查看Sandcastle中的相机示例:

  • Camera Tutorial - 本教程中的代码示例。
  • Camera - 可以飞到特定位置,查看范围并设置相机参考系的代码示例。

另外,请查阅参考文档:

Camera安卓源码-高通mm_camera架构剖析 主要涉及三方面: 1. Camera open 2. Camera preview 3. Camera capture1. Camera Open mm_camera&mm_camera_open() 首先,mm_camera层用一个结构体去表示从底层获取的camera对象,这个结构体叫做mm_camera_obj。 如下结构体所示,mm_camera对象包含了两个线程: 1. mm_ 阅读详情

相关推荐

高通 camera hal 流程

以高通 msm8998 平台为例介绍高通 camera hal。库文件名称:camera.msm8998.so源码目录:/hardware/qcom/camera/msm8998/QCamera2主要文件:QCamera2Hal.cpp 定义了 HAL_MODULE_INFO_SYMQCamera2Hal.cpp 中定义的 HAL_MODULE_INFO_SYM 初始化 camera_module_t 对象,

kk3087961的博客 4012

Cameraview-ex 项目常见问题解决方案

Cameraview-ex 项目常见问题解决方案 1. 项目基础介绍和主要编程语言 Cameraview-ex 是一个开源项目,旨在简化 Android 设备上相机功能的集成。该项目基于 Google 的 cameraview 库进行扩展,提供了更稳定和更多的特性。Cameraview-ex 使用了 Camera2 API(针对 API 21 及以上版本)以及 Camera1 API(针对 API...

gitblog_00223的博客 463

[Camera]RK_Camera_HAL

platform: RK3399 OS: Android 7.1 kernel:4.4 参考: 1. KrisFei https://blog.csdn.net/kris_fei/article/details/52451409 2. Kiazhu https://blog.csdn.net/kiazhu/article/details/84652749 3. https://source.and...

Letcos 1689

android 指纹拍照,Android:Keycode 添加新按键:指纹拍照

前言客户要求给 Camera 做一个 指纹拍照功能,也就是在Camera 界面,点击后置指纹模组时,Camera 能拍摄相片和视频。工作在处理指纹拍照时,就需要指纹模组厂商来协助处理,上层只需要做 KeyCode 获取指纹模组的点击事件;其二就是在 Camera 应用中添加相应的点击事件。这里以上层的 keycode 是286,底层的keycode是 252为例。添加 指纹keyEventGene...

weixin_39601511的博客 563

camera功能真的那么难用吗

Android开发工作过程中,经常需要用到camera相关能力,比如:人脸识别,ai识别,拍照预览,摄像头录制等等需求。都需要使用到camera,且需要拿到camera的预览数据。但是每次开发这块代码都比较繁琐,一大堆的接口(尤其是camera2),用错一个就容易出现意想不到的结果。所以这里我们将Android的camera做一次简单易用的封装,再也不用担心API用错了。

LVEfrist的博客 1379

android-Camera2Basic 解析

1.Android Camera2介绍 Android 5.0(API Level 21) 重新设计了 Camera,废弃了之前的 Camera,改用现在的 Camera2 API,在Camera2上引入了Session/Request的概念,使用的复杂度远超之前的 Camera。 1.1 Camera2主要类简介 CameraManager:摄像头管理类,用于检测,打开系统摄像头,可以通过g...

pvpheroszw的博客 3672

Android Camera了解一下

首发于公众号 Android Camera了解一下 Camera 演进简介 最近在项目中遇到 Camera相关的场景,之前对这块不是很了解,趁机补了一下盲区。Android Camera 相关也是生态碎片化较为严重的一块,Android FrameWorkt提供Camera API来实现拍照与屏幕录制的能力,目前Android有三类API Camera (为了便于区分 下面简称 Camera1) 此类是用于控制设备相机的旧版API,在Android5.0以下使用,现已Deprecated Cam..

Android茶话会 9658

Android Camera预览

简介 因工作原因要学习Android的Camera预览功能,这个DEMO有两个Activity,使用Camera库实现

haowenlai2008的博客 3482

Camera1、Camera2 API的使用

Camera1 使用流程: 检查相机权限(android.permission.CAMERA) Camera.getNumberOfCameras():获取相机硬件数量; Camera.getCameraInfo():获取指定相机信息; Camera.open():打开指定相机; camera.getParameters():获取相机参数并设置; camera.setPreviewTexture...

ikata 3687

Android Camera之 --- Camera API说明(一)

Android Camera API说明:

rony2012的专栏 6732

Android Camera原理之camera provider启动

1.camera provider进程介绍: cameraserver 736 1 274664 69564 binder_thread_read f3de10cc S android.hardware.camera.provider@2.4-service 其中的pid是736...

1476

Android Camera 五 Camera HAL v1

Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Client 链接到 HAL Android Camera 四 Camera HAL 分析 Android Camera 五 Camera HAL v1 Linux v4l2 一 应用层 Lin...

qq_38907791的博客 2601

cameraview-ex,简单的安卓摄像头集成,高级功能。.zip

这是谷歌cameraview库的扩展版本,具有更好的稳定性和更多的功能。

Android Camera原理之camera HAL底层数据结构与类总结

camera HAL层数据结构非常多,看代码的时候常常为了了解这些数据结构找半天,为了方便大家学习,特地总结了一些数据结构以及这些数据结构的位置: 1.hardware/libhardware/include/hardware/camera_common.h: 1.1 camera_info_t : camera_info typedef struct camera_info { int facing; int orientation; uint32_t device_ver

转载和创作优秀的博客 3402

Pro-EX 授权

普洛菲斯编程软件最新授权。专业的同行,你懂得。

proface编辑软件注册号

profce 人机界编辑软件授权 123中

Android camera: camera initialize

frameworks/base/core/java/android/app/SystemServiceRegistry.javaregisterService(Context.CAMERA_SERVICE, CameraManager.class, new CachedServiceFetcher<CameraManager>() { ...

u011279649的专栏 1063

CameraView记录良好的高级Android界面

作者natario1,代码CameraView。 介绍:一个记录良好的高级Android界面,可以轻松捕获图片和视频,解决所有常见问题和需求。

上一篇: 3D Models (3D 模型)
下一篇: 使用 geotools 生成 shapefile
高建伟-joe
博客等级 码龄6年 155粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高建伟-joe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值