Opengl 如何从屏幕坐标中获取对象坐标?

Opengl 如何从屏幕坐标中获取对象坐标?,opengl,Opengl,我试图从鼠标位置获取对象空间坐标。我有一些标准的渲染代码,效果很好 问题在于鼠标拾取代码。我尝试过很多事情,也遇到过类似的问题,但我似乎不明白为什么它不起作用 根据鼠标在对象上的位置,我希望结果返回[-1,1]内的x,y坐标。我确实得到了[-1,1]范围内的点,但它们非常倾斜,例如(2.63813e-012,-1300) 非项目代码: int z; glReadPixels(mouse_pos_[0], int( navWidget->height() - mouse_pos_[1]),

我试图从鼠标位置获取对象空间坐标。我有一些标准的渲染代码,效果很好

问题在于鼠标拾取代码。我尝试过很多事情,也遇到过类似的问题,但我似乎不明白为什么它不起作用

根据鼠标在对象上的位置,我希望结果返回[-1,1]内的x,y坐标。我确实得到了[-1,1]范围内的点,但它们非常倾斜,例如(2.63813e-012,-1300)

非项目代码:

int z;
glReadPixels(mouse_pos_[0], int( navWidget->height() - mouse_pos_[1]), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
glm::vec3 win(mouse_pos_[0], navWidget->height() - mouse_pos_[1], z);
glm::vec4 viewport(0, 0, navWidget->width(), navWidget->height());
auto result_vec3 = glm::unProject(win, view * model1, proj, viewport);

auto result = glm::normalize(glm::vec2(result_vec3.x, result_vec3.y)); // < -- I normalize here since that gave good results without the translate


bool left_image = true;

    if (!(result.x <= length_per_side && result.x >= -length_per_side &&
        result.y <= length_per_side && result.y >= -length_per_side)) {
// do stuff
        }
    }
intz;
glReadPixels(鼠标位置[0],int(导航小部件->高度()-鼠标位置[1]),1,1,GL深度分量,GL浮动,&z);
glm::vec3 win(鼠标位置[0],导航小部件->高度()-鼠标位置[1],z);
glm::vec4视口(0,0,navWidget->width(),navWidget->height());
自动结果=glm::取消项目(win,视图*model1,项目,视口);
自动结果=glm::规格化(glm::vec2(结果_vec3.x,结果_vec3.y));//<--我在这里进行规范化,因为在没有翻译的情况下,这会产生很好的结果
bool left_image=true;
如果(!(result.x=-每侧的长度)&&
结果.y=-长度(每边){
//做事
}
}
渲染代码:

float fov = 2*(atan((camProjModule->camResY()/2*camProjModule->camPixSizeY()) /
    camProjModule->camFocalLength()) / M_PI * 180.0);
float znear = 1.0f;
float zfar = 6000.0f;
//float aspect = 1024.f / 683.f;
float aspect = navWidget->width() / navWidget->height();

glm::mat4 proj = glm::perspective(fov, aspect, znear, zfar);
float required_height =(float)( znear * tan((fov / 2.f) * M_PI / 180.f)); 
float eye_distance = znear / required_height * ((float)(navWidget->height()) / 2.f);
eye_distance = 300.f;
glm::mat4 view = glm::lookAt(glm::vec3(0.f, 0.f, 1.f * eye_distance), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 1.f, 0.f));


glUseProgram(correspond_shader_);
glBindVertexArray(quad_vao_);
glUniform3f(colorLoc, 1.0f, 1.0f, 1.0f);

// draw left
if (left_correspond_texture_) {
    glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE0 + 0);
    glBindTexture(GL_TEXTURE_2D, left_correspond_texture_);
    glUniform1i(drawTexLoc, left_correspond_texture_);
}

GLint proj_loc = glGetUniformLocation(correspond_shader_, "proj");
GLint view_loc = glGetUniformLocation(correspond_shader_, "view");
GLint draw_tex_loc = glGetUniformLocation(correspond_shader_, "drawTex");

glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(proj));
glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(view));


float ratio = 1024.f / 683.f;
float height = navWidget->height() / 2.f;
float ratio_to_multiply = height / 2.f;

glm::vec3 translation_vector = glm::vec3(0.f, height / 2.f, 0.f); // < --- If I remove this translation I get results that seem to be correct, and can be used after normalizing the x and y

glm::mat4 left_model = glm::scale(glm::translate(glm::mat4(1.f), translation_vector), glm::vec3(ratio * ratio_to_multiply, ratio_to_multiply, 1.f));
glm::mat4 right_model = glm::scale(glm::translate(glm::mat4(1.f), -1.f * translation_vector), glm::vec3(ratio * ratio_to_multiply, ratio_to_multiply, 1.f));

glUniformMatrix4fv(glGetUniformLocation(correspond_shader_, "model"), 1, GL_FALSE, glm::value_ptr(left_model));

glDrawArrays(GL_TRIANGLES, 0, 6); //, GL_UNSIGNED_INT, NULL);
float fov=2*(atan((camProjModule->camResY()/2*camProjModule->capixsizey())/
camProjModule->camFocalLength())/M_PI*180.0);
浮球znear=1.0f;
浮子zfar=6000.0f;
//浮动纵横比=1024.f/683.f;
浮动方面=navWidget->width()/navWidget->height();
glm::mat4 proj=glm::透视图(视野、方位、znear、zfar);
所需浮子高度=(浮子)(znear*tan((fov/2.f)*M_PI/180.f));
浮眼距离=znear/required_height*((float)(navWidget->height())/2.f);
视距=300.f;
glm::mat4 view=glm::lookAt(glm::vec3(0.f,0.f,1.f*眼睛距离),glm::vec3(0.f,0.f,0.f),glm::vec3(0.f,1.f,0.f));
glUseProgram(对应着色器);
glBindVertexArray(四轮);
glUniform3f(colorLoc,1.0f,1.0f,1.0f);
//左转
if(左纹理){
glEnable(GL_纹理_2D);
玻璃纹理(GL_纹理0+0);
glBindTexture(GLU纹理2D,左纹理);
glUniform1i(drawTexLoc,左纹理);
}
闪烁项目位置=glGetUniformLocation(对应“项目”);
闪烁视图=glGetUniformLocation(对应于“视图”);
闪烁绘制(GLint draw_tex_loc=glGetUniformLocation(对应于“drawTex”);
glUniformMatrix4fv(项目位置,1,GL错误,glm::value_ptr(项目));
glUniformMatrix4fv(视图位置,1,GL错误,glm::值ptr(视图));
浮动比率=1024.f/683.f;
浮动高度=navWidget->height()/2.f;
浮动比率乘以=高度/2.f;
glm::vec3 translation_vector=glm::vec3(0.f,height/2.f,0.f);//<--如果我删除这个转换,我得到的结果似乎是正确的,并且可以在规范化x和y之后使用
glm::mat4 left_model=glm::scale(glm::translate(glm::mat4(1.f),translation_vector),glm::vec3(ratio*ratio_与_相乘,ratio_与_相乘,1.f));
glm::mat4 right_model=glm::scale(glm::translate(glm::mat4(1.f),-1.f*translation_vector),glm::vec3(ratio*ratio_与_相乘,ratio_与_相乘,1.f));
glUniformMatrix4fv(glGetUniformLocation(对应于“模型”),1,GL_FALSE,glm::value_ptr(左模型));
glDrawArray(GL_三角形,0,6);/,GL_UNSIGNED_INT,NULL);

编辑:我认为我的问题需要改进。我画了两个四边形,并分别渲染了纹理。我想做的是根据它是哪个四边形,将鼠标坐标作为标准化纹理坐标。

我看到您正在使用glm库。可以使用非投影方法获取鼠标坐标/光线方向

glm::vec2 screenPos(mousePos.x, mousePos.y);
screenPos.y = height - screenPos.y;

float aspect = width / height;
glm::vec4 viewport = glm::vec4(0.0f, 0.0f, width , height);
glm::mat4 proj     = glm::perspective(75.0f, aspect, 0.1f, 10000.0f);

glm::vec3 a (screenPos.x, screenPos.y, 0);
glm::vec3 b (screenPos.x, screenPos.y, 1);

glm::vec3 result  = glm::unProject(a, viewMatrix, proj, viewport);
glm::vec3 result2 = glm::unProject(b, viewMatrix, proj, viewport);

glm::vec3 pickingPos = result;
glm::vec3 pickingDir = result2 - result;

之后,您可以使用方向和位置检查碰撞

我看到您正在使用glm库。可以使用非投影方法获取鼠标坐标/光线方向

glm::vec2 screenPos(mousePos.x, mousePos.y);
screenPos.y = height - screenPos.y;

float aspect = width / height;
glm::vec4 viewport = glm::vec4(0.0f, 0.0f, width , height);
glm::mat4 proj     = glm::perspective(75.0f, aspect, 0.1f, 10000.0f);

glm::vec3 a (screenPos.x, screenPos.y, 0);
glm::vec3 b (screenPos.x, screenPos.y, 1);

glm::vec3 result  = glm::unProject(a, viewMatrix, proj, viewport);
glm::vec3 result2 = glm::unProject(b, viewMatrix, proj, viewport);

glm::vec3 pickingPos = result;
glm::vec3 pickingDir = result2 - result;

之后,您可以使用方向和位置检查碰撞

我看到您正在使用glm库。可以使用非投影方法获取鼠标坐标/光线方向

glm::vec2 screenPos(mousePos.x, mousePos.y);
screenPos.y = height - screenPos.y;

float aspect = width / height;
glm::vec4 viewport = glm::vec4(0.0f, 0.0f, width , height);
glm::mat4 proj     = glm::perspective(75.0f, aspect, 0.1f, 10000.0f);

glm::vec3 a (screenPos.x, screenPos.y, 0);
glm::vec3 b (screenPos.x, screenPos.y, 1);

glm::vec3 result  = glm::unProject(a, viewMatrix, proj, viewport);
glm::vec3 result2 = glm::unProject(b, viewMatrix, proj, viewport);

glm::vec3 pickingPos = result;
glm::vec3 pickingDir = result2 - result;

之后,您可以使用方向和位置检查碰撞

我看到您正在使用glm库。可以使用非投影方法获取鼠标坐标/光线方向

glm::vec2 screenPos(mousePos.x, mousePos.y);
screenPos.y = height - screenPos.y;

float aspect = width / height;
glm::vec4 viewport = glm::vec4(0.0f, 0.0f, width , height);
glm::mat4 proj     = glm::perspective(75.0f, aspect, 0.1f, 10000.0f);

glm::vec3 a (screenPos.x, screenPos.y, 0);
glm::vec3 b (screenPos.x, screenPos.y, 1);

glm::vec3 result  = glm::unProject(a, viewMatrix, proj, viewport);
glm::vec3 result2 = glm::unProject(b, viewMatrix, proj, viewport);

glm::vec3 pickingPos = result;
glm::vec3 pickingDir = result2 - result;

然后你可以用方向和位置来检查碰撞

我认为CrSe的答案也是正确的。我已经这样做了,我可以选择模型上的任何点:

我从这两点(p1和p2)拍摄光线:


如果该光线与顶点之间的距离小于阈值,我将拾取该点。我希望它有用

我认为CrSe的答案也是正确的。我已经这样做了,我可以选择模型上的任何点:

我从这两点(p1和p2)拍摄光线:


如果该光线与顶点之间的距离小于阈值,我将拾取该点。我希望它有用

我认为CrSe的答案也是正确的。我已经这样做了,我可以选择模型上的任何点:

我从这两点(p1和p2)拍摄光线:


如果该光线与顶点之间的距离小于阈值,我将拾取该点。我希望它有用

我认为CrSe的答案也是正确的。我已经这样做了,我可以选择模型上的任何点:

我从这两点(p1和p2)拍摄光线:


如果该光线与顶点之间的距离小于阈值,我将拾取该点。我希望它有用

你说的物体坐标是什么意思?你想挑一个要点吗?在德国劳埃德船级社管道中进行了一次很好的步行。倒过来!代码中的规范化显然是错误的。确保首先正确执行窗口->标准化设备。另外,请确保使用投影矩阵是w=1的透视图,因为只有这样,投影矩阵才能通常反转。@祝好运,我想在对象上选择一个相对于对象坐标的点。@starmole我对gl管道有很好的处理能力。非对象处理所有与反向操作相关的事情。你不觉得应该