从CGPoint获取SCNVector3

时间:2014-11-09 19:16:53

标签: objective-c xcode scenekit

我正在尝试从CGPoint获取SCNVector3。我正在使用手势识别器来获取触摸的位置(作为CGPoint)。

问题在于,当我点击测试时,触摸并不会总是碰到某些东西,因为触摸的对象总是没有。 (触摸空白区域将船舶移至该空位)。

我发现的其他Stack Overflow问题使用SCNHitTestResult来获取worldCoordinates,但这对我没有用。

有谁知道怎么找到这个?鉴于我当然知道z坐标。移动的船始终以z位置1移动。

我需要worldCoordinates能够使用将SCNNode移动到具有CGPoint的触摸点的操作。谢谢!

1 个答案:

答案 0 :(得分:6)

那么,您想将视图空间中的某个点转换为场景空间中的某个点吗?当然,问题在于场景空间具有第三维,而视图空间则没有。您可以使用SCNView(或其他渲染器)方法projectPointunprojectPoint在场景空间(即3D)和视图空间(也是3D)之间进行转换? Yep - 屏幕 pixels 点的两个维度,以及归一化深度之一:对于近剪裁平面上的点,z坐标为0,对于远剪裁平面上的点,z坐标为1.

无论如何,您有一个有用的约束,因为您希望将视图空间点映射到场景空间中的特定平面(z=1)。如果您的场景空间是朝向的,那么您有一个更有用的约束,以便所述平面与视图方向正交 - 即摄像机直接指向+ z或-z方向。

如果要将视图空间点映射到特定的场景空间深度,则需要知道该平面的视图空间深度。请使用projectPoint

SCNVector3 projectedPlaneCenter = [view projectPoint:planeNode.position];
float projectedDepth = projectedPlaneCenter.z;

现在,抓住它,您可以在需要将触摸位置映射到该平面时使用它:

CGPoint vp = [recognizer locationInView:view];
SCNVector3 vpWithDepth = SCNVector3Make(vp.x, vp.y, projectedDepth);
SCNVector3 scenePoint = [view unprojectPoint:vpWithDepth];

如果您的场景没有朝向与摄影机平行的z轴,那就更难了 - 您必须找出z=1平面独立于您处理的任何视点空间的位置。在这种情况下,您可能会发现在场景中添加不可见的SCNPlane并使用hitTest / worldCoordinates方法在该平面上定位点更容易。