SceneKit相机,如何补偿欧拉规则(方向)的变化

也许这是一个math问题,但我希望有人能帮助我理解我将如何弥补我的相机的方向的变化。

我想要做的是能够使用类似游戏的控件来移动我的相机。 我有WSAD键设置为分别向前,向后,向左和向右移动相机。 我通过改变摄像机节点的位置vector的值来做到这一点。 我也有左右上下箭头键映射到转动和倾斜相机。 我通过调整摄像机节点的欧拉规则(俯仰和偏航)来做到这一点。

事情运作良好,直到我用左右箭头打开相机。 在按下W之后,将照相机朝向它所面向的方向移动,然后向其施加偏航。 这种行为对我来说是有道理的,但我无法弄清楚为了弥补我所应用的偏航,我需要对位置vector进行调整。

我是否需要通过新变换以某种方式乘以我的位置向量? 或者更好的是,有一些其他的财产,如枢轴,我可以改变,这样我可以保持我的位置代码相同?

感谢任何指针。


这里更新的是我正在使用的代码:

public func displayTimerDidFire(timer: MyCustomDisplayTimer!) { if timer === cameraMoveTimer { var cameraTransform = cameraNode.transform var x = CGFloat(0.0) var y = CGFloat(0.0) var z = CGFloat(0.0) var step : CGFloat = 10.0 if moveUpKeyDown { y += step } if moveDownKeyDown { y -= step } if moveLeftKeyDown { x -= step } if moveRightKeyDown { x += step } if moveForwardKeyDown { z -= step } if moveBackwardKeyDown { z += step } cameraTransform = SCNMatrix4Translate(cameraTransform, x, y, z) cameraNode.transform = cameraTransform } else if timer === cameraTiltTimer { var angles = cameraNode.eulerAngles var stepAngle : CGFloat = CGFloat(M_PI_2 / 90.0) if turnLeftKeyDown { angles.y += stepAngle } if turnRightKeyDown { angles.y -= stepAngle } if tiltForwardKeyDown { angles.x -= stepAngle } if tiltBackwardKeyDown { angles.x += stepAngle } cameraNode.eulerAngles = angles } } 

我有两个计时器,一个更新摄像机位置,另一个更新其方向。

我坚持的部分是我知道我的新变换(旧的位置加上从ASDW的移动增量),我知道相机的旋转,但我不知道如何将这两个变成我真正的新变换。 变换是一个SCNMatrix4,旋转是一个SCNVector4。


更新2

这是代码的重做版本。 我转而使用转换工作。 但我仍然无法find正确的操作来解释旋转。

 public func displayTimerDidFire(timer: MyDisplayTimer!) { var cameraTransform = cameraNode.transform var x = CGFloat(0.0) var y = CGFloat(0.0) var z = CGFloat(0.0) var step : CGFloat = 10.0 if moveUpKeyDown { y += step } if moveDownKeyDown { y -= step } if moveLeftKeyDown { x -= step } if moveRightKeyDown { x += step } if moveForwardKeyDown { z -= step } if moveBackwardKeyDown { z += step } cameraTransform = SCNMatrix4Translate(cameraTransform, x, y, z) // Do something with the transform to compensate for rotation.. // ??? cameraNode.transform = cameraTransform var angles = cameraNode.eulerAngles var stepAngle : CGFloat = CGFloat(M_PI_2 / 90.0) if turnLeftKeyDown { angles.y += stepAngle } if turnRightKeyDown { angles.y -= stepAngle } if tiltForwardKeyDown { angles.x -= stepAngle } if tiltBackwardKeyDown { angles.x += stepAngle } cameraNode.eulerAngles = angles // printNode(cameraNode) } 

最后更新

感谢您的build议。 这是为我工作的实现

我需要这个objc帮助器,因为有些函数看起来在Swift中不可用:

 @implementation MySceneKitUtils + (SCNVector3)position:(SCNVector3)position multipliedByRotation:(SCNVector4)rotation { if (rotation.w == 0) { return position; } GLKVector3 gPosition = SCNVector3ToGLKVector3(position); GLKMatrix4 gRotation = GLKMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z); GLKVector3 r = GLKMatrix4MultiplyVector3(gRotation, gPosition); return SCNVector3FromGLKVector3(r); } @end 

并执行

 public func displayTimerDidFire(timer: MyDisplayTimer!) { var x = CGFloat(0.0) var y = CGFloat(0.0) var z = CGFloat(0.0) var step : CGFloat = 10.0 if moveUpKeyDown { y += step } if moveDownKeyDown { y -= step } if moveLeftKeyDown { x -= step } if moveRightKeyDown { x += step } if moveForwardKeyDown { z -= step } if moveBackwardKeyDown { z += step } var cameraTransform = cameraNode.transform var rotation = cameraNode.rotation var rotatedPosition = MySceneKitUtils.position(SCNVector3Make(x, y, z), multipliedByRotation: cameraNode.rotation) cameraTransform = SCNMatrix4Translate(cameraTransform, rotatedPosition.x, rotatedPosition.y, rotatedPosition.z) cameraNode.transform = cameraTransform // The rotation cameraTransform = cameraNode.transform var stepAngle = CGFloat(0.05) if turnLeftKeyDown { cameraTransform = SCNMatrix4Rotate(cameraTransform, stepAngle, 0.0, 1.0, 0.0); } if turnRightKeyDown { cameraTransform = SCNMatrix4Rotate(cameraTransform, -stepAngle, 0.0, 1.0, 0.0); } if tiltForwardKeyDown { cameraTransform = SCNMatrix4Rotate(cameraTransform, stepAngle, 1.0, 0.0, 0.0); } if tiltBackwardKeyDown { cameraTransform = SCNMatrix4Rotate(cameraTransform, -stepAngle, 1.0, 0.0, 0.0); } cameraNode.transform = cameraTransform } 

如果t是从WSAD键计算出来的翻译,那么你不应该简单地添加它( node.position += t ),而是首先应用一个旋转,然后添加它: node.position += node.rotation * t

我的答案是添加到上面的答案。 我用这个捏缩放。

  //Creating unit vector let unitVector = GLKVector4Make(0, 0, -1, 1) //converting tranform matrix let glktranform = SCNMatrix4ToGLKMatrix4(cameraNode.transform) //multiply unit vector with transform matrix let rotatedMatrix = GLKMatrix4MultiplyVector4(glktranform, unitVector) //scale it with translation you compute from the WSAD key let finalScaledVector = GLKVector4MultiplyScalar(rotatedMatrix, translation) cameraNode.position.x = finalScaledVector.x cameraNode.position.y = finalScaledVector.y cameraNode.position.z = finalScaledVector.z 

希望这有助于。