先上代碼,由於程序結構很清楚,上節也講到了Qt中實現OpenGL的框架,因此代碼讀起來沒有太大困難,如果有問題,歡迎私信~
MyGLWidget:
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QGLWidget>
class MyGLWidget : public QGLWidget
{
Q_OBJECT
public:
MyGLWidget(QWidget *parent = 0);
~MyGLWidget();
void setData(QVector<double> , QVector<double>, QVector<double>);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void wheelEvent(QWheelEvent *event);
public slots:
void setXRotation(int angle);
void setYRotation(int angle);
void setZRotation(int angle);
void setXtran(double x);
void setYtran(double x);
void setScale(double x);
signals:
void xRotationChanged(int angle);
void yRotationChanged(int angle);
void zRotationChanged(int angle);
private:
double xRot, yRot, zRot;
double xtran, ytran;
double scal;
double dMax;
QVector<double> dx, dy, dz, r, g, b;
int dSize;
QPoint lastPos;
};
#endif // MYGLWIDGET_H
#include <QtOpenGL>
#include "myglwidget.h"
MyGLWidget::MyGLWidget(QWidget *parent) : QGLWidget(parent)
{
dMax=0;
xRot =0; yRot =0; zRot =0;
xtran=0; ytran=0;
scal=1;
QVector<double> rl(7), gl(7), bl(7);
rl[0]=1.0; rl[1]=1.0; rl[2]=1.0; rl[3]=0.0; rl[4]=0.0; rl[5]=0.0; rl[6]=1.0;
gl[0]=0.0; gl[1]=0.5; gl[2]=1.0; gl[3]=1.0; gl[4]=0.0; gl[5]=1.0; gl[6]=0.0;
bl[0]=0.0; bl[1]=0.0; bl[2]=0.0; bl[3]=0.0; bl[4]=1.0; bl[5]=1.0; bl[6]=1.0;
r=rl; g=gl; b=bl;
}
MyGLWidget::~MyGLWidget(){}
void MyGLWidget::setData(QVector<double> x, QVector<double> y, QVector<double> z)
{
dSize=x.size(); dx=x; dy=y; dz=z;
for (int i=0;i<dSize;i++)
{
dMax=qMax(dMax,dx.at(i));
dMax=qMax(dMax,dy.at(i));
dMax=qMax(dMax,dz.at(i));
}
}
void MyGLWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
}
void MyGLWidget::resizeGL(int width, int height)
{
int border=qMax(width,height);
glViewport((width-border)/2, (height-border)/2, border, border);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-dMax*1.5, +dMax*1.5, -dMax*1.5, +dMax*1.5, -dMax*10.0, dMax*10.0);
glMatrixMode(GL_MODELVIEW);
}
void MyGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glScalef(scal,scal,scal);
glTranslatef(xtran, ytran, 0);
glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
qglClearColor(Qt::gray);
glBegin(GL_LINES);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f(-dMax, 0.0f, 0.0f);
glVertex3f(dMax,0.0f, 0.0f);
glVertex3f(dMax,0.0f, 0.0f);
glVertex3f(dMax-0.05*dMax,0.05*dMax, 0.0f);
glVertex3f(dMax,0.0f, 0.0f);
glVertex3f(dMax-0.05*dMax,-0.05*dMax, 0.0f);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f(0, -dMax, 0.0f);
glVertex3f(0,dMax, 0.0f);
glVertex3f(0,dMax, 0.0f);
glVertex3f(0.05*dMax,dMax-0.05*dMax, 0.0f);
glVertex3f(0,dMax, 0.0f);
glVertex3f(-0.05*dMax,dMax-0.05*dMax, 0.0f);
glColor3f(0.0f,0.0f,0.0f);
glVertex3f(0, 0, -dMax);
glVertex3f(0, 0, dMax);
glVertex3f(0,0, dMax);
glVertex3f(0,0.05*dMax, dMax-0.05*dMax);
glVertex3f(0,0, dMax);
glVertex3f(0,-0.05*dMax, dMax-0.05*dMax);
glEnd();
glBegin(GL_LINES);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f(-dMax*1.1, -dMax*1.1, -dMax*1.1);
glVertex3f(-dMax*1.1, -dMax*1.1, dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, -dMax*1.1);
glVertex3f(-dMax*1.1, -dMax*1.1, -dMax*1.1);
glVertex3f(-dMax*1.1, -dMax*1.1, -dMax*1.1);
glVertex3f(+dMax*1.1, -dMax*1.1, -dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, -dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, -dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, -dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, +dMax*1.1);
glVertex3f(-dMax*1.1, -dMax*1.1, +dMax*1.1);
glVertex3f(-dMax*1.1, -dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, -dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, -dMax*1.1, +dMax*1.1);
glVertex3f(+dMax*1.1, -dMax*1.1, -dMax*1.1);
glVertex3f(+dMax*1.1, -dMax*1.1, -dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, -dMax*1.1);
glVertex3f(+dMax*1.1, +dMax*1.1, -dMax*1.1);
glVertex3f(-dMax*1.1, +dMax*1.1, -dMax*1.1);
glEnd();
int i=1, j;
while (i<dSize)
{
j=floor(i*1.0/dSize*7);
glBegin(GL_LINES);
glColor3f(r.at(j),g.at(j),b.at(j));
glVertex3f( dx.at(i-1), dy.at(i-1), dz.at(i-1));
glVertex3f( dx.at(i), dy.at(i), dz.at(i));
glEnd();
i++;
}
}
void MyGLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
}
void MyGLWidget::mouseMoveEvent(QMouseEvent *event)
{
int dx = event->x() - lastPos.x();
int dy = event->y() - lastPos.y();
if (event->buttons() & Qt::LeftButton) {
setXRotation(xRot + 8 * dy);
setYRotation(yRot + 8 * dx);
} else if (event->buttons() & Qt::RightButton) {
setXRotation(xRot + 8 * dy);
setZRotation(zRot + 8 * dx);
}
lastPos = event->pos();
}
void MyGLWidget::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_1) setXRotation(xRot + 18);
if (e->key() == Qt::Key_2) setYRotation(yRot + 18);
if (e->key() == Qt::Key_3) setZRotation(zRot + 18);
if (e->key() == Qt::Key_W) setYtran(dMax/10);
if (e->key() == Qt::Key_S) setYtran(-dMax/10);
if (e->key() == Qt::Key_A) setXtran(-dMax/10);
if (e->key() == Qt::Key_D) setXtran(dMax/10);
if (e->key() == Qt::Key_Q) setScale(0.1);
if (e->key() == Qt::Key_E) setScale(-0.1);
}
void MyGLWidget::wheelEvent(QWheelEvent *e)
{
if (e->delta()>0) setScale(0.1);
if (e->delta()<0) setScale(-0.1);
}
static void qNormalizeAngle(int &angle)
{
while (angle < 0)
angle += 360 * 16;
while (angle > 360)
angle -= 360 * 16;
}
void MyGLWidget::setXRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != xRot) {
xRot = angle;
emit xRotationChanged(angle);
updateGL();
}
}
void MyGLWidget::setYRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != yRot) {
yRot = angle;
emit yRotationChanged(angle);
updateGL();
}
}
void MyGLWidget::setZRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != zRot) {
zRot = angle;
emit zRotationChanged(angle);
updateGL();
}
}
void MyGLWidget::setXtran(double x)
{
xtran+=x;
updateGL();
}
void MyGLWidget::setYtran(double x)
{
ytran+=x;
updateGL();
}
void MyGLWidget::setScale(double x)
{
scal*=(1+x);
updateGL();
}
Widget:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
QFont myFont("Times",20);
QFile file("data.txt");
QVector<double> x(0),y(0),z(0),t(0);
char buf[1000];
double x1,x2,x3,x4;
file.open(QIODevice::ReadOnly);
sscanf(buf,"%lf %lf %lf %lf",&x1,&x2,&x3,&x4);
x.fill(x1); y.fill(x2); z.fill(x3); t.fill(x4);
while (!file.atEnd())
{
file.readLine(buf,sizeof(buf));
sscanf(buf,"%lf %lf %lf %lf",&x1,&x2,&x3,&x4);
x.append(x1); y.append(x2); z.append(x3); t.append(x4);
}
file.close();
ui->touying1->addGraph();
ui->touying1->graph(0)->setData(t,x);
ui->touying1->xAxis->setLabel("t");
ui->touying1->yAxis->setLabel("X");
ui->touying1->xAxis->setLabelFont(myFont);
ui->touying1->yAxis->setLabelFont(myFont);
ui->touying1->rescaleAxes();
ui->touying2->addGraph();
ui->touying2->graph(0)->setData(t,y);
ui->touying2->xAxis->setLabel("t");
ui->touying2->yAxis->setLabel("Y");
ui->touying2->xAxis->setLabelFont(myFont);
ui->touying2->yAxis->setLabelFont(myFont);
ui->touying2->rescaleAxes();
ui->touying3->addGraph();
ui->touying3->graph(0)->setData(t,z);
ui->touying3->xAxis->setLabel("t");
ui->touying3->yAxis->setLabel("Z");
ui->touying3->xAxis->setLabelFont(myFont);
ui->touying3->yAxis->setLabelFont(myFont);
ui->touying3->rescaleAxes();
ui->widget->setData(x,y,z);
ui->widget->show();
}
Widget::~Widget()
{
delete ui;
}
Widget.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCustomPlot" name="touying1" native="true"/>
</item>
<item row="0" column="1">
<widget class="QCustomPlot" name="touying3" native="true"/>
</item>
<item row="1" column="0">
<widget class="QCustomPlot" name="touying2" native="true"/>
</item>
<item row="1" column="1">
<widget class="MyGLWidget" name="widget" native="true">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>MyGLWidget</class>
<extends>QWidget</extends>
<header>myglwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
Main:
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowTitle("On a réussi~~單擊3D界面,旋轉:123或鼠標拖動;縮放:QE或鼠標滾輪;移動:WASD。");
w.show();
return a.exec();
}
Pro文件:
QT += core gui opengl printsupport widgets
TARGET = PROJECT
TEMPLATE = app
SOURCES += main.cpp\
widget.cpp \
myglwidget.cpp \
qcustomplot.cpp
HEADERS += widget.h \
myglwidget.h \
qcustomplot.h
FORMS += widget.ui
程序中測試採用密集的“螺旋線”,檢驗渲染和交互的流暢性。
所謂螺旋線,即長得像螺紋的3D曲線。在笛卡爾座標系中,比如可以表示爲:
x = 20cos(360*5t)
y = 20sin(360*5t)
z = 25t
測試效果如下(旋轉:123或鼠標拖動;縮放:QE或鼠標滾輪;移動:WASD):
另外,程序的發佈版本也可以直接在百度網盤中下載,歡迎大家賜教!