Скачиваний:
40
Добавлен:
01.05.2014
Размер:
1.82 Mб
Скачать

Министерство образования и науки Российской Федерации

Санкт-Петербургский государственный электротехнический университет «ЛЭТИ»

кафедра математического обеспечения ЭВМ

Пояснительная записка

к курсовой работе по дисциплине «Компьютерная графика»

«Движение луча света по поверхности Безье»

Выполнил: Рыжок М. гр. 3341

Проверил: Ларионова О.Г.

Санкт-Петербург 2007

Курсовая работа.

Движение луча света по поверхности Безье

Цель работы: Изучить представление в компьютерной графике математические модели трехмерных поверхностей, в частности, поверхностей Безье, и способов их визуализации.

Задание на курсовую работу: разработать программу, осуществляющую имитацию движения луча по поверхности Безье. Программа должна обладать дружественным интерфейсом и предоставлять пользователю возможность влиять на свойства поверхности и луча.

Предварительные сведения

Практическое использование в различных областях науки и техники различных типов поверхностей, таких как бикубическая поверхность Кунса или кубических сплайновых кривых затрудняется необходимостью задания точной, интуитивно неочевидной математической информации, например, координат точек, касательных векторов и векторов кручения. Большинство этих проблем можно преодолеть, если использовать математический аппарат поверхностей Безье.

Поверхности Безье являются обобщением понятии кривых Безье к трехмерному случаю. Декартово или тензорное произведение поверхностей Безье задается в виде:

, где К и 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 <GL\glut.h>

#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, &amplif);

break;

}

case '-':

{

amplif += 0.1;

glLightfv(GL_LIGHT0, GL_CONSTANT_ATTENUATION, &amplif);

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, &amplif);

}

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;

}

Выводы: В процессе выполнения курсовой работы были освоены навыки в представлении полигональных моделей, в частности, поверхностей Безье для аппроксимации и визуализации трехмерных поверхностей.

Список использованных источников

  1. Д.Роджерс, Дж.Адамс. Математические основы машинной графики, Москва, «Мир», 2001г.

  2. Ресурсы сайта alglib.source.ru