RayTracing
|
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 }