Поделиться 

Страницы: 1 2 3 4 5 6 Следующая
Автор: vxstar
Во 2-ой части продолжается рассмотрение работы с OpenGL на Qt 4. Читатель познакомится с настройкой контекста OpenGL, созданием анимации и простым наложением текстур. Заодно в рамках «чистого» OpenGL будет рассмотрена интерактивная графика с помощью режима выбора (выбираем объекты на экране для дальнейшей манипуляции с ними), в рамках «чистого» Qt будет продемонстрировано создание главного окна, меню (menu bar), объяснёны механизм сигналов и слотов и технология дерева объектов (иерархии объектов).
Список частей:
Введение
An opensource of this lecture
scene3D.h
glext.h
scene3D.cpp
mainwindow.h
mainwindow.cpp
main.cpp
pictures.qrc
lecture2.pro
Контекст OpenGL
Классы QGLFormat и QGLContext
Настройка контекста
Версии OpenGL
Анимация
Класс QTimer
QTimer + сигналы и слоты
Другой метод: событие таймера
Синхронизация кадров с дисплеем
Текстуры
Инициализация текстур
Создание текстур
Наложение текстур
Удаление текстур
Пример: наложение текстуры на шар
Рисуем два интерактивных октаэдра
Используя стеки матриц
Накладываемые текстуры
Используя режим выбора
Создаём главное окно и меню
Дерево объектов
Включение изображения в исполняемый файл
Заключение
Литература
Вопросы, связанные с инициализацией рендеринга OpenGL, с настройкой окна виджета и выводом изображения были рассмотрены в 1-ой статье. Также там была нарисована простая трёхмерная фигура с использованием массивов вершин. Во второй части хотелось бы добавить вопросы, связанные с дополнительной настройкой контекста OpenGL, анимацией и наложением текстур. Может показаться, что всё отличие от многократного изложения темы наложения текстур сводится к загрузке изображения средствами Qt, но это не совсем так: Qt имеет собственные методы для работы с текстурами. В свою очередь, анимация сводится к работе с таймером в Qt. Мне хотелось бы дать столько информации читателю, сколько уже достаточно, чтобы ввести в курс дела и чтобы, отталкиваясь от неё, читатель смог продолжить изучение интересующих вопросов более подробно. Мы будем использовать собственный класс Scene3D, введённый в 1-ой статье. Стиль изложения будет таким, как и раньше: вначале читателю предлагается только исходный код программы статьи. А затем последуют объяснение базовых понятий и подробный разбор самой программы. Рассказать обо всём невозможно, зато вполне возможно предоставить начальные знания, отталкиваясь от которых, можно продолжить совершенствовать свои навыки. Итак, начнём!
#ifndef SCENE3D_H #define SCENE3D_H #include <QGLWidget> class Scene3D : public QGLWidget { Q_OBJECT private: GLfloat ratio; GLfloat xRot1; GLfloat yRot1; GLfloat zRot1; GLfloat zTra1; GLfloat xRot2; GLfloat yRot2; GLfloat zRot2; GLfloat zTra2; QTimer *timer; void getVerTexArrays(); void getIndexArray(); void genTextures(); void drawFigure(); void selectFigures(QPoint mp); protected: void initializeGL(); void resizeGL(int nWidth, int nHeight); void paintGL(); void mousePressEvent(QMouseEvent* pe); private slots: void change(); void changeTex(); void stopTmr(); void startTmr(); public: Scene3D(QWidget* parent = 0); ~Scene3D(); }; #endif
Download core API and extension header file "glext.h" from this site.
#include <QtGui> #include <math.h> #include "scene3D.h" #include "glext.h" const GLfloat pi=3.141593, k=pi/180; GLint viewport[4]; GLfloat VertexArray[6][3]; GLfloat TextureArray[6][2]; GLuint IndexArray[8][3]; GLuint textureID[2]; GLint signs[2]={1, 1}; bool motionParameters[2]={1, 1}; int textureParameters[2]={0, 1}; Scene3D::Scene3D(QWidget* parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) { xRot1=-90.0f; yRot1=0.0f; zRot1=0.0f; zTra1=0.0f; xRot2=-90.0f; yRot2=0.0f; zRot2=0.0f; zTra2=0.0f; timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(change())); timer->start(10); QGLFormat frmt; frmt.setSwapInterval(1); setFormat(frmt); } Scene3D::~Scene3D() { } void Scene3D::initializeGL() { qglClearColor(Qt::black); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_MULTISAMPLE); getVerTexArrays(); getIndexArray(); genTextures(); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } void Scene3D::resizeGL(int nWidth, int nHeight) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); ratio=(GLfloat)nHeight/(GLfloat)nWidth; if (nWidth>=nHeight) glOrtho(-2.0/ratio, 2.0/ratio, -2.0, 2.0, -10.0, 10.0); else glOrtho(-2.0, 2.0, -2.0*ratio, 2.0*ratio, -10.0, 10.0); glViewport(0, 0, (GLint)nWidth, (GLint)nHeight); glGetIntegerv(GL_VIEWPORT, viewport); } void Scene3D::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); glTranslatef(-1.0f/ratio, zTra1, 0.0f); glRotatef(xRot1, 1.0f, 0.0f, 0.0f); glRotatef(yRot1, 0.0f, 1.0f, 0.0f); glRotatef(zRot1, 0.0f, 0.0f, 1.0f); glBindTexture(GL_TEXTURE_2D, textureID[textureParameters[0]]); drawFigure(); glPopMatrix(); glPushMatrix(); glTranslatef(1.0f/ratio, zTra2, 0.0f); glRotatef(xRot2, 1.0f, 0.0f, 0.0f); glRotatef(yRot2, 0.0f, 1.0f, 0.0f); glRotatef(zRot2, 0.0f, 0.0f, 1.0f); glBindTexture(GL_TEXTURE_2D, textureID[textureParameters[1]]); drawFigure(); glPopMatrix(); } void Scene3D::mousePressEvent(QMouseEvent* pe) { QPoint mousePosition = pe->pos(); this->selectFigures(mousePosition); } void Scene3D::genTextures() { textureID[0]=bindTexture(QPixmap(QString("../textures/picture1.jpg")), GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); textureID[1]=bindTexture(QPixmap(QString("../textures/picture2.jpg")), GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } void Scene3D::getVerTexArrays() { GLfloat R=1.0f; GLfloat alpha=pi/2; VertexArray[0][0]=0.0f; VertexArray[0][1]=0.0f; VertexArray[0][2]=R; TextureArray[0][0]=0.5f; TextureArray[0][1]=1.0f; VertexArray[1][0]=R*sin(alpha)*sin(0); VertexArray[1][1]=R*sin(alpha)*cos(0); VertexArray[1][2]=R*cos(alpha); TextureArray[1][0]=1.0f; TextureArray[1][1]=0.0f; VertexArray[2][0]=R*sin(alpha)*sin(pi/2); VertexArray[2][1]=R*sin(alpha)*cos(pi/2); VertexArray[2][2]=R*cos(alpha); TextureArray[2][0]=0.0f; TextureArray[2][1]=0.0f; VertexArray[3][0]=R*sin(alpha)*sin(pi); VertexArray[3][1]=R*sin(alpha)*cos(pi); VertexArray[3][2]=R*cos(alpha); TextureArray[3][0]=1.0f; TextureArray[3][1]=0.0f; VertexArray[4][0]=R*sin(alpha)*sin(3*pi/2); VertexArray[4][1]=R*sin(alpha)*cos(3*pi/2); VertexArray[4][2]=R*cos(alpha); TextureArray[4][0]=0.0f; TextureArray[4][1]=0.0f; VertexArray[5][0]=0.0f; VertexArray[5][1]=0.0f; VertexArray[5][2]=-R; TextureArray[5][0]=0.5f; TextureArray[5][1]=1.0f; } void Scene3D::getIndexArray() { IndexArray[0][0]=0; IndexArray[0][1]=2; IndexArray[0][2]=1; IndexArray[1][0]=0; IndexArray[1][1]=3; IndexArray[1][2]=2; IndexArray[2][0]=0; IndexArray[2][1]=4; IndexArray[2][2]=3; IndexArray[3][0]=0; IndexArray[3][1]=1; IndexArray[3][2]=4; IndexArray[4][0]=5; IndexArray[4][1]=1; IndexArray[4][2]=2; IndexArray[5][0]=5; IndexArray[5][1]=2; IndexArray[5][2]=3; IndexArray[6][0]=5; IndexArray[6][1]=3; IndexArray[6][2]=4; IndexArray[7][0]=5; IndexArray[7][1]=4; IndexArray[7][2]=1; } void Scene3D::drawFigure() { glVertexPointer(3, GL_FLOAT, 0, VertexArray); glTexCoordPointer(2, GL_FLOAT, 0, TextureArray); glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, IndexArray); } void Scene3D::selectFigures(QPoint mp) { GLuint selectBuffer[4]; GLint hits; glSelectBuffer(4, selectBuffer); glMatrixMode(GL_PROJECTION); glPushMatrix(); glRenderMode(GL_SELECT); glLoadIdentity(); gluPickMatrix((GLdouble)mp.x(), (GLdouble)(viewport[3]-mp.y()), 1.0, 1.0, viewport); if (width()>=height()) glOrtho(-2.0/ratio, 2.0/ratio, -2.0, 2.0, -10.0, 10.0); else glOrtho(-2.0, 2.0, -2.0*ratio, 2.0*ratio, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glInitNames(); glPushName(0); glPushMatrix(); glTranslatef(-1.0f/ratio, zTra1, 0.0f); glRotatef(xRot1, 1.0f, 0.0f, 0.0f); glRotatef(yRot1, 0.0f, 1.0f, 0.0f); glRotatef(zRot1, 0.0f, 0.0f, 1.0f); glLoadName(1); drawFigure(); glPopMatrix(); glPushMatrix(); glTranslatef(1.0f/ratio, zTra2, 0.0f); glRotatef(xRot2, 1.0f, 0.0f, 0.0f); glRotatef(yRot2, 0.0f, 1.0f, 0.0f); glRotatef(zRot2, 0.0f, 0.0f, 1.0f); glLoadName(2); drawFigure(); glPopMatrix(); hits=glRenderMode(GL_RENDER); if (hits>0) { int figureName=selectBuffer[3]; if (motionParameters[figureName-1]) motionParameters[figureName-1]=0; else motionParameters[figureName-1]=1; } glMatrixMode(GL_PROJECTION); glPopMatrix(); } void Scene3D::change() { if (motionParameters[0]) { xRot1 -=0.05f; yRot1 -=0.05f; zRot1 +=0.05f; if ((xRot1>360)||(xRot1<-360)) xRot1=0.0f; if ((yRot1>360)||(yRot1<-360)) yRot1=0.0f; if ((zRot1>360)||(zRot1<-360)) zRot1=0.0f; if (abs(zTra1)>0.5f) signs[0] *=-1; zTra1 -=signs[0]*0.005f; } if (motionParameters[1]) { xRot2 +=0.05f; yRot2 +=0.05f; zRot2 -=0.05f; if ((xRot2>360)||(xRot2<-360)) xRot2=0.0f; if ((yRot2>360)||(yRot2<-360)) yRot2=0.0f; if ((zRot2>360)||(zRot2<-360)) zRot2=0.0f; if (abs(zTra2)>0.5f) signs[1] *=-1; zTra2 +=signs[1]*0.005f; } updateGL(); } void Scene3D::changeTex() { if (textureParameters[0]==0) { textureParameters[0]=1; textureParameters[1]=0; } else { textureParameters[0]=0; textureParameters[1]=1; } updateGL(); } void Scene3D::stopTmr() { timer->stop(); } void Scene3D::startTmr() { timer->start(); } |
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "scene3D.h" class MainWindow : public QMainWindow { Q_OBJECT private: Scene3D* scene1; QMenu* texture_menu; QAction* changeTexAct; QMenu* timer_menu; QAction* stopTimAct; QAction* startTimAct; void createActions(); void createMenus(); public: MainWindow(); }; #endif
#include <QtGui> #include "mainwindow.h" #include "scene3D.h" MainWindow::MainWindow() { scene1 = new Scene3D; setCentralWidget(scene1); this->setWindowTitle(tr("lecture2")); createActions(); createMenus(); } void MainWindow::createActions() { changeTexAct = new QAction(tr("Change"), this); connect(changeTexAct, SIGNAL(triggered()), scene1, SLOT(changeTex())); stopTimAct = new QAction(tr("Stop"), this); connect(stopTimAct, SIGNAL(triggered()), scene1, SLOT(stopTmr())); startTimAct = new QAction(tr("Start"), this); connect(startTimAct, SIGNAL(triggered()), scene1, SLOT(startTmr())); } void MainWindow::createMenus() { texture_menu = menuBar()->addMenu(tr("Texture")); texture_menu->addAction(changeTexAct); timer_menu = menuBar()->addMenu(tr("Animation")); timer_menu->addAction(stopTimAct); timer_menu->addAction(startTimAct); }
#include <QtGui> #include "mainwindow.h" int main(int argc, char** argv) { QApplication app(argc, argv); MainWindow mainwindow1; mainwindow1.resize(500, 500); mainwindow1.showMaximized(); return app.exec(); }
See you pictures here.
<RCC> <qresource> <file>textures/picture1.jpg</file> <file>textures/picture2.jpg</file> </qresource> </RCC>
TEMPLATE = app RESOURCES = pictures.qrc HEADERS += glext.h scene3D.h mainwindow.h SOURCES += main.cpp scene3D.cpp mainwindow.cpp QT += opengl
Страницы: 1 2 3 4 5 6 Следующая
10 августа 2011
Категории: 3D, графика, OpenGL, Qt, Qt4
Обновление: 7 марта 2012