Среда программирования:
Qt
Статья по теме:
Хотелось бы объяснить использование OpenGL в Qt для вращения трехмерной фигуры.
В данном примере приведен измененный код из статьи "Введение в OpenGL на Qt/C++" для отрисовки разноцветного икосаэдра.
Цвета задаются рандомно, а сама отрисовка производится через встроенные функции отрисовки по массивам координат.
Код программы:
// widget.cpp #include "widget.h" GLfloat VerMas[12][3]; // массив вершин GLubyte IndMas[20][3]; // массив индексов GLfloat ClrMas[12][3]; // массив цветов граней const static float pi=3.141593, k=pi/180; Widget::Widget(QWidget *parent) : QGLWidget(parent) { resize(300,300); xRotation = 0; yRotation = 0; zRotation = 0; scale = 1; } void Widget::initializeGL() { // инициализация OpenGL qglClearColor(Qt::white); glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT); glEnable(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); initVerMas(); // инициализация массива вершин initColorMas(); // инициализация массива цветов initIndMas(); // инициализация массива индексов glEnableClientState(GL_VERTEX_ARRAY); // активизация массива вершин glEnableClientState(GL_COLOR_ARRAY); // активизация массива цветов } void Widget::resizeGL(int nWidth, int nHeight) { // что будем делать при изменении размера окна glViewport(0, 0, nHeight, nHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); } void Widget::paintGL() // рисование { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистка буфера изображения и глубины glMatrixMode(GL_MODELVIEW); // устанавливает положение и ориентацию матрице моделирования glLoadIdentity(); // загружает единичную матрицу моделирования glScalef(scale, scale, scale); // масштабирование glRotatef(xRotation, 1.0f, 0.0f, 0.0f); // поворот по X glRotatef(yRotation, 0.0f, 1.0f, 0.0f); // поворот по Y glRotatef(zRotation, 0.0f, 0.0f, 1.0f); // поворот по Z drawAxis(); QColor clr(128, 128, 0, 255); qglColor(clr); // извлечение данных о массиве вершин glVertexPointer(3, GL_FLOAT, 0, VerMas); // извлечение данных о цветах glColorPointer(3, GL_FLOAT, 0, ClrMas); // построение поверхности, используя массив индексов glDrawElements(GL_TRIANGLES, 60, GL_UNSIGNED_BYTE, IndMas); } void Widget::mousePressEvent(QMouseEvent* pe) // нажатие клавиши мыши { // запоминаем координату нажатия мыши mousePos = pe->pos(); } void Widget::mouseMoveEvent(QMouseEvent* pe) // изменение положения стрелки мыши { xRotation += 180/scale*(GLfloat)(pe->y()-mousePos.y())/height(); // вычисляем углы поворота zRotation += 180/scale*(GLfloat)(pe->x()-mousePos.x())/width(); mousePos = pe->pos(); updateGL(); // обновляем изображение } void Widget::mouseReleaseEvent(QMouseEvent *pe) { } void Widget::drawAxis() { glLineWidth(3.0f); // устанавливаем ширину линии glColor4f(1.00f, 0.00f, 0.00f, 1.0f); // устанавливается цвет последующих линий // ось x glBegin(GL_LINES); // построение линии glVertex3f( 1.0f, 0.0f, 0.0f); // первая точка glVertex3f(-1.0f, 0.0f, 0.0f); // вторая точка glEnd(); QColor halfGreen(0, 128, 0, 255); qglColor(halfGreen); glBegin(GL_LINES); // ось y glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f( 0.0f, -1.0f, 0.0f); glColor4f(0.00f, 0.00f, 1.00f, 1.0f); // ось z glVertex3f( 0.0f, 0.0f, 1.0f); glVertex3f( 0.0f, 0.0f, -1.0f); glEnd(); } void Widget::wheelEvent(QWheelEvent* pe) // вращение колёсика мыши { // если колесико вращаем вперед -- умножаем переменную масштаба на 1.1 // иначе -- делим на 1.1 if ((pe->delta())>0) scale*=1.1; else if ((pe->delta())<0) scale/=1.1; updateGL(); } void Widget::initIndMas() // массив индексов { // задаем индексы каждого из треугольников IndMas[0][0]=0; // индекс первой вершины IndMas[0][1]=2; // индекс второй вершины IndMas[0][2]=1; // индекс третьей вершины IndMas[1][0]=0; IndMas[1][1]=3; IndMas[1][2]=2; IndMas[2][0]=0; IndMas[2][1]=4; IndMas[2][2]=3; IndMas[3][0]=0; IndMas[3][1]=5; IndMas[3][2]=4; IndMas[4][0]=0; IndMas[4][1]=1; IndMas[4][2]=5; IndMas[5][0]=6; IndMas[5][1]=1; IndMas[5][2]=7; IndMas[6][0]=7; IndMas[6][1]=1; IndMas[6][2]=2; IndMas[7][0]=7; IndMas[7][1]=2; IndMas[7][2]=8; IndMas[8][0]=8; IndMas[8][1]=2; IndMas[8][2]=3; IndMas[9][0]=8; IndMas[9][1]=3; IndMas[9][2]=9; IndMas[10][0]=9; IndMas[10][1]=3; IndMas[10][2]=4; IndMas[11][0]=9; IndMas[11][1]=4; IndMas[11][2]=10; IndMas[12][0]=10; IndMas[12][1]=4; IndMas[12][2]=5; IndMas[13][0]=10; IndMas[13][1]=5; IndMas[13][2]=6; IndMas[14][0]=6; IndMas[14][1]=5; IndMas[14][2]=1; IndMas[15][0]=7; IndMas[15][1]=11; IndMas[15][2]=6; IndMas[16][0]=8; IndMas[16][1]=11; IndMas[16][2]=7; IndMas[17][0]=9; IndMas[17][1]=11; IndMas[17][2]=8; IndMas[18][0]=10; IndMas[18][1]=11; IndMas[18][2]=9; IndMas[19][0]=6; IndMas[19][1]=11; IndMas[19][2]=10; } void Widget::initVerMas() // определить массив вершин { GLfloat R=0.75; // радиус сферы // начальные значения GLfloat a=4*R/sqrt(10+2*sqrt(5)); // сторона икосаэдра GLfloat alpha=acos((1-a*a/2/R/R)); // первый угол поворота по тэта // точки икосаэдра VerMas[0][0]=0; // x VerMas[0][1]=0; // y VerMas[0][2]=R; // z VerMas[1][0]=R*sin(alpha)*sin(0); VerMas[1][1]=R*sin(alpha)*cos(0); VerMas[1][2]=R*cos(alpha); VerMas[2][0]=R*sin(alpha)*sin(72*k); VerMas[2][1]=R*sin(alpha)*cos(72*k); VerMas[2][2]=R*cos(alpha); VerMas[3][0]=R*sin(alpha)*sin(2*72*k); VerMas[3][1]=R*sin(alpha)*cos(2*72*k); VerMas[3][2]=R*cos(alpha); VerMas[4][0]=R*sin(alpha)*sin(3*72*k); VerMas[4][1]=R*sin(alpha)*cos(3*72*k); VerMas[4][2]=R*cos(alpha); VerMas[5][0]=R*sin(alpha)*sin(4*72*k); VerMas[5][1]=R*sin(alpha)*cos(4*72*k); VerMas[5][2]=R*cos(alpha); VerMas[6][0]=R*sin(pi-alpha)*sin(-36*k); VerMas[6][1]=R*sin(pi-alpha)*cos(-36*k); VerMas[6][2]=R*cos(pi-alpha); VerMas[7][0]=R*sin(pi-alpha)*sin(36*k); VerMas[7][1]=R*sin(pi-alpha)*cos(36*k); VerMas[7][2]=R*cos(pi-alpha); VerMas[8][0]=R*sin(pi-alpha)*sin((36+72)*k); VerMas[8][1]=R*sin(pi-alpha)*cos((36+72)*k); VerMas[8][2]=R*cos(pi-alpha); VerMas[9][0]=R*sin(pi-alpha)*sin((36+2*72)*k); VerMas[9][1]=R*sin(pi-alpha)*cos((36+2*72)*k); VerMas[9][2]=R*cos(pi-alpha); VerMas[10][0]=R*sin(pi-alpha)*sin((36+3*72)*k); VerMas[10][1]=R*sin(pi-alpha)*cos((36+3*72)*k); VerMas[10][2]=R*cos(pi-alpha); VerMas[11][0]=0; VerMas[11][1]=0; VerMas[11][2]=-R; } void Widget::initColorMas() // задание цветов граней { for (int i=0; i<12; i++) { // цвета генерируем рандомно ClrMas[i][0]=0.1f*(qrand()%10); ClrMas[i][1]=0.1f*(qrand()%10); ClrMas[i][2]=0.1f*(qrand()%10); } }
Прикрепленный файл | Размер |
---|---|
openGL_qt.zip | 5.76 кб |