拾取物体

参考文章:https://www.cnblogs.com/icmzn/p/7373663.html

本来想着可以像Unity一样用射线去拾取物体,但是找资料的时候发现这么一句话:OpenGL中的拾取是对OpenGL图形管线的一个应用。OpenGL中的拾取并不是像D3D一样采用射线交叉测试来判断是否选中一个目标,而是在图形管线投影变换(Projection Transformation)阶段利用拾取矩阵来实现的。

就是说,OpenGL拾取物体的流程大概是这样的:

初始化projection矩阵

鼠标在窗口上点击,获取到鼠标的位置,在该位置产生一个拾取矩阵赋值给projection矩阵:

gluPickMatrix(x, viewport[3] - y, 2, 2, viewport);

x,y为鼠标位置;

viewport[3] - y:由于OpenGL的原点是左上角,和鼠标相反要减掉鼠标坐标。

GLint viewport[4];视口信息;
glGetIntegerv(GL_VIEWPORT, viewport);//获取视口信息

2,2: 拾取窗口的大小;

再通过    glOrtho(-10, 10, -10, 10, -camera->farDist, 0); (注意:z的方向是反的)创建一个投影矩阵;

设置一下物体的渲染模式glRenderMode(GL_SELECT);

创建select缓存    GLuint selectBuff[32] = { 0 };    glSelectBuffer(64, selectBuff);

再设置好物体的name(id);

加渲染物体的代码就可以拾取物体了。

Object* MyWidget::PickObj(GLint x,GLint y)
{
	QMatrix4x4 tempMat;

	GLuint selectBuff[32] = { 0 };
	GLint hits, viewport[4];
	glGetIntegerv(GL_VIEWPORT, viewport);
	glSelectBuffer(64, selectBuff);

	glRenderMode(GL_SELECT);

	glInitNames();
	glPushName(0);

	glMatrixMode(GL_PROJECTION);

	glPushMatrix();
	glLoadIdentity();

	float m[16];
	glGetFloatv(GL_PROJECTION_MATRIX, m);

	gluPickMatrix(x, viewport[3] - y, 2, 2, viewport);
	glGetFloatv(GL_PROJECTION_MATRIX, m);

	glOrtho(-10, 10, -10, 10, -camera->farDist, 0);
	glGetFloatv(GL_PROJECTION_MATRIX, m);
	for (int i = 0; i < sizeof(m) / sizeof(m[0]); i++)
	{
		tempMat.data()[i] = m[i];
	}

	for (int i = 0; i < objList.size(); i++)
	{
		objList[i]->OnSelectMode();//物体切换至Select模式 glRenderMode(GL_SELECT)
		objList[i]->Render(f, tempMat, camera->GetViewMatrix());//渲染物体以拾取
	}

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();

	glGetFloatv(GL_PROJECTION_MATRIX, m);
	hits = glRenderMode(GL_RENDER);//获取拾取物体的数量
	qDebug() << "hits:" <OnRenderMode();//物体切换至Render模式 glRenderMode(GL_RENDER)
	}

	if (hits > 0)
	{
		qDebug() << "id: " << selectBuff[3];//最后结果存在缓存的第四个元素中
		for (int i = 0; i < objList.size(); i++)
		{
			if (selectBuff[3] == objList[i]->id)
				return objList[i];
		}
	}
	else
		return nullptr;



}

渲染物体的代码里加上

	if (mode == GL_SELECT)
	{
		glLoadName(id);
	}

必须加在glDrawArrays之前!

拾取物体_第1张图片

获取到物体的实例之后再对物体的model矩阵进行操作就可以实现拖拽物体的功能了。

你可能感兴趣的:(Qt,OpenGL,毕设)