如何将 SCNVector3 位置转换为 CGPoint SCNView 坐标?

How to Convert a SCNVector3 position to a CGPoint SCNView coordinate?

我有这个应用程序只能在横向模式下使用。

我在 scenekit 上有一个对象。该对象位于特定位置,指定为:

 SCNNode * buttonRef = [scene.rootNode childNodeWithName:@"buttonRef" recursively:YES];
 SCNVector3 buttonRefPosition = [buttonRef position];

现在我需要将 SCNVector3 转换为 mainView 二维坐标,其中

 mainView = (SCNView *)self.view;

场景使用的是正交相机,所以没有透视。相机是默认相机。没有旋转,没有平移。相机的 orthographicScale 是 5.4.

如何转换?

我在 SO 上找到了关于反向问题的其他答案,即从 CGPoint 转换为 SCNVector3,但对我来说如何进行反向转换(从 SCNVector3 到 CGPoint)听起来并不明显。

如果 SCNView 是 UIView 的子类,那么 (0,0) 是左上点,在 iPhone 6 landscape 的情况下,(667, 375) 是右下点。

我的这个按钮几乎完全位于右侧和中间高度。就 UIKit 而言,我会说这个按钮位于 (600, 187) 但当我这样做时:

SCNNode * buttonRef = [scene.rootNode childNodeWithName:@"buttonRef" recursively:YES];
SCNVector3 buttonRefPosition = [buttonRef position];

SCNVector3 projectedPoint = [mainView projectPoint: buttonRefPosition];

我得到的 projectPoint 等于 (7.8, 375, 0) (?)

当我使用 UIKit 将 10x10 视图添加到坐标 (7.8, 375) 时,我在左下方得到了一个视图!!

就像我说的,该应用程序只能在横向模式下运行,但这些坐标系都乱七八糟。

将模型-space 点转换为屏幕-space 点称为投影(因为它应用相机的投影变换以从 3D space 映射到 2D )。渲染器(通过 GPU)每帧执行很多次,以将场景中的点显示在屏幕上。

当你需要自己做的时候,还有一个方便的方法:projectPoint:

很老的问题,但不幸的是@ricksters 的回答对我没有真正的帮助,因为 projectPoint: 在我的案例中也一直提供混乱的视图坐标(与@相同的问题SpaceDog描述)!

但是,我发现,在 我的案例 中,问题是我对我的根节点应用了转换(把世界颠倒了 ;-))。这显然会导致 projectPoint:...

的错误结果

由于我无法删除变换,因此我不得不相应地将我的输入调整为 projectPoint:

SCNVector3  viewStartPosition = ...; // Some place in the scene
SCNVector3  viewStartPositionRel = SCNVector3FromSCNVector4(SCNMatrix4MultV(self.scene.rootNode.worldTransform, SCNVector4FromSCNVector3(viewStartPosition)));
// Vector from UISceneView 0/0 top/left to start point
SCNVector3  viewStartPositionInViewCoords = [self.sceneView projectPoint:viewStartPositionRel];

不幸的是,Apple 没有为 SCNMatrix4 矩阵提供矩阵数学,因此使用的(非常简单的)矩阵处理方法也是 'home made':

/*
 SCNVector4FromSCNVector3

 */
SCNVector4 SCNVector4FromSCNVector3(SCNVector3 pV) {
    return SCNVector4Make(pV.x, pV.y, pV.z, 0.0);
}

/*
 SCNVector3FromSCNVector4

 */
SCNVector3 SCNVector3FromSCNVector4(SCNVector4 pV) {
    return SCNVector3Make(pV.x, pV.y, pV.z);
}

/*
 SCNMatrix4MultV

 */
SCNVector4 SCNMatrix4MultV(SCNMatrix4 pM, SCNVector4 pV) {
    SCNVector4  r = {
        pM.m11 * pV.x + pM.m12 * pV.y + pM.m13 * pV.z + pM.m14 * pV.w,
        pM.m21 * pV.x + pM.m22 * pV.y + pM.m23 * pV.z + pM.m24 * pV.w,
        pM.m31 * pV.x + pM.m32 * pV.y + pM.m33 * pV.z + pM.m34 * pV.w,
        pM.m41 * pV.x + pM.m42 * pV.y + pM.m43 * pV.z + pM.m44 * pV.w
    };
    return r;
}

我不知道这是不是 SceneKit 中的错误,或者是否禁止将转换应用到根节点... 无论如何:问题已解决:-)