курсовая КГ. Курсовая работа. Движение луча света по поверхности Безье
Скачать 1.3 Mb.
|
Курсовая работа. Движение луча света по поверхности Безье Цель работы: Изучить представление в компьютерной графике математические модели трехмерных поверхностей, в частности, поверхностей Безье, и способов их визуализации. Задание на курсовую работу: разработать программу, осуществляющую имитацию движения луча по поверхности Безье. Программа должна обладать дружественным интерфейсом и предоставлять пользователю возможность влиять на свойства поверхности и луча. Предварительные сведения Практическое использование в различных областях науки и техники различных типов поверхностей, таких как бикубическая поверхность Кунса или кубических сплайновых кривых затрудняется необходимостью задания точной, интуитивно неочевидной математической информации, например, координат точек, касательных векторов и векторов кручения. Большинство этих проблем можно преодолеть, если использовать математический аппарат поверхностей Безье. Поверхности Безье являются обобщением понятии кривых Безье к трехмерному случаю. Декартово или тензорное произведение поверхностей Безье задается в виде: , где К и J есть базисные функции Бернштейна в параметрических направлениях u и w: , , а элементы Bij являются вершинами задающей полигональной сетки. Индексы n и m на единицу меньше числа многогранников в направлениях u и w соответственно. Из-за того, что для смешивающих функций используется базис Бернштейна, многие свойства поверхности известны: Степень поверхности в каждом параметрическом направлении на единицу меньше числа вершин задающего многоугольника в этом направлении. Гладкость поверхности в каждом параметрическом направлении на 2 единицы меньше числа вершин задающего многоугольника в этом направлении Поверхность отображает в общем виде форму задающей полигональной сетки Совпадают только угловые точки задающей полигональной сетки и поверхности Поверхность содержится внутри выпуклой оболочки задающей полигональной сетки. Поверхность инварианта относительно аффинного преобразования Каждая из граничных линий поверхности Безье является кривой Безье. В матричном виде декартово произведение поверхности Безье задается преобразованием : Здесь U = [un, un-1, … u1, 1] W = [wn, wn-1, …w1, 1]T , N и M вычисляются по формулам Для специального случая бикубической поверхности Безье размера 4*4 уравнение сокращается до: Поверхность Безье не обязательно должна быть квадратной. Для сетки размера 5*3 уравнение превращается в: На рисунке 1 представлена бикубическая поверхность Безье, на рисунке 2 – поверхность 5*3 Рисунок 1 Рисунок 2 Поверхности Безье связаны со многими другими геометрическими моделями, например, поверхностями Кунса, рассмотрение которых остается за пределами данной работы. Описание интерфейса программы. Программа с помощью матричных преобразований создает и визуализирует поверхность Безье на основе полигональной сетки. Пользователю предоставляется возможность совершать следующие действия с помощью клавиатуры: Перемещение поверхности в пространстве (клавиши ‘a’ и ‘d’ – вправо-влево, ‘w’ и ‘s’ – вверх-вниз, ‘e’и ‘r’ – вперед-назад). Визуализация каркасной сетки поверхности и непрерывного изображения, переключение между ними (клавиша ‘l’) Включение \ выключение источника света (клавиша ‘p’) Увеличение \ уменьшение количества полигональных узлов базисной сетки:(клавиши ‘n’ и ‘m’ в одном направлении, клавиши ‘h’ и ‘j’ – в другом направлении). Выбор цвета источника света: Клавиша ‘1’ – красный Клавиша ‘2’ – зеленый Клавиша ‘3’ – синий Клавиша ‘4’ – желтый Клавиша ‘5’ – фиолетовый Клавиша ‘6’ – голубой Клавиша ‘7’ – белый Расширение и сужение угла прожектора (клавиши ‘8’ и ‘9’) Увеличение и уменьшение яркости цвета (клавиши ‘+’ и ‘-’) Увеличение и уменьшение скорости вращения (клавиши ‘f’ и ‘F’) Поворот оси вращения (клавиши ‘x’ и ‘X’ изменяют наклон оси вращения относительно оси абсцисс, ‘y’ и ‘Y’ – относительно оси ординат, ‘z’ и ‘Z’ – относительно оси апликат). Примеры изображения каркасной сетки поверхности Безье Примеры изображения луча разных цветов и плсщади на поверхности Безье Поверхность Безье: измененная полигональная сетка Пояснение пользователю Приложение Текст программы на языке С++ с использованием библиотеки OpenGL #include "windows.h" #include #include "matrix.h" #include "curves.h" #include "stdio.h" float xt = 0.0f; float yt = 0.0f; float zt = 0.0f; float h = 1.0f; GLfloat light_amb[] = {0.0f, 1.0f, 0.4f, 1.0f}; GLfloat light_diff[] = {0.0f, 0.0f, 0.3f, 1.0f}; GLfloat light_spec[] = {0.3f, 0.8f, 0.3f, 0.5f}; GLfloat light_pos[] = {0,0,0,1}; float amplif = 1.0; //light amplification float spot_cutoff = 180; //light spot cutoff float rotatus[] = {1.0, 0.0, 0.0}; //create control point for patch Point CP[16]; CCubicCurve curves[4]; //four curves CCubicPatch patch; void InitCurves() { CP[0].x = 1.0f; CP[0].y = 1.0f; CP[0].z = 1.0f; CP[1].x = 4.0f; CP[1].y = 2.0f; CP[1].z = 0.0f; CP[2].x = 8.0f; CP[2].y =-2.0f; CP[2].z = 0.0f; CP[3].x = 12.0f; CP[3].y = 0.0f; CP[3].z = 0.0f; CP[4] = CP[0]; CP[4].z += 10.0f; CP[5] = CP[1]; CP[5].y = -20.0f; CP[5].z += 10.0f; CP[6] = CP[2]; CP[6].y = 10.0f; CP[6].z += 10.0f; CP[7] = CP[3]; CP[7].z += 10.0f; CP[7].x += 2.0f; CP[8] = CP[0]; CP[8].z += 20.0f; CP[9] = CP[1]; CP[9].y += -15.0f; CP[9].x = -1.0f; CP[9].z += 20.0f; CP[10] = CP[2]; CP[10].z += 20.0f; CP[11] = CP[3]; CP[11].z += 20.0f; CP[12] = CP[0]; CP[12].z += 30.0f; CP[13] = CP[1]; CP[13].z += 30.0f; CP[14] = CP[2]; CP[14].z += 30.0f; CP[15] = CP[3]; CP[15].z += 30.0f; patch.GeneratePatch(CP); Matrix4x1 p1, p2, p3, p4; p1.M[0] = -7.0f; p1.M[1] = 2.0f; p1.M[2] = 0.0f; p2.M[0] = -7.0f; p2.M[1] = 2.0f; p2.M[2] = 2.0f; p3.M[0] = -7.0f; p3.M[1] = 2.0f; p3.M[2] = 3.0f; p4.M[0] = -7.0f; p4.M[1] = 2.0f; p4.M[2] = 4.0f; curves[0].GenerateBezierCoefficients(p1,p2,p3,p4); //subdivide curve curves[0].SubdivideBezierCurve(&curves[1], &curves[2]); //give subdiveded curves another color curves[1].SetColor(1,0,0,0.5f); curves[2].SetColor(0,1,0,0.5f); curves[1].SubdivideBezierCurve(&curves[0], &curves[3]); curves[0].SetColor(1,1,1,0.5f); curves[3].SetColor(1,1,0,0.5f); } void lightcolor(float R = 0.0f, float G = 0.0f, float B = 0.0f) { if (R > 1.0 || R < 0.0 || G > 1.0 || G < 0.0 || B > 1.0 || B < 0.0) return; light_amb[0] = R; light_amb[1] = G; light_amb[2] = B; light_diff[0] = R; light_diff[1] = G; light_diff[2] = B; glLightfv(GL_LIGHT0, GL_AMBIENT, light_amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diff); } void reshape(int w, int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, 1, 0.1, 200); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0,-10,50, 0,-10,0, 0,1,0); glLightfv(GL_LIGHT0, GL_POSITION, light_pos); } void keyboard(unsigned char key, int x, int y) { static bool line_on = false; switch (key) { case 'l': if (line_on) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); line_on = !line_on; break; case 'a': xt -= 1.0f; break; case 'd': xt += 1.0f; break; case 'w': yt +=1.0f; break; case 's': yt -=1.0f; break; case 'e': zt -= 1.0f; break; case 'r': zt += 1.0f; break; case 'n': patch.ChangeEval(TM_S_EVALS, -1); break; case 'm': patch.ChangeEval(TM_S_EVALS, 1); break; case 'h': patch.ChangeEval(TM_CURVE_EVALS, -1); break; case 'j': patch.ChangeEval(TM_CURVE_EVALS, 1); break; case 'p': { static bool light = false; if (light) glDisable(GL_LIGHTING); else glEnable(GL_LIGHTING); patch.ToggleNormals(); light = !light; }break; case '1': { lightcolor(1, 0, 0); break;} case '2': { lightcolor(0, 1, 0); break;} case '3': { lightcolor(0, 0, 1); break;} case '4': { lightcolor(1, 1, 0); break;} case '5': { lightcolor(1, 0, 1); break;} case '6': { lightcolor(0, 1, 1); break;} case '7': { lightcolor(1, 1, 1); break;} case '8': { spot_cutoff -= 10; glLightf(GL_LIGHT0,GL_SPOT_CUTOFF, spot_cutoff); break; } case '9': { spot_cutoff += 10; glLightf(GL_LIGHT0,GL_SPOT_CUTOFF, spot_cutoff); break; } case '+': { amplif -= 0.1; glLightfv(GL_LIGHT0, GL_CONSTANT_ATTENUATION, &lif); break; } case '-': { amplif += 0.1; glLightfv(GL_LIGHT0, GL_CONSTANT_ATTENUATION, &lif); break; } case 'f':{h = h*2; break;} case 'F':{h = h/2.0; break;} case 'x': { if (rotatus[0] < 1) rotatus[0] += 0.1f; break; } case 'X': { if(rotatus[0] > 0) rotatus[0] -= 0.1f; break; } case 'y': { if (rotatus[1] < 1) rotatus[1] += 0.1f; break; } case 'Y': { if (rotatus[1] > 0) rotatus[1] -= 0.1f; break; } case 'z': { if (rotatus[2] < 1) rotatus[2] += 0.1f; break; } case 'Z': { if (rotatus[2] > 0) rotatus[1] -= 0.1f; break; } case 27: exit(0); break; default: break; } glutPostRedisplay(); } void display() { static float rot = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); //allow the user to move the patch for further examination glTranslatef(-xt, -yt, -zt); glRotatef(rot, rotatus[0], rotatus[1], rotatus[2]); patch.Draw(); glPopMatrix(); glFlush(); glutSwapBuffers(); if (rot >= 360.0f) rot -= 360.0f; rot += h; } void init() { glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glEnable(GL_DEPTH_TEST); glColor3f(0,1,0); glLineWidth(1); InitCurves(); glDisable(GL_LIGHTING); //is turned on by the user glEnable(GL_LIGHT0); GLfloat amb[] = {1,1,1,0.5f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); //init lights glLightfv(GL_LIGHT0, GL_AMBIENT, light_amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diff); glLightfv(GL_LIGHT0, GL_SPECULAR, light_spec); glLightf(GL_LIGHT0,GL_SPOT_CUTOFF, spot_cutoff); glLightfv(GL_LIGHT0, GL_CONSTANT_ATTENUATION, &lif); } void idle() { glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitWindowPosition(100,100); glutInitWindowSize(400,400); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Bezie Curve Demo - By thoooms"); printf("\n\n\n-------------\nBezie Curve Demo - \n-------------"); printf("\n'a' and 'd':\t x axis movement"); printf("\n'w' and 's':\t y axis movement"); printf("\n'e' and 'r':\t z axis movement"); printf("\n'l':\t\t switches between wireframe and solid rendering"); printf("\n'p':\t\t Enables/Disables the calculation of normals and the lighting"); printf("\n'n' and 'm':\t Changes the number of curves used to create the triangles"); printf("\n'h' and 'j':\t Changes the number of evaluations used to make each curve"); printf("\n'1' - '7' :\t Light an object a color"); printf("\n'8':\t : Cut off the entrance angle"); printf("\n'9':\t : Extend tht entrance angle"); printf("\n'+':\t : Add the brightness"); printf("\n'-':\t : Delete the brightness"); printf("\n'f' and 'F':\t Increase and decrease a rotate speed"); printf("\n'x' and 'X':\t Increase and decrease a rotate angle around X axe"); printf("\n'y' and 'Y':\t Increase and decrease a rotate angle around Y axe"); printf("\n'z' and 'Z':\t Increase and decrease a rotate angle around Z axe"); init(); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutReshapeFunc(reshape); glutIdleFunc(idle); glutMainLoop(); return 0; } Выводы: В процессе выполнения курсовой работы были освоены навыки в представлении полигональных моделей, в частности, поверхностей Безье для аппроксимации и визуализации трехмерных поверхностей. Список использованных источников Д.Роджерс, Дж.Адамс. Математические основы машинной графики, Москва, «Мир», 2001г. Ресурсы сайта alglib.source.ru |