通过OpenGL ES在iOS平台实践增强现实(二)
上一篇讲到如何使用OpenGL ES绘制一个3D场景,这一篇我们会配合使用iOS提供的CoreMotion框架把虚拟世界中的摄像机的位置朝向和设备实际的位置朝向绑定起来。本文还对防抖做了处理。
首先说明几个容易混淆的问题:
1. OpenGL ES的摄像机,位置固定在世界坐标系原点,Up方向和世界坐标系y轴重合,Right方向和世界坐标系x轴重合,Look方向和世界坐标系负z轴重合
2. 为了抽象一个可以缩放,旋转,移动的摄像机,我们可以在OpenGL ES的的矩阵操作中通过左乘这个摄像机的变换矩阵的逆矩阵来实现
3. CoreMotion框架中,可以从API中获取代表朝向的欧拉角或者四元数数据,因为欧拉角存在万向节死锁的问题,所以我们取四元数
4. 注意CoreMotion的初始朝向问题,本文采用CMAttitudeReferenceFrameXMagneticNorthZVertical(Right方向和南重合,Up方向指向垂直上方)作为初始朝向
- 初始化CoreMotion的代码
// 启用陀螺仪
motionManager = [[CMMotionManager alloc]init];
if (motionManager.deviceMotionAvailable) {
motionManager.deviceMotionUpdateInterval = motionInterval; [motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXMagneticNorthZVertical toQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
if(motion){
CMRotationRate rotationRate = motion.rotationRate;
double rotationX = rotationRate.x;
double rotationY = rotationRate.y;
double rotationZ = rotationRate.z; double value = rotationX * rotationX + rotationY * rotationY + rotationZ * rotationZ; // 防抖处理,阀值以下的朝向改变将被忽略
if (value > 0.01) {
CMAttitude *attitude = motion.attitude;
t = 0.0f;
s = 0.0f; // 从当前朝向以固定加速度像目标朝向进行四元数插值
srcQuaternion = curQuaternion;
desQuaternion = GLKQuaternionNormalize(GLKQuaternionMake(attitude.quaternion.x, attitude.quaternion.y, attitude.quaternion.z, -attitude.quaternion.w));
}
}
}]; }
- 为了防抖处理,需要将当前朝向平滑过渡到目标朝向
if (s <= ) {
t += 0.05;
// 以固定初速度和加速度对原朝向和目标朝向进行插值
s = v0 *t + a * t * t / ;
curQuaternion = GLKQuaternionNormalize(GLKQuaternionSlerp(srcQuaternion, desQuaternion, s));
}
- 上文已经提到了虚拟摄像机的初始朝向,为了将设备的实际朝向和虚拟摄像机的朝向绑定到一起,我们先将摄像机的坐标轴转动到与CMAttitudeReferenceFrameXMagneticNorthZVertical代表的坐标轴重合,再用上文得到的curQuaternion转动到设备的实际朝向,最后求上述转动的逆即可
- 摄像机初始朝向到设备初始朝向的旋转矩阵
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] =1.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 1.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 1.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 0.0;
_worldTrasform[] = 1.0;
- 将四元数转换为矩阵
GLfloat x = curQuaternion.x;
GLfloat y = curQuaternion.y;
GLfloat z = curQuaternion.z;
GLfloat w = curQuaternion.w;
_worldTrasform[] = -*y*y-*z*z;
_worldTrasform[] = *x*y-*w*z;
_worldTrasform[] = *x*z+*w*y;
_worldTrasform[] = 0.0;
_worldTrasform[] = *x*y+*w*z;
_worldTrasform[] = -*x*-*z*z;
_worldTrasform[] = *y*z-*w*x;
_worldTrasform[] = 0.0;
_worldTrasform[] = *x*z-*w*y;
_worldTrasform[] = *y*z+*w*z;
_worldTrasform[] = -*x*x-*y*y;
_worldTrasform[] = 0.0;
_worldTrasform[] = _position.x;
_worldTrasform[] = _position.y;
_worldTrasform[] = _position.z;
_worldTrasform[] = 1.0;
- 将上面两个矩阵顺次相乘并根据正交矩阵的性质求逆矩阵并左乘当前带渲染实体的世界变换矩阵
glMatrixMode(GL_MODELVIEW_MATRIX);
glLoadIdentity();
glLoadMatrixf(cameraMatrix); // 将模型矩阵设置为摄像机世界矩阵的逆矩阵
glMultMatrixf(transform); // 右乘模型的世界矩阵
- 摄像机初始朝向到设备初始朝向的旋转矩阵
这样,我们就把虚拟摄像机的朝向和设备的朝向绑定在了一起。
通过OpenGL ES在iOS平台实践增强现实(二)的更多相关文章
- 通过OpenGL ES在iOS平台实践增强现实
http://www.cnblogs.com/elvisyzhao/p/3398250.html 本文采用OpenGL ES 1固定渲染管线实现,目标为在设备拍摄到的现实世界中,绘制世界坐标轴,并根据 ...
- 通过OpenGL ES在iOS平台实践增强现实(一)
http://ios.9tech.cn/news/2013/1108/38495.html 1.本文采用OpenGL ES 1固定渲染管线实现,目标为在设备拍摄到的现实世界中,绘制世界坐标轴,并根据设 ...
- OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型
OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...
- [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之二:lib3ds加载模型
[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之二:lib3ds加载模型 作者:u0u0 - iTyran 在上一节中,我们分析了OBJ格式.OBJ格式优点是文本形式,可读 ...
- WebGL 在 OpenGL ES 指令 iOS 在 C 分歧版指令分析
WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途 ...
- OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)
简介 Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同. 首先,uniform是全局的(Global).全局意味着uniform变量必须在每个着 ...
- OpenGL ES应用开发实践指南:iOS卷
<OpenGL ES应用开发实践指南:iOS卷> 基本信息 原书名:Learning OpenGL ES for iOS:A Hands-On Guide to Modern 3D Gra ...
- iOS 中OpenGL ES 优化 笔记 1
1,避免同步和Flushing操作 OpenGL ES的命令执行通常是在command buffer中积累一定量的命令后,再做批处理执行,这样效率会更高:但是一些OpenGL ES命令必须flush ...
- (转)规划从 OpenGL ES 2.0 到 Direct3D 的移植
如果你移植 iOS 或 Android 平台中的游戏,那么你可能需要在 OpenGL ES 2.0 方面进行大量投资.如果你准备将你的图形管道代码库移动到 Direct3D 11 和 Windows ...
随机推荐
- iOSAES加密的实现
+(NSData *)AES256ParmEncryptWithKey:(NSString *)key Encrypttext:(NSData *)text //加密 { char keyPtr[k ...
- js函数式编程(一)-纯函数
我将写的第一个主题是js的函数式编程,这一系列都是mostly adequate guide这本书的读书总结.原书在gitbook上,有中文版.由于原作者性格活泼,书中夹杂很多俚语,并且行文洒脱.中文 ...
- 简单的C++ DLL注入
今天呢,我们来讨论一下用C++实现DLL注入的简单方法. 环境: Visual Studio 2015及以上 Windows 7及以上 入门需要了解的: DLL是什么:DLL_360百科 DLL是Dy ...
- 【启发式拆分】bzoj4059: [Cerc2012]Non-boring sequences
这个做法名字是从武爷爷那里看到的…… Description 我们害怕把这道题题面搞得太无聊了,所以我们决定让这题超短.一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,即每个子 ...
- Linux菜鸟起飞之路【十】进程管理
一.基本概念 进程:程序的一次动态执行 守护进程:在后台运行并提供系统服务的进程 僵尸进程:完成了生命周期但却依然留在进程表中的进程,我们称之为 “僵尸进程” 父进程:指已创建一个或多个子进程的进程. ...
- 多线程辅助类之CountDownLatch(三)
CountDownLatch信号灯是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.它可以实现多线程的同步互斥功能,和wait和notify方法实现功能类似,具体 ...
- ubuntu 16.04下如何打造 sublime python编程环境
一.安装python3 ubuntu自身是安装python2的,例如在ubuntu 16.04中安装的就是python2.7.但我想在python3的环境下进行开发所以就要安装python3. ...
- drf分页器
drf分页器 1.第一种分页: 类似于django中的分页 2.第二种分页: 偏移分页 3.第三种分页: 加密分页(查询速度快) 无法跳跃 基本参数 from rest_framework.pagin ...
- 我的Python分析成长之路7
类 一.编程范式: 1.函数式编程 def 2.面向过程编程 (Procedural Programming) 基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个 ...
- Python头脑风暴4
IT是全国平均薪资最高的行业,2017年全国最高,人均13点4万每年. 但技术固然好,创业拼的还是世界观下的创意. 蘑菇街,并夕夕,TikTok,头条,哪个不是创意用IT技术的现实化?? 未来,大平台 ...