2633
.pdfзначение – GLU_NONE и GLU_FLAT. Далее осуществим включение
текстурирования на квадратичном объекте: |
|
|
|
|
quadratic=gluNewQuadric(); |
|
// Создает |
указатель на |
|
квадратичный объект |
|
|
|
|
gluQuadricNormals(quadratic, GLU_SMOOTH); |
// Создает |
|||
плавные нормали |
|
|
|
|
gluQuadricTexture(quadratic, GL_TRUE); |
// |
Создает |
||
координаты текстуры |
|
|
|
|
Код прорисовки куба приведен ниже: |
|
|
|
|
GLvoid glDrawCube() // Прорисовка куба |
|
|
||
{ |
|
|
|
|
glBegin(GL_QUADS); |
// Прорисовка четырехугольников |
|||
// Передняя сторона |
|
|
|
|
glNormal3f( 0.0f, 0.0f, 1.0f);// Нормаль вперед |
|
|||
glTexCoord2f(0.0f, 0.0f); |
|
|
|
|
glVertex3f(-1.0f, -1.0f, 1.0f);// Низ Лево на текстуре и |
||||
четырехугольнике |
|
|
|
|
glTexCoord2f(1.0f, 0.0f); |
|
|
|
|
glVertex3f(1.0f, -1.0f, 1.0f); |
// Низ Право на текстуре и |
|||
четырехугольнике |
|
|
|
|
glTexCoord2f(1.0f, 1.0f); |
|
|
|
|
glVertex3f( 1.0f, 1.0f, 1.0f); |
// Верх Право на текстуре и |
|||
четырехугольнике |
|
|
|
|
glTexCoord2f(0.0f, 1.0f); |
|
|
|
|
glVertex3f(-1.0f, 1.0f, 1.0f); |
// Верх Лево на текстуре и |
|||
четырехугольнике |
|
|
|
|
// Задняя сторона |
|
|
|
|
glNormal3f( 0.0f, 0.0f,-1.0f); |
|
// Обратная нормаль |
||
glTexCoord2f(1.0f, 0.0f); |
|
|
|
|
glVertex3f(-1.0f, -1.0f, -1.0f); |
// Низ Право на текстуре и |
|||
четырехугольнике |
|
|
|
|
glTexCoord2f(1.0f, 1.0f); |
|
|
|
|
glVertex3f(-1.0f, 1.0f, -1.0f);// Верх Право на текстуре и |
||||
четырехугольнике |
|
|
|
|
glTexCoord2f(0.0f, 1.0f); |
|
|
|
|
glVertex3f(1.0f, 1.0f, -1.0f); |
// Верх Лево на текстуре и |
четырехугольнике glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);// Низ Лево на текстуре и четырехугольнике
// Верхняя грань
glNormal3f( 0.0f, 1.0f, 0.0f);// Нормаль вверх
143
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);// Верх Лево на текстуре и четырехугольнике
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f); // Низ Лево на текстуре и четырехугольнике
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f); // Низ Право на текстуре и четырехугольнике
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);// Верх Право на текстуре и четырехугольнике
// Нижняя грань
glNormal3f( 0.0f,-1.0f, 0.0f);// Нормаль направлена вниз glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f); // Верх Право на текстуре и четырехугольнике
glTexCoord2f(0.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f); // Верх Лево на текстуре и четырехугольнике
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f); // Низ Лево на текстуре и четырехугольнике
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f); // Низ Право на текстуре и четырехугольнике
// Правая грань
glNormal3f( 1.0f, 0.0f, 0.0f); // Нормаль направлена вправо glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f); // Низ Право на текстуре и четырехугольнике
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f); // Верх Право на текстуре и четырехугольнике
glTexCoord2f(0.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f); // Верх Лево на текстуре и четырехугольнике
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f); // Низ Лево на текстуре и четырехугольнике
// Левая грань
glNormal3f(-1.0f, 0.0f, 0.0f); // Нормаль направлена влево
144
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f); // Низ Лево на текстуре и четырехугольнике
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f); // Низ Право на текстуре и четырехугольнике
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f); // Верх Право на текстуре и четырехугольнике
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f); // Верх Лево на текстуре и четырехугольнике
glEnd(); // Заканчиваем рисование четырехугольников
}
Следующая функция DrawGLScene. case – оператор для рисования разных объектов:
int DrawGLScene(GLvoid) // Прорисовка
{
// Очистка видео буфера и буфера глубины glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT); |
|
glLoadIdentity(); |
// Сбрасывает вид |
glTranslatef(0.0f,0.0f,z); |
// Перемещается вглубь экрана |
glRotatef(xrot,1.0f,0.0f,0.0f);// Вращение по оси X glRotatef(yrot,0.0f,1.0f,0.0f);// Вращение по оси Y glBindTexture(GL_TEXTURE_2D, texture[filter]);
//Выбирает фильтрацию текстуре
//Далее следует новая секция кода
switch(object) |
// Проверяет, какой объект рисовать |
|
{ |
|
|
case 0: |
|
// Рисует первый объект |
glDrawCube(); |
// Рисует куб |
|
break; |
|
// Конец |
Второй создаваемый объект – цилиндр: |
||
case 1: |
|
// Рисует второй объект |
glTranslatef(0.0f,0.0f,-1.5f); // Центр цилиндра |
||
gluCylinder(quadratic,1.0f,1.0f,3.0f,32,32);// Рисует цилиндр |
||
break; |
// Конец |
|
Первый параметр (1.0f) – радиус основания цилиндра (низ). Второй параметр (1.0f) –это радиус цилиндра сверху. Третий параметр (3.0f) – это высота цилиндра (какой он длины). Четвертый параметр (32)
– это сколько делений будет "вокруг" оси Z, и пятый (32) – количество
145
делений "вдоль" оси Z. Большее количество делений приведет к увеличению детализации объекта.
Третий объект – поверхность в виде CD-диска:
case 2: |
// Рисует третий объект |
gluDisk(quadratic,0.5f,1.5f,32,32); // Рисует диск (в виде CD) |
|
break; |
// Конец |
Первый параметр диска (0.5f) – внутренний радиус цилиндра. Его значение может быть нулевым, что будет означать, что внутри нет отверстия. Чем больше будет внутренний радиус – тем больше будет отверстие внутри диска. Второй параметр (1.5f) - внешний радиус. Третий параметр (32) – количество частей, из которых состоит диск. Четвертый параметр (32) – это число колец, которые составляют диск (можно задать – одно кольцо). Кольца похожи на треки на записи. Круги внутри кругов. Эти кольца делят диск со стороны внутреннего радиуса к внешнему радиусу, улучшая детализацию.
Четвертый объект – это сфера:
case 3: |
// Рисует четвертый объект |
gluSphere(quadratic,1.3f,32,32); // Рисует сферу |
|
break; |
// Конец |
Первый параметр – |
это радиус сферы. Дальше идет количество |
разбиений "вокруг" оси Z (32), и количество разбиений "вдоль" оси Z (32). Большее количество придаст сфере большую гладкость. Для того, чтобы сфера была достаточно гладкой, обычно необходимо большое количество разбиений.
Чтобы создать пятый объект – конус, используется та же команда, что и для цилиндра. Для того, чтобы сделать конус, имеет смысл сделать один из радиусов равный нулю. Это создаст точку на конце:
case 4: // Рисует пятый объект glTranslatef(0.0f,0.0f,-1.5f); // Центр конуса. Конус с нижним
радиусом 5 и высотой 2 gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32);
break; |
// Конец |
Шестой объект создан с помощью gluParticalDisc: |
|
case 5: |
// Рисует шестой объект |
part1+=p1; |
// Увеличивает стартовый угол |
part2+=p2; |
// Увеличивает конечный угол |
if(part1>359) |
// 360 градусов |
{ |
|
p1=0; |
// Закончить увеличивать начальный угол |
part1=0; |
// Устанавливает начальный угол в 0 |
p2=1; |
// Начинает увеличивать конечный угол |
part2=0; |
// Начиная с 0 |
146
} |
|
if(part2>359) |
// 360 градусов |
{ |
|
p1=1; |
// Начинает увеличивать начальный угол |
p2=0; |
// Перестает увеличивать конечный угол |
}
gluPartialDisk(quadratic,0.5f,1.5f,32,32,part1,part2-part1);
break; |
// Конец |
}; |
|
xrot+=xspeed; |
// Увеличивает угол поворота вокруг оси X |
yrot+=yspeed; |
// Увеличивает угол поворота вокруг оси Y |
return TRUE; |
// Продолжает |
}
Объект, который создается этой командой точно такой же диск, который был до этого, но у команды gluParticalDisc есть еще два новых параметра. Пятый параметр (part1) – это угол, с которого начинается рисование диска. Шестой параметр – это конечный угол (или угол развертки).
Рассмотрим процесс привязки к клавиатуре. Следует добавить код ниже туда, где происходит проверка нажатия клавиш:
if (keys[' '] && !sp) |
// Нажата клавиша "пробел"? |
{ |
|
sp=TRUE; |
// Если так, то устанавливает sp в TRUE |
object++; |
// Цикл по объектам |
if(object>5) |
// Номер объекта больше 5? |
object=0; |
// Если да, то устанавливает 0 |
} |
|
if (!keys[' ']) |
// Клавиша "пробел" отпущена? |
{ |
|
sp=FALSE |
// Если да, то устанавливает sp в FALSE |
} |
|
Результаты работы программы представлены на рис. 26-33. Измените текстуру объетов.
Измените прозрачность текстуры, наложенной на объекты.
147
Рис. 26. Куб, созданный как сложный объект
Рис. 27. Цилиндр, созданный как сложный объект
148
Рис. 28. CD-диск, созданный как сложный объект
Рис. 29. Сфера, созданный как сложный объект
149
Рис. 30. Конус, созданный как сложный объект
Рис. 31. Сложный объект, созданный с помощью gluParticalDisc
В приложении 1 приведен листинг программы, моделирующей стеклянную 3D вазу, которая реализована на языке Microsoft Visual C++ в консольном режиме с помощью библиотеки OPENGL в рамках курсового проекта. Пояснения к программе указаны в листинге в виде комментариев.
Результаты работы программы представлены на рис. 32,33. При прорисовке вазы с гранями были изменены: радиусы цилиндра, высоту и количество полигонов и очищен экран в серый цвет: gluCylinder(quadratic,0.4f,0.8f,2.8f,8,8);
gluDisk(quadratic,0.0f,0.4f,8,8);
150
//Изменяем радиус дна и количество полигонов
glClearColor(0.8f, 0.8f, 0.8f, 0.0f); //Очищаем экран в серый цвет
Рис. 32 Стеклянная 3D ваза, созданная как сложный объект цилиндр
Рис. 33 Стеклянная 3D ваза, созданная с использованием полигонов
Контрольные вопросы
1.В какой части программы происходит инициализация квадратичного объекта?
2.Каково предназначение команды gluPartialDisk()?
3.Какие параметры может иметь команда gluCylinder() ?
4.Почему внешний радиус должен быть больше внутреннего при рисовании поверхности диска?
151
2.18. Машина моделирования частиц
Реализация программного кода рассматриваемого ниже примера имеет очень интересный и красивый результат.
Рассмотрим пример создания машин моделирования частиц
(Particle Engine).
Код, как и в предыдущих работах, основан на первом примере, т.е. используется уже готовое окно, но для выполнения некоторых особенностей, необходимо добавить пять новых строк кода в начало программы:
#include <windows.h> // |
Заголовочный файл для Windows |
|
#include <stdio.h> |
// Заголовочный файл для стандартной |
|
библиотеки ввода/вывода (Новая строка) |
||
#include <gl\gl.h> |
// Заголовочный файл для библиотеки |
|
OpenGL32 |
|
|
#include <gl\glu.h> |
// Заголовочный файл для библиотеки GLu32 |
|
#include <gl\glaux.h> |
// Заголовочный файл для библиотеки GLaux |
|
#define MAX_PARTICLES 1000 // Число частиц для создания |
||
(Новая строка) |
|
|
HDC hDC=NULL; |
// Контекст устройства GDI |
|
HGLRC hRC=NULL; // Постоянный контекст рендеринга |
||
HWND hWnd=NULL;// Сохраняет дескриптор окна |
||
HINSTANCE hInstance; |
// Сохраняет экземпляр приложения |
|
bool keys[256]; // Массив для работы с клавиатурой |
||
bool active=TRUE; |
// Флаг активации окна, по умолчанию = |
|
TRUE |
|
|
bool fullscreen=TRUE;// Флаг полноэкранного режима |
||
bool rainbow=true; |
// Режим радуги? (Новая строка) |
|
bool sp; |
// Пробел нажат? (Новая строка) |
|
bool rp; |
// Ввод нажат? (Новая строка) |
|
Первая строка (stdio.h) |
позволяет читать данные из файлов. Во |
второй строке задается, сколько будет создаваться частиц, и отображаться на экране: пусть MAX_PARTICLES будет равно 1000. В третьей строке будет переключаться режим радуги (включен или выключен).
sp и rp – переменные, которые будут использоваться для предотвращения автогенерации повторений нажатия клавиш 'пробел' или 'ввод' (enter), когда они нажаты.
В следующих четырех строках – разнообразные переменные. Переменная slowdown (торможение) контролирует, как быстро
152