經過大量的研究和測試。我最終使用GLKit進行計算,因爲它也爲我節省了很多麻煩。任何碰巧遇到這個問題的人都可以把它留在這裏。
首先,我使用CMAttitudeReferenceFrameXTrueNorthZVertical啓動了CMMotionManager設備運動更新。
self.hasMotion = NO;
CMMotionManager *cmmotionManager = [[CMMotionManager alloc] init];
[cmmotionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical
toQueue:[[NSOperationQueue alloc] init]
withHandler:^ (CMDeviceMotion *motion, NSError *error) {
self.hasMotion = YES;
}];
self.motionManager = cmmotionManager;
從一些代碼,我發現在網絡上使用CoreMotion旋轉繪製一個OpenGL世界,並將其與正從屏幕的一個點到3D世界搭配:
float aspect = fabsf(self.view.bounds.size.width/self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), aspect, 0.1f, 100.0f);
CMRotationMatrix r = self.motionManager.deviceMotion.attitude.rotationMatrix;
GLKMatrix4 camFromIMU = GLKMatrix4Make(r.m11, r.m12, r.m13, 0,
r.m21, r.m22, r.m23, 0,
r.m31, r.m32, r.m33, 0,
0, 0, 0, 1);
GLKMatrix4 viewFromCam = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, 0);
GLKMatrix4 imuFromModel = GLKMatrix4Identity;
GLKMatrix4 viewModel = GLKMatrix4Multiply(imuFromModel, GLKMatrix4Multiply(camFromIMU, viewFromCam));
bool isInvertible;
GLKMatrix4 modelView = GLKMatrix4Invert(viewModel, &isInvertible);
int viewport[4];
viewport[0] = 0.0f;
viewport[1] = 0.0f;
viewport[2] = self.view.frame.size.width;
viewport[3] = self.view.frame.size.height;
bool success;
//assume center of the view
GLKVector3 vector3 = GLKVector3Make(self.view.frame.size.width/2, self.view.frame.size.height/2, 1.0);
GLKVector3 calculatedPoint = GLKMathUnproject(vector3, modelView, projectionMatrix, viewport, &success);
if(success)
{
//CMAttitudeReferenceFrameXTrueNorthZVertical always point x to true north
//with that, -y become east in 3D world
float angleInRadian = atan2f(-calculatedPoint.y, calculatedPoint.x);
return angleInRadian;
}
謝謝user2629068,通過這種方式一切都按預期工作。 – kokemomuke
太棒了!在網絡上有大量的解決方案,試圖解決這個問題,但這是唯一一個工作正常:) –
感謝這個代碼,很好地支持我的相機的輕微運動!不過,我的標題精確度大概是10度。有沒有辦法將這個精度降低到一個更低的值(從而改善標題的正確性)? –