如何在没有深度值的情况下使用 SceneKit 的 unprojectPoint 将 2D 点转换为 3D? [英] How to convert 2D point to 3D using SceneKit's unprojectPoint without having a depth value?

查看:20
本文介绍了如何在没有深度值的情况下使用 SceneKit 的 unprojectPoint 将 2D 点转换为 3D?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用SceneKit的unprojectPoint 在没有深度值的情况下将 2D 点转换为 3D?我只需要在 XZ 平面中找到 3D 位置.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.

我已经尝试了基于公认答案的解决方案 此处,但它没有用.为 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 方向上查看,因此 3D 场景套件坐标系的 x 轴和 y 轴与它们在 2D 视图坐标系中的方向相同.(嗯,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.这就是您在上面的代码中为 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.

这篇关于如何在没有深度值的情况下使用 SceneKit 的 unprojectPoint 将 2D 点转换为 3D?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆