SceneKit: unprojectPoint returns same/similar 无论你在哪里触摸屏幕
SceneKit: unprojectPoint returns same/similar point no matter where you touch screen
下面的代码应该将触摸坐标转换为 SceneKit 场景的世界坐标。
但是,如下面的输出所示,return由 unprojectPoint
return 编辑的点实际上是同一个点,无论您触摸屏幕的哪个位置(iPhone 5s).
unprojectPoint
的 class 文档建议使用 0 到 1 之间的 Z 值,但使用不同的值(如 0.5)不会更改 unprojectPoint
的输出。
This SO post 讨论了如何为 unprojectPoint
设置深度值,但是将 Z 值设置为大于 1 的值(例如 15、20)也没有改变输出。
在这两种情况下,unprojectPoint
中的 X 和 Y 值 return 实际上也保持不变。
1) unprojectPoint
的正确使用方法是什么?
2) unprojectPoint
如何解释相机旋转?例如,如果您将相机移动到 (0, 20, 0) 并将相机向下旋转 90 度以使其面向地面,您如何确保考虑到旋转?如果将深度设置为 20 并点击原点,则 unprojectPoint
中所需的 return 值应为 (0, 0, 0).
3) 如何在相机前获得unprojectPoint
到return值(例如,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)")
}
输出:
二维点:(154.5, 169.5)。 3D 点:SCNVector3(x: -0.00111810782, y:
0.0232769605, z: 7.9000001)
二维点:(280.5, 252.0)。 3D点:SCNVector3(x: 0.0244967155, y: 0.00650534919, z: 7.9000001)
二维点:(32.0, 181.0)。 3D点:SCNVector3(x: -0.0260214079, y: 0.0209390987, z: 7.9000001)
二维点:(12.0, 505.0)。 3D 点:SCNVector3(x:
-0.0300872531,y:-0.0449275821,z:7.9000001)
二维点:(311.5, 12.5)。 3D点:SCNVector3(x: 0.0307987742, y: 0.0551938377, z: 7.9000001)
二维点:(22.5, 88.0)。 3D点:SCNVector3(x: -0.0279526841, y: 0.0398452766, z: 7.9000001)
二维点:(313.5, 358.0)。 3D点:SCNVector3(x: 0.0312053617, y: -0.0150436237, z: 7.9000001)
二维点:(314.0, 507.0)。 3D点:SCNVector3(x: 0.0313070044, y: -0.0453341678, z: 7.9000001)
二维点:(155.0, 360.5)。 3D点:SCNVector3(x: -0.00101646129, y: -0.0155518558, z: 7.9000001)
只要您使用 0 和 1,值就会发生变化 unprojectPoint.
Z 值使用 0 表示近平面上的点,而使用 1 表示远平面上的点。
所以对于return一个距离相机任意距离的场景点,我们开发了如下函数。我们是 SceneKit 的新手,所以请提供任何编辑或更正!
实际上,您定义了近点和远点之间的 ray/line,然后沿线选取一些点。
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
}
下面的代码应该将触摸坐标转换为 SceneKit 场景的世界坐标。
但是,如下面的输出所示,return由 unprojectPoint
return 编辑的点实际上是同一个点,无论您触摸屏幕的哪个位置(iPhone 5s).
unprojectPoint
的 class 文档建议使用 0 到 1 之间的 Z 值,但使用不同的值(如 0.5)不会更改 unprojectPoint
的输出。
This SO post 讨论了如何为 unprojectPoint
设置深度值,但是将 Z 值设置为大于 1 的值(例如 15、20)也没有改变输出。
在这两种情况下,unprojectPoint
中的 X 和 Y 值 return 实际上也保持不变。
1) unprojectPoint
的正确使用方法是什么?
2) unprojectPoint
如何解释相机旋转?例如,如果您将相机移动到 (0, 20, 0) 并将相机向下旋转 90 度以使其面向地面,您如何确保考虑到旋转?如果将深度设置为 20 并点击原点,则 unprojectPoint
中所需的 return 值应为 (0, 0, 0).
3) 如何在相机前获得unprojectPoint
到return值(例如,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)")
}
输出:
二维点:(154.5, 169.5)。 3D 点:SCNVector3(x: -0.00111810782, y: 0.0232769605, z: 7.9000001)
二维点:(280.5, 252.0)。 3D点:SCNVector3(x: 0.0244967155, y: 0.00650534919, z: 7.9000001)
二维点:(32.0, 181.0)。 3D点:SCNVector3(x: -0.0260214079, y: 0.0209390987, z: 7.9000001)
二维点:(12.0, 505.0)。 3D 点:SCNVector3(x: -0.0300872531,y:-0.0449275821,z:7.9000001)
二维点:(311.5, 12.5)。 3D点:SCNVector3(x: 0.0307987742, y: 0.0551938377, z: 7.9000001)
二维点:(22.5, 88.0)。 3D点:SCNVector3(x: -0.0279526841, y: 0.0398452766, z: 7.9000001)
二维点:(313.5, 358.0)。 3D点:SCNVector3(x: 0.0312053617, y: -0.0150436237, z: 7.9000001)
二维点:(314.0, 507.0)。 3D点:SCNVector3(x: 0.0313070044, y: -0.0453341678, z: 7.9000001)
二维点:(155.0, 360.5)。 3D点:SCNVector3(x: -0.00101646129, y: -0.0155518558, z: 7.9000001)
只要您使用 0 和 1,值就会发生变化 unprojectPoint.
Z 值使用 0 表示近平面上的点,而使用 1 表示远平面上的点。
所以对于return一个距离相机任意距离的场景点,我们开发了如下函数。我们是 SceneKit 的新手,所以请提供任何编辑或更正!
实际上,您定义了近点和远点之间的 ray/line,然后沿线选取一些点。
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
}