Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2633

.pdf
Скачиваний:
6
Добавлен:
07.01.2021
Размер:
54.26 Mб
Скачать

{

done=TRUE; // ESC или DrawGLScene просигналили "выход"

}

else // Не время выходить, обновляет экран

{

SwapBuffers(hDC); // Переключает буферы

Встроке ниже проверяется, нажата ли клавиша '+' на цифровой клавиатуре, если она нажата, и slowdown больше чем 1.0f, то slowdown уменьшается на 0.01f. в таком случае частицы будут двигаться быстрее:

if (keys[VK_ADD] && (slowdown>1.0f)) slowdown-=0.01f; //Скорость частицы увеличилась Далее проверяется, нажата ли клавиша '-' на цифровой клавиатуре,

если она нажата, и slowdown меньше чем 4.0f, то увеличивается slowdown, это заставляет частицы двигаться медленнее:

if (keys[VK_SUBTRACT] && (slowdown<4.0f)) slowdown+=0.01f;

//Торможение частиц

Встроке ниже проверяется, нажата ли клавиша PAGE UP, если она нажата, то переменная zoom увеличивается. Это заставит частицы двигаться на крупном плане:

if (keys[VK_PRIOR]) zoom+=0.1f; // Крупный план

Можно задать возможность противоположного эффекта: нажимая клавишу Page down, уменьшиться zoom, и сцена сместиться глубже в

экран:

 

if (keys[VK_NEXT]) zoom-=0.1f;

// Мелкий план

Вследующей части кода происходит проверка, была ли нажата клавиша Enter:

if (keys[VK_RETURN] && !rp) // нажата клавиша Enter

{

rp=true; // Установка флага, что клавиша нажата rainbow=!rainbow; // Переключение режима радуги в Вкл/Выкл

}

if (!keys[VK_RETURN]) rp=false; // Если клавиша Enter не нажата – сбросить флаг

Если она нажата в первый раз, и она не удерживается некоторое время, то устанавливается rp в true. Тем самым переключается режим радуги. Если радуга была true, она станет false. Если она была false, то станет true. В последней строке проверяется, была ли клавиша Enter отпущена. Если это так, то rp устанавливается в false, сообщая компьютеру, что клавиша больше не нажата.

Впервой строке ниже идет проверка, нажата ли клавиша 'пробел' и не удерживается ли она. Тут же проверяется, включен ли режим радуги,

иесли так, то проверяется значение переменной delay больше чем 25.

163

delay – счетчик, который используется для создания эффекта радуги. При помощи создания задержки, группа частиц останется с одним цветом, прежде чем цвет будет изменен на другой.

Если клавиша 'пробел' была нажата, или радуга включена, и задержка больше чем 25сек., цвет будет изменен:

if ((keys[' '] && !sp) || (rainbow && (delay>25))) // Пробел или режим радуги

{

Строка ниже была добавлена, для того чтобы режим радуги был выключен, если клавиша 'пробел' была нажата:

if (keys[' ']) rainbow=false; // Если пробел нажат запрет режима радуги

Таким образом, если клавиша 'пробел' была нажата, или режим радуги включен, и задержка больше чем 25 сек. – 'пробел' был нажат, делая sp равной true. Затем задается задержка равная 0, чтобы снова начать считать до 25 сек.:

sp=true; // Установка флага нам скажет, что пробел нажат

delay=0;

// Сброс задержки циклической смены цветов радуги

col++;

// Изменить цвет частицы

Если цвет превышает значение одиннадцать, сбрасывается

обратно в ноль:

 

 

if (col>11) col=0;

// Если цвет выше, то сбросить его

}

if (!keys[' ']) sp=false; // Если клавиша пробел не нажата, то сбросим флаг

В строке ниже проверяется, нажата ли 'стрелка вверх'. Если это так, то yspeed будет увеличено. Это заставит частицы двигаться вверх:

//Если нажата клавиша вверх и скорость по Y меньше чем 200, то увеличить скорость

if (keys[VK_UP] && (yspeed<200)) yspeed+=1.0f;

Далее в строке проверяется, нажата ли клавиша 'стрелка вниз':

//Если стрелка вниз и скорость по Y больше чем – 200, то увеличить скорость падения

if (keys[VK_DOWN] && (yspeed>-200)) yspeed-=1.0f;

Если это так, то yspeed будет уменьшено. Это заставит частицу двигаться вниз. И снова, задан максимум скорости вниз не больше чем

200.

Теперь осуществим проверку нажата ли клавиша 'стрелка вправо':

//Если стрелка вправо и X скорость меньше чем 200, то увеличить скорость вправо

if (keys[VK_RIGHT] && (xspeed<200)) xspeed+=1.0f;

164

// Если стрелка влево и X скорость больше чем –200, то увеличить скорость влево

if (keys[VK_LEFT] && (xspeed>-200)) xspeed-=1.0f;

delay управляет скоростью смены цветов, когда используется

режим радуги:

 

delay++;

// Увеличить счетчик задержки циклической

смены цветов в режиме радуги

Если это так, то xspeed будет увеличено. Это заставит частицы двигаться вправо. Задан максимум скорости не больше чем 200.

Далее приведен код проверки заголовока сверху окна:

if (keys[VK_F1])

// Была нажата кнопка F1?

{

 

keys[VK_F1]=FALSE;

// Если так – установит значение

FALSE

 

KillGLWindow();

// Закроет текущее окно OpenGL

fullscreen=!fullscreen;

// Переключит режим "Полный

экран"/"Оконный"

 

// Заново создаст окно OpenGL

if (!CreateGLWindow(640,480,16,fullscreen))

{

 

return 0;

// Выйти, если окно не было создано

}

 

}

 

}

 

}

 

}

 

// Сброс

 

KillGLWindow();

// Закроет окно

return (msg.wParam);

// Выйдет из программы

}

 

Таким образом, в рассмотренном примере были детально объяснены все шаги, которые требуются для создания системы моделирования частиц. Эта система моделирования частиц может использоваться в играх для создания эффектов типа огня, воды, снега, взрывов, падающих звезд, и так далее. Код может быть легко модифицирован для обработки большего количество параметров, и создания новых эффектов (например, фейерверк). Примеры реализации программного кода с небольшими изменениями приведены на рис.3436.

Контрольные вопросы

165

1.Какие параметры должна содержать текстура частицы?

2.Как создать эффект радуги?

3.Как изменить скорость движения частицы?

4.Зачем нужны переменные life и fade?

5.Как реализовать движение частиц вниз или вверх?

6.В какой части кода надо внести изменения и дополнения чтобы реализовать эффект взрыва?

7.Как разместить тот или иной эффект на крупном плане?

8.Поясните смысл команды: particle[loop].x+=particle[loop].xi/(slowdown*1000).

9.Поясните смысл команды: if (keys[VK_NUMPAD8] && (particle[loop].yg<1.5f)) particle[loop].yg+=0.01f.

Рис. 34. Эффект огненного фонтана

166

Рис. 35 Эффект бенгальского огня

Рис. 36 Эффект взрыва

Заключение

Сложность компьютерной графики определяется тем, что она базируется на знаниях многих и многих дисциплин, например, тригономтрии, начертательной геометрии, физики, оптики и др. Компьютерная графика «требовательна» к знаниям и опыту

167

программирования. Несмотря на это «Компьютерная графика» – дисциплина, которая позволяет программисту в полной мере проявить свои творческие способности и неординарные способности к программированию.

Изучение данного пособия – первый шаг в программировании компьютерной графики. Пособие рассчитано на узучение дисциплины в объеме одного семестра и не может охватить обширный теоретический материал зарубежных авторов и, к сожалению, не многие разработки российских авторов.

Всети Inernet любой заинтересованный программист может найти

иочень похожие примеры, и множество более интересных и сложных. Наибольший интерес представляют выложенные коды для реализации сложнейших, в смысле эффектов компьютерной графики, анимационных 3D игр.

168

Библиографический список

1. Ву М., Дэвис Т., Нейдер Дж., Шрайндер Д. OpenGL. Руководство по программированию. Библиотека программиста. 4-е издание. – Питер, 2006. – 624 с.

2.Баяковский Ю.М., Игнатенко А.В. Начальный курс OpenGL. М: – Планета знаний, – 2007. – 221с.

3.Дональд Херн, М. Паулин Бейкер. Компьютерная графика и стандарт OpenGL = Computer Graphics with OpenGL. – 3-е изд. – М.: Вильямс, 2005. – 1168 с.

4.Поляков А.Ю. Методы и алгоритмы компьютерной графики примерах на

Visual C++: Спб.: БХВ-Петербург, 2004 – 416 с.

5.Пореев В.Н. Компьютерная графика. – СПб.: БХВ-Петербург, 2004. – 432 с.

6.Ричард С. Райт мл, Липчак Б. OpenGL. Суперкнига – 3 изд. – М.: Вильямс, 2006. – 1040 с.

7.Энджел Э. Интерактивная компьютерная графика. Вводный курс на базе

OpenGL – 2-е изд. – М.: Вильямс, 2001. – 592 с.

8.Каверин М. OpenGL. Официальное Руководство программиста. [Электронный ресурс] // URL: http://www.geo3dcgp.com/opengl/books/OpenGL_RedBook_rus.pdf (дата обращения 10.01.2012)

9.Тарасов И. OpenGL. [Электронный ресурс] // URL: http://www.helloworld.ru/texts/comp/games/opengl/opengl2/index.html (дата обращения 10.01.2012)

10.OpenGL. Программирование с использованием OpenGL. [Электронный ресурс] //URL:http://opengl.org.ru/books/open_gl/chapter2.8.html (дата обращения 12.01.2012)

11.Программирование в Интернет и под Windows. Программирование графики. [Электронный ресурс] // URL: http://www.ru-coding.com/index.php (дата обращения 22.12.2011)

12.Работа с OpenGL. Электронный ресурс. OpenGL – уроки от NeHe (англ.).

[Электронныйресурс]//URL: http://nehe.gamedev.net/tutorial/volumetric_fog_ipicture_image_loading (дата обращения 08.11.2011)

13.Программирование с использованием OpenGL. Уроки OpenGL. [Электронный ресурс]//URL: http://opengl.org.ru/lesson/index.html (дата обращения: 05.11.2012)

14.Работа с OpenGL. [Электронный ресурс] // URL: http://pmg.org.ru/nehe/index.html (датаобращения:05.12.2011).

169

Приложение 1

Листинг программы создания 3D объкета Стеклянная ваза

#include <windows.h>

Windows

Заголовочный файл для

#include <stdio.h>

стандартной библиотеки ввода/вывода

Заголовочный файл для

#include <gl\glaux.h>

библиотеки GLaux

Заголовочный файл для

HDC

 

hDC=NULL;

Приватный контекст устройства GDI

HGLRC

 

hRC=NULL;

Постоянный контекст рендеринга

HWND

 

hWnd=NULL;

Сохраняет дескриптор окна

HINSTANCE

hInstance;

Сохраняет экземпляр приложения

bool

keys[256];

Массив для работы с клавиатурой

bool

active=TRUE;

Флаг активации окна, по умолчанию = TRUE

bool

fullscreen=TRUE;

Флаг полноэкранного вывода

bool

light;

 

Освещение Вкл/Выкл

bool

lp;

 

L нажата?

 

GLfloat xrot;

 

Xвращение

GLfloat yrot;

Yвращение

GLfloat xspeed;

Xскорость вращения

GLfloat yspeed;

Yскорость вращения

GLfloat z=­5.0f;

Глубина экрана

GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };

Фоновое значение света

GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };

Значение рассеянного света

GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };

Позиция источника

GLuint filter;

Какой фильтр использовать

GLuint texture[1];

Место для текстуры

170

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

Объявление WndProc

AUX_RGBImageRec *LoadBMP(char *Filename)

Загрузка картинки

{

FILE *File=NULL;

Индекс файла

if (!Filename)

Проверка имени файла

{

return NULL;

Если нет вернем NULL

}

File=fopen(Filename,"r");

Проверим существует ли файл

if (File)

Файл существует?

{

fclose(File);

Закрыть файл

return auxDIBImageLoad(Filename);

Загрузка картинки и вернем на нее указатель

}

return NULL;

Если загрузка не удалась вернем NULL

}

int LoadGLTextures()

Загрузка картинки и конвертирование в текстуру

{

int Status=FALSE;

Индикатор состояния

AUX_RGBImageRec *TextureImage[1];

Создать место для текстуры

memset(TextureImage,0,sizeof(void *)*1);

Установить указатель в NULL

Загрузка картинки, проверка на ошибки, если картинка не найдена – выход

if (TextureImage[0]=LoadBMP("Data/Wall.bmp"))

{

Status=TRUE;

Установим Status в TRUE

171

glGenTextures(3, &texture[0]);

Создание трех текстур

glBindTexture(GL_TEXTURE_2D, texture[2]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINE AR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINE AR_MIPMAP_NEAREST);

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]­>sizeX, TextureImage[0]­>sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]­>data);

Создание текстуры с фильтром по соседним пикселям

}

if (TextureImage[0])

Если текстура существует

{

if (TextureImage[0]­>data)

Если изображение текстуры существует

{

free(TextureImage[0]­>data);

Освобождение памяти изображения текстуры

}

free(TextureImage[0]);

Освобождение памяти под структуру

}

return Status;

Возвращаем статус

}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)

Изменить размер и инициализировать окно GL

{

if (height==0)

Предотвращение деления на ноль

{

height=1;

}

glViewport(0,0,width,height);

Сброс текущей области вывода

glMatrixMode(GL_PROJECTION);

Выбор матрицы проекций

glLoadIdentity();

Сброс матрицы проекции

Вычисление соотношения геометрических размеров для окна

172

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]