OpenGL 射线选择中射线的生成过程,代码与图示参考

版权声明:----------------------------未经博主允许, 随意转载---------------------------- https://blog.csdn.net/yulinxx/article/details/78025532

Mouse Picking with Ray Casting

在射线选择中,坐标的转换原理:
http://antongerdelan.net/opengl/raycasting.html

这里写图片描述

参考:
http://blog.csdn.net/wind_hzx/article/details/40016619

构建的视图代码

//glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 50.0f);   // 相机距离原点50
//glm::vec3 cameraTarg = glm::vec3(0.0f, 0.0f, 0.0f);
//glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
glm::mat4 matView = glm::lookAt(cameraPos, cameraTarg, cameraUp);

glm::mat4 matProj = glm::perspective(3.141592f / 2.0f, 
    GLfloat(WIDTH / HEIGH), 1.0f, 100.0f); // 角度, 宽高比,最近点,最远点

所得到的示图剖面如下: (沿X轴看 向上为Y, 红线为Z轴)
黄色部分即为可见区域

在此,用 perspective 角度 3.141592f / 2.0f 为90度, 则半分开来为45度, 涉及的三角形两直线边相等,方便计算

这里写图片描述

点击屏幕只能对应一个平面二维的xy坐标,
在此以Z =1.0f为基准,即xy坐标对应视图最远处z的坐标点 (OpenGL中,XYZ最小最大值 -1 至 1)

上述代码中 perspective 对应的最远处为100,
由于相机在Z=50处,则视图最远处为Z = -50, 即可见区域最远处为竖起的黄线为Z的终点

可得下述对应点关系: (Z轴均在-50处)

若鼠标点击窗口右侧中点, 即点击OpenGL中的(0.0f, 1.0f) 点,
则发出的射线为从相机处,射至(0, 100, -50)方向 (可视区域Y轴正方向最大值为100)

若鼠标点击窗口右上角点, 即点击OpenGL中的(1.0f, 1.0f) 点,
则发出的射线为从相机处,射至(100, 100, -50)方向 (可视区域Y轴正方向最大值为100)

若鼠标点击OpenGL中的(0.0f, 0.5f) 点,
则发出的射线为从相机处,射至(0, 50, -50)方向 (可视区域Y轴正方向的一半50)

若鼠标点击OpenGL中的(0.5f, 0.5f) 点,
则发出的射线为从相机处,射至(50, 50, -50)方向 (可视区域X和Y轴正方向的一半50)


鼠标点击窗口中心点, 即点击OpenGL中的(0.0f, 0.0f) 点,
则发出的射线为从相机处,沿Z轴负方向走(0,0,0),即从相机往红线右侧走

上述即为点与视图间的关系

用代码进行转换:

这里写图片描述


glm::mat4 matView = glm::lookAt(cameraPos, cameraTarg, cameraUp);
glm::mat4 matProj = glm::perspective(3.141592f / 2.0f, GLfloat(WIDTH / HEIGH), 1.0f, 100.0f);

float mouseX = 0.0f;    // 鼠标点击点
float mouseY = 1.0f;

// x y z w  4D裁剪坐标 Z1,至最远处,即z离相机100,即为(0,0-50)
glm::vec4 ray_clip = glm::vec4(mouseX, mouseY, 1.0f, 1.0f);

glm::vec4 ray_eye = glm::inverse(matProj) * ray_clip;   // 转为视觉坐标

glm::vec4 ray_world = glm::inverse(matView) * ray_eye;      // 转为世界坐标
ray_world.x /= ray_world.w;
ray_world.y /= ray_world.w;
ray_world.z /= ray_world.w;
printf("ray_world X Y Z %.3f, %.3f, %.3f\n", ray_world.x, ray_world.y, ray_world.z);
glm::vec3 ray_wordXYZ = glm::vec3(ray_world);
glm::vec3 ray_dir = glm::normalize(ray_wordXYZ - cameraPos);

printf("ray_dir X Y Z %.3f, %.3f, %.3f\n\n", ray_dir.x, ray_dir.y, ray_dir.z);

源码下载:
http://download.csdn.net/download/yulinxx/9984821

模拟了一下,从摄像机位置点击,发射许多线至远端
这里写图片描述

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/yulinxx/article/details/78025532
今日推荐