БГТУ «Военмех» им. Д.Ф.Устинова Кафедра И3 «Системы

advertisement
БГТУ «Военмех» им. Д.Ф.Устинова
Кафедра И3
«Системы обработки информации и управления»
Курсовая работа по Компьютерной Графике
Модель планеты Земля и Луны
Выполнил:
Студент Козятинский А.Ю.
Группа И383
Санкт-Петербург
2010
Краткое описание
Модель призвана продемонстрировать расположение Земли и Луны в реальном масштабе.
Для реализации курсового проекта были использованы:
● quadric-объекты
● освещение
● работа с камерой
● наложение текстур
● анимация
● материалы
Quadric - объекты
Библиотека GLU предоставляет возможность моделирования и вывода на экран полигональных
приближений сфер, цилиндров, дисков и частей дисков.
Данные “quadric” поверхности могут быть описаны следующим квадратным уравнением:
𝑎1 𝑥 2 + 𝑎2 𝑦 2 + 𝑎3 𝑧 2 + 𝑎4 𝑥𝑦 + 𝑎5 𝑦𝑧 + 𝑎6 𝑧𝑥 + 𝑎7 𝑥 + 𝑎8 𝑦 + 𝑎9 𝑧 + 𝑎10 = 0
Чтобы создать “quadric” поверхность необходимо выполнить следующие шаги:
1. Создать quadric объект, используя gluNewQuadric()
2. Определить специфические параметры вывода объекта на экран:
 Используя gluQuadricOrientation() - ориентацию векторов нормали к
поверхности
 Используя gluQuadricDrawStyle() - метод вывода объекта с помощью точек,
линий, либо закрашенных полигонов
 Используя gluQuadricNormal() - количество нормалей
 Используя gluQuadricTexture() – необходимость генерации текстурных
координат
3. При необходимости зарегистрировать функцию обработки ошибок
4. Вызвать gluSphere(),gluCylinder(),gluDisk(), или gluPartialDisk() для вывода объекта
на экран
5. По завершению удалить объект функцией gluDeleteQuadric()
Управление Quadric объектами
Новые объекты создаются с помощью функции:
GLUquadricObj* gluNewQuadric(void);
где
 Возвращаемое значение это указатель на новый quadric объект
 Если объект не может быть создан, возвращаемым значением является ноль
Существующие объекты удаляются функцией:
void gluDeleteQuadric(GLUquadricObj *obj);
где
 obj – объект, который необходимо удалить
Управление параметрами вывода на экран quadric объектов:
Стиль рисования конкретного объекта устанавливается функцией
void gluQuadricDrawStyle(GLUquadricObj *obj, GLenum drawStyle);
где drawStyle может быть
 GLU_POINTS,GLU_LINE,GLU_SILHOUETTE, GLU_POLYGON
Направление векторов нормалей определяется функцией
void gluQuadricOrientation(GLUquadricObj *obj,GLenum orientation);
где orientation может быть:
 GLU_OUTSIDE – вектора направлены наружу
 GLU_INSIDE – вектора направлены внутрь
Число генерируемых нормалей контролируется функцией
void gluQuadricNormals(GLUquadricObj *obj,GLenum normal);
где normal может быть:
 GLU_NONE
 GLU_FLAT, одна нормаль – одна грань
 GLU_SMOOTH, одна нормаль – одна вершина
Генерация текстурных координат включается, либо отключается функцией
void gluQuadricTexture(GLUquadricObj *obj, GLBoolean textureCoords);
где textureCoords может быть
 GLU_TRUE, координаты генерируются
 GLU_FALSE, координаты не генерируются
Создание квадрик поверхностей
Вершины и другие квадрик данные генерируются с использованием одной из следующих
функций, в зависимости от типа поверхности:
Сфера.
void gluSphere(GLUquadricObj *obj,GLdouble radius, Glint slices,Glint stacks);
где
 radius – радиус сферы
 slices – количество вертикальных линий
 stacks – количество горизонтальных линий
Цилиндр
void gluCylinder(GLUquadricObj *obj, GLdouble height, GLdouble baseRadius,GLdouble
topRadius,Glint slices,Glint stacks);
где
 topRadius – радиус цилиндра в сечении z = высота
 baseRadius – радиус цилиндра в сечении z = 0
 slices – количество вертикальных элементов
 stacks – количество горизонтальных элементов
Диск
void gluDisk(GLUquadricObj *obj,GLdouble innerRadius,GLdouble outerRadius, Glint slices,
Glint rings);
где
 innerRadius – радиус внутреннего круга
 outerRadius – внешний радиус
 slices – количество вертикальных элементов
 rings – количество горизонтальных элементов
Освещение
Включение фонового освещения.
По умолчанию освещение отключено. Включается оно командой glEnable(GL_LIGHTING).
Без освещения работать практически невозможно. Сфера всегда будет показываться как
круг, а конус - как круг или треугольник. Если монотонное тело равномерно освещено, то
увидеть его рельеф невозможно. Поэтому необходимо использовать источники света.
Когда освещение разрешено, то можно устанавливать фоновую освещенность. По
умолчанию, значение фоновой освещенности равно (0.2, 0.2, 0.2, 1). Фоновое освещение
устанавливается с помощью функции glLightModel. Если повысить фоновое освещение до
(1,1,1,1), т.е. до максимума, то включать источники света не понадобится. Их действие
просто не будет заметно, т.к. объект уже максимально освещен
Добавление в функцию main вызов следующей функции позволит установить фоновое
освещение.
float ambient[4] = {0.5, 0.5, 0.5, 1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
Задание параметров материала.
Материал может рассеивать, отражать и излучать свет.
Свойства материала устанавливаются при помощи функции
glMaterialfv(GLenum face, GLenum pname, GLtype* params)
Первый параметр определяет грань, для которой устанавливаются свойства. Он может
принимать одно из следующих значений:
GL_BACK
задняя грань
GL_FONT
передняя грань
GL_FRONT_AND_BACK обе грани
Второй параметр функции glMaterialfv определяет свойство материала, которое будет
установлено, и может принимать следующие значения.
GL_AMBIENT рассеянный свет
GL_DIFFUSE тоже рассеянный свет, пояснения смотри ниже
GL_SPECULAR отраженный свет
GL_EMISSION излучаемый свет
GL_SHININESS степень отраженного света
GL_AMBIENT_AND_DIFFUSE оба рассеянных света
Ambient и diffuse переводятся на русский как "рассеянный". Разница между ними не
очень понятна. Я использую только GL_DIFFUSE. Третий параметр определяет цвет
соответствующего света, кроме случая GL_SHININESS. Цвет задается в виде массива из
четырех элементов - RGBA. В случае GL_SHININESS params указывает на число типа float,
которое должно быть в диапазоне от 0 до 128.
Создание, позиционирование и включение одного или более источников света.
Все параметры лампы задаются с помощью функции glLight, которая имеет следующий
прототип:
void glLight[if][v](
GLenum light,
GLenum pname,
GLfloat param)
Буква v в названии функции определяет, используется ли векторная версия команды.
Первый аргумент определяет номер лампы. Его можно задавать двумя способами.
Первый - явно указать GL_LIHGTi, где GL_LIGHTi предопределено в файле gl.h.
Второй способ - GL_LIGHT0 + i, где i номер лампы. Такой способ используется, когда
существует необходимость в цикле изменять параметры ламп. Второй аргумент
определяет имя параметра, а третий его значение.
С помощью следующих функций разрешаем освещение и включаем нулевую лампу.
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
Массивы pos и dir содержат координаты местоположения лампы и направления, куда она
светит. Массив dir содержит три координаты - x,y,z. Массив pos - четыре, назначение
четвертого мне не очень ясно. Если его значение отличается от нуля, то изображение
вполне логичное получается. Если же он ноль, то получается что-то непотребное. По
умолчанию цвет всех источников света кроме GL_LIGHT0 – черный.
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
После настройки параметров источника света его нужно активизировать командой
glEnable().
Параметры источника света.
В аргументе param задается значение или значения, в которые следует установить
характеристику pname. Если используется векторная версия команды, param представляет
собой вектор величин, а если невекторная, то param – одно единственное значение.
Невекторная версия команды может использоваться только для указания параметров, чье
значение выражается одним числом.
Цвет.
OpenGL позволяет ассоциировать с каждым источником света три различных параметра,
связанных с цветом: GL_AMBIENT, GL_DIFFUSE и GL_SPECULAR. Параметр GL_AMBIENT
задает RGBA интенсивность фонового света, который каждый отдельный источник света
добавляет к сцене.
Glfloat light_ambient[]={0.0,0.0,1.0,1.0};
glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
Параметр GL_DIFFUSE наверное наиболее точно совпадает с тем, что вы привыкли
называть «цветом света». Он определяет RGBA цвет диффузного света, который
отдельный источник света добавляет к сцене. По умолчанию для GL_LIGHT0 параметр
GL_DIFFUSE равен (1.0, 1.0, 1.0, 1.0), что соответствует яркому белому свету. Значение по
умолчанию для всех остальных источников света (GL_LIGHT1, GL_LIGHT2, ..., GL_LIGHT7)
равно (0.0, 0.0, 0.0, 0.0).
Параметр GL_AMBIENT влияет на цвет зеркального блика на объекте. В реальном мире на
объектах вроде стеклянной бутылки имеется зеркальный блик соответствующего
освещению цвета (часто белого). Для создания эффекта реалистичности нужно установить
GL_SPECULAR в то же значение, что и GL_DIFFUSE. По умолчанию GL_SPECULAR равно (1.0,
1.0, 1.0, 1.0) для GL_LIGHT0 и (0.0, 0.0, 0.0, 0.0) для остальных источников.
Позиция и ослабление.
Можно выбрать, следует ли считать источник света расположенным бесконечно далеко от
сцены или близко к ней. На источники света первого типа ссылаются как на направленные
(directional): эффект от бесконечно далекого расположения источника заключается в том,
что все лучи его света могут считаться параллельными к моменту достижения объекта.
Примером реального направленного источника света может служить солнце. Источники
второго типа называются позиционными (positional), поскольку их точное положение на
сцене определяет их эффект и, в частности, направление из которого идут лучи.
Примером позиционного источника света является настольная лампа.
Направленный источник:
Glfloat light_position[]={1.0,1.0,1.0,0.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
Как видно, для параметра GL_POSITION задается вектор из четырех величин (x, y, z, w).
Если последняя величина w равна 0, соответствующий источник света считается
направленным, и величины (x, y, z) определяют его направление. Это направление
преобразуется видовой матрицей. По умолчанию параметру GL_POSITION соответствуют
значения (0, 0, 1, 0), что задает свет, направленный вдоль отрицательного направления
оси z. (Заметьте, что никто не запрещает вам создать свет, направленный в (0, 0, 0),
однако такой свет не даст должного эффекта).
Если значение w не равно 0, свет является позиционным, и величины (x, y, z) задают
местоположение источника света в однородных объектных координатах. Это положение
преобразуется видовой матрицей и сохраняется в видовых координатах. Кроме того, по
умолчанию позиционный свет излучается во всех направлениях, но вы можете ограничить
распространение света, создав конус излучения, определяющий прожектор.
Работа с камерой
Моделирование камеры.
В OpenGL точка обзора по умолчанию располагается в центре координат. Направление
зрения – вдоль оси Z противоположно ее направлению (т.е. все, что рисуется, мы видим
из центра координат).
Для моделирования камеры можно использовать видовые преобразования (матрица
MODELVIEW):
glMatrixMode(GL_MODELVIEW); //видовая матрица
glLoadIdentity();
//установим единичную матрицу
glTranslatef(0, 0, -10); //сдвиг по оси Z вглубь экрана
glRotatef(27, 1, 0, 0);
//поворот вокруг оси X
glRotatef(-19, 0, 1, 0); //поворот вокруг оси Y
Теперь наблюдатель (камера) как бы находится на расстоянии 10 единиц от центра
координат (и значит от плоскости изображения), причем повернута относительно
вертикали на 27 градусов, и развернута в горизонтальной плоскости на 19 градусов. При
этом камера всегда смотрит в центр координат.
Для моделирования камеры, которая направлена в произвольную точку пространства и
расположена в заданном месте, удобно использовать функцию библиотеки GLU –
gluLookAt, например:
glMatrixMode(GL_MODELVIEW); //видовая матрица
glLoadIdentity();
//установим единичную матрицу
gluLookAt (x, y, z,
//местоположение камеры
xp, yp, zp,
//камера смотрит в эту точку
0, 1, 0);
//направление вектора «вверх»
Функция имеет 9 параметров: первые три параметра определяют координаты
местоположения камеры; вторая тройка параметров задает координаты точки, в которую
нацелена камера; последние три параметра – направление вектора «вверх» –
используются для поворотов изображения в плоскости проецирования. Например:
gluLookAt (x, y, z, xp, yp, zp, 1, 0, 0);
определяет поворот изображения на 90 градусов (обычно Вы фотографируете, держа
фотоаппарат горизонтально, но иногда бывает удобнее развернуть его вертикально,
чтобы сфотографировать, например, высокое дерево – такой поворот и имеется в виду в
примере).
Направление вектора «вверх» может быть любым, но не должно быть параллельно
вектору нормали к плоскости наблюдения. Удобным является выбор вектора «вверх»
параллельным оси Y, т.е. (0, 1, 0).
Общие сведения о текстурах
Текстура – одномерное, двухмерное или трехмерное изображение, которое имеет множество
ассоциированных с ним параметров, определяющих каким образом будет производиться
наложение изображения на поверхность. Проще говоря, текстура – это изображение,
накладываемое на поверхность. С физической точки зрения текстура - массив данных, например
цветовых, световых или цветовых и альфа. Каждый элемент этого массива называется текселем.
Текстурные координаты – координаты текселя, назначаемого вершине.
Общепринятые имена для текстурных координат – s, t, r, q.
Для использования текстур необходимо выполнить следующую последовательность действий:*
1. Подготовка изображения для использования в текстуре
• Загрузка изображения из файла.
2. Создание текстуры
1) Генерация уникального имени текстуры*
2) Выполнение операции первичного связывания*
3) Связывание изображения с текстурой*
4) Установка режимов фильтрации текстуры
5) Установка параметров взаимодействия объекта, с накладываемой текстурой.
6) Установка режима мозаичного наложения текстуры.
7) Автоматическая генерация текстурных координат, эффект отражения.
3. Использование текстуры
1) Выбор текстуры для использования (вторичное связывание).
2) Согласование геометрических и текстурных координат
3) Создание эффекта отражения с помощью текстур.
* - Звездочкой обозначены обязательные пункты.
Исходный код:
Main.cpp:
//
//
Для работы OpenGL необходимо подключить к проекту заголовочные файлы
<windows.h>,<GL.h> и <GLU.h>, и подключить библиотеки “opengl32.lib” и “glu32.lib”.
#include <windows.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <tchar.h>
#include "draw.h"
static HGLRC hRC;
// Постоянный контекст рендеринга
static HDC hDC;
// Приватный контекст устройства GDI
BOOL keys[256];
// Массив для процедуры обработки клавиатуры
unsigned char curKey;
LRESULT CALLBACK WndProc( HWND
hWnd,UINT
message,WPARAM wParam,LPARAM
{
RECT
Screen;
GLuint
PixelFormat;
static
PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
lParam)
//размер структуры
//версия, всегда 1
//битовая маска формата пиксельного буфера
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
16,
//формат информации о пикселе
//определяет размер буфера пикселя
0, 0, 0, 0, 0, 0,
0,
0,
//специфические размеры для буфера цвета
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
//
//
Структура PIXELFORMATDESCRIPTOR описывает формат пикселя изображения,
рисуемого в окне приложения.
switch (message)
{
//
//
При создании окна задаем, определенный ранее формат пикселя, создаем wGL
контекст для окна и вызываем функции инициализации OpenGL(InitGL)
case WM_CREATE:
hDC = GetDC(hWnd);
PixelFormat = ChoosePixelFormat(hDC, &pfd);
if (!PixelFormat)
{
MessageBox(0,_T("Can't Find A SuitablePixelFormat."),_T("Error"),MB_OK|MB_ICONERROR);
PostQuitMessage(0);
break;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd))
{
MessageBox(0,_T("Can't Set ThePixelFormat."),_T("Error"),MB_OK|MB_ICONERROR);
PostQuitMessage(0);
break;
}
hRC = wglCreateContext(hDC);
if(!hRC)
{
MessageBox(0,_T("Can't Create A GLRenderingContext."),_T("Error"),MB_OK|MB_ICONERROR);
PostQuitMessage(0);
break;
}
if(!wglMakeCurrent(hDC, hRC))
{
MessageBox(0,_T("Can't activate GLRC."),_T("Error"),MB_OK|MB_ICONERROR);
PostQuitMessage(0);
break;
}
GetClientRect(hWnd, &Screen);
InitGL(Screen.right, Screen.bottom);
break;
case WM_DESTROY:
case WM_CLOSE:
ChangeDisplaySettings(NULL, 0);
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd,hDC);
PostQuitMessage(0);
break;
case WM_KEYDOWN:
keys[wParam] = TRUE;
curKey = wParam;
break;
case WM_KEYUP:
keys[wParam] = FALSE;
break;
// В обработчие изменения размеров окна помещаем функцию ReSizeGLScene, которая
// определяет реакцию OpenGL на изменение размеров области рисования.
case WM_SIZE:
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstan,LPSTR lpCmdLine,int nCmdShow)
{
MSG
msg;
WNDCLASS
wc;
HWND
hWnd;
wc.style
= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc
= (WNDPROC) WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= hInstance;
wc.hIcon
= NULL;
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName
= _T("OpenGL WinClass");
if(!RegisterClass(&wc))
{
MessageBox(0,_T("Failed To Register The WindowClass."),_T("Error"),MB_OK|MB_ICONERROR);
return FALSE;
}
hWnd = CreateWindow(_T("OpenGL WinClass"),
_T("First OpenGL program"),
WS_OVERLAPPEDWINDOW ,//| WS_CLIPCHILDREN, //|
WS_CLIPSIBLINGS,
0, 0,
1024, 600,
NULL,
NULL,
hInstance,
NULL);
if(!hWnd)
{
MessageBox(0,_T("Window Creation Error."),_T("Error"),MB_OK|MB_ICONERROR);
return FALSE;
}
if(!hWnd)
{
MessageBox(0,_T("Window Creation Error."),_T("Error"),MB_OK|MB_ICONERROR);
return FALSE;
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
SetFocus(hWnd);
while (1)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
return TRUE;
}
}
drawCurrentScene(); //нарисовать сцену
SwapBuffers(hDC);
if (keys[VK_ESCAPE])
SendMessage(hWnd,WM_CLOSE,0,0);
else
{
if (curKey&&keys[curKey]){
keyClicked(curKey);
keys[curKey]=false;
curKey = 0;
}
}
}
}
“draw.h”:
#pragma once
#include <windows.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <tchar.h>
#include "texObj.h"
#include "cameraObj.h"
GLvoid InitGL(GLsizei Width, GLsizei Height);
GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height);
GLvoid drawCurrentScene(GLvoid);
GLvoid keyClicked(unsigned char key);
GLvoid drawSky();
“draw.cpp”:
#include "draw.h"
//объекты планет
static GLUquadric *planet;
static GLUquadric *moonObj;
//камера
static cameraObj *cam;
//текстуры
static texObj *nebo;
static texObj *earth;
static texObj *moon;
//флаг отрисовки неба
bool skyDraw;
//флаг и угол анимации
bool anim;
static GLfloat angle;
GLvoid InitGL(GLsizei Width, GLsizei Height)
{
//начальные параметры
angle = 0.0f;
skyDraw = true;
anim = true;
//подготовка объектов
cam = new cameraObj("cam");
nebo = new texObj();
earth = new texObj();
moon = new texObj();
cam->lookAtf(0.0f,0.0f,0.0f);
planet = gluNewQuadric();
moonObj = gluNewQuadric();
gluQuadricTexture(planet,true);
gluQuadricTexture(moonObj,true);
//загрузка текстур
glEnable(GL_TEXTURE_2D);
if (!earth->loadFromFile("earth.bmp",GL_BGR_EXT))
return;
if (!nebo->loadFromFile("stars.bmp",GL_BGR_EXT))
return;
if (!moon->loadFromFile("moon.bmp",GL_BGR_EXT))
return;
//подготовка OpenGL
glEnable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glLoadIdentity();
gluPerspective(35.0,static_cast<GLfloat>(Width)/Height,.1,9.0);
//создание освещения
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 3.0f, 0.0f, 0.0f, 1.0f };
GLfloat LightDirection[] = {1.0f,0.0f,0.0f,1.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
glLightf(GL_LIGHT1,GL_SPOT_CUTOFF,120.0f);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, LightDirection);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
GLfloat Diffuse[]={1.0f,0.8f,0.86f,1.0f};
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,Diffuse);
}
GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
{
if (Height==0)
Height=1;
glViewport(0, 0, Width, Height);
}
GLvoid drawCurrentScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
cam->setCamera();
glBindTexture(GL_TEXTURE_2D,earth->texID);
glPushMatrix();
glRotatef(angle/3.0f,1.0f,1.0f,0.0f);
gluSphere(planet,.03f,32,32);
glPopMatrix();
glPushMatrix();
glRotatef(angle,0.0f,1.0f,0.0f);
if (anim)
angle+=1.0f;
glTranslatef(2.0f,0.0f,0.0f);
glBindTexture(GL_TEXTURE_2D,moon->texID);
gluSphere(moonObj,0.009f,32,32);
glPopMatrix();
if (skyDraw)
drawSky();
glPopMatrix();
}
GLvoid keyClicked(unsigned char key)
{
switch(key)
{
case VK_UP:
cam->changeRadius(-0.01f);
break;
case VK_DOWN:
cam->changeRadius(0.01f);
break;
case VK_LEFT:
cam->rotatef(5.0f,0.0f);
break;
case VK_RIGHT:
cam->rotatef(0.0f,5.0f);
break;
case 'M': case 'm':
cam->lookAtf(2.0f,0.0f,0.0f);
break;
case 'E': case 'e':
cam->lookAtf(0.0f,0.0f,0.0f);
break;
case 'S':case 's':
skyDraw = !skyDraw;
break;
case 'A' case 'a':
anim=!anim;
break;
}
}
GLvoid drawSky()
{
glBindTexture(GL_TEXTURE_2D,nebo->texID);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glTexCoord2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glTexCoord2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glTexCoord2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glTexCoord2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glTexCoord2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glEnd();
}
glVertex3f(-3.0f,-3.0f,-3.0f);
glVertex3f( -3.0f,3.0f,-3.0f);
glVertex3f( 3.0f, 3.0f,-3.0f);
glVertex3f( 3.0f, -3.0f,-3.0f);
glVertex3f(-3.0f,3.0f,-3.0f);
glVertex3f( 3.0f,3.0f,-3.0f);
glVertex3f( 3.0f, 3.0f,3.0f);
glVertex3f( -3.0f, 3.0f,3.0f);
glVertex3f(-3.0f,3.0f,-3.0f);
glVertex3f( -3.0f,-3.0f,-3.0f);
glVertex3f( -3.0f, -3.0f,3.0f);
glVertex3f( -3.0f, 3.0f,3.0f);
glVertex3f(-3.0f,3.0f,3.0f);
glVertex3f( 3.0f,3.0f,3.0f);
glVertex3f( 3.0f, -3.0f,3.0f);
glVertex3f( -3.0f, -3.0f, 3.0f);
glVertex3f(3.0f,3.0f,3.0f);
glVertex3f( 3.0f,3.0f,-3.0f);
glVertex3f( 3.0f, -3.0f,-3.0f);
glVertex3f( 3.0f, -3.0f,3.0f);
glVertex3f(-3.0f,-3.0f,3.0f);
glVertex3f( -3.0f,-3.0f,-3.0f);
glVertex3f( 3.0f, -3.0f,-3.0f);
glVertex3f( 3.0f, -3.0f,3.0f);
“baseObject.h”:
#pragma once
#include <Windows.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <string>
class baseObject
{
std::string name;
GLfloat angleX,angleY,angleZ;
GLfloat Xscale,Yscale,Zscale;
GLfloat X,Y,Z;
void moveAndRotateObj();
virtual void drawObject(){};
public:
baseObject(const std::string &_name);
const std::string& getName(){return name;}
void movef(GLfloat deltaX,GLfloat deltaY,GLfloat deltaZ){X+=deltaX;Y+=deltaY;Z+=deltaZ;}
void scalef(GLfloat scX,GLfloat scY,GLfloat scZ){Xscale = scX; Yscale = scY; Zscale = scZ;}
GLfloat getY()const{return Y;}
GLfloat getX()const{return X;}
GLfloat getZ()const{return Z;}
GLfloat getXscale()const{return Xscale;}
GLfloat getYscale()const{return Yscale;}
GLfloat getZscale()const{return Zscale;}
void setXYZ(GLfloat _X,GLfloat _Y,GLfloat _Z){X=_X;Y=_Y;Z=_Z;}
void rotatef(GLfloat deltaAngleX,GLfloat deltaAngleY,GLfloat deltaAngleZ)
{
angleX+=deltaAngleX;
angleY+=deltaAngleY;
angleZ+=deltaAngleZ;
}
void displayObject();
virtual ~baseObject(void);
};
“baseObject.cpp”:
#include "baseObject.h"
baseObject::baseObject(const std::string &_name)
{
name = _name;
X=Y=Z=0;
angleX = angleY = angleZ = 0;
Xscale = Yscale = Zscale = 1.0f;
}
baseObject::~baseObject(void){}
void baseObject::moveAndRotateObj()
{
glTranslatef(X,Y,Z);
glRotatef(angleX,1.0f,0.0f,0.0f);
glRotatef(angleY,0.0f,1.0f,0.0f);
glRotatef(angleZ,0.0f,0.0f,1.0f);
glScalef(Xscale,Yscale,Zscale);
}
void baseObject::displayObject()
{
glPushMatrix();
moveAndRotateObj();
drawObject();
glPopMatrix();
}
“cameraObj.h”:
#pragma once
#include <Windows.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <string>
#include "baseObject.h"
class cameraObj
{
std::string name;
GLfloat lookAt[3];
GLfloat radius;
GLfloat angleLeftRight;
GLfloat angleUpDown;
public:
cameraObj(const std::string&_name);
void rotatef(GLfloat deltaAngleLeftRight,GLfloat angleY){angleLeftRight+=deltaAngleLeftRight;angleUpDown+=angleY;}
void lookAtf(GLfloat lookAtX,GLfloat lookAtY,GLfloat lookAtZ)
{
lookAt[0]=lookAtX;
lookAt[1]=lookAtY;
lookAt[2]=lookAtZ;
}
void lookAtObj(const baseObject *obj)
{
lookAt[0]=obj->getX();
lookAt[1]=obj->getY();
lookAt[2]=obj->getZ();
}
void changeRadius(GLfloat deltaRadius){if (std::abs(radius+deltaRadius)<=3.0f) radius+=deltaRadius;}
void setCamera();
~cameraObj(void);
};
“cameraObj.cpp”:
#include "cameraObj.h"
cameraObj::cameraObj(const std::string &_name)
{
name = _name;
lookAt[0] = 0.0f;
lookAt[2] = 0.0f;
lookAt[1] = 0.0f;
radius = 3.0f;
angleUpDown = 5.0f;
angleLeftRight = 0.0f;
}
void cameraObj::setCamera()
{
GLdouble cameraPos[3];
GLdouble gradToPi = 3.14f/180.0;
cameraPos[0] = lookAt[0]+radius * std::sin(angleUpDown*gradToPi) * std::cos(angleLeftRight*gradToPi);
cameraPos[1] = lookAt[1]+radius * std::cos(angleUpDown*gradToPi);
cameraPos[2] = lookAt[2]+radius * std::sin(angleUpDown*gradToPi) * std::sin(angleLeftRight*gradToPi);
gluLookAt(cameraPos[0],cameraPos[1],cameraPos[2],lookAt[0],lookAt[1],lookAt[2],0.0,1.0,0.0);
}
cameraObj::~cameraObj(void){}
“texObj.h”:
#pragma once
#include <windows.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <tchar.h>
#include <fstream>
struct texFile
{
char *data;
GLuint width;
GLuint height;
};
class texObj
{
texFile tex;
public:
GLuint texID;
texObj(void){};
bool loadFromFile(const char *fileName,GLuint format);
~texObj(void)
{
free(tex.data);
};
};
“texObj.cpp”:
#include "texObj.h"
bool texObj::loadFromFile(const char *fileName,GLuint format)
{
std::ifstream in;
in.open(fileName,std::ios::binary);
BITMAPFILEHEADER fileHeader;
in.read(static_cast<char*>(static_cast<void*>(&fileHeader.bfType)),sizeof(BITMAPFILEHEADER));
if (fileHeader.bfType!=19778)
{
in.close();
return false;
}
BITMAPINFOHEADER header;
in.read(static_cast<char*>(static_cast<void*>(&header.biSize)),4);
in.read(static_cast<char*>(static_cast<void*>(&header.biWidth)),header.biSize-4);
if (header.biSize+sizeof(BITMAPFILEHEADER)==fileHeader.bfOffBits)
{
tex.data = static_cast<char*>(malloc(header.biSizeImage));
in.read(tex.data,header.biSizeImage);
tex.width = header.biWidth;
tex.height = header.biHeight;
}
else
{
in.close();
return false;
}
in.close();
glGenTextures(1,&texID);
glBindTexture(GL_TEXTURE_2D,texID);
glTexImage2D(GL_TEXTURE_2D,0,GL_BGR_EXT,tex.width,tex.height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,tex.data);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, tex.width,tex.height,GL_BGR_EXT,GL_UNSIGNED_BYTE,tex.data);
return true;
}
Download