SceneKit: unprojectPoint возвращает одну и ту же / похожую точку независимо от того, где вы касаетесь экрана
Приведенный ниже код должен переводить сенсорные координаты в мировые координаты для сцены SceneKit.
Однако, как показано в выходных данных ниже, точка, возвращаемая unprojectPoint
эффективно возвращает одну и ту же точку независимо от того, где вы касаетесь экрана (iPhone 5s).
Класс документов для unprojectPoint
предложить использовать значения Z в диапазоне от 0 до 1, но использование других значений, таких как 0,5, не изменило вывод для unprojectPoint
,
Этот пост SO обсуждает, как установить значение глубины для unprojectPoint
, но установка значения Z на значения больше 1 (например, 15, 20) также не изменила выходной сигнал.
В обоих случаях значения X и Y возвращаются из unprojectPoint
фактически остался прежним.
1) Как правильно использовать unprojectPoint
?
2) Как работает unprojectPoint
учитывать повороты камеры? Например, если вы переместили камеру в положение (0, 20, 0) и повернули камеру вниз на 90 градусов, чтобы она была обращена к земле, как вы обеспечиваете учет вращения? Если вы установили глубину 20 и нажали на начало координат, желаемое возвращаемое значение из unprojectPoint
должно быть (0, 0, 0).
3) Как вы получаете unprojectPoint
возвращать значения перед камерой (например, значения Z ниже значения Z камеры)
Код:
cameraNode.position = SCNVector3(x: 0, y: Float(0), z: Float(8))
func sceneViewTapped(recognizer: UITapGestureRecognizer) {
let point = recognizer.locationInView(sceneView)
let unprojectPoint = SCNVector3(x: Float(point.x), y: Float(point.y), z: 0.0)
let scenePos = sceneView.unprojectPoint(unprojectPoint)
print("2D point: \(point). 3D point: \(scenePos)")
}
Выход:
2D точка: (154,5, 169,5). 3D-точка: SCNVector3(x: -0.00111810782, y: 0.0232769605, z: 7.9000001)
2D точка: (280,5, 252,0). 3D-точка: SCNVector3(x: 0,0244967155, y: 0,00650534919, z: 7,9000001)
2D точка: (32,0, 181,0). 3D-точка: SCNVector3(x: -0.0260214079, y: 0.0209390987, z: 7.9000001)
2D точка: (12,0, 505,0). 3D-точка: SCNVector3(x: -0.0300872531, y: -0.0449275821, z: 7.9000001)
2D точка: (311,5, 12,5). 3D-точка: SCNVector3(x: 0,0307987742, y: 0,0551938377, z: 7,9000001)
2D точка: (22,5, 88,0). 3D точка: SCNVector3(x: -0,0279526841, y: 0,0398452766, z: 7,9000001)
2D точка: (313,5, 358,0). 3D-точка: SCNVector3(x: 0,0312053617, y: -0,0150436237, z: 7,9000001)
2D точка: (314,0, 507,0). 3D-точка: SCNVector3(x: 0,0313070044, y: -0,0453341678, z: 7,9000001)
2D точка: (155,0, 360,5). 3D-точка: SCNVector3(x: -0.00101646129, y: -0.0155518558, z: 7.9000001)
1 ответ
Пока вы используете 0 и 1, значения меняются для unprojectPoint.
Использование 0 для значения Z представляет точку на ближней плоскости, а использование 1 дает точку на дальней плоскости.
Таким образом, чтобы вернуть точку сцены, которая находится на произвольном расстоянии от камеры, мы разработали следующую функцию. Мы новички в SceneKit, поэтому, пожалуйста, предлагайте любые изменения или исправления!
По сути, вы определяете луч / линию между ближними и дальними точками, а затем выбираете некоторую точку вдоль линии.
private func touchPointToScenePoint(recognizer: UIGestureRecognizer) -> SCNVector3 {
// Get touch point
let touchPoint = recognizer.locationInView(sceneView)
// Compute near & far points
let nearVector = SCNVector3(x: Float(touchPoint.x), y: Float(touchPoint.y), z: 0)
let nearScenePoint = sceneView.unprojectPoint(nearVector)
let farVector = SCNVector3(x: Float(touchPoint.x), y: Float(touchPoint.y), z: 1)
let farScenePoint = sceneView.unprojectPoint(farVector)
// Compute view vector
let viewVector = SCNVector3(x: Float(farScenePoint.x - nearScenePoint.x), y: Float(farScenePoint.y - nearScenePoint.y), z: Float(farScenePoint.z - nearScenePoint.z))
// Normalize view vector
let vectorLength = sqrt(viewVector.x*viewVector.x + viewVector.y*viewVector.y + viewVector.z*viewVector.z)
let normalizedViewVector = SCNVector3(x: viewVector.x/vectorLength, y: viewVector.y/vectorLength, z: viewVector.z/vectorLength)
// Scale normalized vector to find scene point
let scale = Float(15)
let scenePoint = SCNVector3(x: normalizedViewVector.x*scale, y: normalizedViewVector.y*scale, z: normalizedViewVector.z*scale)
print("2D point: \(touchPoint). 3D point: \(nearScenePoint). Far point: \(farScenePoint). scene point: \(scenePoint)")
// Return <scenePoint>
return scenePoint
}