4

我有这个只适用于横向的应用程序。

我在场景包上有一个对象。该对象位于特定位置,由以下方式指定:

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

现在我需要将其转换SCNVector3mainView2D 坐标,其中

 mainView = (SCNView *)self.view;

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

我该如何转换?

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

如果 SCNView 是 UIView 的子类,则 (0,0) 是左上角,而在 iPhone 6 横向的情况下,(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) 时,我会在左下角看到一个视图!

就像我说的那样,该应用程序仅在横向运行,但这些坐标系都一团糟。

4

2 回答 2

4

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

当您需要自己做时,还有一种方便的方法:projectPoint:

于 2016-05-30T04:47:24.583 回答
3

相当老的问题,但不幸的是,@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 矩阵提供矩阵数学,因此使用的(非常简单的)矩阵处理方法也是“自制的”:

/*
 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 中的错误,或者是否禁止对 rootNode 应用转换...无论如何:问题已解决 :-)

于 2018-03-09T15:51:31.603 回答