首页 文章

继续旋转场景节点,直到设备返回到起始位置

提问于
浏览
0

在尝试使用场景工具包时,我正在使用 self.motionManager.deviceMotion.attitude.quaternion 在3D场景中旋转场景节点(相机) . 让我们说用户启动应用程序并且设备以某种方式倾斜,因此这个起始方向应该被计为休息点,并且在这个位置时不应该发生旋转 . 当用户倾斜设备(向左< - >向右和/或向上< - >向下)时,它应逐渐旋转,直到用户将设备放回到开始/静止方向,此时不会发生旋转 . According to this answer I know how to filter the noise and random jiggling

以下几点很重要:

  • 有一个没有旋转的静止方向
    当设备倾斜时

  • 然后逐渐旋转

  • 通过达到以上几点,用户无需翻转设备即可获得完整的旋转:-)

我不知道如何实现这一目标 . 任何帮助是极大的赞赏 .

edit :添加一些试图实现rickster答案的代码

我必须在 startDeviceMotionUpdatesToQueue:withHandler: 得到滚动,偏航,俯仰值,否则它全部为零

-(void) awakeFromNib
{
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 1.0/60.0;

[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
    if (error == nil)
    {
        if (firstValue == NO)
        {
           firstValue = YES;
           yaw = self.motionManager.deviceMotion.attitude.yaw;
           roll = self.motionManager.deviceMotion.attitude.roll;
           pitch = self.motionManager.deviceMotion.attitude.pitch;
        }
    }
}];
}

我试图首先在x轴上旋转5度,原因很简单:

- (void)renderer:(id<SCNSceneRenderer>)aRenderer didSimulatePhysicsAtTime:(NSTimeInterval)time
{
    currentYaw = self.motionManager.deviceMotion.attitude.yaw;
    currentRoll = self.motionManager.deviceMotion.attitude.roll;
    currentPitch = self.motionManager.deviceMotion.attitude.pitch;
    SCNVector4 q =_cameraNode.presentationNode.rotation;
  float phi = atan((2*(q.x*q.y + q.z*q.w))/(1-2*(pow(q.y,2)*pow(q.z,2))));
  if (currentRoll > 0)
  {
    [_cameraNode runAction:[SCNAction rotateToAxisAngle:SCNVector4Make(1, 0, 0, ( phi + DEGREES_TO_RADIANS(5))) duration:1]];
  }
  else if(currentRoll < 0 )
  {
    [_cameraNode runAction:[SCNAction rotateToAxisAngle:SCNVector4Make(1, 0, 0, (phi - DEGREES_TO_RADIANS(5))) duration:1]];
  }

}

变量的调试输出是:

debug:q =(x = 0.999998092,y = 0,z = 0,w = -0.0872662216)phi = 0 currentRoll = -1.1897298305515105

它实际上根本不旋转 . phi值看起来不太好 . 我究竟做错了什么?

旁注:如何一次对所有轴进行旋转?乘以四元数oldRotation与x然后y然后z?这是正确的顺序吗?

1 回答

  • 2

    要跟踪静止方向,您需要跟踪您采样的第一个 CMAttitude . 然后,您可以使用 multiplyByInverseOfAttitude: 来获取每次采样时该态度与当前态度之间的差异 . (如果由于过滤而已经使用了四元数,则可以使用 GLKQuaternionInvertGLKQuaternionMultiply 执行等效操作 . )

    要进行你所说的增量旋转,最简单的方法是使用欧拉角 - 相对于你刚才发现的态度差异,这样一卷零意味着用户开始的中性方向没有变化(无论如何)那个方向是绝对的术语) . 然后,当在给定时间步长期间滚动角度为正(例如,在 SCNSceneRendererDelegate 更新方法中)时,您可以增加相机节点的滚动,反之亦然 .

    事实上,如果你只是在态度的滚动大于5度时滚动 . 在这种情况下,您可以从 CMAttitude (此答案中较早的差异态度)获得欧拉角,而不必担心自己从四元数中提取欧拉角(not that it's all that hard) .

相关问题