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 }