ArcBall+glm 实现射线拾取Ray Picking
在做一个基于qt和opengl的网格变形实验,用户交互方面需要实现射线拾取,框架本身是使用ArcBall实现鼠标拖拽旋转的。探索了几天,使用glm实现了射线拾取
1 射线拾取原理
射线拾取的原理很多博客也讲过了,主要就是:以当前眼睛位置(摄像机位置)
为起点,以眼睛位置(摄像机位置)
指向鼠标点选位置所对应的世界坐标
的方向为方向,生成一条射线,再判断射线与网格中的各个三角形是否相交。
个人认为重点是得到眼睛位置(摄像机位置)
和鼠标点选位置所对应的世界坐标
2 实现步骤
2.1 生成射线
- 眼睛位置
vec3 eyepos = eye_distance_*eye_direction_;; //视点坐标与观察点坐标
//ptr_arcball_是轨迹球,GetInvertedBallMatrix()是得到旋转四元数构成的矩阵的逆矩阵
glm::mat4 invertM = glm::make_mat4(ptr_arcball_->GetInvertedBallMatrix());
glm::mat3 invertM_3 = glm::mat3(invertM); //取前三行&前三列
glm::vec3 eyepos_glm = glm::vec3(eyepos[0],eyepos[1],eyepos[2]);
glm::vec3 cameraPos = invertM_3 * eyepos_glm;
- 鼠标点选位置对应的世界坐标
// Get the matrix matView & matProj
glm::mat4 matView = glm::make_mat4(ptr_arcball_->GetBallMatrix());//ptr_arcball_是轨迹球,GetBallMatrix()是得到旋转四元数构成的矩阵
glm::mat4 matProj = glm::perspective(3.141592f / 2.0f, GLfloat(WIDTH / HEIGHT), 1.0f, 100.0f);
vec3 mouse_coord = convert(x,y,width(),height());
// x y z w 4D裁剪坐标 Z取1,至最远处,即z离相机100,即为(0,0-50)
glm::vec4 ray_clip = glm::vec4(mouse_coord[0],