How to determine if an ScnNode is left or right of the view direction of a camera node in SceneKit
Asked Answered
M

2

5

I have a camera in the center of SceneKit scene at position(0,0,0) I'm rotation the camera around the y-axis to show different parts of the scene.

I want to show arrows at the left/right side of my screen to show in which direction the user has to move to view a target object.

How can I calculate if a ScnNode is positioned at the left of right side of my view direction?

enter image description here

I know:

  • position and rotation of the camera node
  • position of the target node
Mensural answered 10/1, 2017 at 22:43 Comment(1)
Can you please look into this question, I am stucked at this point - #59502225 . This is something similar which you asked for hope you can help here.Bilander
T
7
  1. Calculate the vector to the node relative to the camera. Calculate the vector by subtracting the camera position from the node position
  2. Use atan2 to convert the vector into an angle. The Apple docs are bit thin on explanation. There's a tutorial on raywenderlich.com.

E.g.

let v = CGPoint(x: nodePosition.x - cameraPosition.x, y: nodePosition.y - cameraPosition.y);
let a = atan2(v.y, v.x) // Note: order of arguments

The angle is in radians, and will range between -π and π (-180 to 180 degrees). If the value is negative the node is to the left of the camera vector, positive values mean the node is to the right, and zero means the node is straight ahead.

Conveniently, you can use this angle as-is to actually perform the rotation if you want. Just increment the camera angle by some fraction of the angle to the node.

E.g.

cameraRotation += a * 0.1

Caveats:

  • "Forward" or "Up" is not necessarily going to be the same as your internal coordinate system. Usually 0 is to the right, so if you want to show an arrow or other UI you may need to add or subtract an amount from the angle (usually -(π/2) to rotate a quarter turn).
  • The angle will always only be between -π and +π. If the node happens to fall directly behind the camera (exactly 180 degrees) you will get either -π or +π, and you might see the angle jump between these two extremes as the node cross over this discontinuity. You sometimes see the side effects of this in games where a nav arrow will point to a target then suddenly flick to the opposite side of the screen. There are various ways to handle this. One easy way is to use a low pass filter on the angle (ie accumulate multiple samples over time).
Tablespoon answered 11/1, 2017 at 7:18 Comment(1)
This is always showing me - value regardless of any movement of camera. Please guide.? Also it would be helpful if you can help me in answering this question #59502225Bilander
G
2

There is an easier way with projectPoint funcion witch show the image as 2d element in your view and based on where it is you can locate where the user should look

func getIfHeIsLookingNew(sceneWidth: CGFloat, nodePosition: SCNVector3){
    if(nodePosition.z < 1){
        if(nodePosition.x > (Float(sceneWidth))){
            print("Look Right")
        }else if(nodePosition.x < 0){
            print("Look Left")
        }else{
            print("Correct")
            return
        }
    }else if(nodePosition.x < 0){
        print("Look Right")
    }else{
        print("Look Left")
    }
}

And use it like below

let sceneWidth:CGFloat = self.sceneView.frame.width

getIfHeIsLookingNew(sceneWidth: sceneWidth, nodePosition: self.sceneView.projectPoint(targetNode.position))
Gopak answered 13/2, 2018 at 12:48 Comment(1)
It is always showing me a static direction For E.g Once shown correct it shows correct always and if left then left always. Is something wrong with my implementation.? Hope you can answer this question for me #59502225Bilander

© 2022 - 2024 — McMap. All rights reserved.