Основы OpenGL
de301fb4

Рисуем кривые и поверхности


В библиотеки glu имеются функции для создания кривых и поверхностей по точкам аппроксимируя их сплайнами. Все это по-моему также круто, как и бесполезно. Здесь я рассмотрю создание поверхности по точкам, которые могут быть заданы в виде массива точек - { (x0, y0, z0), (x1, y1, z1), (x2, y2, z2), ...} или в виде уравнения z(x,y). Задача, как правило, состоит в том, чтобы соединить каждые четыре соседние вершины многоугольником и приписать к ним координаты текстуры. В данной программе я наложу текстуру на поверхность, которая колеблется по синусу. Уравнение такой поверхности: z=sin(x+t). Параметр t - время, нужен для задания анимации. Создайте новый проект с именем flag и скопируйте туда шаблон glaux.c. Объявите в функции display эту переменную следующим образом:

static double t=0; ... t+=0.1; // на каждом кадре увеличиваем ее значение. auxSwapBuffers();

Код построения поверхности будет выглядеть так. Вы проходите в двойном цикле по некой области в плоскости XY и вычисляете z в зависимости от х и y. Каждые четыре соседние вершины соединяете многоугольником. В данном случае мы проходим в плоскости XY от точки (0,0) до точки (7,8). Текстуру можно было бы и не привязывать, но тогда бы был совсем не тот эффект. Привязка текстуры делается способом описанным в главе "Работа с картинками". Левая нижняя точка {0,0, z(0,0)} на поверхности соответствует точке {0,0} на текстуре, а правая верхняя точка на поверхности {7,8,z(7,8)} соответствует точке {1,1} текстуры. Поэтому, если точка на поверхности имеет координаты (x,y), то к ней надо привязать точку текстуры с координатой (x/Max_X, y/Max_Y), т.е. просто приводим к диапазону 0-1. Max_X и Max_Y, как вы понимаете, равны 7 и 8. Ниже следует код функции display c комментариями.

// определяем шаг #define dx 0.7 #define dy 0.8 void CALLBACK display(void) { static double t=0; double x,y,z; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // устанавливаем цвет поверхности белый // с другим цветом будет складываться цвет текстуры // а с белым будет видна сама текстура без искажений glColor3d(1,1,1); // немного повернем сцену glPushMatrix(); glTranslated(-3,-3.5,0); Проходим от точки (0,0) до (7-dy,8-dx) for(y=0;y<9*dy;y+=dy) for(x=0;x<9*dx;x+=dx) { // будем соединять, каждые четыре точки многоугольником glBegin(GL_POLYGON); // вычисляем z от координаты x и от времени t z = sin(x+t); // привязываем координаты текстуры к координатам поверхности glTexCoord2d(x/10/dx, y/10/dy); glVertex3d(x,y,z); // здесь значение z точно такое же // т.к. z не зависит от y, a x у нас не изменилось glTexCoord2d(x/10/dx, (y+dy)/10/dy); glVertex3d(x,y+dy,z); z = sin(x+dx+t); glTexCoord2d((x+dx)/10/dx, (y+dy)/10/dy); glVertex3d(x+dx,y+dy,z); glTexCoord2d((x+dx)/10/dx, y/10/dy); glVertex3d(x+dx,y,z); glEnd(); } glPopMatrix(); t+=0.1; auxSwapBuffers(); }


Теперь измените положение камеры в функции resize: gluLookAt( -2,3,5, 0,0,0, 0,1,0 );

И нам осталось загрузить текстуру. Объявите глобальную переменную AUX_RGBImageRec* image;

Функцию main отредактируйте следующим образом.

void main() { float pos[4] = {3,3,3,1}; float dir[3] = {-1,-1,-1}; GLfloat mat_specular[] = {1,1,1,1}; auxInitPosition( 50, 10, 400, 400); auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE ); auxInitWindow( "Glaux Template" ); auxIdleFunc(display); auxReshapeFunc(resize); glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); glEnable(GL_AUTO_NORMAL); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, pos); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialf(GL_FRONT, GL_SHININESS, 128.0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); image = auxDIBImageLoad("photo.bmp"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, image->sizeX, image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data); glEnable(GL_TEXTURE_2D); auxMainLoop(display); }

Исходный файл смотрите . Исполняемый файл .

PS

В анимированном виде я смотрюсь гораздо лучше. Пивзавод балтика должен мне за рекламу продукта бочку пива поставить. И при том не одну.;-)


Содержание раздела