如何将 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 中的错误,或者是否禁止将转换应用到根节点...
无论如何:问题已解决:-)
我有这个应用程序只能在横向模式下使用。
我在 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 中的错误,或者是否禁止将转换应用到根节点... 无论如何:问题已解决:-)