为了确定物体的 3D 位置,我建议使用光线追踪。
假设模型在世界空间坐标中,您还需要知道眼睛位置的世界空间坐标和图像平面的世界空间坐标。使用这两个点,您可以计算出用于与模型相交的射线,我假设模型由三角形组成。
然后,您可以使用射线三角形测试来确定触摸的 3D 位置,方法是找到与图像平面相交最近的三角形。如果您想触摸哪个三角形,您还需要在进行相交测试时保存该信息。
此页面提供了如何进行射线三角形相交测试的示例:http ://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-9-ray-triangle-intersection/ray-triangle-intersection-geometric-解决方案/
编辑:
更新有一些示例代码。它是我从不久前做的一个 C++ 光线追踪项目中获取的一些稍微修改过的代码,因此您需要对其进行一些修改以使其适用于 iOS。此外,当前形式的代码甚至没有用,因为它不返回实际的交点,而是返回射线是否与三角形相交。
// d is the direction the ray is heading in
// o is the origin of the ray
// verts is the 3 vertices of the triangle
// faceNorm is the normal of the triangle surface
bool
Triangle::intersect(Vector3 d, Vector3 o, Vector3* verts, Vector3 faceNorm)
{
// Check for line parallel to plane
float r_dot_n = (dot(d, faceNorm));
// If r_dot_n == 0, then the line and plane are parallel, but we need to
// do the range check due to floating point precision
if (r_dot_n > -0.001f && r_dot_n < 0.001f)
return false;
// Then we calculate the distance of the ray origin to the triangle plane
float t = ( dot(faceNorm, (verts[0] - o)) / r_dot_n);
if (t < 0.0)
return false;
// We can now calculate the barycentric coords of the intersection
Vector3 ba_ca = cross(verts[1]-verts[0], verts[2]-verts[0]);
float denom = dot(-d, ba_ca);
dist_out = dot(o-verts[0], ba_ca) / denom;
float b = dot(-d, cross(r.o-verts[0], verts[2]-verts[0])) / denom;
float c = dot(-d, cross(verts[1]-verts[0], o-verts[0])) / denom;
// Check if in tri or if b & c have NaN values
if ( b < 0 || c < 0 || b+c > 1 || b != b || c != c)
return false;
// Use barycentric coordinates to calculate the intersection point
Vector3 P = (1.f-b-c)*verts[0] + b*verts[1] + c*verts[2];
return true;
}
您感兴趣的实际交点是 P。