如何转换2D指向3D使用SceneKit的unprojectPoint无需深度值?深度、SceneKit、unprojectPoint

2023-09-08 10:35:53 作者:劳资就是屌

是否有可能使用SceneKit的unprojectPoint到一个2D点到3D转换,而无需深度值? 我只需要找到三维位置,在XZ平面。 Y可以是始终为0或任何价值,因为我不使用它。

Is it possible to use SceneKit's unprojectPoint to convert a 2D point to 3D without having a depth value? I only need to find the 3D location in the XZ plane. Y can be always 0 or any value since I'm not using it.

我试图做到这一点的iOS 8 Beta版。

I'm trying to do this for iOS 8 Beta.

我曾与JavaScript和Three.js(WebGL的),像这样类似的事情:

I had something similar with JavaScript and Three.js (WebGL) like this:

function getMouse3D(x, y) {
    var pos = new THREE.Vector3(0, 0, 0);
    var pMouse = new THREE.Vector3(
        (x / renderer.domElement.width) * 2 - 1,
       -(y / renderer.domElement.height) * 2 + 1,
       1
    );
    //
    projector.unprojectVector(pMouse, camera);

    var cam = camera.position;
    var m = pMouse.y / ( pMouse.y - cam.y );

    pos.x = pMouse.x + ( cam.x - pMouse.x ) * m;
    pos.z = pMouse.z + ( cam.z - pMouse.z ) * m;

    return pos;
};

但我不知道如何与unprojectVector翻译部分SceneKit。

But I don't know how to translate the part with unprojectVector to SceneKit.

我想要做的是能在只在XZ平面拖动的对象。垂直轴线Y将被忽略。

What I want to do is to be able to drag an object around in the XZ plane only. The vertical axis Y will be ignored.

由于对象需要沿平面移动,一种解决方案是使用的hitTest方法,但我不认为是在性能方面非常好做它的每一个触摸/拖动事件。此外,它不会允许对象面外的任何移动

Since the object would need to move along a plane, one solution would be to use hitTest method, but I don't think is very good in terms of performance to do it for every touch/drag event. Also, it wouldn't allow the object to move outside the plane either.

我试过的基础上公认的答案here,但它并没有奏效。使用一个深度值unprojectPoint,如果在+/- Z方向的对象并不在手指下停留过久左右拖动对象,但它远离它吧。 我需要手指在拖动的对象停留无论是在XZ平面移动。

I've tried a solution based on the accepted answer here, but it didn't worked. Using one depth value for unprojectPoint, if dragging the object around in the +/-Z direction the object doesn't stay under the finger too long, but it moves away from it instead. I need to have the dragged object stay under the finger no matter where is it moved in the XZ plane.

推荐答案

首先,你实际上是在寻找在XZ平面或者xy平面的位置?缺省情况下,相机看起来在-z方向,所以x和三维场景套件的y轴坐标系走在同一方向上,因为它们在二维视图做坐标系。 (好吧,Y中默认的UIKit翻转,但它仍然是垂直轴)在XZ平面然后与屏幕垂直的平面上。

First, are you actually looking for a position in the xz-plane or the xy-plane? By default, the camera looks in the -z direction, so the x- and y-axes of the 3D Scene Kit coordinate system go in the same directions as they do in the 2D view coordinate system. (Well, y is flipped by default in UIKit, but it's still the vertical axis.) The xz-plane is then orthogonal to the plane of the screen.

其次,深度值是转换从2D到3D的必要组成部分。我不是three.js方面的专家,但看着他们库文档(这显然不能被链接到),其 unprojectVector 仍需要一个 Vector3类型。而这就是你在你的code以上建设什么 pMouse - 一个向量,其Z和Y坐标来自2D鼠标的位置,并且其Z-坐标1。

Second, a depth value is a necessary part of converting from 2D to 3D. I'm not an expert on three.js, but from looking at their library documentation (which apparently can't be linked into), their unprojectVector still takes a Vector3. And that's what you're constructing for pMouse in your code above — a vector whose z- and y-coordinates come from the 2D mouse position, and whose z-coordinate is 1.

SceneKit的 unprojectPoint 以同样的方式 - 它需要的z坐标指的是深度的裁剪空间,和地图场景中的世界空间中的一个点。

SceneKit's unprojectPoint works the same way — it takes a point whose z-coordinate refers to a depth in clip space, and maps that to a point in your scene's world space.

如果你的世界空间的方向是您所关心的唯一变化是在X轴和Y轴的,你可以把你想要的任何z值,以 unprojectPoint ,而忽略在你回来的矢量的z值。否则,通 1 映射到远剪裁平面, 1 的近裁剪平面,或 0 的一半之间 - 其平面z坐标(在摄像机空间)为 0 。如果您使用的是未投影点到场景中放置一个节点,最好的建议是,只是尝试不同的Z值(-1到1之间),直到你得到你想要的行为。

If your world space is oriented such that the only variation you care about is in the x- and y-axes, you may pass any z-value you want to unprojectPoint, and ignore the z-value in the vector you get back. Otherwise, pass -1 to map to the far clipping plane, 1 for the near clipping plane, or 0 for halfway in between — the plane whose z-coordinate (in camera space) is 0. If you're using the unprojected point to position a node in the scene, the best advice is to just try different z-values (between -1 and 1) until you get the behavior you want.

然而,这是一个好主意,要想着你正在使用的一个未投影载体 - 如果接下来的事情你会做它是交点检测与场景几何体,看看则hitTest:而不是

However, it's a good idea to be thinking about what you're using an unprojected vector for — if the next thing you'd be doing with it is testing for intersections with scene geometry, look at hitTest: instead.