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;

}


 

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

30016. Доплаты и надбавки к заработной плате, их роль в стимулировании труда 108.36 KB
  Оплата труда и премирование.Виды оплаты труда с использованием премиальной системы.Доплаты и надбавки к заработной плате их роль в стимулировании труда29 3. Поощрительные системы оплаты труда прежде всего следует различать по назначению определяющему взаимосвязи поощрительной оплаты с основным заработком а также желание сотрудника выполнять свои обязанности выше установленных норм.
30017. Особенности приготовления блюд русской кухни 1022.86 KB
  Русская кухня давно пользуется широкой известностью во всем мире. Это проявляется как в прямом проникновении в международную ресторанную кухню исконно русских пищевых продуктов
30018. Учет труда и расчетов с персоналом по оплате труда 177.69 KB
  Методика учета расчетов с персоналом по оплате труда 14 1. Структура оплаты труда работников предприятия 19 2.2 Оценка состояния учета расчетов с персоналом по оплате труда 29 2.
30019. Технические условия на изготовление сварочной конструкции 490.35 KB
  Закономерности сварки плавлением излагаются в тесной связи со спецификой отдельных ее видов. Наибольшее внимание уделено дуговой сварке занимающей ведущее положение по сравнению с другими видами сварки. Применение сварки способствует совершенствованию машиностроения и развитию таких отраслей техники как ракетостроение атомная энергетика радиоэлектроника и др.
30021. «Богатырь русского леса. Шишкин И.И.» (мультимедиа программа) 995 KB
  Картина №1. Афонасовский как прозывается он в наших краях под Елабугой Картина эта имела успех у публики. А для меня эта картина стала первой где многолетние свои наблюдения природы пытался я претворить в единый образ русского леса образ родины. Картина №2.
30023. Практические рекомендации по развитию интернет коммуникаций Фонда венчурных инвестиций ЧР www.e-birzha.cap.ru 1.39 MB
  Специфика корпоративного сайта как PRинструмента. Анализ официального сайта Фонда венчурных инвестиций ЧР www. История создания и ключевые требования к содержанию сайта. Анализ существующего состояния сайта www.
30024. Опытно - экспериментальная работа по формированию умений письма и письменной речи по средствам информационно – коммуникационных технологий 121.3 KB
  Информационнокоммуникационные технологии заняли прочное место в процессе обучения иностранному языку. Практика показывает что информационнокоммуникационные технологии имеют немало преимуществ перед традиционными методами обучения. Среди них можно выделить интенсификацию самостоятельной работы учащихся повышение познавательной активности и индивидуализацию обучения.