With SceneKit, I see that a node, to which a camera is attached, has a eulerAngles (SCNVector3 of radian angles) and orientation (SCNQuaternion)
My cameraNode is at 0,0,0 and can change its orientation at any moment.
I need to do hitTestWithSegmentFromPoint... toPoint...
fromPoint is always known.
But I need to project, based on camera orientation a far away point that lies in the line of the camera.
My mind hasn't grabbed quaternions properly yet, and I'm not getting anywhere based on eulerAngles.
Using some linear algebra
func findNextPoint(p0: SCNVector3, direction: SCNVector3) -> SCNVector3{
var x = Float()
var y = Float()
var z = Float()
let t = 100 as Float
x = p0.x + t * direction.x
y = p0.y + t * direction.y
z = p0.z + t * direction.z
let result = SCNVector3Make(x, y, z)
return result
}
This uses p0 as a starting point to, then, find the next point you want on a given direction. t is the length of the vector, or the distance you want to travel from p0.
To find the direction the camera is pointing, you must get its rotation and multiply by a Rotation Matrix.
func calculateCameraDirection(cameraNode: SCNNode) -> GLKVector3 {
let x = -cameraNode.rotation.x
let y = -cameraNode.rotation.y
let z = -cameraNode.rotation.z
let w = cameraNode.rotation.w
let cameraRotationMatrix = GLKMatrix3Make(cos(w) + pow(x, 2) * (1 - cos(w)),
x * y * (1 - cos(w)) - z * sin(w),
x * z * (1 - cos(w)) + y*sin(w),
y*x*(1-cos(w)) + z*sin(w),
cos(w) + pow(y, 2) * (1 - cos(w)),
y*z*(1-cos(w)) - x*sin(w),
z*x*(1 - cos(w)) - y*sin(w),
z*y*(1 - cos(w)) + x*sin(w),
cos(w) + pow(z, 2) * ( 1 - cos(w)))
let cameraDirection = GLKMatrix3MultiplyVector3(cameraRotationMatrix, GLKVector3Make(0.0, 0.0, -1.0))
return cameraDirection
}
You then just need to perform the hitTest using both coordinates. In this case I used rayTestWithSegmentFromPoint:ToPoint , but you may use any other kind of test there, such as hitTestWithSegmentFromPoint:toPoint: .
func raycastTest(cameraDirection: GLKVector3) -> SCNVector3{
let nextPoint = findNextPoint(cameraNode.position, direction: SCNVector3Make(cameraDirection.x, cameraDirection.y, cameraDirection.z))
let hitTest = sceneView.scene!.physicsWorld.rayTestWithSegmentFromPoint(cameraNode.position, toPoint: nextPoint, options: nil)
if hitTest.count > 0 {
return (hitTest.first?.worldCoordinates)!
}else{
return nextPoint
}
}