Chapter 8
Примеры интересных программ
8.5 Рисуем кривые и поверхности
В библиотеке 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
В анимированном виде я смотрюсь гораздо лучше. Пивзавод балтика должен мне
за рекламу продукта бочку пива поставить. И при том не одну.;-)
|