14576

Кривые и поверхности в OpenGL

Лабораторная работа

Информатика, кибернетика и программирование

Лабораторная работа № 7 Кривые и поверхности в OpenGL Кривые Безье Кривая Безье задается векторной функцией одной переменной Cu = [ Xu Yu Zu] Где u изменяется в некоторой области например [0.0 1.0]. Фрагмент поверхности Безье задается векторной фу

Русский

2013-06-08

75 KB

55 чел.

Лабораторная работа № 7

Кривые и поверхности в OpenGL

Кривые Безье

Кривая Безье задается векторной функцией одной переменной

   C(u) = [ X(u), Y(u), Z(u)],

     

Где  u изменяется в некоторой области, например, [0.0, 1.0].

Фрагмент поверхности Безье задается векторной функцией двух переменных

   S(u, v) = [ X(u, v), Y(u, v), Z(u, v) ].

Для каждого значения u и v формула C( ) или S( ) вычисляет точку на кривой ( поверхности ). При использовании Безье-вычисления сначала выбирают функцию C( ) или S( ), включают ее (Безье-вычислитель), а затем используют команду glEvalCoord1( ) или glEvalCoord2( ) вместо команды glVertex*( ). В этом случае вершина кривой или поверхности может использоваться точно также, как и любая другая вершина, например, для формирования точки или линии. Кроме того, другие команды автоматически генерируют серии вершин, образующих пространство регулярной однородной сетки по оси u (или по осям u и v ).  

Если  представляет набор контрольных точек, то уравнение

   C(u) =   - представляет собой кривую Безье при изменении u от 0.0 до 1.0, где

 

- многочлен Бернштейна степени n, который задается следующим уравнением

    

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

Функция обработки полинома одной переменной настраивается в процессе инициализации OpenGL- программы посредством вызова функции

 glMap1f(type, u_min, u_max, stride, order, point array)

 Аргумент  type задает тип объекта, который будет представлен полиномом Безье. Можно назначить в качестве значения этого аргумента константы, задающие трех- и четырехмерные геометрические точки, цвет в формате RGBA, нормали, индексированные цвета и координаты текстур ( от одно- до четырехмерных).

Table 12-1 : Types of Control Points for glMap1*()

Parameter

Meaning

GL_MAP1_VERTEX_3

x, y, z vertex coordinates

GL_MAP1_VERTEX_4

x, y, z, w vertex coordinates

GL_MAP1_INDEX

color index

GL_MAP1_COLOR_4

R, G, B, A

GL_MAP1_NORMAL

normal coordinates

GL_MAP1_TEXTURE_COORD_1

s texture coordinates

GL_MAP1_TEXTURE_COORD_2

s, t texture coordinates

GL_MAP1_TEXTURE_COORD_3

s, t, r texture coordinates

GL_MAP1_TEXTURE_COORD_4

s, t, r, q texture coordinates

 Указатель на массив опорных точек полинома передается функции через аргумент point_array. Аргументы u_min, u_max определяют область существования параметра полинома. Аргумент stride представляет собой количество значений параметра между сегментами кривой. Значение аргумента order должно быть равно количеству опорных точек. Для формирования кубической трехмерной кривой в форме В-сплайна, определенной на интервале (0,1), функции glMap1f() следует передать такой набор аргументов:

point data[]= {…};

glMap1f(GL_MAP_VERTEX_3, 0.0, 1.0, 3, 4, data);

 После настройки функция активизируется посредством вызова:

 glEnable(type);

 Если функция расчета активизирована, то можно получить от нее значения полинома, вызвав функцию:

 glEvalCoord1f(u);

 Таким образом, обращение к glEvalCoord1f() может заменить обращение к функциям glVertex(), glColor(), glNormal(). Пусть, например, функция расчета настроена на формирование кривой Безье на интервале (0,10) по некоторому массиву опорных точек. Набор из 100 точек кривой, равноотстоящих на этом интервале можно получить с помощью такого фрагмента программы:

 glBegin(GL_LINE_STRIP)

 for(i=0; i<100; i++) glEvalCoord1f( (float)i/100.);

glEnd();  

 Если значения параметра u распределены равномерно, то для вычисления точек на кривой следует использовать функции glMapGrid1f() и glEvalMesh1(), например:

 glMapGrid1f(100, 0.0, 10.0);

glEvalMesh1(GL_LINE, 0, 100);

 После вызова glMapGrid1f() устанавливается равномерная сетка в 100 отсчетов, а после вызова функции glEvalMesh1() будет сформирована кривая.

Пример программы вычисления и рисования полинома Безье.

#include <GL/glut.h>

#include <stdlib.h>

GLfloat ctrlpoints[4][3] = {

{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},

{2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}};

void init(void)

{

  glClearColor(0.0, 0.0, 0.0, 0.0);

  glShadeModel(GL_FLAT);

  glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);

  glEnable(GL_MAP1_VERTEX_3);

}

void display(void)

{

  int i;

  glClear(GL_COLOR_BUFFER_BIT);

  glColor3f(1.0, 1.0, 1.0);

  glBegin(GL_LINE_STRIP);

     for (i = 0; i <= 30; i++)

        glEvalCoord1f((GLfloat) i/30.0);

  glEnd();

  /* The following code displays the control points as dots. */

  glPointSize(5.0);

  glColor3f(1.0, 1.0, 0.0);

  glBegin(GL_POINTS);

     for (i = 0; i < 4; i++)

        glVertex3fv(&ctrlpoints[i][0]);

  glEnd();

  glFlush();

}

void reshape(int w, int h)

{

  glViewport(0, 0, (GLsizei) w, (GLsizei) h);

  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

  if (w <= h)

     glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,

              5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);

  else

     glOrtho(-5.0*(GLfloat)w/(GLfloat)h,

              5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);

  glMatrixMode(GL_MODELVIEW);

  glLoadIdentity();

}

void keyboard(unsigned char key, int x, int y)

{

  switch (key) {

     case 27:

        exit(0);

        break;

  }

}

int main(int argc, char** argv)

{

  glutInit(&argc, argv);

  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

  glutInitWindowSize (500, 500);

  glutInitWindowPosition (100, 100);

  glutCreateWindow (argv[0]);

  init ();

  glutDisplayFunc(display);

  glutReshapeFunc(reshape);

  glutKeyboardFunc (keyboard);

  glutMainLoop();

  return 0;

}

Поверхности Безье

Математически  фрагмент  поверхности  Безье  задается  уравнением                                                                                                   S(u,v)=

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

Поверхности Безье формируются в OpenGL примерно по той же методике, что и кривые, только роль функции инициализации играет не glMap1*(), а glMap2*(), а для считывания результатов следует обращаться к функции glEvalCoord2*() вместо glEvalCoord1*(). В обеих функциях нужно специфицировать данные, относящиеся к двум независимым параметрам u и v. Например, функция glMap2f() имеет такой формат вызова:

glMap2f(type, u_min, u_max, u_stride, u_order, v_min, v_max, v_stride, v_order, point_array);

 Настройка функции вычисления на работу с бикубической поверхностью Безье, определенной на области (0,1)х(0,1), выполняется таким вызовом glMap2f():

glMap2f(GL_MAP_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4, data);

 Для обоих независимых переменных нужно задать порядок полинома (аргументы u_order и v_order) и количество значений параметра между сегментами (аргументы u_stride и v_stride), что обеспечивает дополнительную гибкость при формировании поверхности. Обратите внимание на то, что значение v_stride для второго параметра равно 12, поскольку в массиве опорных точек  data данные хранятся по строкам. Поэтому для перехода к следующему элементу этой же строки нужно «перешагнуть» три числа в формате float, а для перехода к следующему элементу в этом же столбце нужно «перешагнуть» через 3*4=12 чисел в формате float. Способ вызова программы расчета зависит от того, какой результат мы хотим получить,- вывести на экран сеть или сформировать многоугольники для последующего раскрашивания. Если ставится задача сформировать на экране сеть, то соответствующий фрагмент программы должен выглядеть примерно так:

 for(j=0; j<100; j++)

{

glBegin(GL_LINE_STRIP);

 for(i=0; i<100; i++)

 glEvalCoord2f((float)i/100.0, (float)j/100.0);

glEnd();

  glBegin(GL_LINE_STRIP);

 for(i=0; i<100; i++)

 glEvalCoord2f((float)j/100.0, (float)i/100.0);

glEnd();

}

 Если же желательно сформировать множество многоугольников, то фрагмент должен выглядеть так:

 for(j=0; j<99; j++)

{

 glBegin(GL_QUAD_STRIP)

 for(i=0; i<=100; i++)

 {

 glEvalCoord2f( (float)i/100.0, (float)j/100.0);

 glEvalCoord2f( (float)(i+1)/100.0, (float)j/100.0);

 }

 glEnd();

}

Для работы на равномерной сетке следует использовать функции glMapGrid2*() и glEvalMesh2(). Тогда в самое начало программы, в ту часть, которая отвечает за инициализацию, нужно включить такой фрагмент:

 glMapGrid2f(100, 0.0, 1.0, 100, 0.0, 1.0);

 В функции отображения display() нужно вызвать glEvalMesh2():

glEvalMesh2(GL_FILL, 0, 100, 0, 100);

 Для работы алгоритмов тонирования (закрашивания) сформированной поверхности при настройке режима учета освещения нужно дополнительно вызвать функцию glEnable(), передав ей в качестве аргумента константу GL_AUTO_NORMAL:

glEnable(GL_AUTO_NORMAL);

 Это позволит OpenGL автоматически вычислять вектор нормали к каждому участку формируемой поверхности и использовать этот вектор при закрашивании участков этой поверхности.

Пример программы аппроксимации с помощью поверхности Безье функции z=sin(x+y):

#include <stdlib.h>

#include <GL/glut.h>

#include <math.h>

#include <stdio.h>

GLfloat ctrlpoints[6][6][3];

void initlights(void)

{

  GLfloat ambient[] = {1.0, 1.0, 1.0, 1.0};

  GLfloat position[] = {0.0, 0.0, 2.0, 1.0};

  GLfloat mat_diffuse[] = {1.0, 1.0, 1.0, 1.0};

  GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};

  GLfloat mat_shininess[] = {50.0};

  glEnable(GL_LIGHTING);

  glEnable(GL_LIGHT0);

  glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

  glLightfv(GL_LIGHT0, GL_POSITION, position);

  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glPushMatrix();

  glRotatef(85.0, 1.0, 0.0, 0.0);

glEvalMesh2(GL_FILL, 0, 10, 0, 10);

  glPopMatrix();

  glFlush();

}

void init(void)

{

float x,y;

int i,j;

for (i=0; i<6;i++)

{

x=3.1415/5.0*(float)i;

for(j=0; j<6; j++)

{

 y=3.1415/5.0*(float)j;

 ctrlpoints[i][j][0]=x;

 ctrlpoints[i][j][1]=y;

 ctrlpoints[i][j][2]=sin(x+y);

}

}

  glClearColor(0.0, 0.0, 0.0, 0.0);

  glEnable(GL_DEPTH_TEST);

  glMap2f(GL_MAP2_VERTEX_3, 0, 4, 3, 4,

          0, 4, 18, 4, &ctrlpoints[0][0][0]);

  glEnable(GL_MAP2_VERTEX_3);

  glEnable(GL_AUTO_NORMAL);

 glMapGrid2f(10, 0.0, 4.0, 10, 0.0, 4.0);

  initlights();       /* for lighted version only */

}

void reshape(int w, int h)

{

  glViewport(0, 0, 400, 400);

  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

        glOrtho(-1.0,2.0, -1.0, 2.0, -2.0, 2.0);

  glMatrixMode(GL_MODELVIEW);

  glLoadIdentity();

}

void keyboard(unsigned char key, int x, int y)

{

  switch (key) {

     case 27:

        exit(0);

        break;

  }

}

int main(int argc, char **argv)

{

  glutInit(&argc, argv);

  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);

  glutInitWindowSize (500, 500);

  glutInitWindowPosition (100, 100);

  glutCreateWindow(argv[0]);

  init();

  glutReshapeFunc(reshape);

  glutDisplayFunc(display);

  glutKeyboardFunc(keyboard);

  glutMainLoop();

  return 0;

}


 

А также другие работы, которые могут Вас заинтересовать

31594. ПАТОФІЗІОЛОГІЯ СИСТЕМИ КРОВІ 82 KB
  Численні форми патології і реактивні зміни в системі крові умовно можна об’єднати у 5ть груп. Типові форми патології і реактивних змін загального об’єму співвідношення плазми і формених елементів крові. Типові форми патології зсідаючої та протизсідаючої систем крові порушення гемостазу.
31595. ПАТОФІЗІОЛОГІЯ ТРАВЛЕННЯ 85.5 KB
  Класифікація недостатності травлення: За масштабами порушення: а загальна тотальна порушення засвоєння всіх видів поживних речовин і б селективна парціальна – порушення засвоєння окремих класів поживних речовин. інфекційного походження вплив бактерій бактеріальних токсинів вірусів найпростіших гельмінтів обумовлену дією фізичних факторів травми гостра променева хвороба пов’язану із дією хімічних агентів отруєння неорганічними і органічними речовинами дисрегуляційну – різні види порушення нервової і гуморальної...
31596. ПОРУШЕННЯ БІЛКОВОГО та ВУГЛЕВОДНОГО ОБМІНІВ 80.5 KB
  Порушення білкового обміну проявляється розвитком білкової недостатності яка може обумовлюватися: 1 Аліментарними причинами. 2 Порушенням біосинтезу білка. 3 Порушенням проміжного обміну амінокислот.
31597. ПОРУШЕННЯ ВИЩОЇ НЕРВОВОЇ ДІЯЛЬНОСТІ 85.5 KB
  Порушення відчуттів і сприйняття подразнень із зовнішнього середовища. Порушення зорової сенсорної системи зона кори навколо шпорної борозни – sulcus clcrinus. Ушкодження зорового аналізатора письмової мови ІІ сигнальна система gyrus ngulris lobulus prietlis inferior супроводжується виникненням алексії – порушення здатності читати та розуміти написане.
31598. ПОРУШЕННЯ ГЕМОСТАЗУ. Тромбоцитопенії 83 KB
  2 Тромбоцитопенії пов’язані із посиленим руйнуванням тромбоцитів: а імунне ушкодження обумовлене антитромбоцитарними антитілами на власні компоненти кров’яних пластинок чи на лікарські препарати адсорбовані на тромбоцитах розвиток ідіопатичної тромбоцитопеничної пурпури хвороби Верльгофа; б гіперспленізм гіперфункція селезінки що супроводжується підвищенням фагоцитарної активності фіксованих макрофагів які фагоцитують усі формені елементи крові у тому числі і тромбоцити; в механічне ушкодження тромбоцитів часто виникає при...
31599. ПОРУШЕННЯ ГЕМОСТАЗУ. Система гемостазу 76.5 KB
  За нормальних умов кров перебуває в рідкому агрегатному стані що забезпечується системою РАСК умовна назва від перших літер слів: рідкий агрегатний стан крові яка обумовлюється: 1 Впливом простацикліну який синтезується ендотеліоцитами із арахідонової кислоти під дією циклоксигенази ЦОГ і простациклінсинтетази ПЦС попереджує адгезію тромбоцитів до судинної стінки має виражений антиагрегантний вплив. 2 Впливом оксиду азоту NO який синтезується ендотеліоцитами із Lаргініну під впливом NOсинтетази дифундує у м‘язову оболонку...
31600. ПОРУШЕННЯ ЕНЕРГЕТИЧНОГО ОБМІНУ. ГОЛОДУВАННЯ 71.5 KB
  Енергетичний обмін – це складний біохімічний процес обміну речовин, в якому задіяний каскад біохімічних реакцій, в результаті яких енергія, закладена в структурі вуглеводів, білків, жирів, які надходять в організм, акумулюється в макроергічних зв‘язках особливих хімічних сполук, зокрема, АТФ.
31601. ПОРУШЕННЯ ЛІПІДНОГО ОБМІНУ 80.5 KB
  Характерні: а високий рівень холестерину і ТГ у плазмі; б ксантелазми ліктьові і колінні ксантоми жовтуватокоричневі відкладення ліпідів у шкірі долонних ліній і в місцях тиску кілець; в атеросклероз коронарних артерій периферичних судин і судин мозку; в ожиріння цукровий діабет гіпотиреоз. Клінічно проявляються: а загальним ожирінням б ожирінням печінки в цукровим діабетом г хронічними захворювання нирок д органними ангіопатіями є жировими відкладеннями в сітківці. 4 Гормональні порушення хвороби обміну...