我在SceneKit场景的中心位置(0,0,0)有一个摄像头我围绕y轴旋转摄像机以显示场景的不同部分 .
我想在屏幕的左/右侧显示箭头,以显示用户移动以查看目标对象的方向 .
如何计算ScnNode是否位于视图方向右侧的左侧?
我知道:
摄像机节点的位置和旋转
目标节点的位置
计算相对于摄像机的节点向量 . 通过从节点位置减去摄像机位置来计算矢量
使用atan2将矢量转换为角度 . Apple的文档在解释上有点薄弱 . 有一个关于raywenderlich.com的教程 .
例如 .
let v = CGPoint(x: nodePosition.x - cameraPosition.x, y: nodePosition.y - cameraPosition.y); let a = atan2(v.y, v.x) // Note: order of arguments
角度以弧度为单位,范围介于-π和π(-180到180度)之间 . 如果值为负,则节点位于摄像机矢量的左侧,正值表示节点位于右侧,零值表示节点位于正前方 .
方便的是,您可以根据需要使用此角度实际执行旋转 . 只需将摄像机角度增加一定角度即可达到节点 .
cameraRotation += a * 0.1
注意事项:
"Forward"或"Up"不一定与内部坐标系相同 . 通常0在右侧,因此如果您想要显示箭头或其他UI,您可能需要从角度添加或减去一定量(通常 - (π/ 2)旋转四分之一圈) .
角度始终仅在-π和π之间 . 如果节点恰好落在摄像机后面(恰好是180度),您将得到-π或π,当节点越过这个不连续点时,您可能会看到这两个极端之间的角度跳跃 . 你有时会在游戏中看到这种副作用,导航箭头指向目标,然后突然轻弹到屏幕的另一侧 . 有各种方法来处理这个问题 . 一种简单的方法是在角度上使用低通滤波器(即随时间累积多个样本) .
使用projectPoint funcion有一种更简单的方法,可以在视图中将图像显示为2d元素,并根据它可以找到用户应该看到的位置
let sceneWidth:CGFloat = self.sceneView.frame.width getIfHeIsLookingNew(sceneWidth: sceneWidth, nodePosition: self.sceneView.projectPoint(targetNode.position)) 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") } } }
2 回答
计算相对于摄像机的节点向量 . 通过从节点位置减去摄像机位置来计算矢量
使用atan2将矢量转换为角度 . Apple的文档在解释上有点薄弱 . 有一个关于raywenderlich.com的教程 .
例如 .
角度以弧度为单位,范围介于-π和π(-180到180度)之间 . 如果值为负,则节点位于摄像机矢量的左侧,正值表示节点位于右侧,零值表示节点位于正前方 .
方便的是,您可以根据需要使用此角度实际执行旋转 . 只需将摄像机角度增加一定角度即可达到节点 .
例如 .
注意事项:
"Forward"或"Up"不一定与内部坐标系相同 . 通常0在右侧,因此如果您想要显示箭头或其他UI,您可能需要从角度添加或减去一定量(通常 - (π/ 2)旋转四分之一圈) .
角度始终仅在-π和π之间 . 如果节点恰好落在摄像机后面(恰好是180度),您将得到-π或π,当节点越过这个不连续点时,您可能会看到这两个极端之间的角度跳跃 . 你有时会在游戏中看到这种副作用,导航箭头指向目标,然后突然轻弹到屏幕的另一侧 . 有各种方法来处理这个问题 . 一种简单的方法是在角度上使用低通滤波器(即随时间累积多个样本) .
使用projectPoint funcion有一种更简单的方法,可以在视图中将图像显示为2d元素,并根据它可以找到用户应该看到的位置