gpt4 book ai didi

objective-c - SceneKit – 映射物理 360 度旋转

转载 作者:太空狗 更新时间:2023-10-30 03:15:07 26 4
gpt4 key购买 nike

我很难将设备运动(传感器融合)映射到 SceneKit 节点旋转。问题的前提如下,

我有球体,相机位于球体内部,使球体的几何中心与相机节点的中心重合。我想要实现的是,当我围绕一个点进行物理旋转时,运动也需要准确地映射到相机上。

具体实现如下:

我有一个节点,以球体作为几何图形,是根节点的子节点。我正在使用传感器融合来获取姿态四元数,然后将它们转换为欧拉角。代码是:

- (SCNVector3)eulerAnglesFromCMQuaternion:(CMQuaternion) {
GLKQuaternion gq1 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(90), 1, 0, 0);
GLKQuaternion gq2 = GLKQuaternionMake(q.x, q.y, q.z, q.w);
GLKQuaternion qp = GLKQuaternionMultiply(gq1, gq2);
CMQuaternion rq = {.x = qp.x, .y = qp.y, .z = qp.z, .w = qp.w};
CGFloat roll = atan2(-rq.x*rq.z - rq.w*rq.y, .5 - rq.y*rq.y - rq.z*rq.z);
CGFloat pitch = asin(-2*(rq.y*rq.z + rq.w*rq.x));
CGFloat yaw = atan2(rq.x*rq.y - rq.w*rq.z, .5 - rq.x*rq.x - rq.z*rq.z);
return SCNVector3Make(roll, pitch, yaw);
}

转换方程式来自3D Math Primer for Graphics and Game Development .以前看书作为引用,没看过。但绝对在我的阅读 list 上。

现在要模拟 SceneKit 中的物理旋转,我正在旋转包含 SCNCamera 的节点。这是 rootNode 的子节点。我正在使用 .rotation属性(property)做同样的事情。这里要注意的一件事是现在我的设备运动更新线程看起来像这样

[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryCorrectedZVertical toQueue:mq withHandler:^(CMDeviceMotion *motion, NSError *error) {
CMAttitude *currentAttitude = motion.attitude;
[SCNTransaction begin];
[SCNTransaction setDisableActions:YES];
SCNVector3 v = [self eulerAnglesFromCMQuaternion:currentAttitude.quaternion];
self.cameraNode.eulerAngles = SCNVector3Make( v.y, -v.x, 0); //SCNVector3Make(roll, yaw, pitch)
[SCNTransaction commit];
}];

这里需要注意的是设备和 SceneKit 节点的欧拉角不同。链接对其进行了解释。

SceneKit Euler Angles

CMAttitude Euler Angles

在我的理解中,两者之间的映射是这样的。

[Image]

现在我面临的问题是,在我围绕一个点进行物理旋转之前,相机的 360 度旋转已经结束。我正试图通过下图进行预测。

[Image2]

我怀疑四元数 -> 欧拉角转换是导致错误的原因,四元数数学现在已经超出了我的理解范围。

我希望我已经提供了所有信息,如果需要更多信息,我很乐意补充。

最佳答案

感谢您对问题的描述和解决方案的开始!我很确定这不能用欧拉角来完成,因为 gimbal lock (失去 1 个自由度)。

有效的解决方案是获取姿态并使用四元数设置相机的方向:

[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryCorrectedZVertical toQueue:myQueue withHandler:^(CMDeviceMotion *motion, NSError *error) {
CMAttitude *currentAttitude = motion.attitude;
[SCNTransaction begin];
[SCNTransaction setDisableActions:YES];

SCNQuaternion quaternion = [self orientationFromCMQuaternion:currentAttitude.quaternion];
_cameraNode.orientation = quaternion;

[SCNTransaction commit];
}];
- (SCNQuaternion)orientationFromCMQuaternion:(CMQuaternion)q
{
GLKQuaternion gq1 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-90), 1, 0, 0); // add a rotation of the pitch 90 degrees
GLKQuaternion gq2 = GLKQuaternionMake(q.x, q.y, q.z, q.w); // the current orientation
GLKQuaternion qp = GLKQuaternionMultiply(gq1, gq2); // get the "new" orientation
CMQuaternion rq = {.x = qp.x, .y = qp.y, .z = qp.z, .w = qp.w};

return SCNVector4Make(rq.x, rq.y, rq.z, rq.w);
}

关于objective-c - SceneKit – 映射物理 360 度旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25282543/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com