Pee*_*eeS 15 opengl math matrix
是时候进行一些数学计算了...
我需要预测窗口大小的4个点:
<0,0> <1024,768>
进入一个世界空间坐标,它将形成一个四边形的形状,以后将用于地形剔除 - 没有GluUnproject
仅供测试,我使用鼠标坐标 - 并尝试将它们投射到世界坐标上
Pee*_*eeS 31
解决
这是如何准确地,一步一步地做到这一点.
0)在客户区域内获取鼠标坐标
1)如果不需要模型矩阵,请获取投影矩阵和视图矩阵.
2)乘法投影*查看
3)反转乘法的结果
4)构造一个由4组成的vector4
x = mouseposition.x在窗口x的范围内 - 转换为-1和1之间的值
y = mouseposition.y在窗口y的范围内 - 转换为介于-1和1之间的值 - 如果需要,请记住反转mouseposition.y
z = the depth value(这可以通过glReadPixel获得) - 你可以手动从-1到1(zNear,zFar)
w =1.0
5)通过之前创建的反转矩阵乘以向量
6)在矩阵乘法(透视除法)之后将结果向量除以它的w分量
POINT mousePos;
GetCursorPos(&mousePos);
ScreenToClient( this->GetWindowHWND(), &mousePos );
CMatrix4x4 matProjection = m_pCamera->getViewMatrix() * m_pCamera->getProjectionMatrix() ;
CMatrix4x4 matInverse = matProjection.inverse();
float in[4];
float winZ = 1.0;
in[0]=(2.0f*((float)(mousePos.x-0)/(this->GetResolution().x-0)))-1.0f,
in[1]=1.0f-(2.0f*((float)(mousePos.y-0)/(this->GetResolution().y-0)));
in[2]=2.0* winZ -1.0;
in[3]=1.0;
CVector4 vIn = CVector4(in[0],in[1],in[2],in[3]);
pos = vIn * matInverse;
pos.w = 1.0 / pos.w;
pos.x *= pos.w;
pos.y *= pos.w;
pos.z *= pos.w;
sprintf(strTitle,"%f %f %f / %f,%f,%f ",m_pCamera->m_vPosition.x,m_pCamera->m_vPosition.y,m_pCamera->m_vPosition.z,pos.x,pos.y,pos.z);
SetWindowText(this->GetWindowHWND(),strTitle);
Run Code Online (Sandbox Code Playgroud)
将所有矩阵相乘.然后反转结果.投影后的点总是在-1,1.所以四角屏幕点是-1,-1; 1,1; 1,-1; 1,1.但是你仍然需要选择z值.如果你在OpenGL中,z介于-1和1之间.对于directx,范围是0到1.最后取点并用矩阵转换它们
小智 6
我不得不对这里提供的答案进行一些调整。但这是我最终得到的代码(注意我使用的是 GLM,这可能会影响乘法顺序)。NearResult 是近平面上的投影点, farResult 是远平面上的投影点。我想执行光线投射以查看我的鼠标悬停在什么上面,因此我将它们转换为方向向量,然后该向量将从我的相机的位置发出。
vec3 getRayFromScreenSpace(const vec2 & pos)
{
mat4 invMat= inverse(m_glData.getPerspective()*m_glData.getView());
vec4 near = vec4((pos.x - Constants::m_halfScreenWidth) / Constants::m_halfScreenWidth, -1*(pos.y - Constants::m_halfScreenHeight) / Constants::m_halfScreenHeight, -1, 1.0);
vec4 far = vec4((pos.x - Constants::m_halfScreenWidth) / Constants::m_halfScreenWidth, -1*(pos.y - Constants::m_halfScreenHeight) / Constants::m_halfScreenHeight, 1, 1.0);
vec4 nearResult = invMat*near;
vec4 farResult = invMat*far;
nearResult /= nearResult.w;
farResult /= farResult.w;
vec3 dir = vec3(farResult - nearResult );
return normalize(dir);
}
Run Code Online (Sandbox Code Playgroud)