我有一个只适用于横向的应用程序。
我在scenekit上有一个物体。该对象位于某个位置,由指定
SCNNode * buttonRef = [scene.rootNode childNodeWithName:@"buttonRef" recursively:YES];
SCNVector3 buttonRefPosition = [buttonRef position];
现在我需要将SCNVector3
转换为mainView
2D坐标,其中
mainView = (SCNView *)self.view;
该场景使用正交摄影机,因此没有透视。摄影机是默认摄影机。没有旋转,就没有平移。摄影机的正交比例为5.4。
我该如何转换?
我在SO上找到了关于反向问题的其他答案,即从CGPoint转换为SCNVector3,但对我来说,如何从SCNVector 3转换为CGPoint,听起来并不明显。
如果SCNView是UIView的子类,则than(0,0)是左上点,在iPhone 6横向的情况下,(667375)是右下点。
我的这个按钮几乎在右边和中间的高度。就UIKit而言,我会说这个按钮在(600187),但当我这样做时:
SCNNode * buttonRef = [scene.rootNode childNodeWithName:@"buttonRef" recursively:YES];
SCNVector3 buttonRefPosition = [buttonRef position];
SCNVector3 projectedPoint = [mainView projectPoint: buttonRefPosition];
我得到的projectPoint等于(7.8375,0)(?)
当我使用UIKit将10x10视图添加到坐标(7.8375)时,我会在左下角看到一个视图!!
就像我说的,这个应用程序只在风景中运行,但这些坐标系都一团糟。
将模型空间点转换为屏幕空间点称为投影(因为它应用相机的投影变换将3D空间映射到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];
不幸的是,苹果没有为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。。。无论如何:问题解决了:-)