Разработка программы построения и визуализации 3D объекта

Особенность определения модулей программы. Выбор среды программирования. Построение твердотельной модели замка при помощи программного продукта Autodesk 3ds Max 2015. Проведение тестирования в рабочем порядке. Исследование алгоритма загрузки 3D-модели.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 21.02.2019
Размер файла 3,6 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Министерство образования Российской Федерации

Пензенский государственный университет

Кафедра «Вычислительная техника»

ПОЯСНИТЕЛЬНАЯ ЗАПИСКА

к курсовой работе

по курсу «Компьютерная графика»

на тему «Разработка программы построения и визуализации 3D объекта»

Выполнили:

Чиркин К.Д.

Пенза 2017

Аннотация

Цель данного курсового проекта: разработать программу, на языке С++ с использованием библиотеки OpenGL, которая визуализирует заданный 3D-объект. Также необходимо реализовать анимацию объекта и интерактивное перемещение камеры посредством клавиатуры (мыши).

В данной пояснительной записке приведено описание разработанной программы, реализующая процесс построения и визуализации 3D-объекта/сцены с элементами динамики на основе графической библиотеки стандарта OpenGL. Программа разработана и отлажена на языке Microsoft Visual C++.

Содержание

Введение

1. Исходные данные на проектирование

2. Выбор решения

2.1 Определение модулей программы

2.2 Создание модели

3. Описание разработки программы

3.1 Выбор среды программирования

3.2 Отладка и тестирование

4. Описание программы

4.1 Общие сведения

Заключение

Список используемой литературы

Приложение

Введение

В наш XXI век, век высоких технологий, понятие компьютерной графики неразрывно связано с нашей жизнью. Суперблокбастер кинематографа, реклама, выбор прически в парикмахерской - везде мы сталкиваемся с примерами графической обработки данных.

Она охватывает все виды и формы представления изображений, доступных для восприятия человеком либо на экране монитора, либо в виде копии на внешнем носителе (бумага, кинопленка, ткань и прочее). Без компьютерной графики невозможно представить себе не только компьютерный, но и обычный, вполне материальный мир. Визуализация данных находит применение в самых разных сферах человеческой деятельности. Для примера назовем медицину (компьютерная томография), научные исследования (визуализация строения вещества, векторных полей и других данных), моделирование тканей и одежды, опытно-конструкторские разработки.

Отдельным предметом считается трехмерная (3D) графика, изучающая приемы и методы построения объемных моделей объектов в виртуальном пространстве. Как правило, в ней сочетаются векторный и растровый способы формирования изображений.

Особенности цветового охвата характеризуют такие понятия, как черно-белая и цветная графика. На специализацию в отдельных областях указывают названия некоторых разделов: инженерная графика, научная графика, Web-графика, компьютерная полиграфия и прочие.

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

Заметное место в компьютерной графике отведено развлечениям. Появилось даже такое понятие, как механизм графического представления данных (Graphics Engine). Рынок игровых программ имеет оборот в десятки миллиардов долларов и часто инициализирует очередной этап совершенствования графики и анимации.

Хотя компьютерная графика служит всего лишь инструментом, ее структура и методы основаны на передовых достижениях фундаментальных и прикладных наук: математики, физики, химии, биологии, статистики, программирования и множества других. Это замечание справедливо как для программных, так и для аппаратных средств создания и обработки изображений на компьютере. Поэтому компьютерная графика является одной из наиболее бурно развивающихся отраслей информатики и во многих случаях выступает “локомотивом”, тянущим за собой всю компьютерную индустрию.

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

В данной курсовой работе мы разрабатываем 3D-модель замка, используя программный продукт Autodesk 3ds Max 2015, и при помощи библиотеки OpenGL в среде Microsoft Visual Studio 2017 реализуем программу, добавляющую для нашего объекта анимацию, освещение и т.п.

1. Исходные данные на проектирование

Разработка графической программы визуализации 3D модели и фона с использованием библиотеки OpenGL на языке программирования СИ, для реализации процесса динамики объекта, фона и камеры в трехмерной сцене.

Объект моделирования: 3D модель реального объекта - замок.

2. Выбор решения

2.1 Определение модулей программы

Каждый модуль отвечает за набор определенных действий:

1. Файл «Inv3Ds.h» - информация о блоке 3ds-файла, описывающего объект. Определение именованных констант в соответствии с числовыми кодами 3ds файла. Определение структуры модели t3DObject. Определение 2-степенных структур: материалов, вершинных координат, блоков 3ds файла, описывающих объекты и других. Описание класса CLoad3DS (нижний уровень загрузки), содержащего функции чтения различных частей 3ds файла.

2. Файл «Download3Ds.h» - объявление функций класса C3dsLoader, включает объект класса CLoad3DS и функции прорисовки, выгрузки модели. В данном классе объявляется массив TextureArray3ds, используемый для хранения путей к файлам текстур.

3. Файл «Main.h» - подключение библиотек OpenGL и стандартных заголовочных файлов: ввода/вывода, математических операций и др. Так же в файле описываются структуры 2D и 3D векторов.

4. Файл «Inv3Ds.cpp» - содержит функции класса CLoad3DS для чтения блоков 3ds файла, описывающих объекты из 3ds файла.

5. Файл «Download3Ds.cpp» - вывод изображения/выгрузка 3ds файла (функции класса C3dsLoader).

6. Файл «main.cpp» - основной файл программы. Содержит инициализацию OpenGL и функцию создания Windows - окна. В нём происходит обработка событий мыши и клавиатуры. Вызываются различные функции описанных выше классов. По завершении программы, вызывается функция освобождения памяти.

2.2 Создание модели

При помощи программного продукта Autodesk 3ds Max 2015 мы построили твердотельную модель замка. Использовали стандартные примитивы, поддерживаемые программой. Проекции смоделированной модели, вы можете увидеть на рисунках:

Рисунок 1. 3D-модель замка в Autodesk 3Ds Max 2015.

Рисунок 2. Проекция на плоскость YOZ.

Рисунок 3. Проекция на плоскость XOZ.

Рисунок 4. Проекция на плоскость XOY.

3. Описание разработки программы

3.1 Выбор среды программирования

В качестве среды программирования был выбран программный продукт Visual Studio 2017. Были использованы библиотеки OpenGL (Open Graphics Library -- открытая графическая библиотека, графическое API). В OpenGL используется модель освещения, в соответствии с которой цвет точки определяется несколькими факторами: свойствами материала и текстуры, величиной нормали в этой точке, а также положением источника света и наблюдателя.

Решено было считать только наиболее значимые блоки:

#define PRIMARY 0x4D4D - начало сцены

#define OBJECTINFO 0x3D3D - блок информации об объекте

#define VERSION 0x0002 - версия объекта

#define MATERIAL 0xAFFF - материал объекта

#define OBJECT 0x4000 - сам объект

#define MATNAME 0xA000 - имя материала

#define MATDIFFUSE 0xA020 - цвет материала

#define MATMAP 0xA200 - текстура материала

#define MATMAPFILE 0xA300 - путь к файлу с текстурой

#define OBJECT_MESH 0x4100 - начало trimesh-объекта

#define OBJECT_VERTICES 0x4110 - список вершин

#define OBJECT_FACES 0x4120 - список граней

#define OBJECT_MATERIAL 0x4130 - материалы граней

#define OBJECT_UV 0x4140 - текстурные координаты

3.2 Отладка и тестирование

В качестве среды разработки была выбрана программа Visual Studio 2017. Программа предоставляет все средства необходимые при разработке и отладке разрабатываемых модулей и программ. Для отладки использовались такие инструменты как точка останова, выполнение кода по шагам, анализ содержимого локальных и глобальных переменных, анализ содержимого памяти.

Тестирование проводилось в рабочем порядке, в процессе разработки, после завершения написания программы. В ходе тестирования были выявлены и исправлены ошибки в работе программы, приводящие к неправильной работе программы.

Рисунок 5-Схема программы

Как только функция обнаружила событие от клавиатуры, вызывается обработка события. События делятся на несколько типов:

· работа с освещением

· движение модели

· движение камеры

· анимация

Рисунок 6-Схема данных

4. Описание программы

4.1 Общие сведения

Программа создана для экономии ресурсов. Благодаря программам моделирования моделям можно придать вид очень реальных (с известной долей приближения). Ранее эта технология не слишком активно применялась по той причине, что небыли такие пакеты, как 3D max Autocad и т.д., в которых поддерживается технология "твердотельного" моделирования. Изготовить правильную модель было подчас задачей весьма и весьма нетривиальной.

4.2 Основные структуры программы

Структура объектов модели/сцены

struct t3DObject

{

int numOfVerts; // Число вершин в модели

int numOfFaces; // Число полигонов в модели

int numTexVertex; // Число текстурных координат

int materialID; // ID текстуры для использования, индекс массива текстур

bool bHasTexture; // TRUE если есть текстурная карта для этого обьекта

char strName[255]; // Имя объекта

tVector3 *pVerts; // Массив вершин объекта

tVector3 *pNormals; // Нормали объекта

tVector2 *pTexVerts; // Текстурные координаты

tFace *pFaces; // Полигоны объекта

tVector3 *pRotate; // Вращение объекта

tVector3 *pVRotate; // Центр вращения объекта

tVector3 *pPosition; // Перемещение объекта

tVector3 *pScale; // Масштабирование объекта

}

Структура описывающая материалы объекта

struct tMaterialInfo

{

char strName[255]; // Имя текстуры

char strFile[255]; // Имя файла текстуры

BYTE color[3]; // Цвет объекта (R, G, B)

int texureId; // ID текстуры

float uTile; // u-tiling текстуры (не используется)

float vTile; // v-tiling текстуры (не используется)

float uOffset; // u-offset текстуры (не используется)

float vOffset; // v-offset текстуры (не используется)

}

Структура, описывающая вершины объекта и id материалов

struct t3DModel

{

int numOfObjects; // Число объектов в модели

int numOfMaterials; // Число материалов модели

vector<tMaterialInfo> pMaterials; // Число объектов материалов (текстуры и цвета)

vector<t3DObject> pObject; // Список объектов в модели

}

4.3 Управление программой

Для управления работой программы, была реализована поддержка - клавиатуры, мыши. Следующая схема показывает действия при нажатии соответствующих клавиш.

Рисунок 7. Обработка событий клавиатуры (мыши).

Рисунок 8. Алгоритм загрузки 3D-модели.

Заключение

В рамках выполнения курсовой работы была написана программа, загружающая 3d модель из 3ds файла. Программа предоставляет небольшой, но достаточный для использования список возможностей. Не требует большого количества системных ресурсов и обеспечивает быструю обработку файла.

С помощью проверенных и доступных библиотек OpenGl и с помощью Visual C можно выводить текстурированные, анимированные 3D модели, созданные в среде 3dsmax.

Удалось реализовать всё, что задумывалось. Так как запросы на начальном этапе были примитивными, основной целью было показать четкую реализацию модели. программный тестирование рабочий загрузка

Список используемой литературы

1. Петров М., Молочков В. Компьютерная графика. - М: Питер, 2003 г.

2. Мильчин Ф.М. 3D Studio Max 7.0: Всё, что Вы хотели знать, но боялись спросить. - М: Бук-Пресс и К, 2005 г.

3. Понамарев В. Программирование на C++ в Visual Studio. - М: БХВ-Петербург. 2004 г.

4. Керниган Б., Ритчи Д. Язык программирования С. - М: Вильямс. 1985 г.

5. Страуструп Б. Язык программирования С++. - М: Бином. 2015 г.

Приложение

На рисунках 9, 10, 11, 12, 13 представлена блок-схема файла main.cpp:

Рисунок 9 - Схема файла main.cpp (1)

Рисунок 10 - Схема файла main.cpp (2)

Рисунок 11 - Схема файла main.cpp (3)

Рисунок 12 - Схема файла main.cpp (4)

Рисунок 13 - Схема файла main.cpp (5)

Листинги программы

Приложение B.1

Файл «Inv3Ds.cpp»

#include "main.h" // объявление про-

#include "Inv3Ds.h" // тотипов библио-

#include "Operations3D.h" // течных функций

CLoad3DS::CLoad3DS()//Конструктор инициализирует данные tChunk

{

m_CurrentChunk = new tChunk;

m_TempChunk = new tChunk;

}

bool CLoad3DS::Import3DS(t3DModel *pModel, char *strFileName)

{

char strMessage[255] = {0};

m_FilePointer=fopen(strFileName, "rb"); // Открываем .3ds файл

if(!m_FilePointer) // Убедимся, что указатель на файл верен (мы открыли файл)

{

sprintf(strMessage, "Unable to find the file: %s!", strFileName);

MessageBox(NULL, strMessage, "Error", MB_OK);

return false;

}

ReadChunk(m_CurrentChunk); // Читаем первый chunk файла, чтобы убедится, что это 3DS

if (m_CurrentChunk->ID != PRIMARY) // Убедимся, что это 3DS

{

sprintf(strMessage, "Unable to load PRIMARY chuck from file: %s!", strFileName);

MessageBox(NULL, strMessage, "Error", MB_OK);

return false;

}

ProcessNextChunk(pModel, m_CurrentChunk);

ComputeNormals(pModel);

CleanUp(); // В конце подчищаем всё

return true;

}

void CLoad3DS::CleanUp() //Функция чистит всю занятую память и закрывает файл

{

fclose(m_FilePointer); // Закрываем файл

delete m_CurrentChunk;

delete m_TempChunk;

}

void CLoad3DS::ProcessNextChunk(t3DModel *pModel, tChunk *pPreviousChunk)

{

t3DObject newObject = {0};

tMaterialInfo newTexture = {0};

int version = 0;

int buffer[20000] = {0};

m_CurrentChunk = new tChunk;

while (pPreviousChunk->bytesRead < pPreviousChunk->length)

{

ReadChunk(m_CurrentChunk); // Читаем следующий chunk

switch (m_CurrentChunk->ID) // Получаем chunk ID

{

case VERSION: // Версия файла

m_CurrentChunk->bytesRead += fread(&version, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);

if (version > 0x03)

MessageBox(NULL, "This 3DS file is over version 3 so it may load incorrectly", "Warning", MB_OK);

break;

case OBJECTINFO: // Содержит версию меша

ReadChunk(m_TempChunk);

m_TempChunk->bytesRead += fread(&version, 1, m_TempChunk->length - m_TempChunk->bytesRead, m_FilePointer);// Получаем версию меша

m_CurrentChunk->bytesRead += m_TempChunk->bytesRead;

ProcessNextChunk(pModel, m_CurrentChunk);

break;

case MATERIAL: // Содержит информацию о материале

pModel->numOfMaterials++; // Увеличиваем число материалов

pModel->pMaterials.push_back(newTexture);

ProcessNextMaterialChunk(pModel, m_CurrentChunk);

break;

case OBJECT: // Хранит имя читаемого обьекта

pModel->numOfObjects++; // Увеличиваем счетчик обьектов

pModel->pObject.push_back(newObject);

memset(&(pModel->pObject[pModel->numOfObjects - 1]), 0, sizeof(t3DObject));

m_CurrentChunk->bytesRead += GetString(pModel->pObject[pModel->numOfObjects - 1].strName);

ProcessNextObjectChunk(pModel, &(pModel->pObject[pModel->numOfObjects - 1]), m_CurrentChunk); // Переходим к чтению оставшейся информации обьекта

break;

case EDITKEYFRAME:

m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);

break;

default:

m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);

break;

}

pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;

}

delete m_CurrentChunk;

m_CurrentChunk = pPreviousChunk;

}

void CLoad3DS::ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk) //Функция сохраняет всю информацию об обьекте

{

tChunk currentChunk = {0};// Текущий chunk, с которым работаем

int buffer[20000] = {0};

while (pPreviousChunk->bytesRead < pPreviousChunk->length)

{

ReadChunk(&currentChunk);// Читаем следующую секцию

switch (currentChunk.ID)// Проверяем, что это за секция

{

case OBJECT_MESH: // Даёт нам знать, что мы читаем новый обьект

ProcessNextObjectChunk(pModel, pObject, &currentChunk);

break;

case OBJECT_VERTICES: // Вершины нашего обьекта

ReadVertices(pObject, &currentChunk);

break;

case OBJECT_FACES: // Полигоны обьекта

ReadVertexIndices(pObject, &currentChunk);

break;

case OBJECT_MATERIAL: // Имя материала обьекта

ReadObjectMaterial(pModel, pObject, &currentChunk);

break;

case OBJECT_UV: // Хранит текстурные координаты обьекта

ReadUVCoordinates(pObject, &currentChunk);

break;

default:// Читаем игнорируемые/неизвестные данные в "мусорный" массив

currentChunk.bytesRead += fread(buffer, 1, currentChunk.length - currentChunk.bytesRead, m_FilePointer);

break;

}

pPreviousChunk->bytesRead += currentChunk.bytesRead;

}

}

void CLoad3DS::ProcessNextMaterialChunk(t3DModel *pModel, tChunk *pPreviousChunk)

{

tChunk currentChunk = {0};// Текущий chunk для работы

int buffer[50000] = {0};

while (pPreviousChunk->bytesRead < pPreviousChunk->length)

{

ReadChunk(&currentChunk);// Читаем следующую секцию

switch (currentChunk.ID)// Проверяем, что именно мы прочитали

{

case MATNAME: // Эта секция хранит имя материала

currentChunk.bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strName,1, currentChunk.length - currentChunk.bytesRead, m_FilePointer);

break;

case MATDIFFUSE: // Хранит RGB-цвет обьекта

ReadColorChunk(&(pModel->pMaterials[pModel->numOfMaterials - 1]), &currentChunk);

break;

case MATMAP: // Это хидер информации о текстуре

ProcessNextMaterialChunk(pModel, &currentChunk);

break;

case MATMAPFILE: // Хранит имя файла материала// Читаем имя файла материала

currentChunk.bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strFile, 1, currentChunk.length - currentChunk.bytesRead, m_FilePointer);

break;

default:// Читаем остальные данные в "мусор"

currentChunk.bytesRead += fread(buffer, 1, currentChunk.length - currentChunk.bytesRead,m_FilePointer);

break;

}

pPreviousChunk->bytesRead += currentChunk.bytesRead;

}

}

void CLoad3DS::ReadChunk(tChunk *pChunk) //Функция читает ID chunk-а и его длинну в байтах

{

pChunk->bytesRead = fread(&pChunk->ID, 1, 2, m_FilePointer);

pChunk->bytesRead += fread(&pChunk->length, 1, 4, m_FilePointer);

}

int CLoad3DS::GetString(char *pBuffer)//Читает строку в массив char-ов

{

int index = 0;

fread(pBuffer, 1, 1, m_FilePointer);// Читаем 1 байт данных, первую букву строки

while (*(pBuffer + index++) != 0) // Цикл, пока не получаем NULL

{

fread(pBuffer + index, 1, 1, m_FilePointer);

}

return strlen(pBuffer) + 1;

}

void CLoad3DS::ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk)

{

tChunk tempChunk = {0};

ReadChunk(&tempChunk);// Читаем информацию о цвете

tempChunk.bytesRead += fread(pMaterial->color, 1, tempChunk.length - tempChunk.bytesRead, m_FilePointer);// Читаем RGB-цвет (3 байта - от 0 до 255)

pChunk->bytesRead += tempChunk.bytesRead; // Увеличиваем счетчик

}

void CLoad3DS::ReadVertexIndices(t3DObject *pObject, tChunk *pPreviousChunk)

{

unsigned short index = 0;// Используется для чтения индекса текущего полигона

pPreviousChunk->bytesRead += fread(&pObject->numOfFaces, 1, 2, m_FilePointer);

pObject->pFaces = new tFace [pObject->numOfFaces];

memset(pObject->pFaces, 0, sizeof(tFace) * pObject->numOfFaces);

for(int i = 0; i < pObject->numOfFaces; i++)

{

for(int j = 0; j < 4; j++)

{

pPreviousChunk->bytesRead += fread(&index, 1, sizeof(index), m_FilePointer); // Читаем первый индекс вершины для текущего полигона

if(j < 3)

{

pObject->pFaces[i].vertIndex[j] = index;

}

}

}

}

void CLoad3DS::ReadUVCoordinates(t3DObject *pObject, tChunk *pPreviousChunk)

{

pPreviousChunk->bytesRead += fread(&pObject->numTexVertex, 1, 2, m_FilePointer);

pObject->pTexVerts = new tVector2 [pObject->numTexVertex];

pPreviousChunk->bytesRead += fread(pObject->pTexVerts, 1,

pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);

}

void CLoad3DS::ReadVertices(t3DObject *pObject, tChunk *pPreviousChunk)

{ // Как и в большинстве chunk-ов, прежде чем читать сами вершины,

pPreviousChunk->bytesRead += fread(&(pObject->numOfVerts), 1, 2, m_FilePointer);

pObject->pVerts = new tVector3 [pObject->numOfVerts];

memset(pObject->pVerts, 0, sizeof(tVector3) * pObject->numOfVerts);

pPreviousChunk->bytesRead += fread(pObject->pVerts, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);// Читаем в массив вершин (массив из 3 float)

}

void CLoad3DS::ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk)

{

char strMaterial[255] = {0}; // Хранит имя материала

int buffer[50000] = {0};// Читаем имя материала, привязанного к текущему обьекту.

pPreviousChunk->bytesRead += GetString(strMaterial);

for(int i = 0; i < pModel->numOfMaterials; i++)// Проходим через все материалы

{

if(strcmp(strMaterial, pModel->pMaterials[i].strName) == 0)

{

pObject->materialID = i;

if(strlen(pModel->pMaterials[i].strFile) > 0) {

pObject->bHasTexture = true;

}

break;

}

}// Остальное читаем в "мусор"

pPreviousChunk->bytesRead += fread(buffer, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);

}// Рассчитывает величину нормали (magnitude = sqrt(x^2 + y^2 + z^2)

#define Mag(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))

tVector3 Vector(tVector3 vPoint1, tVector3 vPoint2)

{

tVector3 vVector; // Хранит результирующий вектор

vVector.x = vPoint1.x - vPoint2.x;

vVector.y = vPoint1.y - vPoint2.y;

vVector.z = vPoint1.z - vPoint2.z;

return vVector; // Вернём результирующий вектор

}

tVector3 AddVector(tVector3 vVector1, tVector3 vVector2)

{

tVector3 vResult; // Хранит результирующий вектор

vResult.x = vVector2.x + vVector1.x;

vResult.y = vVector2.y + vVector1.y;

vResult.z = vVector2.z + vVector1.z;

return vResult; // Вернём результат

}

tVector3 DivideVectorByScaler(tVector3 vVector1, float Scaler)

{

tVector3 vResult;

vResult.x = vVector1.x / Scaler;

vResult.y = vVector1.y / Scaler;

vResult.z = vVector1.z / Scaler;

return vResult;

}

void CLoad3DS::ComputeNormals(t3DModel *pModel)

{

tVector3 vVector1, vVector2, vNormal, vPoly[3];

if(pModel->numOfObjects <= 0) return;// Если обьектов нет, пропускаем этот шаг

for(int index = 0; index < pModel->numOfObjects; index++)

{

t3DObject *pObject = &(pModel->pObject[index]);// Получим текущий обьект

tVector3 *pNormals = new tVector3 [pObject->numOfFaces];

tVector3 *pTempNormals = new tVector3 [pObject->numOfFaces];

pObject->pNormals = new tVector3 [pObject->numOfVerts];

pObject->pRotate = new tVector3(0.0f, 0.0f, 0.0f);

pObject->pVRotate = new tVector3(0.0f, 0.0f, 0.0f);

pObject->pPosition = new tVector3(0.0f, 0.0f, 0.0f);

pObject->pScale = new tVector3(1.0f, 1.0f, 1.0f);

for(int i=0; i < pObject->numOfFaces; i++)

{ // Сохраняем 3 точки этого полигона, чтобы избежать большого кода

vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];

vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];

vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];

vVector1 = vPoly[0] - vPoly[2]; // вектор полигона (из 2х его сторон)

vVector2 = vPoly[2] - vPoly[1]; // Второй вектор полигона

vNormal = Cross(vVector1, vVector2); // получаем cross product векторов

pTempNormals[i] = vNormal;

vNormal = Normalize(vNormal);

pNormals[i] = vNormal; // Сохраняем нормаль в массив

}// Теперь получаем вершинные нормали

tVector3 vSum(0.0, 0.0, 0.0);

tVector3 vZero = vSum;

int shared=0;

for (int i = 0; i < pObject->numOfVerts; i++)// Проходим через все вершины

{

for (int j = 0; j < pObject->numOfFaces; j++)

{// Проверяем, используется ли вершина другим полигоном

if (pObject->pFaces[j].vertIndex[0] == i || pObject->pFaces[j].vertIndex[1] == i || pObject->pFaces[j].vertIndex[2] == i)

{

vSum = vSum + pTempNormals[j];

shared++;//Увеличиваем число полигонов с общими вершиными

}

}

pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared));

pObject->pNormals[i] = Normalize(pObject->pNormals[i]);

vSum = vZero; // Сбрасываем сумму

shared = 0; // И общие полигоны

}// Освобождаем память временных переменных

delete [] pTempNormals;

delete [] pNormals;

}

}

Файл «Download3Ds.cpp»

#include"Download3Ds.h"

void C3dsLoader::Init_3ds(char* filename) //Инициализация 3Ds

{

mLoad3ds.Import3DS(&m3DModel, filename);

for(int i = 0; i < m3DModel.numOfMaterials; i++)

{

if(strlen(m3DModel.pMaterials[i].strFile) > 0)

{

Texture_3ds(TextureArray3ds, m3DModel.pMaterials[i].strFile, i);

}

m3DModel.pMaterials[i].texureId = i;

}

}

void C3dsLoader::Render_3ds() //Рендеринг 3Ds

{

for(int i = 0; i < m3DModel.numOfObjects; i++)

{

if(m3DModel.pObject.size() <= 0) break;

t3DObject *pObject = &m3DModel.pObject[i];

glScalef(pObject->pScale->x,pObject->pScale->y,pObject->pScale->z);

glTranslatef(-pObject->pPosition->x, -pObject->pPosition->y, -pObject->pPosition->z);

glRotatef(pObject->pRotate->x, 1.0f,0.0f,0.0f);

glRotatef(pObject->pRotate->y, 0.0f,1.0f,0.0f);

glRotatef(pObject->pRotate->z, 0.0f,0.0f,1.0f);

glTranslatef(-pObject->pVRotate->x, -pObject->pVRotate->y, -pObject->pVRotate->z);

if(pObject->bHasTexture)

{

glEnable(GL_TEXTURE_2D);

glColor3ub(255, 255, 255);

glBindTexture(GL_TEXTURE_2D, TextureArray3ds[pObject->materialID]);

}

else

{

glDisable(GL_TEXTURE_2D);

glColor3ub(255, 255, 255);

}

glBegin(GL_TRIANGLES);

for(int j = 0; j < pObject->numOfFaces; j++)

{

for(int whichVertex = 0; whichVertex < 3; whichVertex++)

{

int index = pObject->pFaces[j].vertIndex[whichVertex];

glNormal3f(pObject->pNormals[ index ].x, pObject->pNormals[ index ].y, pObject->pNormals[ index ].z);

if(pObject->bHasTexture) {

if(pObject->pTexVerts)

{

glTexCoord2f(pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);

}

}

else {

if(m3DModel.pMaterials.size() < pObject->materialID)

{

BYTE *pColor = m3DModel.pMaterials[pObject->materialID].color;

glColor3ub(pColor[0], pColor[1], pColor[2]);

}

}

glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z);

}

}

glEnd();

glTranslatef(pObject->pVRotate->x, pObject->pVRotate->y, pObject->pVRotate->z);

glRotatef(pObject->pRotate->z, 0.0f, 0.0f,-1.0f);

glRotatef(pObject->pRotate->y, 1.0f,-1.0f, 0.0f);

glRotatef(pObject->pRotate->x,-1.0f, 0.0f, 0.0f);

glTranslatef(pObject->pPosition->x, pObject->pPosition->y, pObject->pPosition->z);

glScalef(1.0f/pObject->pScale->x,1.0f/pObject->pScale->y,1.0f/pObject->pScale->z);

}

}

void C3dsLoader::Texture_3ds(UINT textureArray[], LPSTR strFileName, int ID)

{

AUX_RGBImageRec *pBitMap = NULL;

FILE *pFile = NULL;

unsigned char *pJpeg = NULL;

unsigned long width, height;

int type;

CJPEGFile jpeg;

char tempstring[5] = {0};

strncpy(tempstring, strFileName + strlen(strFileName)-4, 4);

char FilePath[200];

sprintf(FilePath, "data/%s", strFileName);

if(!strFileName) return;

if(!strcmp(tempstring, ".BMP"))

{

pFile = fopen(FilePath,"r");

if(pFile)

{

pBitMap = auxDIBImageLoad(FilePath);

type = 1;

}

else

{

MessageBox(NULL, FilePath /*"не мог найти текстуры!"*/, "Error!", MB_OK);

exit(0);

}

}

else if(!strcmp(tempstring, ".JPG") || !strcmp(tempstring, "JPEG"))

{

jpeg.GetSize(FilePath, width, height);

pJpeg = new unsigned char[width*height*3];

jpeg.Load(FilePath, 24, pJpeg);

type = 2;

}

glGenTextures(1, &textureArray[ID]);

glPixelStorei (GL_UNPACK_ALIGNMENT, 1);

glBindTexture(GL_TEXTURE_2D, textureArray[ID]);

if(type==1) gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitMap->sizeX, pBitMap->sizeY, GL_RGB, GL_UNSIGNED_BYTE, pBitMap->data);

if(type==2) gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, pJpeg);

lTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

lTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

if (pBitMap)

{

if (pBitMap->data)

{

free(pBitMap->data);

}

free(pBitMap);

}

if (pJpeg) delete [] pJpeg;

}

void C3dsLoader::Unload_3ds() //Разгружает 3Ds

{

for(int i = 0; i < m3DModel.numOfObjects; i++)

{

delete [] m3DModel.pObject[i].pFaces;

delete [] m3DModel.pObject[i].pNormals;

delete [] m3DModel.pObject[i].pVerts;

delete [] m3DModel.pObject[i].pTexVerts;

}

}

Файл «Main.cpp»

#include "main.h"

#include "Download3Ds.h"

#include <GL/glut.h>

HDC hDC=NULL; // приватный контекст устройства GDI

HGLRC hRC=NULL; // постоянный контекст рендеринга

HWND hWnd=NULL; // Дескриптор окна

HINSTANCE hInstance; // Дескриптор приложения

bool keys[256]; // Массив для обработки клавиатуры

bool active=TRUE; // Флаг активности окна

bool fullscreen=false; // Флаг режима окна

POINT mouse_p; // Позиция мыши

int SW_2=0, SH_2=0; // горизонтально и вертикальное положение координат мыши

float rc=0.0,bc=0.0,gc=0.0; // Изменения цвета пространства

float _Angle=0, _Diff=0; // Перемещение по координатам мыши

float dx=0, dy=0; // Хранение полученных координат мыши

float pi=3.1415926535897932384626433832795;

float x_0=0, y_0=0; // Координаты цетра

int counter=0; // Счетчик вращения

int counter1=1000; // Счетчик поднимания и опускания

float perspective=100.0; // Перспектива

C3dsLoader obj3dsLoader; // Объект 3DsLoader класса

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // инициализация окна OpenGL

{

if(height==0) // предотвращение деления на ноль

{

height=1;

}

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // установка цвет для очистки буфера цвета

glClearDepth(1.0); // установка параметр для очистки буфера глубины

glDepthFunc(GL_LESS); // настройка Z буфера

glEnable(GL_DEPTH_TEST); // включение

glShadeModel(GL_SMOOTH); // выбираем режим затенения

glMatrixMode(GL_PROJECTION); // устанавливаем текушей матрицей матрицу проекта

glLoadIdentity(); // обнуление эту самую матрицу

SW_2=width/2; // перемещение позиции камеры по горизонтали

SH_2=height/2; // перемещение позиции камеры по горизонтали

gluPerspective(perspective,(GLfloat)width/(GLfloat)height,0.1f,1000.0f);

glMatrixMode(GL_MODELVIEW); // переключение в модельную матрицу

}

int InitGL(GLvoid) // все настройки для OpenGL

{

glShadeModel(GL_SMOOTH); // включение сглаженных теней

glClearDepth(1.0f); // глубина установки буфера

glEnable(GL_DEPTH_TEST); // включение проверки глубины

glDepthFunc(GL_LEQUAL); // тип проверки глубины

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// улучшенные вычисления перспективы

glEnable(GL_LIGHTING); // вычисление освещения

GLfloat LightAmbient[]= { 0.1f, 0.1f, 0.1f, 1.0f }; // значения фонового света

GLfloat LightDiffuse1[]= { 1.0f, 0.0f, 0.0f, 1.0f }; // значения диффузного света 1

GLfloat LightPosition1[]= { 1.0f, 0.0f, 10.0f, 0.5f }; // позиция света 1

GLfloat LightDiffuse2[]= { 0.0f, 1.0f, 0.0f, 1.0f }; // значения диффузного света 2

GLfloat LightPosition2[]= { 1.0f, 1.0f, 10.0f, 0.5f }; // позиция света 2

GLfloat LightDiffuse3[]= { 0.0f, 0.0f, 1.0f, 1.0f }; // значения диффузного света 3

GLfloat LightPosition3[]= { 1.0f, 0.0f, 10.0f, 0.5f }; // позиция света 3

glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // установка фонового света

glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse1); // установка диффузного света 1

glLightfv(GL_LIGHT1, GL_POSITION, LightPosition1); // установка позиции света 1

glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2); // установка диффузного света 2

glLightfv(GL_LIGHT2, GL_POSITION, LightPosition2); // установка позиции света 2

glLightfv(GL_LIGHT3, GL_DIFFUSE, LightDiffuse3); // установка диффузного света 3

glLightfv(GL_LIGHT3, GL_POSITION, LightPosition3); // установка позиции света 3

glEnable(GL_TEXTURE_2D); // включение наложения текстур

obj3dsLoader.Init_3ds("data/Release.3ds"); // загрузка 3ds файла

return TRUE; // инициализация прошла успешно

}

int DrawGLScene(GLvoid) // Здесь мы делаем все чертежи

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);// Очистка экрана и глубины буфера

glLoadIdentity(); // Сброс матрицы вида модели

glEnable(GL_LIGHT0); // Освещение

gluLookAt(0,0,perspective,0,0,0,0,1,0);

glClearColor(rc, gc, bc, 0.0f); // цвет пространства

GetCursorPos(&mouse_p); // получение позиции мыши

dx=(float)(mouse_p.x-SW_2)*0.1f; // присвоение переменной горизонтальной позиции

dy=(float)(SH_2-mouse_p.y)*0.1f; // присвоение переменной вертикальной позиции

_Angle=_Angle+dx; // изменение позиции по горизонтали

_Diff=_Diff-dy; // изменение позиции по вертикали

SetCursorPos(SW_2, SH_2); // установка позиции курсора

glRotatef(_Angle,0,1.0f,0); // вращение камеры по горизонтали

glRotatef(_Diff,1.0f,0,0); // вращение камеры по вертикали

float counter2=(counter*0.25)*(2*pi/360);

obj3dsLoader.m3DModel.pObject[7].pRotate->z=counter*0.5; // вращение груза

obj3dsLoader.m3DModel.pObject[0].pPosition=new tVector3(0.0f, 0.0f,-50+counter1*0.05); // поднимание-опускаиние груза

obj3dsLoader.Render_3ds(); // рендеринг

glEnd(); // конец построения

return true; // флаг успеха

}

GLvoid KillGLWindow(GLvoid) // Функция убивает окно GL

{

if (fullscreen) // полный экран?

{

ChangeDisplaySettings(NULL,0);// Если так Переключиться обратно на рабочий стол

ShowCursor(TRUE); // Показать указатель мыши

}

if (hRC) // У нас есть контекст рендеринга?

{

if (!wglMakeCurrent(NULL,NULL)) // Мы в состоянии выпустить DC и RC контексты?

{

MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

}

if (!wglDeleteContext(hRC)) // Мы в состоянии удалить RC?

{

MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

}

hRC=NULL; // Установить RC до нуля

}

if (hDC && !ReleaseDC(hWnd,hDC)) // Мы в состоянии выпустить DC

{

MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

hDC=NULL; // Установить DC до нуля

}

if (hWnd && !DestroyWindow(hWnd)) // Мы в состоянии уничтожить окно?

{

MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

hWnd=NULL; // Установить hWnd до нуля

}

if (!UnregisterClass("OpenGL",hInstance))// Можем ли мы отменить регистрацию класса

{

MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

hInstance=NULL; // Установить hInstance до нуля

}

}

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag//создание GL Windows

{

GLuint PixelFormat; // Хранит результат после поиска

WNDCLASS wc; // Структура класса окна

DWORD dwExStyle; // Расширенный стиль окна

DWORD dwStyle; // Обычный стиль окна

RECT WindowRect; // Забирает прямоугольник Верхний левый / правый нижний значения

WindowRect.left=(long)0; // Установить левую составляющую в 0

WindowRect.right=(long)width; Установить правую составляющую в Width

WindowRect.top=(long)0; // Установить верхнюю составляющую в 0

WindowRect.bottom=(long)height; Установить нижнюю составляющую в Height

fullscreen=fullscreenflag; //Устанавливаем значение глобальной переменной fullscreen

hInstance=GetModuleHandle(NULL); // Считаем дескриптор нашего приложения

wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;

wc.lpfnWndProc=(WNDPROC) WndProc; // Процедура обработки сообщений

wc.cbClsExtra=0; // Нет дополнительной информации для окна

wc.cbWndExtra=0; Нет дополнительной информации для окна

wc.hInstance=hInstance; // Устанавливаем дескриптор

wc.hIcon=LoadIcon(NULL, IDI_WINLOGO); // Загружаем иконку по умолчанию

wc.hCursor=LoadCursor(NULL, IDC_ARROW); Загружаем указатель мышки

wc.hbrBackground=NULL; Фон не требуется для GL

wc.lpszMenuName=NULL; Меню в окне не будет

wc.lpszClassName="OpenGL"; // Устанавливаем имя классу

if( !RegisterClass( &wc ) ) Пытаемся зарегистрировать класс окна

{

MessageBox( NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION );

return false; // Выход и возвращение функцией значения false

}

if (fullscreen) // Полноэкранный режим?

{

DEVMODE dmScreenSettings; // Режим устройства

memset(&dmScreenSettings,0,sizeof(dmScreenSettings));

dmScreenSettings.dmSize=sizeof(dmScreenSettings); Размер структуры Devmode

dmScreenSettings.dmPelsWidth=width; Ширина экрана

dmScreenSettings.dmPelsHeight=height; Высота экрана

dmScreenSettings.dmBitsPerPel=bits; // Глубина цвета

dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

if( ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN )!=DISP_CHANGE_SUCCESSFUL)

{

if(MessageBox( NULL, "The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES )

{

fullscreen=false; }

else

{

MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);

return false;// Выход и возвращение функцией false

}

}

}

if(fullscreen) // Мы остались в полноэкранном режиме?

{

dwExStyle=WS_EX_APPWINDOW; // Расширенный стиль окна

dwStyle=WS_POPUP; // Обычный стиль окна

ShowCursor( false ); // Скрыть указатель мышки

}

else

{

dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE; // Расширенный стиль окна

dwStyle=WS_OVERLAPPEDWINDOW; // Обычный стиль окна

} // Windows стиль

AdjustWindowRectEx(&WindowRect,dwStyle,false,dwExStyle);

if(!(hWnd=CreateWindowEx(dwExStyle, // Расширенный стиль для окна

"OpenGL", // Имя класса

title, // Заголовок окна

WS_CLIPSIBLINGS| // Требуемый стиль для окна

WS_CLIPCHILDREN| // Требуемый стиль для окна

dwStyle, // Выбираемые стили для окна

0,0, // Позиция окна

WindowRect.right-WindowRect.left, // Вычисление подходящей ширины

WindowRect.bottom-WindowRect.top, // Вычисление подходящей высоты

NULL, // Нет родительского

NULL, // Нет меню

hInstance, // Дескриптор приложения

NULL))) // Не передаём ничего до WM_CREATE (???)

{

KillGLWindow(); // Восстановить экран

MessageBox( NULL, "Window Creation Error.", "ERROR", MB_OK | MB_ICONEXCLAMATION );

return false; // Вернуть false

}

static PIXELFORMATDESCRIPTOR pfd=

{

sizeof(PIXELFORMATDESCRIPTOR),

1, // Номер версии

PFD_DRAW_TO_WINDOW| // Формат для Окна

PFD_SUPPORT_OPENGL| // Формат для OpenGL

PFD_DOUBLEBUFFER, // Формат для двойного буфера

PFD_TYPE_RGBA, // Требуется RGBA формат

bits, // Выбирается бит глубины цвета

0,0,0,0,0,0, // Игнорирование цветовых битов

0, // Нет буфера прозрачности

0, // Сдвиговый бит игнорируется

0, // Нет буфера накопления

0,0,0,0, // Биты накопления игнорируются

32, // 32 битный Z-буфер (буфер глубины)

0, // Нет буфера трафарета

0, // Нет вспомогательных буферов

PFD_MAIN_PLANE, // Главный слой рисования

0, // Зарезервировано

0,0,0 // Маски слоя игнорируются

};

if(!(hDC=GetDC(hWnd))) // Можем ли мы получить Контекст Устройства?

{

KillGLWindow(); // Восстановить экран

MessageBox(NULL,"Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);

return false; // Вернуть false

}

if(!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))

{

KillGLWindow(); // Восстановить экран

MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);

return false; // Вернуть false

}

if( !SetPixelFormat( hDC, PixelFormat, &pfd ) )

{

KillGLWindow(); // Восстановить экран

MessageBox( NULL, "Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION );

return false; // Вернуть false

}

if(!(hRC=wglCreateContext(hDC))) // Возможно ли установить Контекст Рендеринга?

{

KillGLWindow(); // Восстановить экран

MessageBox( NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);

return false; // Вернуть false

}

if(!wglMakeCurrent(hDC,hRC)) // Попробовать активировать Контекст Рендеринга

{

KillGLWindow(); // Восстановить экран

MessageBox( NULL, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION );

return false; // Вернуть false

}

ShowWindow(hWnd,SW_SHOW); // Показать окно

SetForegroundWindow(hWnd); // Слегка повысим приоритет

SetFocus(hWnd); // Установить фокус клавиатуры на наше окно

ReSizeGLScene(width,height); // Настроим перспективу для нашего OpenGL экрана.

if(!InitGL()) // Инициализация только что созданного окна

{

KillGLWindow(); // Восстановить экран

MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);

return false; // Вернуть false

}

return true; // Всё в порядке!

}

LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam, LPARAM lParam)

{

switch (uMsg) // Проверка сообщения для окна

{

case WM_ACTIVATE: // Проверка сообщения активности окна

{

if (!HIWORD(wParam)) // Проверить состояние минимизации

{

active=true; // Программа активна

}

else

{

active=false; // Программа теперь не активна

}

return 0; // Возвращаемся в цикл обработки сообщений

}

case WM_SYSCOMMAND: // Перехватываем системную команду

{

switch (wParam) // Останавливаем системный вызов

{

case SC_SCREENSAVE:

case SC_MONITORPOWER: return 0; // Предотвращаем это

}

break; // Выход

}

case WM_CLOSE: // Мы получили сообщение о закрытие?

{

PostQuitMessage(0); // Отправить сообщение о выходе

return 0; // Вернуться назад

}

case WM_KEYDOWN: // Была ли нажата кнопка?

switch(wParam)

{

case VK_ESCAPE:

PostQuitMessage(0); //Выход

break;

case VK_F1:

glEnable(GL_LIGHT1);

break;

case VK_F2:

glEnable(GL_LIGHT2);

break;

case VK_F3:

glEnable(GL_LIGHT3);

break;

case VK_F4:

glDisable(GL_LIGHT1);

glDisable(GL_LIGHT2);

glDisable(GL_LIGHT3);

break;

case VK_F5:

if(rc<1.0) // если не полностью светло

{

rc=rc+0.1; // осветление

gc=gc+0.1; // окружающего

bc=bc+0.1; // пространства

}

else

{

rc=0.0; // полная

gc=0.0; // темнота

bc=0.0; // пространства

}

break;

case VK_SHIFT:

perspective--; // Приближение камеры

break;

case VK_CONTROL:

perspective++; // Отдаление камеры

break;

case VK_UP:

if(counter1!=700.0)

counter1=counter1-10.0; // поднимание груза

break;

case VK_DOWN:

if(counter1!=1000.0)

counter1=counter1+10.0;//опускание груза

break;

case VK_LEFT:

counter=(counter+10)%1440; // вращение влево

break;

case VK_RIGHT:

counter=(counter-10)%1440; // вращение вправо

break;

}

break;

case WM_KEYUP: // Была ли отпущена клавиша?

{

keys[wParam]=false; // Если так, мы присваиваем этой ячейке false

return 0; // Возвращаемся

}

case WM_SIZE:// Изменены размеры OpenGL окна

{

ReSizeGLScene(LOWORD(lParam),HIWORD(lParam))

return 0; // Возвращаемся

}

case WM_DESTROY: // Можете ли вы получить сообщение о выходе

{

obj3dsLoader.Unload_3ds(); // разгрузка 3ds файла

return 0; // Возвращаемся

}

}

return DefWindowProc(hWnd,uMsg,wParam,lParam);

}

int WINAPI WinMain(HINSTANCE hInstance,/*пример*/ HINSTANCE hPrevInstance,/*предыдущий пример*/ LPSTR lpCmdLine,/* Параметры командной строки*/ int nCmdShow)// показать окно

{

MSG msg; // структура Windows сообщения

BOOL done=FALSE; // Логическая переменная выхода из цикла

int rX=GetSystemMetrics(SM_CXSCREEN); // масштабирование окна по горизонтали

int rY=GetSystemMetrics(SM_CYSCREEN); // масштабирование окна по вертикали

if (!CreateGLWindow("Курсовой проект",rX,rY,32,fullscreen)) // Создаем наше OpenGL окно

{

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

}

while(!done) // Цикл, который проходит пока не ложь

{

if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Является ожидающим сообщения?

{

if (msg.message==WM_QUIT) // Разве мы получили сообщение о выходе?

{

done=TRUE; // Если так, сделать = TRUE

}

else // Если нет, продолжаем работать с сообщениями окна

{

TranslateMessage(&msg); // Перевести сообщение

DispatchMessage(&msg); // Отправка сообщений

}

}

else // Если Там нет сообщений

{// Рисуем сцену. Ожидаем нажатия кнопки ESC и сообщения выхода от DrawGLScene()

if ((active && !DrawGLScene()) || keys[VK_ESCAPE])

done=TRUE; // ESC или DrawGLScene подается сигнал выхода

}

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

{

SwapBuffers(hDC); // Переключаем буферы (Двойная буферизация)

}

if (keys[VK_F11]) // Является F1 нажатой?

{

keys[VK_F1]=FALSE; // Если так установим значение FALSE

KillGLWindow(); // Убивать наших текущее окно

fullscreen=!fullscreen// Переключает полноэкранный / оконный режим

if (!CreateGLWindow("Курсовой проект",rX,rY,32,fullscreen)) {

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

}

}

}

} // Завершение работы

KillGLWindow(); // убийство окна

return (msg.wParam); // выход из программы

}

Результаты работы программы

Приложение C.1

Анимация

Рисунок 14. Поворот ключа.

Рисунок 15.Щеколда опущена.

Рисунок 16. Щеколда поднята.

Текстуры

Рисунок 17. Текстура тела замка.

Рисунок 18. Текстура левой части щеколды.

Рисунок 19. Текстура верхней части щеколды.

Рисунок 15. Текстура правой части щеколды.

Рисунок 16. Текстура поверхности земли.

Рисунок 17. Текстура цепочки.

Размещено на Allbest.ru

...

Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.