3 回答

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超10個(gè)贊
3D圖形管線中的典型深度緩沖區(qū)不是線性的。透視劃分導(dǎo)致歸一化設(shè)備坐標(biāo)中的深度處于不同的比例。(另請參見此處。)
因此,您要輸入的z坐標(biāo)unprojectPoint實(shí)際上并不是您想要的。
那么,如何找到與世界空間中的平面匹配的歸一化深度坐標(biāo)呢?好吧,如果該平面與相機(jī)正交(這就是您的相機(jī))是有幫助的。然后,您要做的就是在該平面上投影一個(gè)點(diǎn):
let projectedOrigin = gameView.projectPoint(SCNVector3Zero)
現(xiàn)在,您可以在3D視圖+歸一化深度空間中找到世界原點(diǎn)的位置。要將2D視圖空間中的其他點(diǎn)映射到該平面上,請使用此向量的z坐標(biāo):
let vp = gestureRecognizer.locationInView(scnView)
let vpWithZ = SCNVector3(x: vp.x, y: vp.y, z: projectedOrigin.z)
let worldPoint = gameView.unprojectPoint(vpWithZ)
這樣可以在世界空間中獲得一個(gè)點(diǎn),該點(diǎn)將單擊/點(diǎn)擊位置映射到z = 0平面,position如果要向用戶顯示該位置,則適合用作節(jié)點(diǎn)的位置。
(請注意,此方法僅在映射到垂直于相機(jī)視線方向的平面上才有效。如果要將視線坐標(biāo)映射到不同方向的表面上,則in中的歸一化深度值vpWithZ將不會(huì)恒定)

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超6個(gè)贊
經(jīng)過一些實(shí)驗(yàn)后,我們開發(fā)出了將觸摸點(diǎn)投影到場景中給定點(diǎn)任意深度的工具。
您需要進(jìn)行的修改是計(jì)算Z = 0平面與此線的交點(diǎn),這就是您的觀點(diǎn)。
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
}
- 3 回答
- 0 關(guān)注
- 883 瀏覽
添加回答
舉報(bào)