在pointOfView获得ARK的Y旋转
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在pointOfView获得ARK的Y旋转相关的知识,希望对你有一定的参考价值。
我试图在ARKit场景(0 - 360度)中获得视角的真实生活角度。我正在使用来自观点的SCNNode的欧拉角。
print("(pointOfView.eulerAngles.y.radiansToDegrees)")
问题是,当向北看时,我得到的结果为0,当向南看时,我也得到0.当看NE时,我得到-45度,当看SE时,我也得到-45度。似乎SCNNode无法确定南北之间,只能介于西方和东方之间。有什么建议?
我通常需要在我的ARKit现实世界场景中实现雷达视图。预期的行为是北:0,东:90,南:180,西:270。
提前致谢!
我刚刚开始研究类似的情况。在我称之为“标题”之后你是什么,这不像你想象的那样容易定义。
快速背景:仅供参考,有两种旋转,“欧拉”,它们相对于现实世界空间而言,在“极端”极端情况下遭受了他们所谓的万向锁。然后是相对于设备轴的旋转角度,保持在ARCamera
的变换属性中。
为了说明差异,euler.y
总是意味着设备面向的方式(除非它是扁平的,在这种情况下,万向节锁将其弄脏,因此我们的问题),而变换y
总是意味着围绕垂直轴旋转通过电话(其中,只是为了让事情更加混乱,基于ARKit中的设备持有景观)。
(旁注:如果你习惯了CoreMotion,你可能已经注意到在ARKit中,当设备保持平坦时会发生万向节锁定,而在CM中它是直立的)。
那么,无论设备是扁平还是直立,我们如何获得“标题”?下面的解决方案(抱歉,它的目标是c!)执行以下操作:
- 取两个法线向量,一个沿着手机的Z轴(从屏幕直接出来)和一个伸出手机底部的向量,我称之为-Y轴(尽管它实际上是+ X轴,当保持风景)。
- 通过设备的变换(不是Euler)旋转矢量,投影到XZ平面上,并获得Z轴的投影矢量角度。
- 当手机处于直立状态时,Z Normal将是完美的标题,但是当手机是平的时,Y标准是正常使用的。在两者之间,我们将根据手机的“倾斜”(即
euler.x
)“交叉淡化”。 - 一个小问题是,当用户将手机稍微向下压过平面时,由Z Normal给出的标题翻转。我们并不是真的想要这个(更多来自用户体验的视角而不是数学视角)所以让我们检测到这种“向下倾斜”并在发生时将
zHeading
翻转180˚。
无论设备方向如何,最终结果都是一致且平滑的heading
。当设备在肖像和风景之间移动时,它甚至可以工作...... huzzah!
// Create a Quaternion representing the devices curent rotation (NOT the same as the euler angles!)
GLKMatrix3 deviceRotM = GLKMatrix4GetMatrix3(SCNMatrix4ToGLKMatrix4(SCNMatrix4FromMat4(camera.transform)));
GLKQuaternion Q = GLKQuaternionMakeWithMatrix3(deviceRotM);
// We want to use the phone's Z normal (in the phone's reference frame) projected onto XZ to get the angle when the phone is upright BUT the Y normal when it's horizontal. We'll crossfade between the two based on the phone tilt (euler x)...
GLKVector3 phoneZNormal = GLKQuaternionRotateVector3(Q, GLKVector3Make(0, 0, 1));
GLKVector3 phoneYNormal = GLKQuaternionRotateVector3(Q, GLKVector3Make(1, 0, 0)); // why 1,0,0? Rotation=(0,0,0) is when the phone is landscape and upright. We want the vector that will point to +Z when the phone is portrait and flat
float zHeading = atan2f(phoneZNormal.x, phoneZNormal.z);
float yHeading = atan2f(phoneYNormal.x, phoneYNormal.z);
// Flip the zHeading if phone is tilting down, ie. the normal pointing down the device suddenly has a +y component
BOOL isDownTilt = phoneYNormal.y > 0;
if (isDownTilt) {
zHeading = zHeading + M_PI;
if (zHeading > M_PI) {
zHeading -= 2 * M_PI;
}
}
float a = fabs(camera.eulerAngles.x / M_PI_2);
float heading = a * yHeading + (1 - a) * zHeading;
NSLog(@"euler: %3.1f˚ %3.1f˚ %3.1f˚ zHeading=%3.1f˚ yHeading=%3.1f˚ heading=%3.1f˚ a=%.2f status:%li:%li zNorm=(%3.2f, %3.2f, %3.2f) yNorm=(%3.2f, %3.2f, %3.2f)", GLKMathRadiansToDegrees(camera.eulerAngles.x), GLKMathRadiansToDegrees(camera.eulerAngles.y), GLKMathRadiansToDegrees(camera.eulerAngles.z), GLKMathRadiansToDegrees(zHeading), GLKMathRadiansToDegrees(yHeading), GLKMathRadiansToDegrees(heading), a, camera.trackingState, camera.trackingStateReason, phoneZNormal.x, phoneZNormal.y, phoneZNormal.z, phoneYNormal.x, phoneYNormal.y, phoneYNormal.z);
以上是关于在pointOfView获得ARK的Y旋转的主要内容,如果未能解决你的问题,请参考以下文章