Ios SceneKit:unprojectPoint返回相同/相似的点,无论您在触摸屏的何处

Ios SceneKit:unprojectPoint返回相同/相似的点,无论您在触摸屏的何处,ios,3d,scenekit,scnnode,sceneview,Ios,3d,Scenekit,Scnnode,Sceneview,下面的代码应将触摸坐标转换为SceneKit场景的世界坐标 但是,如下面的输出所示,unprojectPoint返回的点实际上返回相同的点,无论您在屏幕上触摸到什么位置(iPhone 5s) unprojectPoint的类文档建议使用介于0和1之间的Z值,但使用不同的值(如0.5)不会更改unprojectPoint的输出 讨论如何设置取消投影点的深度值,但将Z值设置为大于1的值(例如15、20)也不会更改输出 在这两种情况下,从unprojectPoint返回的X和Y值实际上也保持不变 1)

下面的代码应将触摸坐标转换为SceneKit场景的世界坐标

但是,如下面的输出所示,
unprojectPoint
返回的点实际上返回相同的点,无论您在屏幕上触摸到什么位置(iPhone 5s)

unprojectPoint
的类文档建议使用介于0和1之间的Z值,但使用不同的值(如0.5)不会更改
unprojectPoint
的输出

讨论如何设置
取消投影点的深度值,但将Z值设置为大于1的值(例如15、20)也不会更改输出

在这两种情况下,从
unprojectPoint
返回的X和Y值实际上也保持不变

1) 使用
取消项目点的正确方法是什么

2)
unprojectPoint
如何解释摄像机旋转?例如,如果将摄影机移动到(0、20、0)并将摄影机向下旋转90度,使其面向地面,如何确保旋转得到考虑?如果将深度设置为20并点击原点,则
unprojectPoint
的所需返回值应为(0,0,0)

3) 如何使
取消投影点
返回相机前面的值(例如,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)")
}
输出:

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.5169.5)。3D点:SCInvector3(x:-0.00111810782,y: 0.0232769605,z:7.9000001)

2D点:(280.5252.0)。3D点:SCInvector3(x:0.0244967155,y:0.00650534919,z:7.9000001)

2D点:(32.0181.0)。3D点:SCInvector3(x:0.0260214079,y:0.0209390987,z:7.9000001)

2D点:(12.0505.0)。三维点:SCInvector3(x: -0.0300872531,y:-0.0449275821,z:7.9000001)

2D点:(311.5,12.5)。3D点:SCInvector3(x:0.0307987742,y:0.0551938377,z:7.9000001)

2D点:(22.5,88.0)。3D点:SCInvector3(x:0.0279526841,y:0.0398452766,z:7.9000001)

2D点:(313.5358.0)。3D点:SCInvector3(x:0.0312053617,y:0.0150436237,z:7.9000001)

2D点:(314.0507.0)。3D点:SCInvector3(x:0.0313070044,y:0.0453341678,z:7.9000001)


2D点:(155.0360.5)。3D点:SCInvector3(x:-0.00101646129,y:-0.0155518558,z:7.9000001)

只要使用0和1,未投影点的值就会改变。
使用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
}
private func接触点到场景点(识别器:UIgestureRecognitor)->SCInvector3{
//获得接触点
让接触点=识别器。位置查看(场景查看)
//计算近点和远点
设nearVector=scinvector3(x:Float(touchPoint.x),y:Float(touchPoint.y),z:0)
设nearScenePoint=sceneView.unprojectPoint(nearVector)
设farVector=SCInvector3(x:Float(touchPoint.x),y:Float(touchPoint.y),z:1)
设farScenePoint=sceneView.unprojectPoint(farVector)
//计算视图向量
让viewVector=scinvector3(x:Float(farScenePoint.x-nearScenePoint.x),y:Float(farScenePoint.y-nearScenePoint.y),z:Float(farScenePoint.z-nearScenePoint.z))
//规范化视图向量
设vectorLength=sqrt(viewVector.x*viewVector.x+viewVector.y*viewVector.y+viewVector.z*viewVector.z)
设normalizedViewVector=SCInvector3(x:viewVector.x/vectorLength,y:viewVector.y/vectorLength,z:viewVector.z/vectorLength)
//缩放规格化向量以查找场景点
让刻度=浮动(15)
设scenePoint=SCInvector3(x:normalizedViewVector.x*比例,y:normalizedViewVector.y*比例,z:normalizedViewVector.z*比例)
打印(“二维点:\(接触点)。三维点:\(近场景点)。远点:\(远场景点)。场景点:\(场景点)”)
//返回
返回场景点
}

这解决了您的问题吗?我面临着同样的问题。我不理解
let scale=Float(15)
部分。这如何帮助你找到一个任意点?你不需要在第二次辩论中通过吗?