上一篇介绍了如何随机生成线,这一片,将介绍如何手动绘制线。
手动绘制线就是根据鼠标在绘图区内点击鼠标,从而绘制线段,由于我们目前所处的状态是透视投影,也就是近大远小。而且看到的并不是一个二维平面,而是三维的,所以鼠标获取的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();
}
上面这些都是新加代码,其中包括随机生成线,手动绘制线等方法;这样就可以手动绘制线段。