上一篇讲到如何使用OpenGL ES绘制一个3D场景,这一篇我们会配合使用iOS提供的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 <= 1) { t += 0.05; // 以固定初速度和加速度对原朝向和目标朝向进行插值 s = v0 *t + a * t * t / 2; curQuaternion = GLKQuaternionNormalize(GLKQuaternionSlerp(srcQuaternion, desQuaternion, s)); }
_worldTrasform[0] = 0.0; _worldTrasform[1] = 0.0; _worldTrasform[2] =1.0; _worldTrasform[3] = 0.0; _worldTrasform[4] = 1.0; _worldTrasform[5] = 0.0; _worldTrasform[6] = 0.0; _worldTrasform[7] = 0.0; _worldTrasform[8] = 0.0; _worldTrasform[9] = 1.0; _worldTrasform[10] = 0.0; _worldTrasform[11] = 0.0; _worldTrasform[12] = 0.0; _worldTrasform[13] = 0.0; _worldTrasform[14] = 0.0; _worldTrasform[15] = 1.0;
GLfloat x = curQuaternion.x; GLfloat y = curQuaternion.y; GLfloat z = curQuaternion.z; GLfloat w = curQuaternion.w; _worldTrasform[0] = 1-2*y*y-2*z*z; _worldTrasform[1] = 2*x*y-2*w*z; _worldTrasform[2] = 2*x*z+2*w*y; _worldTrasform[3] = 0.0; _worldTrasform[4] = 2*x*y+2*w*z; _worldTrasform[5] = 1-2*x*2-2*z*z; _worldTrasform[6] = 2*y*z-2*w*x; _worldTrasform[7] = 0.0; _worldTrasform[8] = 2*x*z-2*w*y; _worldTrasform[9] = 2*y*z+2*w*z; _worldTrasform[10] = 1-2*x*x-2*y*y; _worldTrasform[11] = 0.0; _worldTrasform[12] = _position.x; _worldTrasform[13] = _position.y; _worldTrasform[14] = _position.z; _worldTrasform[15] = 1.0;
glMatrixMode(GL_MODELVIEW_MATRIX); glLoadIdentity(); glLoadMatrixf(cameraMatrix); // 将模型矩阵设置为摄像机世界矩阵的逆矩阵 glMultMatrixf(transform); // 右乘模型的世界矩阵
这样,我们就把虚拟摄像机的朝向和设备的朝向绑定在了一起。