RayTracing

- Титульная страница
- Классы
- Файлы

- Файлы
- Список членов всех файлов

C:/Users/user/Desktop/qt/task4/scene3D.cpp
См. документацию.

    00001 #include <QtGui>      // подключаем модуль QtGui
    00002 #include <math.h>     // подключаем математическую библиотеку
    00003 #include "scene3D.h"  // подключаем заголовочный файл scene3D.h
    00004 #include "glext.h"    // подключаем заголовочный файл glext.h
    00005
    00007 //#ifndef GL_CLAMP_TO_EDGE
    00008 //#define GL_CLAMP_TO_EDGE 0x812F
    00009 //#endif
    00010
    00012 //#ifndef GL_MULTISAMPLE
    00013 //#define GL_MULTISAMPLE  0x809D
    00014 //#endif
    00015
    00016 const GLfloat pi=3.141593, k=pi/180; // глобальная переменная
    00017
    00018 GLint viewport[4]; // декларируем матрицу поля просмотра
    00019
    00020 GLfloat VertexArray[6][3];  // декларируем массив вершин
    00021 GLfloat TextureArray[6][2]; // декларируем массив текстурных координат
    00022 GLuint IndexArray[8][3];    // декларируем массив индексов вершин
    00023 GLuint textureID[2];        // декларируем массив текстурных объектов (id текстур)
    00024
    00025 GLint signs[2]={1, 1}; // массив знаков +1 или -1 (понадобятся при трансляции)
    00026 bool motionParameters[2]={1, 1}; // массив параметров, определяющих движение
    00027 int textureParameters[2]={0, 1}; // массив индексов массива текстурных ID
    00028
    00029 Scene3D::Scene3D(QWidget* parent/*= 0*/) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) // конструктор класса Scene3D
    00030 {
    00031    // начальные значения
    00032    xRot1=-90.0f; yRot1=0.0f; zRot1=0.0f; zTra1=0.0f;
    00033    xRot2=-90.0f; yRot2=0.0f; zRot2=0.0f; zTra2=0.0f;
    00034
    00035    timer = new QTimer(this); // создаём таймер
    00036    connect(timer, SIGNAL(timeout()), this, SLOT(change())); // связываем сигналы и слоты
    00037    timer->start(10); // запускаем таймер
    00038 }
    00039
    00040 Scene3D::~Scene3D() // деструктор
    00041 {
    00042
    00043 }
    00044
    00045 void Scene3D::initializeGL() // инициализация
    00046 {
    00047    qglClearColor(Qt::black); // цвет для очистки буфера изображения - здесь просто фон окна
    00048    glEnable(GL_DEPTH_TEST);  // устанавливает режим проверки глубины пикселей
    00049    glEnable(GL_CULL_FACE);   // устанавливается режим, когда строятся только внешние поверхности
    00050    glEnable(GL_TEXTURE_2D);  // установить режим двумерных текстур
    00051    glEnable(GL_MULTISAMPLE); // включаем мультивыборку
    00052
    00053    getVerTexArrays(); // определить массив вершин и текстурных координат
    00054    getIndexArray();   // определить массив индексов вершин
    00055    genTextures();     // создать текстуры
    00056
    00057    glEnableClientState(GL_VERTEX_ARRAY); // активизация массива вершин
    00058    glEnableClientState(GL_TEXTURE_COORD_ARRAY); // активизация массива текстурных координат
    00059 }
    00060
    00061 void Scene3D::resizeGL(int nWidth, int nHeight) // окно виджета
    00062 {
    00063    glMatrixMode(GL_PROJECTION); // устанавливает текущей проекционную матрицу
    00064    glLoadIdentity();            // присваивает проекционной матрице единичную матрицу
    00065
    00066    ratio=(GLfloat)nHeight/(GLfloat)nWidth; // отношение высоты окна виджета к его ширине
    00067
    00068    // мировое окно
    00069    if (nWidth>=nHeight)
    00070       glOrtho(-2.0/ratio, 2.0/ratio, -2.0, 2.0, -10.0, 10.0); // параметры видимости ортогональной проекции
    00071    else
    00072       glOrtho(-2.0, 2.0, -2.0*ratio, 2.0*ratio, -10.0, 10.0); // параметры видимости ортогональной проекции
    00073
    00074    // поле просмотра
    00075    glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);
    00076
    00077    glGetIntegerv(GL_VIEWPORT, viewport); // извлечь матрицу поля просмотра в viewport
    00078 }
    00079
    00080 void Scene3D::paintGL() // рисование
    00081 {
    00082    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистка буфера изображения и глубины
    00083
    00084    glMatrixMode(GL_MODELVIEW); // устанавливает положение и ориентацию матрицы моделирования
    00085    glLoadIdentity();           // загружает единичную матрица моделирования
    00086
    00087    glPushMatrix(); // поместить матрицу моделирования в стек матриц
    00088       glTranslatef(-1.0f/ratio, zTra1, 0.0f); // трансляция
    00089       glRotatef(xRot1, 1.0f, 0.0f, 0.0f); // поворот вокруг оси X
    00090       glRotatef(yRot1, 0.0f, 1.0f, 0.0f); // поворот вокруг оси Y
    00091       glRotatef(zRot1, 0.0f, 0.0f, 1.0f); // поворот вокруг оси Z
    00092       glBindTexture(GL_TEXTURE_2D, textureID[textureParameters[0]]); // выбираем текстуру для наложения
    00093       drawFigure(); // нарисовать фигуру
    00094    glPopMatrix(); // извлечь матрицу моделирования из стека матриц
    00095
    00096    glPushMatrix(); // поместить в стек матрицу моделирования
    00097       glTranslatef(1.0f/ratio, zTra2, 0.0f); // трансляция
    00098       glRotatef(xRot2, 1.0f, 0.0f, 0.0f); // поворот вокруг оси X
    00099       glRotatef(yRot2, 0.0f, 1.0f, 0.0f); // поворот вокруг оси Y
    00100       glRotatef(zRot2, 0.0f, 0.0f, 1.0f); // поворот вокруг оси Z
    00101       glBindTexture(GL_TEXTURE_2D, textureID[textureParameters[1]]); // выбираем текстуру для наложения
    00102       drawFigure(); // нарисовать фигуру
    00103    glPopMatrix(); // взять из стека матрицу моделирования
    00104 }
    00105
    00106 void Scene3D::mousePressEvent(QMouseEvent* pe) // нажатие клавиши мыши
    00107 {
    00108    // при нажатии пользователем кнопки мыши переменной mousePosition будет
    00109    QPoint mousePosition = pe->pos(); // присвоена координата указателя мыши
    00110
    00111    this->selectFigures(mousePosition); // выбрать фигуру
    00112 }
    00113
    00114 void Scene3D::genTextures() // создаём текстуры
    00115 {
    00116    // создаём, связываем, загружаем, возвращаем уникальный номер:
    00117    textureID[0]=bindTexture(QPixmap(QString("C:/Users/user/Desktop/qt/task4/picture1.jpg")), GL_TEXTURE_2D);
    00118    // далее параметры текстурного объекта
    00119    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // при фильтрации игнорируются тексели, выходящие за границу текстуры для s координаты
    00120    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // при фильтрации игнорируются тексели, выходящие за границу текстуры для t координаты
    00121    // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // цвет текселя полностью замещает цвет фрагмента фигуры
    00122
    00123    // создаём, связываем, загружаем, возвращаем уникальный номер:
    00124    textureID[1]=bindTexture(QPixmap(QString("C:/Users/user/Desktop/qt/task4/picture1.jpg")), GL_TEXTURE_2D);
    00125    // далее параметры текстурного объекта
    00126    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // при фильтрации игнорируются тексели, выходящие за границу текстуры для s координаты
    00127    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // при фильтрации игнорируются тексели, выходящие за границу текстуры для t координаты
    00128    // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // цвет текселя полностью замещает цвет фрагмента фигуры
    00129 }
    00130
    00131 void Scene3D::getVerTexArrays() // определить массив вершин и текстурных координат
    00132 {
    00133    GLfloat R=1.0f; // радиус сферы
    00134    GLfloat alpha=pi/2;
    00135
    00136    // вычисляем точки
    00137    //0 точка
    00138    VertexArray[0][0]=0.0f; // x
    00139    VertexArray[0][1]=0.0f; // y
    00140    VertexArray[0][2]=R;    // z
    00141
    00142    TextureArray[0][0]=0.5f; // x (s)
    00143    TextureArray[0][1]=1.0f; // y (t)
    00144
    00145    //1 точка
    00146    VertexArray[1][0]=R*sin(alpha)*sin(0);
    00147    VertexArray[1][1]=R*sin(alpha)*cos(0);
    00148    VertexArray[1][2]=R*cos(alpha);
    00149
    00150    TextureArray[1][0]=1.0f;
    00151    TextureArray[1][1]=0.0f;
    00152
    00153    //2 точка
    00154    VertexArray[2][0]=R*sin(alpha)*sin(pi/2);
    00155    VertexArray[2][1]=R*sin(alpha)*cos(pi/2);
    00156    VertexArray[2][2]=R*cos(alpha);
    00157
    00158    TextureArray[2][0]=0.0f;
    00159    TextureArray[2][1]=0.0f;
    00160
    00161    //3 точка
    00162    VertexArray[3][0]=R*sin(alpha)*sin(pi);
    00163    VertexArray[3][1]=R*sin(alpha)*cos(pi);
    00164    VertexArray[3][2]=R*cos(alpha);
    00165
    00166    TextureArray[3][0]=1.0f;
    00167    TextureArray[3][1]=0.0f;
    00168
    00169    //4 точка
    00170    VertexArray[4][0]=R*sin(alpha)*sin(3*pi/2);
    00171    VertexArray[4][1]=R*sin(alpha)*cos(3*pi/2);
    00172    VertexArray[4][2]=R*cos(alpha);
    00173
    00174    TextureArray[4][0]=0.0f;
    00175    TextureArray[4][1]=0.0f;
    00176
    00177    //5 точка
    00178    VertexArray[5][0]=0.0f;
    00179    VertexArray[5][1]=0.0f;
    00180    VertexArray[5][2]=-R;
    00181
    00182    TextureArray[5][0]=0.5f;
    00183    TextureArray[5][1]=1.0f;
    00184 }
    00185
    00186 void Scene3D::getIndexArray() // определить массив индексов
    00187 {
    00188    // 0 треугольник
    00189    IndexArray[0][0]=0; // индекс (номер) 1-ой вершины
    00190    IndexArray[0][1]=2; // индекс (номер) 2-ой вершины
    00191    IndexArray[0][2]=1; // индекс (номер) 3-ей вершины
    00192
    00193    // 1 треугольник
    00194    IndexArray[1][0]=0;
    00195    IndexArray[1][1]=3;
    00196    IndexArray[1][2]=2;
    00197
    00198    // 2 треугольник
    00199    IndexArray[2][0]=0;
    00200    IndexArray[2][1]=4;
    00201    IndexArray[2][2]=3;
    00202
    00203    // 3 треугольник
    00204    IndexArray[3][0]=0;
    00205    IndexArray[3][1]=1;
    00206    IndexArray[3][2]=4;
    00207
    00208    // 4 треугольник
    00209    IndexArray[4][0]=5;
    00210    IndexArray[4][1]=1;
    00211    IndexArray[4][2]=2;
    00212
    00213    // 5 треугольник
    00214    IndexArray[5][0]=5;
    00215    IndexArray[5][1]=2;
    00216    IndexArray[5][2]=3;
    00217
    00218    // 6 треугольник
    00219    IndexArray[6][0]=5;
    00220    IndexArray[6][1]=3;
    00221    IndexArray[6][2]=4;
    00222
    00223    // 7 треугольник
    00224    IndexArray[7][0]=5;
    00225    IndexArray[7][1]=4;
    00226    IndexArray[7][2]=1;
    00227 }
    00228
    00229 void Scene3D::drawFigure() // построить фигуру
    00230 {
    00231    glVertexPointer(3, GL_FLOAT, 0, VertexArray); // указываем, откуда нужно извлечь данные о массиве вершин
    00232    glTexCoordPointer(2, GL_FLOAT, 0, TextureArray); // указываем, откуда нужно извлечь данные о массиве текстурных координат
    00233    glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, IndexArray); // используя массивы вершин и индексов, строим поверхности
    00234 }
    00235
    00236 void Scene3D::selectFigures(QPoint mp) // выбрать фигуру
    00237 {
    00238    GLuint selectBuffer[4]; // буфер выбора (буфер совпадений)
    00239    GLint hits; // счетчик соответствий
    00240    glSelectBuffer(4, selectBuffer); // использовать указанный буфер выбора
    00241
    00242    glMatrixMode(GL_PROJECTION); // матрица проекции стала активной
    00243    glPushMatrix(); // поместить текущую матрицу в стек матриц
    00244    glRenderMode(GL_SELECT); // переход в режим выбора
    00245    glLoadIdentity(); // загрузить единичную матрицу
    00246
    00247    // новый объём под указателем мыши
    00248    gluPickMatrix((GLdouble)mp.x(), (GLdouble)(viewport[3]-mp.y()), 1.0, 1.0, viewport);
    00249    // мировое окно
    00250    if (width()>=height())
    00251       glOrtho(-2.0/ratio, 2.0/ratio, -2.0, 2.0, -10.0, 10.0); // параметры видимости ортогональной проекции
    00252    else
    00253       glOrtho(-2.0, 2.0, -2.0*ratio, 2.0*ratio, -10.0, 10.0); // параметры видимости ортогональной проекции
    00254
    00255    glMatrixMode(GL_MODELVIEW); // модельно-видовая матрица стала активной
    00256    glLoadIdentity();           // загружается единичная матрица моделирования
    00257
    00258    glInitNames(); // инициализируется и очищается стек имён
    00259    glPushName(0); // в стек имён помещается значение 0 (обязательно должен храниться хотя бы один элемент)
    00260
    00261    glPushMatrix(); // поместить матрицу моделирования в стек матриц
    00262       glTranslatef(-1.0f/ratio, zTra1, 0.0f); // трансляция
    00263       glRotatef(xRot1, 1.0f, 0.0f, 0.0f); // поворот вокруг оси X
    00264       glRotatef(yRot1, 0.0f, 1.0f, 0.0f); // поворот вокруг оси Y
    00265       glRotatef(zRot1, 0.0f, 0.0f, 1.0f); // поворот вокруг оси Z
    00266       glLoadName(1); // загрузить имя на вершину стека имён
    00267       drawFigure(); // нарисовать фигуру
    00268    glPopMatrix(); // извлечь матрицу моделирования из стека матриц
    00269
    00270    glPushMatrix(); // поместить в стек матрицу моделирования
    00271       glTranslatef(1.0f/ratio, zTra2, 0.0f); // трансляция
    00272       glRotatef(xRot2, 1.0f, 0.0f, 0.0f); // поворот вокруг оси X
    00273       glRotatef(yRot2, 0.0f, 1.0f, 0.0f); // поворот вокруг оси Y
    00274       glRotatef(zRot2, 0.0f, 0.0f, 1.0f); // поворот вокруг оси Z
    00275       glLoadName(2); // загрузить имя на вершину стека имён
    00276       drawFigure(); // нарисовать фигуру
    00277    glPopMatrix(); // взять из стека матрицу моделирования
    00278
    00279    // glPopName(); // вытащить имя из стека имён
    00280
    00281    hits=glRenderMode(GL_RENDER); // число совпадений и переход в режим рисования
    00282
    00283    if (hits>0) // есть совпадания и нет ошибок
    00284    {
    00285       int figureName=selectBuffer[3]; // имя фигуры
    00286
    00287       if (motionParameters[figureName-1]) // изменение параметров движения
    00288          motionParameters[figureName-1]=0; // углы и величина трансляции не изменяется
    00289       else
    00290          motionParameters[figureName-1]=1; // углы и величина трансляция изменяются
    00291    }
    00292
    00293    glMatrixMode(GL_PROJECTION); // матрица проекции стала активной
    00294    glPopMatrix(); // извлечь матрицу из стека матриц
    00295 }
    00296
    00297 void Scene3D::change() // слот - изменение углов поворота и величины трансляции
    00298 {
    00299    if (motionParameters[0]) // изменение для первой фигуры
    00300    {
    00301       xRot1 -=0.05f;
    00302       yRot1 -=0.05f;
    00303       zRot1 +=0.05f;
    00304
    00305       if ((xRot1>360)||(xRot1<-360)) xRot1=0.0f;
    00306       if ((yRot1>360)||(yRot1<-360)) yRot1=0.0f;
    00307       if ((zRot1>360)||(zRot1<-360)) zRot1=0.0f;
    00308
    00309       if (abs(zTra1)>0.5f) signs[0] *=-1;
    00310       zTra1 -=signs[0]*0.005f;
    00311    }
    00312
    00313    if (motionParameters[1]) // изменение для второй фигуры
    00314    {
    00315       xRot2 +=0.05f;
    00316       yRot2 +=0.05f;
    00317       zRot2 -=0.05f;
    00318
    00319       if ((xRot2>360)||(xRot2<-360)) xRot2=0.0f;
    00320       if ((yRot2>360)||(yRot2<-360)) yRot2=0.0f;
    00321       if ((zRot2>360)||(zRot2<-360)) zRot2=0.0f;
    00322
    00323       if (abs(zTra2)>0.5f) signs[1] *=-1;
    00324       zTra2 +=signs[1]*0.005f;
    00325    }
    00326
    00327    updateGL(); // обновить изображение
    00328 }
    00329
    00330 void Scene3D::changeTex() // слот - поменять текстуры местами
    00331 {
    00332    if (textureParameters[0]==0)
    00333    {
    00334       textureParameters[0]=1;
    00335       textureParameters[1]=0;
    00336    }
    00337    else
    00338    {
    00339       textureParameters[0]=0;
    00340       textureParameters[1]=1;
    00341    }
    00342
    00343    updateGL(); // обновить изображение
    00344 }
    00345
    00346 void Scene3D::stopTmr() // слот - остановить таймер
    00347 {
    00348    timer->stop();
    00349 }
    00350
    00351 void Scene3D::startTmr() // слот - запустить таймер
    00352 {
    00353    timer->start();
    00354 }