我使用SceneKit处理这个移动地图项目。 我制作了一个地球仪并旋转它的枢轴,使你当前的位置面向相机。 要在地图上投射一些文字,我需要计算一些世界坐标,我可以将其转换为屏幕坐标并发送到我的overlaySKScene。 我没有成功使用 worldTransform 或 convertPosition / convertTransform ,所以我想出了自己的计算:
import SceneKit
import simd
// a rotation-matrix which rotates the globe
// so 52º North, 4.75º East [Benelux] faces the camera @ [0,0,0]
let pivot = float4x4([
float4(0.996566, 0.0, -0.0828082, 0.0),
float4(-0.0652537, 0.615662, -0.785304, 0.0),
float4(0.0509818, 0.788011, 0.613547, 0.0),
float4(0.0, 0.0, 0.0, 1.0)
])
// position of Brussel in cartesian coordinates
let posBrussel = float4(0.0493100174, 0.776061833, 0.628726125, 1.0)
// setup globe
// apply scale & translation -> zoom in on Benelux
let zoom = Float(14.6193)
let distance = Float(-16.5852)
let node = SCNNode()
node.position = SCNVector3(0, 0, distance)
node.scale = SCNVector3(zoom, zoom, zoom)
node.pivot = SCNMatrix4(pivot)
// Manual calculation of world coordinates
let posBrusselScaled = zoom * posBrussel
let resultIntermediate = posBrusselScaled * pivot
let resultFinal = resultIntermediate + float4(0.0, 0.0, distance, 0.0)
// world coordinates Brussel
// resultFinal = float4(-0.0427321, -0.280209, -1.96864, 14.6193)
现在我希望有一种更简单的方法来计算这些世界坐标。就像将变换和枢轴相乘一样。
let transform = float4x4(node.transform)
posBrussel * pivot * transform // float4(-0.0427321, -0.280209, 14.6166, -15.5821)
posBrussel * transform * pivot // float4(-0.0427321, -0.280209, 14.6166, -9.42755)
虽然x,y值接近我自己的计算,但是z值是偏离的[由于距离和距离,它应该接近-2。变焦]。
计算这些世界坐标的最佳/正确方法是什么?
答案 0 :(得分:0)
您不应该自己计算。 SceneKit使用convertPosition(_:, to:)
函数为您完成此任务。它允许您将坐标从本地节点的坐标系转换为其他节点的坐标系。
具有世界坐标的节点为rootNode
。
因此,考虑到posBrussel
在节点坐标空间中的位置,结果必须像
resultFinal = node.convertPosition(posBrussel, to: scene.rootNode)
screenPoint = sceneView.projectPoint(resultFinal)