title: SceneKit camera, how to compensate for euler rules (orientation) changes
body: <p>Maybe this is more of a math question, but I am hoping somebody can help me understand how I would compensate for changes to my camera's orientation.</p>
  
  <p>What I would like to do is to be able to move my camera around the scene using game-like controls. I have W S A D keys set up to move the camera forward, backward, left and right respectively. I do this by changing the values of the camera node's position vector.  I also have the right left up and down arrow keys mapped to turning and tilting the camera. I do this by adjusting the camera node's euler rules (pitch and yaw). </p>
  
  <p>Things work well until I turn the camera with the right and left arrows. Pressing W after this moves the camera in the direction it was facing before I applied yaw to it. The behavior makes sense to me, but I cannot figure out what I need to do to my position-vector tweaking to compensate for the yaw I've applied. </p>
  
  <p>Do I need to multiply my position vector somehow by new transform?  Or better yet is there some other property like the pivot that I can change, so that I can keep my position code the same?</p>
  
  <p>Thanks for any pointers. </p>
  
  <hr>
  
  <p>Update here is the code I'm working with so far:</p>
  
  <pre><code>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
      }
  }
  </code></pre>
  
  <p>I have two timers, one that updates the cameras position, and the other that updates its orientation. </p>
  
  <p>The part I'm stuck on is that I know my new transform (old position plus the move increment from A S D W), and I know the camera's rotation, but I don't know how to combine those two into my true new transform. Transform is a SCNMatrix4, and rotation is a SCNVector4.</p>
  
  <hr>
  
  <p>Update 2</p>
  
  <p>Here is a reworked version of the code. I switched to working with the transform instead. I still cannot find the right manipulation to account for the rotation however. </p>
  
  <pre><code>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)
  }
  </code></pre>
  
  <hr>
  
  <p>Last Update</p>
  
  <p>Thanks for the suggestions. Here is the implementation that is working for me</p>
  
  <p>I needed this objc helper, as some of these functions to not seem to be available in Swift:</p>
  
  <pre><code>@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
  </code></pre>
  
  <p>And the implementation</p>
  
  <pre><code>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
  }
  </code></pre>