问题描述
今天尝试使用 Qt 的OpenGL相关的函数进行编程,在编译链接的时候,遇到了链接错误:
编写代码的时候,我引入了这些库:
#include <QGLWidget>
#include <gl/gl.h>
#include <gl/GLU.h>
编写过程中,VS2019没有任何报错与提示,所使用的函数也都可以正常使用
由于我使用的是VS2019,并不是Qt Creator,在网上查了一些解决办法,大部分都是讲Qt Creator的解决方法,主要是修改pro文件,打开pro文件修改LIBS:
LIBS += -lopengl32 -lglu32
但我这个项目并没有pro文件,需要额外去生成。
搜了很久,也没找到太多相关的解决方法。只能从报错去分析,可能是缺少一些静态库,导致链接发生了问题
解决办法
既然感觉是缺少静态库,那就尝试添加一些静态库吧
根据我调用的库以及Qt Creator解决方法,我初步判定应该是需要下面两个静态库:
- OpenGL32.Lib
- GlU32.Lib
所以我就给项目配置了这两个静态库:
- 打开项目属性页–>链接器–>常规–>附加库目录,在这个里面添加两个文件所在的目录,一般在下面的路径下是可以找到的:
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64
- 链接器–>输入–>附近依赖项,输入:
OpenGL32.Lib GLU32.Lib
完成上述配置以后,再次重新生成解决方案,可以看到成功生成,并且可以运行!
完整代码:
OpenGLTools.h
/// OpenGLTools.h
#ifndef OPENGL_TOOLS_H
#define OPENGL_TOOLS_H
#include <QGLWidget>
#include <QMouseEvent>
#include <QPoint>
#include <QColor>
#include <QColorDialog>
#include <gl/gl.h>
#include <gl/GLU.h>
// #include "ui_OpenGlTools.h"
class COpenGlTools : public QGLWidget
{
Q_OBJECT
public:
COpenGlTools(QWidget *parent = nullptr);
~COpenGlTools();
protected:
// inherited by QGLWidget
void initializeGL();
void resizeGL(int width, int height);
void paintGL();
// inherited by QWidget
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void mouseDoubleEvent(QMouseEvent* event);
private:
// Ui::COpenGlToolsClass ui;
void draw();
int faceAtPosition(const QPoint& pos);
GLfloat rotationX;
GLfloat rotationY;
GLfloat rotationZ;
QColor faceColors[4];
QPoint lastPos;
};
#endif // OPENGL_TOOLS_H
OpenGLTools.cpp
#include "OpenGlTools.h"
COpenGlTools::COpenGlTools(QWidget *parent)
: QGLWidget(parent)
{
// ui.setupUi(this);
// 显示描述表
setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
// 初始化私有变量
rotationX = -21.0;
rotationY = -57.0;
rotationZ = 0.0;
faceColors[0] = Qt::red;
faceColors[1] = Qt::green;
faceColors[2] = Qt::blue;
faceColors[3] = Qt::yellow;
}
COpenGlTools::~COpenGlTools()
{}
// 在调用paintGL()之前只被调用一次
void COpenGlTools::initializeGL()
{
// 定义显示列表以及其他初始化
qglClearColor(Qt::black);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
// 窗口部件改变大小时,调用resizeGL
void COpenGlTools::resizeGL(int width, int height)
{
// 设置视口
glViewport(0, 0, width, height);
// 设置投影
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat x = GLfloat(width) / height;
glFrustum(-x, x, -1.0, 1.0, 4.0, 15.0);
glMatrixMode(GL_MODELVIEW);
}
// 需要重绘时调用paintGL,类似于paintEvent
void COpenGlTools::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 等价于QPainter
draw(); // 实际的绘制
}
void COpenGlTools::mousePressEvent(QMouseEvent* event)
{
lastPos = event->pos();
}
void COpenGlTools::mouseMoveEvent(QMouseEvent* event)
{
GLfloat dx = GLfloat(event->x() - lastPos.x()) / width();
GLfloat dy = GLfloat(event->y() - lastPos.y()) / height();
// 左键沿着 x 和 y 轴旋转
if (event->buttons() & Qt::LeftButton)
{
rotationX += 180 * dy;
rotationY += 180 * dx;
updateGL(); // 重绘场景
}
else if (event->buttons() & Qt::RightButton) // 右键沿着 x 和 y 轴旋转
{
rotationX += 180 * dy;
rotationZ += 180 * dx;
updateGL(); // 重绘场景
}
lastPos = event->pos();
}
void COpenGlTools::mouseDoubleEvent(QMouseEvent* event)
{
int face = faceAtPosition(event->pos()); // 确定光标下的面
if (face != -1)
{
QColor color = QColorDialog::getColor(faceColors[face], this);
if (color.isValid())
{
faceColors[face] = color;
updateGL();
}
}
}
void COpenGlTools::draw()
{
static const GLfloat P1[3] = { 0.0, -1.0, 2.0 };
static const GLfloat P2[3] = { 1.73205081 , -1.0, -1.0 };
static const GLfloat P3[3] = { -1.73205081, -1.0, -1.0 };
static const GLfloat P4[3] = { 0.0, 2.0, 0.0 };
static const GLfloat* const coords[4][3] = {
{ P1, P2, P3 }, { P1, P3, P4 }, { P1, P4, P2 }, { P2, P4, P3 }
};
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -10.0);
glRotatef(rotationX, 1.0, 0.0, 0.0);
glRotatef(rotationY, 0.0, 1.0, 0.0);
glRotatef(rotationZ, 0.0, 0.0, 1.0);
for (int i = 0; i < 4; i++)
{
glLoadName(i);
glBegin(GL_TRIANGLES);
qglColor(faceColors[i]);
for (int j = 0; j < 3; j++)
{
glVertex3f(coords[i][j][0], coords[i][j][1],
coords[i][j][2]);
}
glEnd();
}
}
// 确定光标下的面,返回窗口部件某位置所处的面的编号,没有面就返回1
int COpenGlTools::faceAtPosition(const QPoint& pos)
{
const int maxSize = 512;
GLuint buffer[maxSize];
GLint viewport[4];
makeCurrent(); // 确保正确使用OpenGL描述表
glGetIntegerv(GL_VIEWPORT, viewport);
glSelectBuffer(maxSize, buffer);
glRenderMode(GL_SELECT); // 以GL_SELECT模式绘制场景
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(GLdouble(pos.x()), GLdouble(viewport[3] - pos.y()), 5.0, 5.0, viewport);
GLfloat x = GLfloat(width() / height());
glFrustum(-x, x, -1.0, 1.0, 4.0, 15.0);
draw();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
if (!glRenderMode(GL_RENDER))
return -1;
return buffer[3];
}
main.cpp
#include "OpenGlTools.h"
#include <QtWidgets/QApplication>
#include <iostream>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
if (!QGLFormat::hasOpenGL())
{
std::cerr << "This system has no OpenGL support" << std::endl;
return 1;
}
COpenGlTools w;
w.setWindowTitle(QObject::tr("Tetrahedron"));
w.resize(300, 300);
w.show();
return app.exec();
}
运行结果: