我正在开发一款3D安卓游戏,我是新手。我正在使用GLM,Android NDK,Opengl ES 2.0。
当我触摸屏幕时,我想在世界空间中获得3D点。
我的部分代码:
//Camera data
float eye[3] = {0.0f, 11.0f, -2.0f};
float look[3] = {0.0f, -1.0f, 3.0f};
const float up[3] = {0.0f, 1.0f, 0.0f};
glViewport(0, 0, width, height);
...
const float ratio = (float) width / height;
mViewMatrix = glm::lookAt(glm::make_vec3(eye), glm::make_vec3(look), glm::make_vec3(up));
mProjMatrix = glm::perspective(30.0f, -ratio, near, far); // near = 1.0f; far = 100.0f;
mMVPMatrix = mProjMatrix * mViewMatrix;
....
我试过这个:
glm::vec3 worldXYZ = glm::unProject(glm::vec3(x, height - y, 1.0f), mViewMatrix, mProjMatrix, glm::vec4(0, 0, width, height));
其中x和y是像素中的屏幕坐标,但我得到了奇怪的结果。当我触摸示例原始文件时,结果应该类似于(0,0,0)
,但我得到了这个:(0.5, -89.6, 16)
。
我在哪里弄错了?
更新我的回答:
Andon M. Coleman是对的,我根据他的回答改变了我的代码。我没有使用glm::unProject
方法,因为我最终得到了不好的结果,所以我退后一步,我自己计算了一些东西。
float xx = (2.0f * x) / width - 1.0f; // between [-1;+1]
float yy = (2.0f * (height - y)) / height - 1.0f; // between [-1;+1]
float zzN = 0.0f; // near
float zzF = 1.0f; // far
glm::mat4 invM = glm::inverse(mMVPMatrix);
glm::vec4 mmN = invM * glm::vec4(xx, yy, zzN, 1.0f);
glm::vec4 mmF = invM * glm::vec4(xx, yy, zzF, 1.0f);
规范化向量:
glm::vec3 nn = glm::vec3(mmN[0] / mmN[3], mmN[1] / mmN[3], mmN[2] / mmN[3]);
glm::vec3 ff = glm::vec3(mmF[0] / mmF[3], mmF[1] / mmF[3], mmF[2] / mmF[3]);
然后我需要光线(从nn到ff)。我使用了这个线方程:
x = x1 +(x2-x1)* t
y = y1 +(y2-y1)* t
z = z1 +(z2-z1)* t
其中P(x,y,z)是光线中的点,nn =(x1,y1,z1),ff =(x2,y2,z2)是定义光线的2个点。我对y = 0(光线和平面正在相遇)的点感兴趣,所以我最终计算出x和z世界坐标,如下所示:
float t = nn[1] / (nn[1] - ff[1]);
float wx = nn[0] + (ff[0] - nn[0]) * t;
float wz = nn[2] + (ff[2] - nn[2]) * t;
答案 0 :(得分:2)
您已解决投射到(x, height - y)
的 最远 点。这在大多数时候都不是特别有用。
你也应该解决 最近的 点(Z = 0.0 ),然后你可以投射穿过这两点的光线。生成的光线将代表投射到(x,y,*)
的无限数量的点。