Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
openGL中三维物体的触摸位置检测_Opengl_Iphone_Objective C_Opengl Es_3d - Fatal编程技术网

openGL中三维物体的触摸位置检测

openGL中三维物体的触摸位置检测,opengl,iphone,objective-c,opengl-es,3d,Opengl,Iphone,Objective C,Opengl Es,3d,我已经在中为我的一个应用程序创建了一个3D对象。这个物体有点像人体,可以触摸旋转。如何检测此3D对象上的触摸位置。意味着如果用户触摸头部,我必须检测到它是头部。如果触摸在手上,则必须识别。即使对象旋转到其他方向,它也应该工作。我认为需要3D对象上的触摸坐标。 这是我在视图上获得触摸位置的方法 - (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event { UITouch* touch = [touches any

我已经在中为我的一个应用程序创建了一个3D对象。这个物体有点像人体,可以触摸旋转。如何检测此3D对象上的触摸位置。意味着如果用户触摸头部,我必须检测到它是头部。如果触摸在手上,则必须识别。即使对象旋转到其他方向,它也应该工作。我认为需要3D对象上的触摸坐标。
这是我在视图上获得触摸位置的方法

- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event
{
    UITouch* touch = [touches anyObject];
    CGPoint location  = [touch locationInView: self];
    m_applicationEngine->OnFingerDown(ivec2(location.x, location.y));
}

有人能帮忙吗?提前谢谢

要确定物体的三维位置,我建议使用光线跟踪

假设模型位于世界空间坐标中,您还需要知道眼睛位置的世界空间坐标和图像平面的世界空间坐标。使用这两个点可以计算出一条光线,用于与模型相交,我假设模型由三角形组成

然后,您可以使用“光线三角形测试”(ray triangle test)来确定触摸的三维位置,方法是查找与图像平面具有最近交点的三角形。如果您想要触摸哪个三角形,您还需要在进行交叉测试时保存该信息

本页给出了如何进行光线三角形相交测试的示例:

编辑:

更新了一些示例代码。它的一些稍微修改的代码,我从一个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;
}
//d是光线的方向
//o是射线的起源
//顶点是三角形的3个顶点
//faceNorm是三角形曲面的法线
布尔
三角形::相交(向量3D、向量o、向量3*顶点、向量3面范数)
{
//检查平行于平面的线
浮点r_dot_n=(点(d,面范数));
//如果r_dot_n==0,那么直线和平面是平行的,但我们需要
//根据浮点精度进行范围检查
如果(r_点n>-0.001f和&r_点n<0.001f)
返回false;
//然后计算光线原点到三角形平面的距离
浮点t=(点(面范数,(顶点[0]-o))/r_点n;
如果(t<0.0)
返回false;
//现在我们可以计算交点的重心坐标
向量3 ba_ca=交叉(顶点[1]-顶点[0],顶点[2]-顶点[0]);
浮点数=dot(-d,ba_-ca);
dist_out=dot(o-verts[0],ba_-ca)/denom;
浮点b=点(-d,交叉(r.o-verts[0],verts[2]-verts[0]))/denom;
浮点数c=点(-d,交叉点(顶点[1]-顶点[0],o-顶点[0]))/denom;
//检查tri或b&c是否有NaN值
如果(b<0 | | c<0 | | b+c>1 | | b!=b | c!=c)
返回false;
//使用重心坐标计算交点
向量3p=(1.f-b-c)*顶点[0]+b*顶点[1]+c*顶点[2];
返回true;
}

您可能感兴趣的实际交点是p。

光线跟踪是一个选项,在许多应用程序中用于执行此操作(拾取)。光线跟踪的问题是,要使一个非常简单的基本功能正常工作,这个解决方案需要做大量的工作。光线跟踪也可能很慢,但是如果只有一条光线要跟踪(比如说手指的位置),那么应该可以

OpenGL的API还提供了一种拾取对象的技术。例如,我建议你看看:


最后,最后一个选项是在屏幕空间中投影对象的顶点,并使用简单的2d技术找出手指与对象的哪些面重叠。

忘记光线跟踪和其他顶级算法。我们在App Store上为我们的一个应用程序(Iyan 3D)使用了一个简单的技巧。但每次将场景旋转到新角度时,此技术都需要一个额外的渲染过程。以不同的颜色渲染不同的对象(头、手、腿等)(不是实际的颜色,而是唯一的颜色)。读取与屏幕位置对应的渲染图像中的颜色。可以根据对象的颜色查找对象


在这种方法中,您可以使用更改渲染图像分辨率来平衡精度和性能。

我可以在iOS中使用此光线三角形交点获得任何示例代码吗?我添加了一些示例代码,其中列出了需要进行的计算。它在C++中因为我从我的一个旧项目中获取它,但是它应该是容易理解的。此外,函数的返回值不是您要查找的,但函数的结尾是计算交点,因此您应该能够将其转换为有用的格式。ES不提供拾取API,但他可以通过对每个多边形进行渲染来执行类似的操作,每个多边形渲染一种唯一的颜色,然后使用
glReadPixels
在触摸位置获取颜色,或者甚至提出了一个稍微复杂但可能更有效的系统,该系统基于在非常接近的表面上绘制一个孔,然后继续使用分割几何体和遮挡查询(如果内存可用,从iOS 5开始在iOS上提供)。如果线段是闭合的,那么您可以在绘制时通过将封面置于背景中并反转深度测试来进行遮挡。+1-这是一种非常简单且易于实现的技术。这里有更多的信息和源代码在处理(类似于Java)-搜索渲染到纹理进行渲染。那么你应该很容易找到颜色。这是正确的答案。确保关闭照明效果,例如环境光/镜面反射照明您只需在顶点着色器中计算顶点位置,并在片段着色器中输入相应的颜色值。RTT简单且易于实现。您可以使用2048x2048来提高精度