QOpenGLWidget 第八篇 手动绘制点、线、三角形

上一篇介绍了如何随机生成线,这一片,将介绍如何手动绘制线。

        手动绘制线就是根据鼠标在绘图区内点击鼠标,从而绘制线段,由于我们目前所处的状态是透视投影,也就是近大远小。而且看到的并不是一个二维平面,而是三维的,所以鼠标获取的xy坐标与实际绘制出来的是不一样。

下面我们进行代码编写:

1、在鼠标状态枚举值中添加一个获取点的枚举之后:kMousePoint = 4;

enum MouseStatusFlag
{
	kMouseNone = 0,
	kMouseMove = 1,
	kMouseScale = 2,
	kMousePoint = 4
};

2、在OpenGLMain 文件中添加初始化工具栏按钮

OpenGLMain头文件

    /* @接口
	* @类名 [OpenGLMain]
	* @邮箱 575814050@qq.com
	* @时间 2021年10月18号
	*/
	void initToolBar();
OpenGLMain源文件


#define QS(str) QString::fromLocal8Bit(str)

void OpenGLMain::initToolBar()
{
	QAction *pAction = NULL;
	pAction = ui.mainToolBar->addAction(QS("绘制线")); connect(pAction, &QAction::triggered, m_glWidget, &OpenGLWidget::drawLine);
	pAction = ui.mainToolBar->addAction(QS("绘制点")); connect(pAction, &QAction::triggered, m_glWidget, &OpenGLWidget::drawPoint);
	pAction = ui.mainToolBar->addAction(QS("随机生成线")); connect(pAction, &QAction::triggered, m_glWidget, &OpenGLWidget::randLines);
	pAction = ui.mainToolBar->addAction(QS("绘制折线")); connect(pAction, &QAction::triggered, m_glWidget, &OpenGLWidget::drawPolyline);
	pAction = ui.mainToolBar->addAction(QS("绘制三角形")); connect(pAction, &QAction::triggered, m_glWidget, &OpenGLWidget::drawTriangle);
}

3、在OpenGLWidget 文件中添加绘制线、点、折线等接口

OpenGLWidget 头文件


public:

	/* @接口
	 * @类名 [OpenGLMain]
	 * @时间 2021年10月18号
	 */
	void drawLine();

	/* @接口
	 * @类名 [OpenGLMain]
	 * @邮箱 575814050@qq.com
	 * @时间 2021年10月19号
	 */
	void drawPoint();

	/* @接口
	 * @返回
	 * @类名 [OpenGLWidget]
	 * @邮箱 575814050@qq.com
	 * @时间 2021年10月19号
	 */
	void randLines();

	/* @接口
	 * @类名 [OpenGLMain]
	 * @邮箱 575814050@qq.com
	 * @时间 2021年10月18号
	 */
	void drawPolyline();

	/* @接口
	 * @类名 [OpenGLMain]
	 * @邮箱 575814050@qq.com
	 * @时间 2021年10月19号
	 */
	void drawTriangle();

private:

	/* @接口
	 * @类名 [OpenGLWidget]
	 * @邮箱 575814050@qq.com
	 * @时间 2021年10月19号
	 */
	void timeOut();

	/* @接口
	 * @类名 [OpenGLWidget]
	 * @邮箱 575814050@qq.com
	 * @时间 2021年10月19号
	 */
	QPoint getPoint();

private:

	QEventLoop *m_loop;
	QTimer *m_timer = NULL;

void OpenGLWidget::timeOut()
{
	makeCurrent();
	int xVal1 = rand() % 4000;
	int yVal1 = rand() % 4000;
	int zVal1 = rand() % 4000;
	int xVal2 = rand() % 4000;
	int yVal2 = rand() % 4000;
	int zVal2 = rand() % 4000;

	float xVals = xVal1 * 1.0 / 4000 * 2 - 1.0;
	float yVals = yVal1 * 1.0 / 4000 * 2 - 1.0;
	float zVals = zVal1 * 1.0 / 4000 * 2 - 1.0;

	float xVale = xVal2 * 1.0 / 4000 * 2 - 1.0;
	float yVale = yVal2 * 1.0 / 4000 * 2 - 1.0;
	float zVale = zVal2 * 1.0 / 4000 * 2 - 1.0;

	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	float vertices[] = {
		xVals, yVals, zVals, xVals, yVals, zVals,
		xVale, yVale, zVale, xVale, yVale, zVale,
	};

	GLuint indices[] = {
		0, 1
	};

	GLuint vboebo[2];
	glGenBuffers(2, vboebo);
	glBindBuffer(GL_ARRAY_BUFFER, vboebo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboebo[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//顶点属性设置
	m_shaderProgram->setAttributeBuffer("vPosition", GL_FLOAT, 0, 3, sizeof(GLfloat) * 6);
	m_shaderProgram->enableAttributeArray("vPosition");
	//颜色属性设置
	m_shaderProgram->setAttributeBuffer("vColor", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 6);
	m_shaderProgram->enableAttributeArray("vColor");

	m_vaos << vao; repaint();
}

void OpenGLWidget::drawLine()
{
	QPoint spt = getPoint();
	QPoint ept = getPoint();

	Point3 spt1, ept1; QVector<Point3> node;
	spt1.x = spt.x() * 1.0 / width() * 2 - 1; spt1.y = spt.y() * 1.0 / height() * 2 - 1;
	ept1.x = ept.x() * 1.0 / width() * 2 - 1; ept1.y = ept.y() * 1.0 / height() * 2 - 1;
	spt1.z = (spt1.x + spt1.y) / 2; ept1.z = (ept1.x + ept1.y) / 2;
	node << spt1 << ept1; drawEntity(node, GL_LINES);
}

void OpenGLWidget::drawPoint()
{

}

void OpenGLWidget::randLines()
{
	if(m_timer == NULL)
	{
		m_timer = new QTimer;
		connect(m_timer, &QTimer::timeout, this, &OpenGLWidget::timeOut);
		m_timer->start(500);
	}
	else
	{
		m_timer->stop();
		delete m_timer;
		m_timer = NULL;
	}
}

QPoint OpenGLWidget::getPoint()
{	
	m_mouseStatus |= kMousePoint;
	m_loop->exec();
	m_mouseStatus ^= kMousePoint;
	return m_lastPt;
}

void OpenGLWidget::drawPolyline()
{

}

void OpenGLWidget::drawTriangle()
{

}

void OpenGLWidget::mousePressEvent(QMouseEvent *ev)
{
	m_lastPt = ev->pos();
	if(ev->button() == Qt::MiddleButton)
	{
		m_mouseStatus |= kMouseMove;
	}
	if(ev->button() == Qt::LeftButton)
	{
		if(m_mouseStatus & kMousePoint)
			m_loop->exit();
	}
	QOpenGLWidget::mousePressEvent(ev);
}

void OpenGLWidget::mouseReleaseEvent(QMouseEvent *ev)
{
	if(ev->button() == Qt::MiddleButton)
		m_mouseStatus ^= kMouseMove;
	QOpenGLWidget::mouseReleaseEvent(ev);
}

void OpenGLWidget::drawEntity(const QVector<Point3> &node, int type)
{
	GLuint vao;
	makeCurrent();
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	float *plist = new float[node.length() * 6];
	GLuint *pindices = new GLuint[node.length()];
	for(int idx = 0; idx < node.length(); ++idx)
	{
		Point3 pt = node[idx];
		plist[idx * 6 + 0] = pt.x;
		plist[idx * 6 + 1] = pt.y;
		plist[idx * 6 + 2] = pt.z;
		pindices[idx] = idx;
		plist[idx * 6 + 3] = fabs(plist[idx * 6 + 0]);
		plist[idx * 6 + 4] = fabs(plist[idx * 6 + 1]);
		plist[idx * 6 + 5] = fabs(plist[idx * 6 + 2]);
	}
	GLuint vboebo[2];
	glGenBuffers(2, vboebo);
	glBindBuffer(GL_ARRAY_BUFFER, vboebo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(plist), plist, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboebo[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pindices), pindices, GL_STATIC_DRAW);

	//顶点属性设置
	m_shaderProgram->setAttributeBuffer("vPosition", GL_FLOAT, 0, 3, sizeof(GLfloat) * 6);
	m_shaderProgram->enableAttributeArray("vPosition");
	//颜色属性设置
	m_shaderProgram->setAttributeBuffer("vColor", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 6);
	m_shaderProgram->enableAttributeArray("vColor");

	//delete[] plist; delete[] pindices;

	m_vaos << vao; repaint();
}

上面这些都是新加代码,其中包括随机生成线,手动绘制线等方法;这样就可以手动绘制线段。

 

 QOpenGLWidget 第七篇 vao、vbo随机绘制线

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值