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

时间:2014-12-28 10:45:13

标签: ios rotation quaternions core-motion scenekit

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

以下几点非常重要:

  1. 有一个没有旋转的静止方向
  2. 当设备倾斜时,然后逐渐旋转
  3. 通过实现以上几点,用户无需翻转设备即可完成旋转: - )
  4. 我不知道如何实现这一目标。非常感谢任何帮助。

    编辑:添加一些试图实现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 个答案:

答案 0 :(得分:2)

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

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

事实上,如果您以这种方式进行增量轮换,则可能不需要过滤步骤(来自我链接到的其他答案)。相反,你可以通过原始态度输入和阈值来逃避。例如,仅在姿态的滚动大于5度时增加节点的滚动。在这种情况下,您可以从CMAttitude(此答案中较早的差异态度)获得欧拉角,而不必担心自己从四元数中提取欧拉角(not that it's all that hard)。 / p>