我尝试通过碰撞进行光线拾取,这意味着屏幕上的 2D 位置被转换为模型空间中的 3D 位置。我的问题是,光线并不总是与模型相交以产生有效的 3D 位置。
这就是我所做的:
我在帧缓冲区中创建了一个深度纹理,以便glReadPixels()
稍后使用它。
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
cv::Mat_<float> depthCV(screenHeight, screenWidth);
glReadPixels(0, 0, screenWidth, screenHeight, GL_DEPTH_COMPONENT, GL_FLOAT, depthCV.ptr());
之后我将深度线性化并将其存储到cv::Mat_<uchar>
边缘检测中cv::Canny()
:(不要忘记翻转图像。)
cv::blur(gray, edge, cv::Size(3, 3));
cv::Canny(edge, edge, edgeThresh, edgeThresh * ratio, 3);
...并通过
cv::findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cv::Point(0, 0));
轮廓的 2D 坐标 (x,y) 现在正在通过以下方式转换为 3D 模型坐标:
GLint viewport[4];
GLfloat winX, winY, winZ;
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)(y);
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
glm::vec4 viewportvec(viewport[0], viewport[1], viewport[2], viewport[3]);
glm::vec3 winCoords(winX, winY, winZ);
glm::vec3 modelCoords = glm::unProject(winCoords, view*model, proj, viewportvec);
完成此操作并查看它显示的 3D 点后,某些光线不会与模型相交。射线的长度接近远平面的值。我试图通过查看输入 (x,y) 周围的一个像素邻域来扩大输入。仍然有一些光线不与模型相交。
知道这是为什么吗?或者如何解决?具有先前模糊的边缘提取是否负责?
我附上了一张可以看到分布的图片。蓝色点是不与模型相交的点(光线长度接近远平面的值),红色点是。我使用茶壶模型进行测试。
为了便于阅读,我不想在这里粘贴我的整个代码。如果需要更多代码或信息来更好地理解可能出现的问题,请告诉我。