简体   繁体   中英

SceneKit calculate vertex world coordinates for node with pivot

I working on this moving-map project using SceneKit. I've made a globe and rotate it's pivot so your current position faces the camera. To project some text on the map I need to calculate some world coordinates which I can convert to screen coordinates and send to my overlaySKScene. I haven't been successful in using worldTransform or convertPosition/convertTransform so I came up with my own calculations:

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)

Now I expect there is an easier method to calculate these world coordinates. Like multiplying the transform and the pivot.

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)

While the x,y-values are close to my own calculation, the z-value is way off [which should be near -2 due the distance & zoom].

What is the best/correct way to calculate these world-coordinates?

You shouldn't calculate that by your own. SceneKit does that for you with convertPosition(_:, to:) function. It allows you to convert coordinates from local node's coordinate system to other node's coordinate system.

The node with the world coordinates is rootNode . So, considering that posBrussel is position in node's coordinate space, the result has to be as simple as

resultFinal = node.convertPosition(posBrussel, to: scene.rootNode)
screenPoint = sceneView.projectPoint(resultFinal)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM