Модераторы: Rickert

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Программирование игрового движка GR-Engine, Введение 
:(
    Опции темы
php
Дата 10.2.2009, 14:11 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Программирование игрового движка GR-Engine.

Автор: php (Танцер Максим aka Verg)

Введение.

Здравствуйте друзья!

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

В приведённых статьях будет взят примером игровой движок GreenRay Engine 
(впоследствии будет называться сокращенно GRE) моей собственной разработки,
далее он будет выкладываться блоками всё в новых и новых статьях 
(всё будет полностью открытым кодом - OpenSource, никаких вызовов из библиотек, 
что как правило присуще коммерческим версиям движков), так что можно будет его обсуждать и коллективно его дорабатывать, вносить изменения и дополнения, можно даже критиковать, только не очень сильно, т.к это всё делается и приводится в качестве примера, и я сам пока не являюсь профессиональным программистом в области программирования 3D и буду учиться вместе с вами.

Примечание! Сразу стоит оговориться разработка движка будет вестись в
среде Visual Studio 2005 (v8.0) в связке C++ и DirectX 9.0c и будут рассматриваться аспекты связанные только с разработкой и программированием GRE, создание моделей,
текстур и прочее в данных статьях рассматриваться не будут этим занимаются другие разработчики из нашей команды, так, что все вопросы связанные с моделированием или Photoshop будут адресовываться именно им (Master Lucky и Zerg).

Все обсуждения, дополнения, критику, отловленные баги (а они будут smile)
предлагаю вести в отдельных топиках, а затем дополненную и обработанную информацию я буду дополнять в самих статьях (пока так, а потом посмотрим как далее пойдёт)

Так что все желающие прошу присоединяться!!! smile

Итак начнём:

Часть 1. Подготовка к разработке.

1.1. Описание возможности движка.

Сначала опишем, что уже включает и умеет сам движок GRE версии 3.0 
(версию 2.0 разбирать не будем, т.к изначально он разрабатывался на Delphi):

1. Поддержка довольно большого кол-ва полигонов (максимально тестируемое пока было 300 тыс. полигонов при этом fps (Frames Per Second) - кол-во кадров в секунду) даже не менялось, в принципе я считаю, что при таком кол-ве можно смоделировать неплохой по размерам городской квартальчик (игру GTA (первая часть) в расчёт не берём каково там кол-во полигонов было я не знаю!)

2. Поддержка шейдеров версии 2.0 и 3.0 (освещение по Фонгу)

3. Используется уже готовый физический движок от NVidia PhysX (ранее принадлежал Ageia PhysX а до этого вообще был платный и назывался Novodex до сих пор многие операторы и процедуры начинаются с аббревиатуры Nx, но об этом позже когда будем разбирать сам физический движок)

4. Поддержка аудио библиотек и воспроизведение mp3

5. Управление и камера от первого лица с использованием DirectInput

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

Примечание! Полигон - это весьма  абстрактное понятие, обычно служит для визуализации 3D объекта в пространстве и являются составным обычно состоит из треугольников, соответственно сам треугольник состоит из 3х вершин, затем 3D Render объединяет эти вершины в результате на экране мы видим "цельный" треугольник залитый так сказать пикселями (точками) одного или более цветами, на пиксельном уровне уже обычно работают через шейдеры (ретушь, закраска), (в принципе используя шейдеры полигон можно закрасить и разными цветами) о шейдерах будем рассказывать позже. 

7. Отрисовка небесного куба – SkyBox. Создание иллюзии большого пространства,
как бы общее окружение облака, горы и прочее.. (позже попробуем разобраться с весьма интересной технологией 3D SkyBox суть его заключается в проецировании уменьшенной фоновой декорации с использованием уменьшенных 3D моделей в реальную сцену окружения, при помощи специальной проецирующей камеры, в рез-те чего создаётся иллюзия огромнейших игровых пространств или больших возвышающихся объектов с применением относительно малого кол-ва полигонов, данная технология впервые была реализована разработчиками в игре Half-Life 2)

1.2. Самое начало..
 
Далее, что следует разобрать это структуру игрового движка, т.е из
чего он состоит и с чего начинает программист взявшись за его разработку.

Примечание! Вообще данный раздел содержит пример простейшего создания проекта в среде разработки Visual Studio и предназначен для самых самых новичков, тех кто вообще ничего не смыслит в программировании и считаю, что по приведённому здесь материалу с иллюстрациями в два счёта можно создать новый проект, единственное требование это наличие всех необходимых материалов и средств для разработки – это Visual Studio, DirectX SDK 9.0c и NVidia PhysX..

Итак, приступим: 

1) Для начала устанавливаем среду Visual Studio 2005 
(у кого нет желательно "приобрести", также подойдёт и более новая версия VS 2008):

user posted image

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

user posted image

Примечание ! Maintenance Mode у меня потому, что Visual Studio на момент написания статьи уже было установлено на моём компьютере, у вас может быть и по другому.

Далее после того как завершится установка Visual Studio устанавливаем DirectX SDK.

2) Устанавливаем DirectX 9.0 (я пока использую версию DirectX 9.0c April 2005, т.к более устойчивая да и менее глючная (в процессе разработки движка в более новых версиях были выявлены некоторые баги) но в последствии придётся всё же использовать новую версию DX если планируется двигаться дальше вместе с прогрессом и осваивать DX 10 smile так, что можно устанавливать и более новую версию это на разработку движка никак не повлияет:

user posted image

user posted image

3) Скачиваем с сайта NVidia физический движок PhysX и устанавливаем его:
Сначала желательно установить так называемое системное программное обеспечение необходимое для нормального функционирования физического движка для этого придётся скачать файл под названием PhysX_8.10.13_SystemSoftware.exe и установить его: 

user posted image

После этого скачиваем файл PhysX_2.8.1_SDK_Core.msi (это PhysX SDK собственной персоной) и устанавливаем его:

user posted image

4) Создаём новый проект, для этого запускаем Visual Studio и заходим в меню File->New->Project… как показано на рисунке ниже:

user posted image

В появившемся окне выбираем Project types (тип проекта) – General, Templates (шаблоны) – Empty Project, Name (имя проекта) – GRDebugger, Location (месторасположение папки с проектом) – выбираем любое нажав на кнопку Browse (у меня GreenRay), убираем галочку с Create directory for solution, короче говоря делаем всё в точности как показано на рисунке ниже:

user posted image

Все теперь мы создали совершенно новый пустой проект под названием GRDebugger (имя файла проекта называется GRDebugger.sln этот sln – файл сокращённо от Solution является базовым запустив его по клику мыши мы тут же мгновенно запустим наш проект для отладки и компоновки). Всё поехали дальше..

5) Прописываем пути для заголовочных файлов и библиотек:
Данная операция необходима для того, чтобы среда Visual Studio понимала и знала во первых где находится само DirectX SDK (SDK – Software Developers Kit) ну и соответственно где находится необходимый для работы DirectX-овский "бутор" это различные заголовочные header (*.h) и *.cpp (C++) файлы, все вызовы идут через них и основным промежуточным звеном является либы (*.lib файлы) это двоичные файлы необходимые для взаимодействия между API-кодом нашей программы и ядром DirectX (Сами файлы ядра находятся в папке Windows\System32 в виде динамических библиотек и имеют имена типа d3d9.dll, d3dx9_36.dll и др. разные имена. Код данных библиотек не доступен никому (кроме самой компании Мелкософт конечно которая их и разрабатывает), мы можем лишь использовать или вызывать из них необходимые нам функции, но не смотреть, а тем более редактировать их, это относится не только к DirectX SDK, но и к PhysX SDK тоже да и вообще к любому виду SDK. Как прописывать подобные библиотеки будет описано ниже в п.7)

Заходим в меню Tools->Options

user posted image

В появившемся окне слева в списке раскрываем дерево Projects and Solutions и выбираем VC++Directories, затем сверху из выпадающего списка Show directories for: необходимо выбрать Library files здесь как раз и будет прописан путь к нашим либам для этого нажимаем на пустом месте мышью где находятся другие прописанные пути необходимые среде Visual Studio, и нажимаем на кнопку с троеточием и выбираем путь к папке с либами, у меня по умолчанию путь: 
C:\Program Files\Microsoft DirectX 9.0 SDK (April 2005)\Lib\x86
У вас путь может быть другой в зависимости от версии установленного SDK, обычно по умолчанию он устанавливается в Program Files.

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

user posted image

Примечание ! Иногда возникает ситуация когда программа установки DirectX SDK автоматически находит и сама прописывает пути в среде Visual Studio их нужно удалить и всё равно прописать или указать вручную, будьте внимательны это очень важный момент !!!

Примечание !  Если заметить, то выше был указан путь к 32х разрядным версиям библиотек, но счастливые обладатели 64х разрядных систем могут указать путь и к 64х разрядным версиям библиотек !! Путь тогда будет выглядеть уже следующим образом:
C:\Program Files\Microsoft DirectX 9.0 SDK (April 2005)\Lib\x64

Также аналогичным образом прописываем пути к заголовочным (*h – файлам и *cpp),
выбираем из выпадающего списка под названием Show directories for: Include files
и прописываем или указываем путь: 
C:\Program Files\Microsoft DirectX 9.0 SDK (April 2005)\Include

user posted image

И нажимаем ОК

Добавлено @ 14:12
6) Прописываем пути для заголовочных файлов и библиотек PhysX SDK:
Аналогичным образом как описано выше прописываем пути к PhysX SDK для Library files 
Путь будет выглядеть следующим образом: 
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\lib\Win32

Для Include files будет несколько путей:
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\Cooking\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\Foundation\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\NxCharacter\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\Physics\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\Physics\include\cloth
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\Physics\include\fluids
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\Physics\include\softbody
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.1\SDKs\PhysXLoader\include


user posted image

Нажимаем кнопку ОК. Всё PhysX SDK прописан..

7) Прописываем необходимые Libraries (Lib-библиотеки):
Это необходимо для дальнейшей компиляции и разработки самого движка, поэтому
пропишем их все и сразу, чтоб в дальнейшем к ним не возвращаться и не акцентировать на них своё внимание, для этого заходим в меню Project->GRDebugger Properties… или нажимаем комбинацию клавиш Alt+F7

user posted image

В появившемся окне в раскрывающемся "дереве" выбираем Configuration Properties->Linker->Input далее нажимаем мышью на пункте Additional Dependencies в поле появится кнопка с троеточием для выбора подключаемых библиотек см. рисунок ниже:

user posted image

В окне Additional Dependencies прописываем через пробел или нажимаем Enter после каждой библиотеки:

Список необходимых библиотек:
d3d9.lib d3dx9.lib d3dx9d.lib d3dxof.lib dinput.lib dinput8.lib dxguid.lib winmm.lib dsound.lib strmiids.lib PhysXLoader.lib

user posted image

После того как все либы (*.lib) прописаны нажимаем OK.

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

#include <d3d9.h>
#include <d3dx9.h>

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")



Я выбрал способ непосредственной интеграции библиотек в "тело"  проекта.

Теперь, что касается strmiids.lib остутствие её будет вызывать ошибку после процесса компиляции данная либа не прилагается в поставке DirectX SDK, её можно взять из файла: Sound_Modules.rar
в самом низу статьи.

После, того как вы скачаете этот файл его нужно разархивировать в папку:
C:\GreenRay\GRDebugger\Sound_Modules\Lib

Этот lib-файл будет необходим нам в будущем во время реализации функции проигрывания mp3-файлов в движке, также нужно скачать раздел Common для работы со звуком он частично взят из раздела DirectShow (были взяты только файлы необходимые для работы с mp3),
находится в том же файле: Sound_Modules.rar

Раздел Common нужно разархивировать в папку:
C:\GreenRay\GRDebugger\Sound_Modules\Common

Теперь нужно прилинковать эти файлы к среде Visual Studio, делаем, это точностью также как мы поступали с DirectX SDK и PhysX SDK. Заходим в меню Tools->Options,
в появившемся окне Options из списка слева раскрываем Projects and Solutions и выбрать VC++Directories, далее из выпадающего списка Show directories for: выбираем
Library files и прописываем путь куда мы ранее разархивировали файл strmiids.lib, он должен быть  в папке C:\GreenRay\GRDebugger\Sound_Modules\Lib

user posted image

Дальше прописываем путь к ранее скачанной папке Common, аналогично только в выпадающем списке Show directories for: выбираем Include files: и прописываем путь
C:\GreenRay\GRDebugger\Sound_Modules\Common

user posted image

Нажимаем кнопку ОК. 
Всё все необходимые либы у нас есть и прописаны.

Часть 2. Проектирование игрового движка.

2.1. Создание игрового полотна.
Под таким страшным названием скрывается обычное создание виндового (Windows) окна, которое будет служить "подложкой" для вывода и отрисовки трёхмерного пространства и всей графики и игровой сцены в целом.

1) Сначала создадим файл Form_Layer.cpp (в принципе название может быть и любое другое, на ваше усмотрение, но всё же советую создавать все модули с названиями как у меня, иначе впоследствии потеряем все связки, да и вообще потом получится "каша" особенно в разделе #include я буду приводить код с одним названием модуля, а у вас будет называться по другому, в прочем ваше дело smile) моё дело предупредить)

Для этого в "дереве" нашего проекта выбираем Source Files и нажимаем на нём правой кнопкой мыши, далее из выпадающего меню выбираем Add->New Item…

user posted image

В появившемся окне New Item в колонке Categories: выбираем пункт Code, в Templates выбираем C++ File (.cpp), в строке Name: прописываем имя файла Form_Layer, 
Создадим папку под названием Engine_Modules где будут храниться модули и исходные коды самого движка, так удобнее, для этого заходим в папку где находится наш ранее созданный проект, она должна быть по пути C:\GreenRay\GRDebugger\ и в ней создаём папку Engine_Modules, затем возвращаемся к Visual Studio в строке Location: указываем местоположение где будет находиться этот файл. Необходимо, чтобы он создался в папке Engine_Modules поэтому в строке Location: будет путь C:\GreenRay\GRDebugger\Engine_Modules см. рисунок ниже:

user posted image

Всё нажимаем кнопку Add

Теперь таким же образом нужно создать заголовочный Header File (.h), для этого также в "дереве" проекта нажимаем правой кнопкой на Header Files и выбираем Add->New Item.. В появившемся окне New Item в колонке Categories: выбираем пункт Code, в Templates выбираем Header File (.h), в строке Name: также прописываем имя файла Form_Layer, Location: остаётся тот же без изменений C:\GreenRay\GRDebugger\Engine_Modules
Всё снова нажимаем кнопку Add. У нас появилось в "дереве" нашего проекта два файла – файл содержащий код .cpp и заголовочный файл .h содержащий вызовы процедур или функций и прочие параметры необходимые для работы всего проекта в целом.
Но для нормального взаимодействия между файлом кода .cpp и .h его нужно прописать в среде Visual Studio, тут ничего нового заходим в меню Tools->Options в окне Options из списка выбираем Project and Solutions->VC++Directories и в выпадающем списке Show directories for: выбираем Include files и добавляем туда путь C:\GreenRay\GRDebugger\Engine_Modules

user posted image

Нажимаем ОК, файлы прилинкованы к проекту.

Всё вся эта канитель завершена, небось уже поднадоела вся эта процедура по собиранию и компоновке движка ? smile, но процедура согласитесь нужная, и надеюсь позволит избежать лишних вопросов в будущем!

Ок теперь всё скомпоновано, среда Visual Studio настроена, 
и можно начинать полноценное программирование..

2) Создание полотна для вывода графики.
Возвращаемся к "дереву" нашего проекта, делаем двойной щелчок мыши на файле Form_Layer.cpp перед нами появится пустой экран где можно вводить код. 

Вот вам домашнее задание: Необходимо создать окно на Win API, и продумать методы и процедуры инициализации Direct3D, определить, какие возможности поддерживает ваша видеокарта…. Шутка smile..

Копируем и вставляем этот код в ваше пустое окно файла Form_Layer.cpp:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine Debugger Module v.3.0.0.1
// Form_Layer.cpp Visual Studio 8 Version.
// It's An GreenRay Form_Layer Source File.
// Made Specially For Check And Debugging 3DEngine.
/*****************************************************************************/
#define STRICT //Обеспечивает переносимость кода, к примеру мы прогу пишем на другой
//винде 16-разрядной, а объявление этого параметра позволит избежать многих ошибок при 
//компиляции уже под 32 разрядной ОС и наоборот.
//Использование STRICT позволяет: 
//1) выполнять строгую проверку типов; 
//2) корректировать и согласовывать описания типа параметра и возвращаемого значения; 
//3) создавать прототипы определений типов для функций обратного вызова (оконные, диалоговые и специальные процедуры); 
//4) согласовывать с ANSI описания структур COMM, DCB и COMSTAT. 
//ну и многое другое, не будем уже углубляться в эти программистские Debri.

#define WIN32_LEAN_AND_MEAN //Позволяет обойти ошибки множественного объявления 
//структур при подключении заголовочных файлов уже имеющих эти структуры. 

#include "Form_Layer.h" //Объявляем здесь наш заголовочный Header-файл

////////////////////////////////////////////////////////////////////////////////
// External Definitions And Prototypes 
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WindowProcessing(HWND Hndl_Wnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow);

//-----------------------------------------------------------------------------
// Name: WindowProcessing()
// Desc: Здесь обрабатываются оконные сообщения
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProcessing(HWND Hndl_Wnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
  switch(Msg)
  {
    case WM_KEYDOWN:
    {
      if (wParam == VK_ESCAPE) //Перехватили нажатие кнопки Esc на клавиатуре
      {
        PostQuitMessage(0); break; //Обрабатываем
      }
    }
    break;

    case WM_CLOSE: //Перехватили момент закрытия окна при нажатии на крестике в углу экрана 
    {
      PostQuitMessage(0); //Обрабатываем
    }
        
    case WM_DESTROY: //Перехватили момент закрытия окна через трей или диспетчер задач Windows
    {
      PostQuitMessage(0); //Обрабатываем
    }
    break;

    default:
    {
      return DefWindowProc(Hndl_Wnd,Msg,wParam,lParam); //А иначе продолжаем обрабатывать сообщения
    }
    break;
  }
  return 0;

  //Вообще здесь можно обрабатывать любые оконные сообщения, по сути даже осуществить 
  //управление игровым персонажем, но мы будем использовать для этого DirectInput.
} //EndWindowProcessingFunction

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Эта функция предназначена для создания нашего окна
// Это является точкой входа для нашего приложения, иначе в процессе компиляции
// вернётся сообщение об ошибке: Entry point must be defined.
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
  WNDCLASSEX WindowClass; //Структура необходимая для регистрации оконного класса 
  MSG uMsg; //Оконные сообщения
  HWND Hndl_Wnd = NULL; //Дескриптор оконного класса

  int FormWidth = 640; //Ширина нашего окна 
  int FormHeight = 480; //Высота нашего окна
  LPCSTR FormCaption = "GreenRay Engine v3.0.0.1"; //Название выводимое в заголовке окна

  memset(&uMsg,0,sizeof(uMsg)); //Передача в структуру флага для оконных сообщений

  //Установка параметров окна, таких как цвет, иконка, стиль окна, курсор
  //и передача их структуре WNDCLASSEX
  WindowClass.lpszClassName = "MainWindow";
  WindowClass.cbSize        = sizeof(WNDCLASSEX);
  WindowClass.style         = CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
  WindowClass.lpfnWndProc   = WindowProcessing;
  WindowClass.hInstance     = hInstance;
  WindowClass.hIcon            = ::LoadIcon(0,IDI_APPLICATION);
  WindowClass.hIconSm        = ::LoadIcon(0,IDI_APPLICATION);
  WindowClass.hCursor       = LoadCursor(NULL,IDC_ARROW);
  WindowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  WindowClass.lpszMenuName  = NULL;
  WindowClass.cbClsExtra    = 0;
  WindowClass.cbWndExtra    = 0;

  //Регистрация класса окна
  if (!RegisterClassEx(&WindowClass)) return E_FAIL;

  //Теперь когда класс зарегистрирован можно создавать само окно
  Hndl_Wnd = CreateWindowEx(NULL,              //Window Style
                         "MainWindow",         //Window Class Name 
                         FormCaption,          //Caption Of The Window
                         WS_OVERLAPPEDWINDOW,  //Window Style Criterium
                         100,100,              //Left And Top Corner On Desktop
                         FormWidth,FormHeight, //Width And Height Of The Window
                         NULL,                 //Descriptor Of Parent Window
                         NULL,                 //Descriptor Of The Window Menu
                         hInstance,            //Descriptor Of Example Application
                         NULL);                //Pointer On Data Created Window

  //Если создание окна прошло неудачно, то функция вернёт ошибку
  if (Hndl_Wnd == NULL) return E_FAIL;

  ShowWindow(Hndl_Wnd,nCmdShow); //Иначе покажем
  UpdateWindow(Hndl_Wnd); //и обновим наше окно


  //Здесь наше окно начинает интенсивно обрабатывать сообщения от Windows
  while (uMsg.message != WM_QUIT)
  {
    if (PeekMessage(&uMsg,NULL,0,0,PM_REMOVE)) //Нддаа если возникает это событие, то
                                               //происходит уже явный перебор потока сообщений!
    {                                          //они начинают попросту удаляться из потока (данный манёвр 
                                               //позволяет немного разгрузить процессор)
      TranslateMessage(&uMsg); //Трансляция, перевод потока сообщений
      DispatchMessage(&uMsg); //Обслуживание потока сообщений
    } 
  }
 
  //Выгрузка оконного класса он выполнил своё предназначение ;)
  UnregisterClass("MY_WINDOWS_CLASS",WindowClass.hInstance);
  return uMsg.wParam;
} //EndWinMainFunction



Теперь делаем двойной щелчок мыши в "дереве" проекта на файле Form_Layer.h
Код у него будет следующим: 

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine Debugger Module v.3.0.0.1
// Form_Layer.h
// It's An GreenRay Form_Layer Header File.
// Made Specially For Check And Debugging 3DEngine Keep Needed Engine Imports.
/*****************************************************************************/
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

//Windows And System Directives
#include <windows.h>
#include <atlstr.h>   
#include <stdio.h>
#include <tchar.h>
#include <wchar.h>
#include <strsafe.h>



Не забываем после этого нажать кнопку сохранить, пробуем скомпилировать проект, нажав на зелёную стрелку вверху окна Visual Studio:

user posted image

Если процесс компиляции завершился ошибкой то внизу окна рабочей среды выводится окно отладки содержащее информацию об ошибке, где можно отладить или устранить причину ошибки, двойным кликом мыши по надписи с ошибкой среда программирования как правило позиционирует и устанавливает курсор на участке кода вызвавшего эту ошибку, обычно она выводится в окне Output:

user posted image

Если же процесс компиляции прошёл нормально, то перед нами должно появиться окно как на рисунке представленном ниже:

user posted image

Поздравляю вы совершили первый шаг по созданию вашего игрового движка. Двигаемся дальше..

3) Инициализируем Direct3D:
В "дереве" нашего проекта нажимаем правой кнопкой мыши на Header Files  в появившемся меню выбираем Add->New Item далее в окне Categories: Выбираем категорию Code, в окне Templates: выбираем Header File (.h), далее в поле Name: вводим GR_Engine, а в поле Location: указываем путь к папке C:\GreenRay\GRDebugger\Engine_Modules
В общем выполняем все те же действия, что мы и делали ранее когда создавали файл модуля Form_Layer, кто уже забыл читаем Часть 2 п.2.1.

Далее снова в "дереве" нашего проекта нажимаем правой кнопкой мыши уже на Source Files в появившемся меню выбираем Add->New Item далее в окне Categories: Выбираем категорию Code, в окне Templates: выбираем С++ File (.сpp), далее в поле Name: вводим GR_Engine, а в поле Location: указываем путь к папке C:\GreenRay\GRDebugger\Engine_Modules
Всё теперь в "дереве" нашего проекта к существующим Form_Layer.h и Form_Layer.cpp добавилось ещё два файла под названием GR_Engine.h и GR_Engine.cpp соответственно.

Делаем двойной щелчок в "дереве" проекта на файле Form_Layer.h, стираем у него всё содержимое и меняем на это:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine Debugger Module v.3.0.0.2
// Form_Layer.h
// It's An GreenRay Form_Layer Header File.
/*****************************************************************************/

#include <GR_Engine.h>



Потом делаем двойной щелчок на файле Form_Layer.cpp также удаляем всё его содержимое и меняем на это:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine Debugger Module v.3.0.0.2
// Form_Layer.cpp Visual Studio 8 Version.
// It's An GreenRay Form_Layer Source File.
// Made Specially For Check And Debugging 3DEngine.
/*****************************************************************************/
#define STRICT //Обеспечивает переносимость кода, к примеру мы прогу пишем на другой
//винде 16 разрядной к примеру, а объявление этого параметра позволит избежать многих ошибок при 
//компиляции уже к примеру под 32 разрядной ОС.
//Использование STRICT позволяет: 
//1) выполнять строгую проверку типов; 
//2) корректировать и согласовывать описания типа параметра и возвращаемого значения; 
//3) создавать прототипы определений типов для функций обратного вызова (оконные, диалоговые и специальные процедуры); 
//4) согласовывать с ANSI описания структур COMM, DCB и COMSTAT. 
//ну и многое другое, не будем уже углубляться в эти программистские Debri.

#define WIN32_LEAN_AND_MEAN //Позволяет обоийти ошибки множественного объявления 
//стркутур при подключении заголовочных файлов уже имеющих эти структуры. 

#include "Form_Layer.h" //Объявляем здесь наш заголовочный Header-файл

////////////////////////////////////////////////////////////////////////////////
// External Definitions And Prototypes 
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WindowProcessing(HWND Hndl_Wnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow);

//-----------------------------------------------------------------------------
// Name: WindowProcessing()
// Desc: Здесь обрабатываются оконные сообщения
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProcessing(HWND Hndl_Wnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
  switch(Msg)
  {
    case WM_KEYDOWN:
    {
      if (wParam == VK_ESCAPE) //Перехватили нажатие кнопки Esc на клавиатуре
      {
        PostQuitMessage(0); break; //Обрабатываем
      }
    }
    break;

    case WM_CLOSE: //Перехватили момент закрытия окна при нажатии на крестике в углу экрана 
    {
      PostQuitMessage(0); //Обрабатываем
    }
        
    case WM_DESTROY: //Перехватили момент закрытия окна через трей или диспетчер задач Windows
    {
      PostQuitMessage(0); //Обрабатываем
    }
    break;

    default:
    {
      return DefWindowProc(Hndl_Wnd,Msg,wParam,lParam); //А иначе продолжаем обрабатывать сообщения
    }
    break;
  }
  return 0;

  //Вообще здесь можно обрабатывать любые оконные сообщения, по сути даже осуществить 
  //управление игровым персонажем, но мы будем использовать для этого DirectInput.
} //EndWindowProcessingFunction

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Эта функция предназначена для создания нашего окна
// Это является точкой входа для нашего приложения, иначе в процессе компиляции
// вернётся сообщение об ошибке: Entry point must be defined.
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
  WNDCLASSEX WindowClass; //Структура необходимая для регистрации оконного класса 
  MSG uMsg; //Оконные сообщения
  HWND Hndl_Wnd = NULL; //Дескриптор оконного класса

  int FormWidth = 640; //Ширина нашего окна 
  int FormHeight = 480; //Высота нашего окна
  LPCSTR FormCaption = "GreenRay Engine v3.0.0.2"; //Название выводимое в заголовке окна

  memset(&uMsg,0,sizeof(uMsg)); //Передача в структуру флага для оконных сообщений

  //Установка параметров окна, таких как цвет, иконка, стиль окна, курсор
  //и передача их структуре WNDCLASSEX
  WindowClass.lpszClassName = "MainWindow";
  WindowClass.cbSize        = sizeof(WNDCLASSEX);
  WindowClass.style         = CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
  WindowClass.lpfnWndProc   = WindowProcessing;
  WindowClass.hInstance     = hInstance;
  WindowClass.hIcon            = ::LoadIcon(0,IDI_APPLICATION);
  WindowClass.hIconSm        = ::LoadIcon(0,IDI_APPLICATION);
  WindowClass.hCursor       = LoadCursor(NULL,IDC_ARROW);
  WindowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  WindowClass.lpszMenuName  = NULL;
  WindowClass.cbClsExtra    = 0;
  WindowClass.cbWndExtra    = 0;

  //Регистрация класса окна
  if (!RegisterClassEx(&WindowClass)) return E_FAIL;

  //Теперь когда класс зарегистрирован можно создавать само окно
  Hndl_Wnd = CreateWindowEx(NULL,              //Window Style
                         "MainWindow",         //Window Class Name 
                         FormCaption,          //Caption Of The Window
                         WS_OVERLAPPEDWINDOW,  //Window Style Criterium
                         100,100,              //Left And Top Corner On Desktop
                         FormWidth,FormHeight, //Width And Height Of The Window
                         NULL,                 //Descriptor Of Parent Window
                         NULL,                 //Descriptor Of The Window Menu
                         hInstance,            //Descriptor Of Example Application
                         NULL);                //Pointer On Data Created Window

  //Если создание окна прошло неудачно, то функция вернёт ошибку
  if (Hndl_Wnd == NULL) return E_FAIL;

  ShowWindow(Hndl_Wnd,nCmdShow); //Иначе покажем
  UpdateWindow(Hndl_Wnd); //и обновим наше окно

  //Создаём наше Direct3D устройство и укажем Handle нашего окна куда будет в 
  //дальнейшем выводиться графика
  CreateDirect3D(Hndl_Wnd);

  //Здесь наше окно начинает интенсивно обрабатывать сообщения от Windows
  //"крутим" этот цикл пока не поступит комманда закрытия нашего окна
  while (uMsg.message != WM_QUIT)
  {
    if (PeekMessage(&uMsg,NULL,0,0,PM_REMOVE)) //Нддаа если возникает это событие, то
                                               //происходит уже явный перебор потока сообщений!
    {                                          //они начинают попросту удаляться из потока (данный манёвр 
                                               //позволяет немного разгрузить процессор)
      TranslateMessage(&uMsg); //Трансляция, перевод потока сообщений
      DispatchMessage(&uMsg); //Обслуживание потока сообщений
    } 
    //Всё ОК рендерим нашу сцену
    else RenderingDirect3D();
  }

  ReleaseDirect3D(); //Освобождение ресурсов и выгрузка Direct3D
 
  //Выгрузка оконного класса он выполнил своё предназначение ;-)
  UnregisterClass("MY_WINDOWS_CLASS",WindowClass.hInstance);
  return uMsg.wParam;
} //EndWinMainFunction



Тут же быстренько нажимаем на GR_Engine.h и вставляем это:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GREngine.h Visual Studio 8 Version.
// It's An GreenRay GR_Engine Header File.
/*****************************************************************************/
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

//Windows And System Directives
#include <windows.h>
#include <atlstr.h>   
#include <stdio.h>
#include <tchar.h>
#include <wchar.h>
#include <strsafe.h>

//Direct3D Directives
#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9core.h>
#include <d3dx9mesh.h>
#include <dinput.h>

////////////////////////////////////////////////////////////////////////////////
// External Definitions And Prototypes 
////////////////////////////////////////////////////////////////////////////////
HRESULT CreateDirect3D(HWND Hndl_Wnd);
void RenderingDirect3D();
void ReleaseDirect3D();



Это сообщение отредактировал(а) php - 5.9.2014, 07:07
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
php
Дата 10.2.2009, 14:29 (ссылка)   | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Теперь снова нажимаем на GR_Engine.cpp и вставляем следующий код:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GREngine.cpp Visual Studio 8 Version.
// It's An GreenRay GREngine Source File.
// Made Specially For Implement 3D Engine Parameters.
/*****************************************************************************/
//#pragma comment(lib,"d3d9.lib");
//#pragma comment(lib,"d3dx9.lib");
#include <GR_Engine.h>

////////////////////////////////////////////////////////////////////////////////
// Global Variables 
////////////////////////////////////////////////////////////////////////////////
IDirect3DDevice9* m_pDevice = NULL; //The Direct3D Device Interface

//-----------------------------------------------------------------------------
// Name: CreateDirect3D()
// Desc: Эта функция создаёт основное Direct3D устройство
//-----------------------------------------------------------------------------
HRESULT CreateDirect3D(HWND Hndl_Wnd)
{
  HRESULT m_pResult = S_OK; //Set Result By Default
  IDirect3D9* m_pDirect3D = NULL; //This General Direct3D Initialization Interface

  //Создаём объект Direct3D
  m_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);

  //Проверяем, если возникнет ошибка то освобождаем D3D интерфейс
  if (!m_pDirect3D)
  {
    if (m_pDirect3D != NULL) m_pDirect3D->Release();
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

  //Автоматическая проверка параметров поддерживаемых дисплеем
  //далее полученные параметры помещаются в стркутуру m_pDisplay
  D3DDISPLAYMODE m_pDisplay; 
  if (FAILED(m_pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&m_pDisplay)))
  {
    if (m_pDirect3D != NULL) m_pDirect3D->Release();
    MessageBoxA(NULL,"GR_Engine.cpp: Failed Get Adapter Display Mode..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

  //All System Checks Passed, Create The Direct3D Device
  D3DPRESENT_PARAMETERS m_pD3DParam;
  memset(&m_pD3DParam,0,sizeof(m_pD3DParam));

  //Установка параметров и режимов работы Direct3D устройства 
  m_pD3DParam.SwapEffect                 = D3DSWAPEFFECT_DISCARD; //D3DSWAPEFFECT_COPY;
  
  //Установка разрешения
  m_pD3DParam.BackBufferWidth            = 640; 
  m_pD3DParam.BackBufferHeight           = 480;
  //Здесь указывается режим работы устройства в полный экран (FALSE) или в окне (TRUE)
  //угадайте в каком режиме будет у нас :-))
  m_pD3DParam.Windowed                   = TRUE;

  //Формат заднего буфера, обычно определяется автоматически (m_pDisplay.Format), 
  //но можно указать и вручную в зависимости от поставленных целей
  m_pD3DParam.BackBufferFormat           = m_pDisplay.Format; //D3DFMT_A8R8G8B8 

  //Данный параметр необходимо раскомментировать лишь в том случае, если наше 
  //приложение будет работать на полный экран (здесь как правило указывается 
  //частота развёртки монитора) крайне не советую "играться" с этим параметром, 
  //пусть уж частота определится автоматически (m_pDisplay.RefreshRate)
  //m_pD3DParam.FullScreen_RefreshRateInHz = m_pDisplay.RefreshRate; //D3DPRESENT_RATE_DEFAULT; 
  
  //Включение "стенсельного" буфера, в основном предназначен в дальнейшем для отрисовки
  //эффектов теней и зеркал, короче повторяет очертания исходного объекта
  m_pD3DParam.EnableAutoDepthStencil     = TRUE;

  //Здесь уже указывается формат "стенсельного" буфера
  m_pD3DParam.AutoDepthStencilFormat     = D3DFMT_D16; //D3DFMT_D16 D3DFMT_D15S1 D3DFMT_D24X8
                                                       //D3DFMT_D24S8 D3DFMT_D24X4S4 D3DFMT_D32
  
  //Количество задних буферов
  m_pD3DParam.BackBufferCount            = 2;

  //Кол-во степеней сглаживания для антиалиасинга
  m_pD3DParam.MultiSampleType            = D3DMULTISAMPLE_4_SAMPLES; //4_SAMPLES //For Antialiasing Mode On 4x
  
  //Качество сглаживания
  //m_pD3DParam.MultiSampleQuality       = 1;
  
  //Буфер глубины обычно активируется для создания эффекта Shadow Volume "тень" 
  //m_pD3DParam.Flags                    = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; //|D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  
  //Интервал представления отображаемых объектов и игровой сцены
  m_pD3DParam.PresentationInterval       = D3DPRESENT_INTERVAL_ONE;

  //Если раскомментировать этот параметр, то ощутится явный прирост fps и вообще
  //сцена начнёт отображаться существенно быстрее, т.е помимо видеокарты в процессе 
  //рендеринга начнёт участвовать ваш центральный процессор и загрузит его на 100%
  //Данный параметр использовать не рекомендуется, система работает на износ..
  //Да и вообще процессорное время лучше поберечь для других нужд, 
  //хотя-бы на обработку физики игры..
  //m_pD3DParam.PresentationInterval     = D3DPRESENT_INTERVAL_IMMEDIATE;

  //Создание Direct3D устройства, "скармливаем" ранее установленные параметры нашему устройству
  //Также указываем Handle (Hndl_Wnd) нашего ранее созданного окна, то бишь полотна куда будет выводиться графика 
  if (FAILED(m_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,Hndl_Wnd,
  D3DCREATE_HARDWARE_VERTEXPROCESSING,&m_pD3DParam,&m_pDevice)))
  {
    //Ошибка создания Direct3D устройства освобождаем его
    if (m_pDirect3D != NULL) m_pDirect3D->Release();    
    //Вообще если возникает подобная ошибка, значит мы "скормили" нашему устройству 
    //неверные или не поддерживаемые видеокартой параметры, попробуйте "поиграться" с другими 
    //значениями выставляемые в параметрах, а может вы забыли поставить "дрова" на видеокарту?? :-))))
    MessageBoxA(NULL,"GR_Engine.cpp: Error Creating Direct3D Device..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

  //Ending Direct3D Presets Parameters
  if (m_pDevice != NULL)
  {
    //Установка режимов рендера:
    //Весьма интересный и нужный режим состояния рендера
    //при этом режиме происходит "отсечение" невидимых взору граней (полигонов), т.е
    //граней находящихся с задней стороны модели или 3D объекта, они попросту не ренерятся
    //и не отображаюся, это позволяет очень сильно разгрузить работу нашей видеокарты и всей
    //системы в целом.
    //Режим D3DCULL_CW - устанавливает отсечение невидимый граней
    //Режим D3DCULL_CСW - устанавливает тоже отсечение только уже видимых граней (инверсия)
    //Режим D3DCULL_NONE - отключает оба этих режима рендерится вся модель как есть даже 
    //её внутренние части, это уже слишком тяжело для видеокарты, сразу же ощущается падение fps
    //после установки этого режима.
    m_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);
    
    //Включаем буфер глубины или Z-Buffer, или эффект отдаления объектов или моделей
    //"вглубь" экрана, да уж совсем образно объяснил..
    m_pDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);

    //Режим освещения, нам он пока не нужен, поэтому FALSE
    m_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE); 
   
    //Режим рендера отображающий полигоны не цельными SOLID, а в режиме сетки WIREFRAME
    //m_pDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
    
    //Установка цвета амбиентного (общего) освещения
    //m_pDevice->SetRenderState(D3DRS_AMBIENT,0xFFFFFFFF);
    
    //Данная установка включает режим работы антиалиасинга (прменения эффекта сглаживания 
    //рёбер или неровности краёв полигона называется антиалиасингом), нам пока не нужен 
    //поэтому закомментирован
    //m_pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,TRUE);
    
    //Установка режима закраски по Гуро, обычно она устанавливается по умолчанию 
    //(закраска по Гуро обычно нужна для сглаживания одутлых или круглых поверхностей,
    //например чтобы шар походил на шар, а не на ребристый комок)
    //m_pDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);
  }

  if (m_pDirect3D != NULL) m_pDirect3D->Release(); //Освобождаем Direct3D интерфейс он 
  //выполнил своё предназначение
  return m_pResult; //В конце возвращаем результат работы функции
} //EndCreateDirect3DFunction

//Примечание! Я всё время везде употребляю слово "рендер", а что же это такое
//спросите вы, да всё очень просто Рендер - это отображение, отрисовка если хотите 
//вашего объекта или игровой сцены на экране, или конечный результат обработки данных,
//расчета освещения и.др и последующий вывод на экран монитора, еще иногда 
//употребляют слово "рендерится".

//-----------------------------------------------------------------------------
// Name: RenderingDirect3D()
// Desc: Здесь в этой процедуре происходит отрисовка нашей игровой сцены
//-----------------------------------------------------------------------------
void RenderingDirect3D()
{   
  if (m_pDevice != NULL) 
  {
    //Здесь идёт очистка заднего и Z-буфера соответственно..
    m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET/*|D3DCLEAR_STENCIL*/,D3DCOLOR_XRGB(0,0,0),1.0f,0);
    
    //Begin Scene
    if (SUCCEEDED(m_pDevice->BeginScene()))
    {

      //Здесь и происходит отрисовка нашей конечной сцены
      //начиная от отрисовки моделей, освещения, и заканчивая шейдерными эффектами.
      //Иными словами рендеринг игровой сцены...
      //Vitia_Bubuka->Draw();

      m_pDevice->EndScene();
    }
    m_pDevice->Present(NULL,NULL,NULL,NULL);
  }
} //EndRenderingDirect3DProcedure

//-----------------------------------------------------------------------------
// Name: ReleaseDirect3D()
// Desc: Освобождение ресурсов и устройства Direct3D
//-----------------------------------------------------------------------------
void ReleaseDirect3D()
{
  if (m_pDevice != NULL) m_pDevice->Release();
} //EndReleaseDirect3DProcedure

//------------------------------------------------------------------------------



Не забываем сохраниться, затем компилируем наш проект, в итоге должно появиться уже не белое как ранее, а чёрное окно как на рисунке:

user posted image

Это говорит, что наше Direct3D устройство нормально создалось и инициализировалось,
Так как происходит очистка заднего буфера, то экран становится чёрным, в принципе можно "поиграться" с цветом заднего буфера, его цвет задаётся в строке:

Код

m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET/*|D3DCLEAR_STENCIL*/,D3DCOLOR_XRGB(0,0,0),1.0f,0);


В параметре: D3DCOLOR_XRGB(0,0,0) – это RGB палитра, так, что к примеру выставление параметра D3DCOLOR_XRGB(255,0,0) приведёт к заливке экрана красным цветом, величина 255 это интенсивность цвета и лежит в пределах от 0..255.

Всё! заготовка ("болванка" так сказать) нашего игрового движка полностью готова, на её основе можно полноценно дальше создавать игру, добавляя все новые и новые возможности.

В последующих частях мы продолжим разбирать движок GRE, "прикрутим" к нему игровую камеру, загрузим высокополигональную модель, добавим освещение и SkyBox. 

Продолжение следует..
_________________________________________________________________________
© Digital Dreams Development Inc., 2009 
(С) GR-Engine Technical Documentation.
Любая публикация изложенного материала только с разрешения автора.

Это сообщение отредактировал(а) php - 5.9.2014, 07:11
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
net968
Дата 13.2.2009, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 13.2.2009

Репутация: нет
Всего: нет



жду с нетерпением продолжения.Респект тебе smile 
PM MAIL   Вверх
LVI
Дата 25.3.2009, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 25.3.2009

Репутация: нет
Всего: нет



В последней версии Microsoft DirectX SDK нет библиотнки "dinput.lib" осталась только "dinput8.lib",
поэтому для нормальной компиляции ее нужно убрать из списка добавляемых библиотек.
PM MAIL   Вверх
php
Дата 26.3.2009, 07:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Ок спасибо за поправку!
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
pirat77
  Дата 12.4.2009, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 10.11.2008

Репутация: нет
Всего: нет



Спасибо за урок smile ,с нетерпением жду продолжения. smile 
PM MAIL   Вверх
ISergeyN
Дата 14.4.2009, 02:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Цитата(php @  10.2.2009,  14:11 Найти цитируемый пост)
для тех кто ещё не умеет программировать, но уже хочет быстро начать "делать свою игру" 

Ну c этим я сомневаюсь. 

PS. ИМХО ваш код уж больно перегружен комментариями. 

Это сообщение отредактировал(а) ISergeyN - 14.4.2009, 02:41
PM MAIL Skype   Вверх
Rickert
Дата 14.4.2009, 07:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: 6
Всего: 52



php, молоток, неплохо расписал smile 


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
Master Lucky
Дата 22.4.2009, 05:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 22.1.2008
Где: Торонто, Канада

Репутация: нет
Всего: нет



Макс, клёва, продолжай в том же духе! Такими темпами скоро мы с тобой уже и игрушку свою забабахаем!  smile

Добавлено через 3 минуты
Цитата

PS. ИМХО ваш код уж больно перегружен комментариями. 


А ты попробуй без комментов в коде разобраться......
PM MAIL   Вверх
Rickert
Дата 22.4.2009, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: 6
Всего: 52



Цитата(Master Lucky @  22.4.2009,  05:37 Найти цитируемый пост)
А ты попробуй без комментов в коде разобраться...... 

Каждый день smile 


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
ISergeyN
Дата 22.4.2009, 11:02 (ссылка)   | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Вот это странный код
Код

  if (m_pDirect3D==NULL)//if (!m_pDirect3D)
  {
    if (m_pDirect3D != NULL) //это зачем ? эсли словие ни когда не сработает!
             m_pDirect3D->Release(); //
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

PM MAIL Skype   Вверх
php
Дата 22.4.2009, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Цитата:

Вот это странный код

код C++ 
1:
2:
3:
4:
5:
6:
7:
8:

   if (m_pDirect3D==NULL)//if (!m_pDirect3D)
  {
    if (m_pDirect3D != NULL) //это зачем ? эсли словие ни когда не сработает!
             m_pDirect3D->Release(); //
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  } 
 
 

smile Вот вы уже и запутались, а ведь это самые азы и вы хотите сказать, что потом в состоянии разобраться? 

ISergeyN  Вы пред тем что до этого идет хоть удосужились прочитать?

Добавлено через 13 минут и 52 секунды
Master Lucky, да я соббсно могу код вообще без комментариев выкладывать мне же легче будет, но смысл тогда всего этого и этой затеи вообще?, так что ваше замечание абсолютно верно - поддерживаю!
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
ISergeyN
Дата 22.4.2009, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Цитата

 Вот вы уже и запутались, а ведь это самые азы и вы хотите сказать, что потом в состоянии разобраться? 

Та вроде нет.
Код

m_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);

//Проверяем, если возникнет ошибка то освобождаем D3D интерфейс
//то есть функция Direct3DCreate9(D3D_SDK_VERSION) вернула не указатель
//а NULL
if (!m_pDirect3D)//здесь проверяем
{
//эли условие сработало то m_pDirect3D не был создан

//потом вы проверяете если m_pDirect3D был каким то чудом создан
//то освободить память (но условие if (!m_pDirect3D) то сработало значит он НЕ создан)
    if (m_pDirect3D != NULL) m_pDirect3D->Release();//<-
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
//здесь было бы логично вообще выйти из функции HRESULT CreateDirect3D(HWND Hndl_Wnd)
// return E_FAIL;
//и не мучать остальной код(все равно одни ошибки будут)
}

PM MAIL Skype   Вверх
php
Дата 22.4.2009, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



А вы уверены, что в результате ошибки функция Direct3DCreate9(D3D_SDK_VERSION) вернёт 
значение NULL я лично не уверен!
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
ISergeyN
Дата 22.4.2009, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Цитата(php @  22.4.2009,  13:50 Найти цитируемый пост)
А вы уверены, что в результате ошибки функция Direct3DCreate9(D3D_SDK_VERSION) вернёт значение NULL я лично не уверен!

Уверен. В справке по DirectX 
Цитата

Return Values
If successful, this function returns a pointer to an IDirect3D9 interface; otherwise, a NULL pointer is returned.


Код

//Create an IDirect3D9 object as shown here:
LPDIRECT3D9 g_pD3D = NULL;
    
if( NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
    return E_FAIL;


PM MAIL Skype   Вверх
Master Lucky
Дата 22.4.2009, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 22.1.2008
Где: Торонто, Канада

Репутация: нет
Всего: нет



Цитата(Rickert @  22.4.2009,  05:14 Найти цитируемый пост)
Каждый день smile


Ну, я имел ввиду новичков. Вы, как я посмотрю, человек опытный, поэтому для вас это намного легче  smile 

PM MAIL   Вверх
Rickert
Дата 23.4.2009, 02:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: 6
Всего: 52



Цитата
"And remember, kids: the higher your postcount - the bigger your penis is"



--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
php
Дата 23.4.2009, 04:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Вообще в принципе ошибки на данном участке кода могут возникать довольно редко,
я по крайней мере на своей практике их не встречал, разве что из-за неправильно установленного или используемго SDK (версии SDK), мы ведь там просто указываем программе
какую версию DX мы хотим использовать, в принципе этот интерфейс нам больше и не нужен,
это всё так скать начально заготовочная "мишура" нужна лишь к подготовке к созданию нашего основного Direct3D устройства, вот там уже на этапе создания этого устройства согласен могут возникнуть уже серьёзные ошибки и отлавливать их нужно уже более внимательно, может там у меня в коде не всё гладко и чисто как хотелось бы, нужно бы подредактировать сделать более серьёзную обработку ошибок, замечания и предложения естественно принимаются!..  smile 

Теперь разберём этот искомый участок кода:
Я постараюсь просто объяснить подробнее почему я так сделал и в коде присутствует именно такая запись:

Код

 if (m_pDirect3D != NULL) m_pDirect3D->Release();//<-


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

Итак, что у нас сначала происходит заведомо обнуляем интерфейс:

Код

   IDirect3D9* m_pDirect3D = NULL; 


Затем указываем данному интерфейсу какую версию DX SDK мы хотим использовать здесь:

Код

  m_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);


Создался там этот интерфейс или не создался нам глубоко "не важно"

Здесь мы выводим причину чисто для отладки:
Код

    if (m_pDirect3D != NULL) m_pDirect3D->Release();//<-
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL; 


Здесь читаем медленно вдумавшись:  smile 
ЕСЛИ интерфейс не создан то он вернёт значение NULL, но вот здесь проверяем:
Код

 if (m_pDirect3D != NULL) m_pDirect3D->Release();//<-


ЕСЛИ ВДРУГ (не исключаем такую ситуацию) всё таки интерфейс был создан и вернул не NULL, то предварительно очищаем его, и  какой тогда сымысл если он вернул NULL его опять освобождать если он изначально был NULL, т.е освобождать освобождённое - это может уже привести даже к ошибкам в системе типа Access Violation и даже возникновению "синего экрана" (хотя это вряд-ли  smile )

В конце мы этот интерфейс вообще "выкидываем" за ненадобностью, т.к нужную версию SDK мы
определили и установили:

Код

  ....
  //m_pDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);
  }

  if (m_pDirect3D != NULL) m_pDirect3D->Release(); //Освобождаем Direct3D интерфейс он 
  //выполнил своё предназначение
  ...


Так, что с точки зрения логики самой программы эта запись верна, и вообще честно говоря не вижу смысла здесь, что либо менять или переделывать, другое дело на этапе создания уже самого устройства там надо бы подлатать код, "грязновато" оформлен я бы сказал!

Это хорошо, что вы обратили внимание, я рад был разъяснить - обсуждение движка идёт полным ходом - это радует! Так, что спрашивайте или указывайте на ошибки всё будем разбирать вместе на то и делается уклон! Кстати скоро появится вторая часть статьи..

А комментарии мне пожалуй делать всё таки придётся, т.к здесь этот участок кода видимо остался без внимания и плоховато задокументирован и возникли небольшие вопросы..

Нда целая диссертация опять получилась, никак у меня не получается короче!  smile 

Это сообщение отредактировал(а) php - 23.4.2009, 04:28
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
ISergeyN
Дата 23.4.2009, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Ну с этим ладно. Но всёже прийдется немного доработать обработку ошибок.
Цитата(php @  23.4.2009,  04:26 Найти цитируемый пост)
Кстати скоро появится вторая часть статьи..

Будем ждать.
PM MAIL Skype   Вверх
php
Дата 6.7.2009, 06:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Часть 2. Программирование игрового движка (Продолжение..)

Вступление.

Итак продолжим разработку игрового движка, сорри за столь длительный перерыв,
было много дел..

В данных разделах мы рассмотрим, как осуществляется привязка камеры к движку,
также начнём работу с текстурированием и моделированием простейших объектов - 
создадим SkyBox, понятие SkyBox разбиралось в предыдущей статье так, что можно прочитать, что это такое и для чего это нужно именно там. 

Рассматривать и разбирать как делаются всякие детские вращающиеся кубики мы не будем, а займёмся серьёзными "игровыми" вещами.. мы же с вами делаем игру, а не рекламный ролик smile))

2.2. Привязка камеры к проекту.
В данном разделе статьи мы рассмотрим как привязать "камеру" к нашему проекту.
Как уже описывалось ранее сама камера будет реализована на DirectInput.

Для этого выполним следующие действия:

1) Для начала создадим новый файл под названием GR_Camera.cpp:
Для этого в "дереве" нашего проекта выбираем Source Files и нажимаем на нём правой кнопкой мыши, далее из выпадающего меню выбираем Add->New Item.. В общем делаем всё по аналогии как описано в пункте 2.1. предыдущей статьи, только не забудьте этот созданный модуль сохранить в папку Engine_Modules (или как она у вас там теперь называется?? smile)).

2) Также необходимо создать файл GR_Camera.h:
Для этого также в "дереве" проекта выбираем Header Files, и не забываем сохранить этот файл также в папке Engine_Modules.

Всё мы создали заготовки файлов GR_Camera.h и GR_Camera.cpp (пара - заголовочный .h и .cpp файлы). Начинаем программирование..

2.3. Подключение и инициализация устройства ввода DirectInput.
Для начала прежде чем работать с "камерой" в движке мы должны подготовить и инициализировать устройство ввода, т.е. иными словами подключить возможность управления объектами или вращением объектов используя клавиатуру или мышь, будь то просто управление "взглядом" камеры дающее возможность непосредственно
оглядываться да и просто смотреть по сторонам, или обработка нажатия кнопок мыши или клавиатуры для реализации "выстрелов" из оружия к примеру... Всё это мы будем делать и разбирать в дальнейшем.

Поток данных поступаемых от клавиатуры или мыши обрабатывается непрерывно в следствие чего возможна обработка одновременного нажатия нескольких кнопок на клавиатуре, мыши, тут же одновременного вращения и обзора мышью по сторонам, чем и был обусловлен переход GRE на DirectInput.

1) Для начала необходимо выбрать из "дерева" нашего проекта GR_Engine.h сделав на нём двойной щелчок мыши, 
стереть полностью его содержимое и заменить на это:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_Engine.h Visual Studio 8 Version.
// It's An GreenRay GREngine Header File.
// Made Specially For Implement 3D Engine Parameters.
/*****************************************************************************/
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

//Windows And System Directives
#include <windows.h>
#include <atlstr.h>   
#include <stdio.h>
#include <tchar.h>
#include <wchar.h>
#include <strsafe.h>

//Direct3D Directives
#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9core.h>
#include <d3dx9mesh.h>
#include <dinput.h>

//Sound System Directives
#include <mmsystem.h>
#include <dshow.h>
#include <dsound.h>
#include <dmusici.h>

////////////////////////////////////////////////////////////////////////////////
// External Definitions And Prototypes 
////////////////////////////////////////////////////////////////////////////////
HRESULT CreateDirect3D(HWND Hndl_Wnd);
void RenderingDirect3D();
void ReleaseDirect3D();

////////////////////////////////////////////////////////////////////////////////
// Global Variables
////////////////////////////////////////////////////////////////////////////////
extern HWND FormL_HWnd; //Global Form Layer HWnd Handle



Теперь разберём следующий участок кода:

Код

...
void ReleaseDirect3D();

////////////////////////////////////////////////////////////////////////////////
// Global Variables
////////////////////////////////////////////////////////////////////////////////
extern HWND FormL_HWnd; //Хендл нашего ранее созданного игрового полотна
...



Здесь в участке кода мы объявляем глобальную переменную FormL_HWnd которая будет хранить в себе значение или Handle нашего ранее созданного окна для вывода графики (обычно все окна в  системе Windows имеют свой уникальный номер (даже скрытые и невидимые) для того, чтобы ось (операционная система) могла определить различные привязки, вызовы, какие окна запущены и работают, и просто знать к какому конкретному окну происходит обращение, и обратиться к нему можно по 
этому уникальному номеру который и будет "передан" и присвоен этой нашей переменной).  В принципе, получив нужный Handle окна можно делать с ним практически, что угодно - менять заголовки,  надписи в самой форме этого окна, получать его изображение, но это мы пожалуй разбирать здесь  уже не будем, так как это уже выходит за рамки документации GRE.. 

2) Теперь из "дерева" проекта выбираем GR_Engine.cpp - делаем также на нём двойной щелчок мыши, стираем полностью его содержимое и меняем на это:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_Engine.cpp Visual Studio 8 Version.
// It's An GreenRay GREngine Source File.
// Made Specially For Implement 3D Engine Parameters.
/*****************************************************************************/
//#pragma comment(lib,"d3d9.lib");
//#pragma comment(lib,"d3dx9.lib");
#include <GR_Engine.h>
#include <GR_Methods.h>
#include <GR_Camera.h>
#include <GR_SkyBox.h>

////////////////////////////////////////////////////////////////////////////////
// Global Variables 
////////////////////////////////////////////////////////////////////////////////
IDirect3DDevice9* m_pDevice = NULL; //The Direct3D Device Interface
HWND FormL_HWnd; //Form Layer Handle

CGRDeltaTimer* gr_Timer = NULL; //GreenRay Delta Timer Interface Class
CGRCamera* gr_Camera = NULL; //GreenRay Camera Global Interface Class
CGRSkyBox* gr_SkyBox = NULL; //GreenRay SkyBox Global Interface Class

//-----------------------------------------------------------------------------
// Name: CreateDirect3D()
// Desc: Эта функция создаёт основное Direct3D устройство
//-----------------------------------------------------------------------------
HRESULT CreateDirect3D(HWND Hndl_Wnd)
{
  HRESULT m_pResult = S_OK; //Set Result By Default
  IDirect3D9* m_pDirect3D = NULL; //This General Direct3D Initialization Interface

  //Создаём объект Direct3D
  m_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);

  //Проверяем, если возникнет ошибка то освобождаем D3D интерфейс
  if (!m_pDirect3D)
  {
    if (m_pDirect3D != NULL) m_pDirect3D->Release();
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

  //Автоматическая проверка параметров поддерживаемых дисплеем
  //далее полученные параметры помещаются в стркутуру m_pDisplay
  D3DDISPLAYMODE m_pDisplay; 
  if (FAILED(m_pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&m_pDisplay)))
  {
    if (m_pDirect3D != NULL) m_pDirect3D->Release();
    MessageBoxA(NULL,"GR_Engine.cpp: Failed Get Adapter Display Mode..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

  //All System Checks Passed, Create The Direct3D Device
  D3DPRESENT_PARAMETERS m_pD3DParam;
  memset(&m_pD3DParam,0,sizeof(m_pD3DParam));

  //Установка параметров и режимов работы Direct3D устройства 
  m_pD3DParam.SwapEffect                 = D3DSWAPEFFECT_DISCARD; //D3DSWAPEFFECT_COPY;
  
  //Установка разрешения
  m_pD3DParam.BackBufferWidth            = 640; 
  m_pD3DParam.BackBufferHeight           = 480;
  //Здесь указывается режим работы устройства в полный экран (FALSE) или в окне (TRUE)
  //угадайте в каком режиме будет у нас :-))
  m_pD3DParam.Windowed                   = TRUE;

  //Формат заднего буфера, обычно определяется автоматически (m_pDisplay.Format), 
  //но можно указать и вручную в зависимости от поставленных целей
  m_pD3DParam.BackBufferFormat           = m_pDisplay.Format; //D3DFMT_A8R8G8B8 

  //Данный параметр необходимо раскомментировать лишь в том случае, если наше 
  //приложение будет работать на полный экран (здесь как правило указывается 
  //частота развёртки монитора) крайне не советую "играться" с этим параметром, 
  //пусть уж частота определится автоматически (m_pDisplay.RefreshRate)
  //m_pD3DParam.FullScreen_RefreshRateInHz = m_pDisplay.RefreshRate; //D3DPRESENT_RATE_DEFAULT; 
  
  //Включение "стенсельного" буфера, в основном предназначен в дальнейшем для отрисовки
  //эффектов теней и зеркал, короче повторяет очертания исходного объекта
  m_pD3DParam.EnableAutoDepthStencil     = TRUE;

  //Здесь уже указывается формат "стенсельного" буфера
  m_pD3DParam.AutoDepthStencilFormat     = D3DFMT_D16; //D3DFMT_D16 D3DFMT_D15S1 D3DFMT_D24X8
                                                       //D3DFMT_D24S8 D3DFMT_D24X4S4 D3DFMT_D32
  
  //Количество задних буферов
  m_pD3DParam.BackBufferCount            = 2;

  //Кол-во степеней сглаживания для антиалиасинга
  m_pD3DParam.MultiSampleType            = D3DMULTISAMPLE_4_SAMPLES; //4_SAMPLES //For Antialiasing Mode On 4x
  
  //Качество сглаживания
  //m_pD3DParam.MultiSampleQuality       = 1;
  
  //Буфер глубины обычно активируется для создания эффекта Shadow Volume "тень" 
  //m_pD3DParam.Flags                    = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; //|D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  
  //Интервал представления отображаемых объектов и игровой сцены
  m_pD3DParam.PresentationInterval       = D3DPRESENT_INTERVAL_ONE;

  //Если раскомментировать этот параметр, то ощутится явный прирост fps и вообще
  //сцена начнёт отображаться существенно быстрее, т.е помимо видеокарты в процессе 
  //рендеринга начнёт участвовать ваш центральный процессор и загрузит его на 100%
  //Данный параметр использовать не рекомендуется, система работает на износ..
  //Да и вообще процессорное время лучше поберечь для других нужд, 
  //хотя-бы на обработку физики игры..
  //m_pD3DParam.PresentationInterval     = D3DPRESENT_INTERVAL_IMMEDIATE;

  FormL_HWnd = Hndl_Wnd; //Set Layer Window Handle

  //Создание Direct3D устройства, "скармливаем" ранее установленные параметры нашему устройству
  //Также указываем Handle (Hndl_Wnd) нашего ранее созданного окна, то бишь полотна куда будет выводиться графика 
  if (FAILED(m_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,Hndl_Wnd,
  D3DCREATE_HARDWARE_VERTEXPROCESSING,&m_pD3DParam,&m_pDevice)))
  {
    //Ошибка создания Direct3D устройства освобождаем его
    if (m_pDirect3D != NULL) m_pDirect3D->Release();    
    //Вообще если возникает подобная ошибка, значит мы "скормили" нашему устройству 
    //неверные или не поддерживаемые видеокартой параметры, попробуйте "поиграться" с другими 
    //значениями выставляемые в параметрах, а может вы забыли поставить "дрова" на видеокарту?? :-))))
    MessageBoxA(NULL,"GR_Engine.cpp: Error Creating Direct3D Device..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

  //Ending Direct3D Presets Parameters
  if (m_pDevice != NULL)
  {
    //Установка режимов рендера:
    //Весьма интересный и нужный режим состояния рендера
    //при этом режиме происходит "отсечение" невидимых взору граней (полигонов), т.е
    //граней находящихся с задней стороны модели или 3D объекта, они попросту не ренерятся
    //и не отображаюся, это позволяет очень сильно разгрузить работу нашей видеокарты и всей
    //системы в целом.
    //Режим D3DCULL_CW - устанавливает отсечение невидимый граней
    //Режим D3DCULL_CСW - устанавливает тоже отсечение только уже видимых граней (инверсия)
    //Режим D3DCULL_NONE - отключает оба этих режима рендерится вся модель как есть даже 
    //её внутренние части, это уже слишком тяжело для видеокарты, сразу же ощущается падение fps
    //после установки этого режима.
    m_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);
    
    //Включаем буфер глубины или Z-Buffer, или эффект отдаления объектов или моделей
    //"вглубь" экрана, да уж совсем образно объяснил..
    m_pDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);

    //Режим освещения, нам он пока не нужен, поэтому FALSE
    m_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE); 
   
    //Режим рендера отображающий полигоны не цельными SOLID, а в режиме сетки WIREFRAME
    //m_pDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
    
    //Установка цвета амбиентного (общего) освещения
    //m_pDevice->SetRenderState(D3DRS_AMBIENT,0xFFFFFFFF);
    
    //Данная установка включает режим работы антиалиасинга (прменения эффекта сглаживания 
    //рёбер или неровности краёв полигона называется антиалиасингом), нам пока не нужен 
    //поэтому закомментирован
    //m_pDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,TRUE);
    
    //Установка режима закраски по Гуро, обычно она устанавливается по умолчанию 
    //(закраска по Гуро обычно нужна для сглаживания одутлых или круглых поверхностей,
    //например чтобы шар походил на шар, а не на ребристый комок)
    //m_pDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);



    //Cоздаём класс таймера.
    gr_Timer = new CGRDeltaTimer(); //Construct A CGRDeltaTimer Class

    //Cоздаём класс камеры
    gr_Camera = new CGRCamera(m_pDevice); //Construct A CGRCamera Class
    gr_Camera->SetCameraPos(D3DXVECTOR3(5.0f,50.78f,5.0f)); //Set Player Camera Position In Space
    gr_Camera->SetCameraSpeed(40.0f); //Set Player Camera Speed
    gr_Camera->SetMouseSpeed(0.3f); //Set Mouse Speed

    //Create SkyBox Class
    gr_SkyBox = new CGRSkyBox(m_pDevice); //Construct A CGRSkyBox Class  
    gr_SkyBox->CreateBox(100.0f,100.0f,100.0f); //Create Our SkyBox Model With Size WHD
    gr_SkyBox->SetTextures(TEXT("\Textures\\SkyBox\\Arch\\zneg.png"),
                           TEXT("\Textures\\SkyBox\\Arch\\xneg.png"),
                           TEXT("\Textures\\SkyBox\\Arch\\zpos.png"),
                           TEXT("\Textures\\SkyBox\\Arch\\xpos.png"),
                           TEXT("\Textures\\SkyBox\\Arch\\yneg.png"),
                           TEXT("\Textures\\SkyBox\\Arch\\ypos.png"));
  } //End if (m_pDevice != NULL)

  if (m_pDirect3D != NULL) m_pDirect3D->Release(); //Освобождаем Direct3D интерфейс он 
  //выполнил своё предназначение
  return m_pResult; //В конце возвращаем результат работы функции
} //EndCreateDirect3DFunction

//-----------------------------------------------------------------------------
// Name: RenderingDirect3D()
// Desc: Здесь в этой процедуре происходит отрисовка нашей игровой сцены
//-----------------------------------------------------------------------------
void RenderingDirect3D()
{   
  if (m_pDevice != NULL) 
  {
    if (gr_Timer != NULL) gr_Timer->UpdateTimer(); //Update GreenRay Timer Every Frame
    //Обновление и получение данных с камеры, 
    //код процедуры находится в модуле GR_Camera.cpp
    if (gr_Camera != NULL) gr_Camera->UpdateCamera(); //Update GreenRay Camera 

    //Здесь идёт очистка заднего и Z-буфера соответственно..
    m_pDevice->Clear(0,NULL,D3DCLEAR_TARGET/*|D3DCLEAR_STENCIL*/,
    D3DCOLOR_XRGB(0,0,0),1.0f,0);
    
    //Begin Scene
    if (SUCCEEDED(m_pDevice->BeginScene()))
    {
      //Рендерим SkyBox
      if (gr_SkyBox != NULL) gr_SkyBox->Render(); //Render The SkyBox ! 

      m_pDevice->EndScene();
    }
    m_pDevice->Present(NULL,NULL,NULL,NULL);
  }
} //EndRenderingDirect3DProcedure

//-----------------------------------------------------------------------------
// Name: ReleaseDirect3D()
// Desc: Освобождение ресурсов и устройства Direct3D
//-----------------------------------------------------------------------------
void ReleaseDirect3D()
{
  if (gr_Camera != NULL) { /*gr_Camera->Release();*/ ReleaseClass(gr_Camera); DeleteClass(gr_Camera); } //Free Camera Class 
  if (gr_SkyBox != NULL) { gr_SkyBox->Release(); ReleaseClass(gr_SkyBox); DeleteClass(gr_SkyBox); } //Free SkyBox Class
  
  if (m_pDevice != NULL) m_pDevice->Release();
} //EndReleaseDirect3DProcedure

//------------------------------------------------------------------------------



3) Теперь займемся программированием самой DirectInput "камеры" и DI-устройства,
для этого вернемся к ранее созданному модулю GR_Camera.h выделив и сделав на нем двойной щелчок мыши в  "дереве" проекта и заполним его следующим кодом:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_Camera.h
// It's An GreenRay GR_Camera Header File.
/*****************************************************************************/
#pragma once
#include <GR_Engine.h>
#include <GR_Methods.h>

////////////////////////////////////////////////////////////////////////////////
// Classes Used By This Header
////////////////////////////////////////////////////////////////////////////////
//class CGRCamera;

//-----------------------------------------------------------------------------
// Name: Struct CGRCamera
// Desc: 
//-----------------------------------------------------------------------------
#if !defined(AFX_CAMERA_H__)
#define AFX_CAMERA_H__
class CGRCamera
{    
public:
  /*Public Directives*/
  CGRCamera(LPDIRECT3DDEVICE9 pDevice);
  virtual ~CGRCamera();
  void Release();
  
  HRESULT CreateInputDevices(HWND _HWnd);
  void UpdateCamera();
  
  //Установка начального расположения камеры в игровом мире или
  //вообще установка "глаз" в нужное местоположение.
  void SetCameraPos(D3DXVECTOR3 Pos_XYZ) { Position = Pos_XYZ; }

  //Скорость передвижения камеры, т.е фактически здесь
  //мы задаём скорость для движения камеры в стороны при управлении с клавиатуры.
  void SetCameraSpeed(float Cam_Speed) { m_fCameraSpeed = Cam_Speed; } 

  //Здесь задаётся скорость вращения и обзора мыши.
  void SetMouseSpeed(float Mouse_Speed) { m_fMouseSpeed = Mouse_Speed; }
 
  //Функция возвращающая местоположение камеры в игровом мире.
  D3DXVECTOR3 Pos() { return Position; }
private:
  /*Private Directives*/ 
  LPDIRECT3DDEVICE9 d_pDevice;      //Pointer On Direct3D Device Interface
  IDirectInput8* m_pDirectInput;    //Base DirectInput Device
  IDirectInputDevice8* m_pMouse;    //Mouse Input Device
  IDirectInputDevice8* m_pKeyboard; //Keyboard Input Device

  //Base Camera Directives
  float Pitch,Yaw;
  D3DXVECTOR3 Position;
  D3DXVECTOR3 Target;
  D3DXVECTOR3 Up;
  D3DXVECTOR3 Velocity;
  D3DXVECTOR3 Look_Vector; //Base Look Vector
  D3DXMATRIX View;
  D3DXMATRIX Projection;

  float PosX,PosY,PosZ; 

  float m_fCameraSpeed; //Set Camera Speed
  float m_fMouseSpeed; //Set Mouse Speed

  //"Тайминг" интерфейс нам понадобится позже для обработки 
  //режима ведения огня из автоматического оружия или 
  //одиночными выстрелами соответственно.
  CGRTimer* m_pTimer; //Timing Interface
};
#endif //!defined(AFX_CAMERA_H__)

////////////////////////////////////////////////////////////////////////////////
// Global Variables Or Constants
////////////////////////////////////////////////////////////////////////////////
extern CGRCamera* gr_Camera; //GreenRay Camera Global Interface Class



4) Модуль GR_Camera.cpp заполняем этим кодом:

Код

/****************************************************************************/ 
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_Camera.cpp
// It's An GreenRay GR_Camera Source File.
/*****************************************************************************/
#include <GR_Camera.h>

//////////////////////////////////////////////////////////////////////////////
// Construction/Destruction For CGRCamera Class
//////////////////////////////////////////////////////////////////////////////
CGRCamera::CGRCamera(LPDIRECT3DDEVICE9 pDevice)
{
  //Set Default Parameters
  d_pDevice = pDevice; //Apropritate Device Pointer To Class
  m_pDirectInput = NULL;
  m_pMouse = NULL;
  m_pKeyboard = NULL;
  m_pTimer = NULL;

  //Create Input Devices
  if (SUCCEEDED(CreateInputDevices(FormL_HWnd)))
  {
    m_pMouse->Acquire();
    m_pKeyboard->Acquire();
  }
  
  m_fCameraSpeed = 0.01f;
  m_fMouseSpeed = 0.01f;

  Pitch = 0.0f;
  Yaw = 0.0f;
  Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  Target = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
  Velocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  D3DXVec3Normalize(&Look_Vector,&(Target-Position));

  //Set The Projection Matrix
  float Aspect_Ratio = 1.0f;
  D3DXMatrixPerspectiveFovLH(&Projection,D3DX_PI/4,Aspect_Ratio,0.1f,1000.0f);
  d_pDevice->SetTransform(D3DTS_PROJECTION,&Projection);

  m_pTimer = new CGRTimer(); //Construct A Timer Class
} //EndConstructionDirectives

CGRCamera::~CGRCamera()
{
} //EndDestructionDirectives

//-----------------------------------------------------------------------------
// Name: CGRCamera::Release()
// Desc: Освобождение занятых ресурсов
//-----------------------------------------------------------------------------
void CGRCamera::Release()
{
  m_pMouse->Unacquire(); //UnControl Mouse
  m_pKeyboard->Unacquire(); //UnControl Keyboard

  ReleaseClass(m_pMouse); //Release Mouse
  ReleaseClass(m_pKeyboard); //Release Keyboard
  ReleaseClass(m_pDirectInput); //Release DirectInput

  if (m_pTimer != NULL) { m_pTimer = NULL; DeleteClass(m_pTimer); } //Free Timer Class 
} //EndReleaseProcedure

//-----------------------------------------------------------------------------
// Name: CGRCamera::CreateInputDevices()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT CGRCamera::CreateInputDevices(HWND _HWnd)
{
  HRESULT Result = S_OK;
  //Create InputDevice
  //Создаём тут основной DirectInput интерфейс с указанием его версии для DX API
  if (FAILED(DirectInput8Create(GetModuleHandle(NULL),DIRECTINPUT_VERSION,
  IID_IDirectInput8,(void**)&m_pDirectInput,NULL))) 
  {
    //Интерфейс DirectInput вернул ошибку, чтож продолжать далее не имеет смысла
    //Выводим сообщение об ошибке:
    MessageBoxA(NULL,"Can't Create DirectInputContext","GreenRay Engine Error",
    MB_SYSTEMMODAL|MB_ICONEXCLAMATION); 
    Result = E_FAIL;
  }
  else //Всё в порядке продолжаем:
  {
    //Create Mouse Input Device
    //Создаём виртуальное устройство ввода для мыши
    if (FAILED(m_pDirectInput->CreateDevice(GUID_SysMouse,&m_pMouse,NULL)))
    {
      MessageBoxA(NULL,"Can't Create MouseInputDevice","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION); 
      m_pDirectInput->Release(); 
      Result = E_FAIL;
    }

    //Создаем формат данных для мыши и передаём его в структуру 
    //DirectInput Data Format (DIDATAFORMAT)
    if (FAILED(m_pMouse->SetDataFormat(&c_dfDIMouse2))) 
    {
      MessageBoxA(NULL,"Can't Set MouseDataFormat","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
      m_pMouse->Release();
      m_pDirectInput->Release();
      m_pMouse = NULL;
      m_pDirectInput = NULL;
      Result = E_FAIL;
    }
 
    if (FAILED(m_pMouse->SetCooperativeLevel(_HWnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE)))
    {
      MessageBoxA(NULL,"Can't Set Mouse CooperativeLevel","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
      m_pMouse->Release();
      m_pDirectInput->Release();
      m_pMouse = NULL;
      m_pDirectInput = NULL;
      Result = E_FAIL;
    }

    //Create Keyboard Input Device
    //Создаём виртуальное устройство ввода для клавиатуры
    if FAILED(m_pDirectInput->CreateDevice(GUID_SysKeyboard,&m_pKeyboard,NULL))
    {
      MessageBoxA(NULL,"Can't Create KeyboardInputDevice","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
      m_pKeyboard->Release();
      m_pKeyboard = NULL;
      Result = E_FAIL;
    }
    
    //Создаем формат данных для клавиатуры и передаём его в структуру 
    //DirectInput Data Format (DIDATAFORMAT)
    if (FAILED(m_pKeyboard->SetDataFormat(&c_dfDIKeyboard))) 
    {
      MessageBoxA(NULL,"Can't Set KeyboardDataFormat","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
      m_pMouse->Release();
      m_pKeyboard->Release();
      m_pDirectInput->Release();
      m_pDirectInput = NULL;
      Result = E_FAIL;
    }

    if (FAILED(m_pKeyboard->SetCooperativeLevel(_HWnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE)))
    {
      MessageBoxA(NULL,"Can't Set Keyboard CooperativeLevel","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
      m_pMouse->Release();
      m_pKeyboard->Release();
      m_pDirectInput->Release();
      m_pDirectInput = NULL;
      Result = E_FAIL;
    }

    /*DIPROPDWORD dipdw = {
    {
      sizeof(DIPROPDWORD),  //diph.dwSize
      sizeof(DIPROPHEADER), //diph.dwHeaderSize
      0,                    //diph.dwObj
      DIPH_DEVICE,},        //diph.dwHow
      DINPUT_BUFFERSIZE256, //dwData
    };
           
    if (FAILED(m_pKeyboard->SetProperty(DIPROP_BUFFERSIZE,&dipdw.diph)))
    {
      MessageBoxA(NULL,"Can't Set Property For KeyboardDevice","GreenRay Engine Error",
      MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
      m_pMouse->Release();
      m_pKeyboard->Release();
      m_pDirectInput->Release();
      m_pDirectInput = NULL;
      return;
    } */
  }
  return Result;
} //EndCreateInputDevicesFunction

//-----------------------------------------------------------------------------
// Name: CGRCamera::UpdateCamera()
// Desc: Poll The DirectInput Devices
//-----------------------------------------------------------------------------
void CGRCamera::UpdateCamera()

  DIMOUSESTATE2 Mouse_Data; //Value Keep Mouse States
  char Key_Buffer[256]; //Buffer To Hold Prev. Keyboard States

  //d_pDevice->TestCooperativeLevel(); 
  float m_fForward = 0;
  float m_fSideward = 0;

  //Donation: GetMouseState 
  if (m_pMouse != NULL) //Check On Ready Mouse
  {         
    //Get Mouse Input Data
    //Перехватываем и обрабатываем входные данные поступающие от "мыши". 
    ZeroMemory(&Mouse_Data,sizeof(Mouse_Data));
    m_pMouse->GetDeviceState(sizeof(Mouse_Data),&Mouse_Data);
    m_pMouse->Acquire();

    //Here Getting Mouse States:
    //Здесь получаем непосредственно координаты поступающие при движении
    //мышкой.
    Pitch-= (double)Mouse_Data.lY*gr_Timer->GetTime()*m_fMouseSpeed;
    Yaw-= (double)Mouse_Data.lX*gr_Timer->GetTime()*m_fMouseSpeed;
   
    //Mouse Button States (0- It's Button Up)
    //Обрабатываем нажатия кнопок мыши:
    if ((Mouse_Data.rgbButtons[0x00] & 0x80) != 0) 
    {
      //Здесь происходит обработка события когда нажата левая кнопка мыши
      //Это понадобится нам позже
    }

  }

  //Donation: GetKeyboardState
  if (m_pKeyboard != NULL) //Check On Ready Keyboard
  {
    //Keyboard Input Data
    //Перехватываем и обрабатываем входные данные поступающие от клавиатуры. 
    ZeroMemory(&Key_Buffer,sizeof(Key_Buffer));
    m_pKeyboard->GetDeviceState(sizeof(Key_Buffer),Key_Buffer);
    m_pKeyboard->Acquire();

    //Keyboard Contol Input Mode
    //Здесь реализовано WASD-овское управление игроком т.е вперёд, назад, вбок 
    //и Strafe соответственно, не долго думая при желании можно переделать его 
    //и в "тракторное" управление, кому как нравится и привычнее, тогда
    //в клавиатурном буфере нужно поменять на: Key_Buffer[DIK_UP], Key_Buffer[DIK_DOWN],
    //Key_Buffer[DIK_LEFT], Key_Buffer[DIK_RIGHT] соответственно..  
    if (Key_Buffer[DIK_W] & 0x80) m_fForward = m_fCameraSpeed*gr_Timer->GetTime();
    if (Key_Buffer[DIK_S] & 0x80) m_fForward = -m_fCameraSpeed*gr_Timer->GetTime();
    if (Key_Buffer[DIK_A] & 0x80) m_fSideward = -m_fCameraSpeed*gr_Timer->GetTime();
    if (Key_Buffer[DIK_D] & 0x80) m_fSideward = m_fCameraSpeed*gr_Timer->GetTime();
    
    //Эта строка понадобится, когда к движку будет подключен PhysX :))
    //и здесь будет обрабатываться "прыжок" игрока..
    //if (Key_Buffer[DIK_SPACE] & 0x80) gr_PhysX->JumpPhysXPlayer(m_fJumpSpeed); //Make The Player Jump
  }

  //Restrict The Ability To Look Too High Or Too Low
  //Здесь происходит ограничение взгляда камеры мышью в 
  //самой верхней точке, т.е когда мы смотрим в потолок, и 
  //в самой нижней когда смотрим в пол..
  //Если не применять этот "ограничитель" то при движении мышкой
  //камера начнет прокручиваться дальше и получится совсем ненужный
  //эффект вставания игрока в "мостик" или на "голову" при взгляде вниз.. :)))) 
  if (Pitch < -1.56f) Pitch = -1.56f; //Y
  if (Pitch > 1.56f) Pitch = 1.56f;
  
  if (Yaw >= 6.28f) Yaw = 0.0f;  //X
  if (Yaw <= -6.28f) Yaw = 0.0f;

  //Get Camera X,Y,Z Position Coordinates
  //Получение позиции камеры игрока в пространстве..
  //Это пригодится к примеру когда мы будем делать привязку SkyBox к
  //нашей камере и много еще для чего в дальнейшем..
  PosX = (cosf(Pitch)*cosf(Yaw)*10.0f);
  PosY = (sinf(Pitch)*10.0f);
  PosZ = (sinf(Yaw)*cosf(Pitch)*10.0f);

  //Здесь идёт расчёт и преобразоание по формуле - позиций, координат, векторов и
  //передача их в матрицы:
  //Set The Target Of The Camera
  Target = D3DXVECTOR3(PosX,PosY,PosZ)+Position;

  //Update The Look Vector
  D3DXVec3Normalize(&Look_Vector,&(Target-Position));
  D3DXVECTOR3 XZLook_Vector = Look_Vector;
  XZLook_Vector.y = 0;
  D3DXVec3Normalize(&XZLook_Vector,&XZLook_Vector);
  D3DXVECTOR3 Side_Vector(XZLook_Vector.z,0.0f,-XZLook_Vector.x);
  Velocity = (XZLook_Vector*m_fForward)+(Side_Vector*m_fSideward);
  

  //Временные преобразования, после подключения PhysX их не станет..
  //Apply Transform
  Position+= (XZLook_Vector*m_fForward)+(Side_Vector*m_fSideward);
  Target+= (XZLook_Vector*m_fForward)+(Side_Vector*m_fSideward);

  //Update The View Matix
  D3DXMatrixLookAtLH(&View,&Position,&Target,&Up);
  //Update The Active View
  d_pDevice->SetTransform(D3DTS_VIEW,&View);
} //EndUpdateCameraProcedure

//-----------------------------------------------------------------------------



А сейчас разберём следующий участок кода:

Код

...
  if (FAILED(m_pMouse->SetCooperativeLevel(_HWnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE)))
  {
    MessageBoxA(NULL,"Can't Set Mouse CooperativeLevel","GreenRay Engine Error",
    MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
    m_pMouse->Release();
    m_pDirectInput->Release(); 
    m_pMouse = NULL;
    m_pDirectInput = NULL;
    Result = E_FAIL;
  }
...



Здесь происходит подключение и привязка устройства мыши к нашему окну, 
как видите, здесь фигурирует HWND переменная 
_HWnd - хендл нашего окна, вот здесь при подключении мыши и позже клавиатуры мы её и применяем.

Примечание! Следует также отметить, что после установки кооперативного режима мышь полностью перехватывается нашим приложением, и курсор мыши становится невидимым, но чтобы его увидеть вновь - необходимо вызвать метод m_pMouse->Unacquire(); и остановив обработчик gr_Camera->UpdateCamera(); тогда наше приложение "отпустит" мышь восвояси. 
Также курсор можно будет сэмулироать и отрисовывать отдельно, но это можно будет реализовать позже - уже при разработке графического интерфейса GRE..


Это сообщение отредактировал(а) php - 5.9.2014, 07:13
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
php
Дата 6.7.2009, 06:53 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



2.4. Собираем "куб".
1) Для начала создадим новый файл под названием GR_SkyBox.cpp:
Для этого в "дереве" нашего проекта выбираем Source Files и нажимаем на нём правой кнопкой мыши, далее из выпадающего меню выбираем Add->New Item.. Делаем те же действия, что и при создании файла модуля GR_Camera.cpp, не забываем этот файл сохранить в папке Engine_Modules.

Наполняем файл следующим кодом:

Код

/*******************************************************************************
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_SkyBox.cpp
// It's The GreenRay SkyBox Geometry Transform Engine Source File.
// Made Specially For Implementing Only SkyBox Geometry And Effects.
*******************************************************************************/
#include <GR_SkyBox.h>

//////////////////////////////////////////////////////////////////////////////
// Construction/Destruction For CGRSkyBox Class
//////////////////////////////////////////////////////////////////////////////
CGRSkyBox::CGRSkyBox(LPDIRECT3DDEVICE9 pDevice)
{
  //Присваивание и "передача" указателя Direct3D Device в наш класс
  d_pDevice = pDevice; //To Appropriate Device Pointer To Class
  
  //Подготовка вершинного буфера
  m_pVertexBuffer = NULL; //Prepare Vertex Buffer

  //Подготовка индексного буфера
  m_pIndexBuffer = NULL; //Prepare Index Buffer

  //Подготовка текстур, присваивание массиву текстур значения
  //NULL как видите идёт одной строкой:
  memset(m_pTex,0x00,sizeof(m_pTex)); 
} //EndConstructionDirectives

CGRSkyBox::~CGRSkyBox()
{  
} //EndDestructionDirectives

//------------------------------------------------------------------------------
// Name: CGRSkyBox::Release()
// Desc: 
//------------------------------------------------------------------------------
void CGRSkyBox::Release()
{
  for (UINT I = 0; I < 6; I++) { ReleaseClass(m_pTex[I]); m_TexPath[I] = NULL; } //Free Textures
  ReleaseClass(m_pVertexBuffer); //Free Vertex Buffer
  ReleaseClass(m_pIndexBuffer); //Free Index Buffer
  d_pDevice = NULL; //NULL Device Pointer
} //EndReleaseProcedure

//-----------------------------------------------------------------------------
// Name: CGRSkyBox::SetTextures()
// Desc: Loading And Init Textures
//-----------------------------------------------------------------------------
void CGRSkyBox::SetTextures(TCHAR* _TexBack,TCHAR* _TexLeft,
TCHAR* _TexFront,TCHAR* _TexRight,TCHAR* _TexFloor,TCHAR* _TexCeiling)
{
  m_TexPath[0] = _TexBack;
  m_TexPath[1] = _TexLeft;
  m_TexPath[2] = _TexFront;
  m_TexPath[3] = _TexRight;
  m_TexPath[4] = _TexFloor;
  m_TexPath[5] = _TexCeiling;

  //Create Some Textures
  for (UINT I = 0; I < 6; I++)
  {
    if (FAILED(D3DXCreateTextureFromFileEx(d_pDevice,m_TexPath[I],D3DX_DEFAULT,D3DX_DEFAULT,
    1,0,D3DFMT_UNKNOWN,D3DPOOL_MANAGED,D3DX_DEFAULT,D3DX_DEFAULT,0,NULL,NULL,&m_pTex[I])))
    {
      ShowMessage("GRWorld.cpp: Can't Load SkyBox Texture");
    }
  }
} //EndSetTexturesProcedure

//-----------------------------------------------------------------------------
// Name: CGRSkyBox::CreateBox()
// Desc: Создание "коробки" SkyBox-а с инициализацией вершинного и индексного
// буфера.
//-----------------------------------------------------------------------------
HRESULT CGRSkyBox::CreateBox(float fWidth,float fHeight,float fDepth)
{
  m_pWidth = fWidth;
  m_pHeight = fHeight;
  m_pDepth = fDepth;

  //Массив с описанием 6 сторон куба в данной структуре вершин 
  //описываются координаты вершин в пространстве и текстурные
  //"барицентрические" (Barycentric) TU - TV координаты.
  SKYBOX_VERTEX Vertexes[] =
  {
    //Width   Height   Depth  tu(W) tv(H)
    //Back Wall
    { fWidth, 0.0f,    0.0f, 0.0f, 1.0f, }, //A
    { fWidth, fHeight, 0.0f, 0.0f, 0.0f, }, //B
    { 0.0f,   fHeight, 0.0f, 1.0f, 0.0f, }, //C
    { 0.0f,   0.0f,    0.0f, 1.0f, 1.0f, }, //D
   
    //Left Wall
    { 0.0f, 0.0f,    0.0f,   0.0f, 1.0f, }, //A2
    { 0.0f, fHeight, 0.0f,   0.0f, 0.0f, }, //B2
    { 0.0f, fHeight, fDepth, 1.0f, 0.0f, }, //C2
    { 0.0f, 0.0f,    fDepth, 1.0f, 1.0f, }, //D2
    
    //Front Wall
    { 0.0f,   0.0f,    fDepth, 0.0f, 1.0f, }, //A3
    { 0.0f,   fHeight, fDepth, 0.0f, 0.0f, }, //B3
    { fWidth, fHeight, fDepth, 1.0f, 0.0f, }, //C3
    { fWidth, 0.0f,    fDepth, 1.0f, 1.0f, }, //D3
    
    //Right Wall
    { fWidth, 0.0f,    fDepth, 0.0f, 1.0f, }, //A4  
    { fWidth, fHeight, fDepth, 0.0f, 0.0f, }, //B4
    { fWidth, fHeight, 0.0f,   1.0f, 0.0f, }, //C4
    { fWidth, 0.0f,    0.0f,   1.0f, 1.0f, }, //D4
    
    //Floor    
    { fWidth, 0.0f, 0.0f,   1.0f, 1.0f, }, //A5
    { 0.0f,   0.0f, 0.0f,   0.0f, 1.0f, }, //B5
    { 0.0f,   0.0f, fDepth, 0.0f, 0.0f, }, //C5
    { fWidth, 0.0f, fDepth, 1.0f, 0.0f, }, //D5
     
    //Ceiling
    { fWidth, fHeight, fDepth, 1.0f, 1.0f, }, //A6 
    { 0.0f,   fHeight, fDepth, 0.0f, 1.0f, }, //B6
    { 0.0f,   fHeight, 0.0f,   0.0f, 0.0f, }, //C6
    { fWidth, fHeight, 0.0f,   1.0f, 0.0f, }, //D6
    //  x        y       z     tu(W) tv(H)
  }; //End Vertexes Description

  //Массив индексов содержащий и описывающий 6 сторон куба (12 треугольников)
  const unsigned short Index[] = 
  {
  0,1,2,    2,3,0,
  4,5,6,    6,7,4,
  8,9,10,   10,11,8,
  12,13,14, 14,15,12,
  16,17,18, 18,19,16,
  20,21,22, 22,23,20, 
  }; //End Indexes Description
    
  //Create Vertex Buffer
  //Создание буфера вершин
  if (FAILED(d_pDevice->CreateVertexBuffer(36*sizeof(SKYBOX_VERTEX),0, 
  D3DFVF_SKYBOXVERTEX,D3DPOOL_DEFAULT,&m_pVertexBuffer,NULL))) return E_FAIL;

  //Lock The Vertex Buffer
  //Блокируем вершинный буфер
  VOID* pBV;
  if (FAILED(m_pVertexBuffer->Lock(0,sizeof(Vertexes),(void**)&pBV,0))) return E_FAIL;
  
  //Заполнение вершинного буфера данными
  memcpy(pBV,Vertexes,sizeof(Vertexes)); //Copy Vertex Data To Memory

  //Разблокируем вершинный буфер
  m_pVertexBuffer->Unlock(); //Unlock The Vertex Buffer
    
  //Create Index Buffer
  //Создание индексного буфера, здесь всё происходит 
  //примерно тоже самое, что и при создании вершинного буфера.
  d_pDevice->CreateIndexBuffer(36*sizeof(Index),0,D3DFMT_INDEX16,D3DPOOL_DEFAULT,&m_pIndexBuffer,NULL);
    
  //Lock The Index Buffer
  VOID* pBI;
  m_pIndexBuffer->Lock(0,sizeof(Index),(void**)&pBI,0); 
    
  memcpy(pBI,Index,sizeof(Index)); //Copy Index Data To Memory
      
  m_pIndexBuffer->Unlock(); //Unlock The Index Buffer
 
  return S_OK;
} //EndCreateSkyBoxFunction

//-----------------------------------------------------------------------------
// Name: CGRSkyBox::Render()
// Desc: Rendering The SkyBox Geometry With Textures
//-----------------------------------------------------------------------------
void CGRSkyBox::Render()
{  
  //Устанавливаем параметры рендера и отключаем Z-Буфер
  d_pDevice->SetRenderState(D3DRS_ZENABLE,FALSE);
  d_pDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
  d_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
  d_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE);

  //VU Addr Задаём параметры текстурного сэмплера.
  d_pDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
  d_pDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);

  //Set Texture Mode
  //d_pDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
  //d_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);    
  //d_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
  d_pDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
  d_pDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
  //d_pDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_POINT);

  //Set Perspective View For Spherical Show SkyBox In Space (60 Degree) 
  //Установка камеры и "перспективы" FOV - Field Of View (область обзора)
  //в сферическое представление с углом в 60 градусов.
  float Aspect_Ratio = 1.1f;
  D3DXMATRIXA16 Mat_Proj;
  //FLOAT fAspectRatio = (float)m_d3dsdBackBuffer.Width/(float)m_d3dsdBackBuffer.Height;
  D3DXMatrixPerspectiveFovLH(&Mat_Proj,/*D3DX_PI/4*/D3DXToRadian(60.0f),Aspect_Ratio,1.0f,1000.0f);
  d_pDevice->SetTransform(D3DTS_PROJECTION,&Mat_Proj); 

  //Translation Matrices For The SkyBox Object
  //Устанавливаем размеры, позицию в центр, и привязываем SkyBox к камере,
  //чтобы SkyBox как бы двигался вместе с игроком и сам игрок не "приближался" 
  //к граням SkyBox в игровом пространстве.
  D3DXMATRIXA16 Mat_Trans,Mat_Rotate,Mat_Pos,Mat_Centered; 
  //                                        W           H           D
  D3DXMatrixTranslation(&Mat_Centered,-m_pWidth/2,-m_pHeight/2,-m_pDepth/2); 
  D3DXMatrixRotationYawPitchRoll(&Mat_Rotate,D3DX_PI,0.0f,0.0f);
  D3DXMatrixTranslation(&Mat_Pos,gr_Camera->Pos().x,gr_Camera->Pos().y,gr_Camera->Pos().z);
  Mat_Trans = (Mat_Centered*Mat_Rotate)*Mat_Pos; //Multiply Matrices
  d_pDevice->SetTransform(D3DTS_WORLD,&Mat_Trans); //Transform Object Position In Space

  //Draw The SkyBox Here
  //Set Vertex And Index Buffers To Render
  //Ну а здесь уже собственно происходит отрисовка самих граней (полигонов) 
  //SkyBox-куба и наложение текстур..
  d_pDevice->SetTexture(0,NULL);
 
  //Устанавливаем в устройстве текущий вершинный буфер
  d_pDevice->SetStreamSource(0,m_pVertexBuffer,0,sizeof(SKYBOX_VERTEX));
  //Устанавливаем подготовленный ранее FVF наших вершин D3DFVF_SKYBOXVERTEX)
  d_pDevice->SetFVF(D3DFVF_SKYBOXVERTEX); 
  //Устанавливаем индексы из ранее подготовленного индексного буфера:
  d_pDevice->SetIndices(m_pIndexBuffer);
  
  //Output For Created Objects
  //Рендеринг "стенок" куба и  текстур. Вывод примитивов 
  //посредством индексного буфера осуществляется методом DrawIndexedPrimitive

  //Render BackWall
  if (m_pTex[0] != NULL) d_pDevice->SetTexture(0,m_pTex[0]);
  d_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2 );
  
  //Render LeftWall
  if (m_pTex[1] != NULL) d_pDevice->SetTexture(0,m_pTex[1]);
  d_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 4, 0, 4, 0, 2 ); //Offset To 4 Base Vertex Index 

  //Render FrontWall
  if (m_pTex[2] != NULL) d_pDevice->SetTexture(0,m_pTex[2]);
  d_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 8, 0, 4, 0, 2 ); //Offset To 8 Base Vertex Index 

  //Render RightWall
  if (m_pTex[3] != NULL) d_pDevice->SetTexture(0,m_pTex[3]);
  d_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 12, 0, 4, 0, 2 ); //Offset To 12 Base Vertex Index 

  //Render Floor
  if (m_pTex[4] != NULL) d_pDevice->SetTexture(0,m_pTex[4]);
  d_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 16, 0, 4, 0, 2 ); //Offset To 16 Base Vertex Index

  //Render Ceiling
  if (m_pTex[5] != NULL) d_pDevice->SetTexture(0,m_pTex[5]);
  d_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 20, 0, 4, 0, 2 ); //Offset To 20 Base Vertex Index

  //Здесь уже возвращаем исходные параметры и активируем Z-Buffer, это необходимо
  //для устранения влияния параметров SkyBox на отрисовку последующих
  //элементов сцены которые будут рендериться после самого SkyBox-а в дальнейшем..
  d_pDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
  d_pDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
  
  //VU Addr Возвращаем исходные параметры для отрисовки текстур,
  //так называемые текстурные "сэмплеры" и устанавливаем их в режим 
  //"обёртки" - WRAP, если этого не сделать, то модель или другая геометрия
  //игрового "мира" имеющая текстуры будет рендериться некорректно, т.е 
  //изображение текстуры будет как бы растягиваться от краёв к центру, иными словами
  //будет сказываться влияние текстурного состояния CLAMP которое мы устанавливали
  //ранее для отрисовки SkyBox..
  d_pDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
  d_pDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
} //EndRenderProcedure

//-----------------------------------------------------------------------------



2) Создаем файл GR_SkyBox.h:
Для этого также в "дереве" проекта выбираем Header Files, и не забываем сохранить этот файл туда же в папку Engine_Modules и наполняем этот файл следующим кодом:

Код

/*******************************************************************************
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_SkyBox.h: Interface For The SkyBox Geometry Implementation Class.
// It's The GreenRay SkyBox Geometry Transform Engine.
// Made Specially For Implementing Only SkyBox Geometry And Effects.
*******************************************************************************/
#include <GR_Engine.h>
#include <GR_Methods.h>
#include <GR_Camera.h>

////////////////////////////////////////////////////////////////////////////////
// Classes Used By This Header
////////////////////////////////////////////////////////////////////////////////
//class CGRSkyBox;

//-----------------------------------------------------------------------------
// Name: CGRSkyBox
// Desc: The Box Class
//-----------------------------------------------------------------------------
#if !defined(AFX_SKYBOX_H__)
#define AFX_SKYBOX_H__

//Константа FVF содержащая формат и структуру вершин 
#define D3DFVF_SKYBOXVERTEX (D3DFVF_XYZ|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE3(0)) //Vertex Format

class CGRSkyBox
{
public:
   /*Public Directives*/
  //SkyBox Vertex, Normals, Texures Positions
  //Структура содержащая координаты вершин, нормали,
  //цвет и текстурные координаты.
  struct SKYBOX_VERTEX
  {
    FLOAT x,y,z;    //Coordinates
    FLOAT nx,ny,nz; //Normals
    DWORD _Color;   //Vertex Color
    FLOAT tu,tv;    //Textures
  }; //End SkyBox Vertex Formats

  CGRSkyBox(LPDIRECT3DDEVICE9 pDevice);
  virtual ~CGRSkyBox();
  void Release();
  void SetTextures(TCHAR* _TexBack,TCHAR* _TexLeft,TCHAR* _TexFront,
  TCHAR* _TexRight,TCHAR* _TexFloor,TCHAR* _TexCeiling);
  HRESULT CreateBox(float fWidth,float fHeight,float fDepth);
  void Render();
protected:
  /*Protected Directives*/
  LPDIRECT3DDEVICE9 d_pDevice; //Pointer On Direct3D Device Interface
  IDirect3DVertexBuffer9* m_pVertexBuffer; //The Vertex Buffer
  IDirect3DIndexBuffer9* m_pIndexBuffer; //The Index Buffer
  IDirect3DTexture9* m_pTex[6]; //Variable Keep Same Textures
  TCHAR* m_TexPath[6]; //Variable Keep Texture Path
  float m_pWidth,m_pHeight,m_pDepth; //Variables Keep SkyBox WHD Size
};
#endif //!defined(AFX_SKYBOX_H__)



3) Если заметите в разделе include я использую #include <GR_Methods.h>
В этом модуле содержатся различные вспомогательные процедуры и функции которые вызываются в движке это различные таймеры, диалоговые окна и др. Создаём и его - для этого в "дереве" нашего проекта выбираем Source Files и нажимаем на нём правой кнопкой мыши, далее из выпадающего меню выбираем Add->New Item.. и сохраняем его под именем GR_Methods.cpp в папку Engine_Modules.
Код файла модуля будет следующим:

Код

/******************************************************************************
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_Methods.cpp
// It's The GreenRay Direct3D Useful Control Interfaces Engine Source File.
// Made Specially For Implementing Useful Engine System Manipulations Parameters.
******************************************************************************/
#include <GR_Methods.h>

//-----------------------------------------------------------------------------
// Name: ShowMessage()
// Desc: 
//-----------------------------------------------------------------------------
void ShowMessage(LPCSTR Mes_String)
{
  MessageBoxA(NULL,Mes_String,"GreenRay Engine",MB_SYSTEMMODAL|MB_ICONERROR);
} //EndShowMessageProcedure

///////////////////////////////////////////////////////////////////////////////
// Construction/Destruction For CGRDeltaTimer Class
///////////////////////////////////////////////////////////////////////////////
CGRDeltaTimer::CGRDeltaTimer()
{
} //EndConstructionDirectives

CGRDeltaTimer::~CGRDeltaTimer()

} //EndDestructionDirectives

//-----------------------------------------------------------------------------
// Name: CGRDeltaTimer::UpdateTimer()
// Desc: Execute Each Frame To Establish Time Base
//-----------------------------------------------------------------------------
void CGRDeltaTimer::UpdateTimer()
{
  CurrentTime = timeGetTime();
  DeltaTime = (float)((CurrentTime-LastTime)*0.001f);
  LastTime = CurrentTime;
} //EndUpdateTimerProcedure

//-----------------------------------------------------------------------------
// Name: CGRDeltaTimer::GetTime()
// Desc:
//-----------------------------------------------------------------------------
float CGRDeltaTimer::GetTime()
{
  return DeltaTime;
} //EndGetTimeFunction

///////////////////////////////////////////////////////////////////////////////
// Construction/Destruction For CGRTimer Class
///////////////////////////////////////////////////////////////////////////////
CGRTimer::CGRTimer()
{
  m_bUsingQPF         = false;
  m_bTimerStopped     = true;
  m_llQPFTicksPerSec  = 0;

  m_llStopTime        = 0;
  m_llLastElapsedTime = 0;
  m_llBaseTime        = 0;

 //Use QueryPerformanceFrequency() To Get Frequency Of Timer.  
 LARGE_INTEGER qwTicksPerSec;
 m_bUsingQPF = (bool)(QueryPerformanceFrequency(&qwTicksPerSec) != 0);
 m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
} //EndConstructionDirectives

CGRTimer::~CGRTimer()

} //EndDestructionDirectives

//-----------------------------------------------------------------------------
// Name: CGRTimer::Reset()
// Desc: 
//-----------------------------------------------------------------------------
void CGRTimer::Reset()
{
  if (!m_bUsingQPF) return;

  //Get Either The Current Time Or The Stop Time
  LARGE_INTEGER qwTime;
  if (m_llStopTime != 0) qwTime.QuadPart = m_llStopTime;
  else QueryPerformanceCounter(&qwTime);

  m_llBaseTime = qwTime.QuadPart;
  m_llLastElapsedTime = qwTime.QuadPart;
  m_llStopTime = 0;
  m_bTimerStopped = FALSE;
} //EndResetProcedure

//-----------------------------------------------------------------------------
// Name: CGRTimer::Start()
// Desc: 
//-----------------------------------------------------------------------------
void CGRTimer::Start()
{
  if (!m_bUsingQPF) return;

  //Get The Current Time
  LARGE_INTEGER qwTime;
  QueryPerformanceCounter(&qwTime);

  if (m_bTimerStopped) m_llBaseTime+= qwTime.QuadPart-m_llStopTime;
  m_llStopTime = 0;
  m_llLastElapsedTime = qwTime.QuadPart;
  m_bTimerStopped = FALSE;
} //EndStartProcedure

//-----------------------------------------------------------------------------
// Name: CGRTimer::Stop()
// Desc: 
//-----------------------------------------------------------------------------
void CGRTimer::Stop()
{
  if (!m_bUsingQPF) return;

  if (!m_bTimerStopped)
  {
    //Get Either The Current Time Or The Stop Time
    LARGE_INTEGER qwTime;
    if (m_llStopTime != 0) qwTime.QuadPart = m_llStopTime;
    else QueryPerformanceCounter(&qwTime);

    m_llStopTime = qwTime.QuadPart;
    m_llLastElapsedTime = qwTime.QuadPart;
    m_bTimerStopped = TRUE;
  }
} //EndStopProcedure

//-----------------------------------------------------------------------------
// Name: CGRTimer::Advance()
// Desc: 
//-----------------------------------------------------------------------------
void CGRTimer::Advance()
{
  if (!m_bUsingQPF) return;
  m_llStopTime+= m_llQPFTicksPerSec/10;
} //EndAdvanceProcedure

//-----------------------------------------------------------------------------
// Name: CGRTimer::GetAbsoluteTime()
// Desc: 
//-----------------------------------------------------------------------------
double CGRTimer::GetAbsoluteTime()
{
  if (!m_bUsingQPF) return -1.0;

  //Get Either The Current Time Or The Stop Time
  LARGE_INTEGER qwTime;
  if (m_llStopTime != 0) qwTime.QuadPart = m_llStopTime;
  else QueryPerformanceCounter(&qwTime);

  double fTime = qwTime.QuadPart/(double) m_llQPFTicksPerSec;
  return fTime;
} //EndGetAbsoluteTimeFunction

//-----------------------------------------------------------------------------
// Name: CGRTimer::GetTime()
// Desc: 
//-----------------------------------------------------------------------------
double CGRTimer::GetTime()
{
  if (!m_bUsingQPF) return -1.0;

  //Get Either The Current Time Or The Stop Time
  LARGE_INTEGER qwTime;
  if (m_llStopTime != 0) qwTime.QuadPart = m_llStopTime;
  else QueryPerformanceCounter(&qwTime);

  double fAppTime = (double)(qwTime.QuadPart-m_llBaseTime)/(double)m_llQPFTicksPerSec;
  return fAppTime;
} //EndGetTimeFunction

//-----------------------------------------------------------------------------
// Name: CGRTimer::GetElapsedTime()
// Desc: 
//-----------------------------------------------------------------------------
double CGRTimer::GetElapsedTime()
{
  if (!m_bUsingQPF) return -1.0;

  //Get Either The Current Time Or The Stop Time
  LARGE_INTEGER qwTime;
  if (m_llStopTime != 0) qwTime.QuadPart = m_llStopTime;
  else QueryPerformanceCounter(&qwTime);

  double fElapsedTime = (double)(qwTime.QuadPart-m_llLastElapsedTime)/(double)m_llQPFTicksPerSec;
  m_llLastElapsedTime = qwTime.QuadPart;

  return fElapsedTime;
} //EndGetElapsedTimeFunction

//-----------------------------------------------------------------------------
// Name: CGRTimer::IsStopped()
// Desc: 
//-----------------------------------------------------------------------------
bool CGRTimer::IsStopped()
{
  return m_bTimerStopped;
} //EndIsStoppedFunction



4) Также создаём и файл GR_Methods.h выбрав для этого из "дерева" проекта Header Files, и сохранив в папку Engine_Modules.
Код модуля:

Код

/******************************************************************************
// It's Unofficial Version Of The GreenRay Engine v.3.0.0.2
// GR_Methods.h
// It's The GreenRay Direct3D Useful Control Interfaces Engine Header File.
// Made Specially For Implementing Useful Engine System Manipulations Parameters.
******************************************************************************/
#include <GR_Engine.h>

////////////////////////////////////////////////////////////////////////////////
// Directives For Release Classes
////////////////////////////////////////////////////////////////////////////////
#define ReleaseClass(_Ptr) { if (_Ptr) { (_Ptr)->Release(); (_Ptr) = NULL; } }
//Directive For Delete Classes
#define DeleteClass(_Ptr) { if (_Ptr) { delete(_Ptr); (_Ptr) = NULL; } }
//Directive For Delete Arrays
#define DeleteArray(_Ptr) { if (_Ptr) { delete[](_Ptr); (_Ptr) = NULL; } }

////////////////////////////////////////////////////////////////////////////////
// Exporting Procedures And Functions
////////////////////////////////////////////////////////////////////////////////
void ShowMessage(LPCSTR Mes_String);

////////////////////////////////////////////////////////////////////////////////
// Classes Used By This Header
////////////////////////////////////////////////////////////////////////////////
//class CGRFPSCounter;
//class CGRDeltaTimer;
//class CGRTimer;

//-----------------------------------------------------------------------------
// Name: Struct CGRDeltaTimer
// Desc:
//-----------------------------------------------------------------------------
#if !defined(AFX_DELTATIMER_H__)
#define AFX_DELTATIMER_H__

class CGRDeltaTimer

public:
  /*Public Directives*/
  CGRDeltaTimer();
  virtual ~CGRDeltaTimer();
  void UpdateTimer();
  float GetTime();
private:
  /*Private Directives*/
  DWORD CurrentTime; //Current Timer Value
  DWORD LastTime;    //Previous Timer Value
  float DeltaTime;   //Time Elapsed Since Last Frame
};
#endif //!defined(AFX_DELTATIMER_H__)

//-----------------------------------------------------------------------------
// Name: Struct CGRTimer
// Desc:
//-----------------------------------------------------------------------------
#if !defined(AFX_TIMER_H__)
#define AFX_TIMER_H__

class CGRTimer

public:
  /*Public Directives*/  
  CGRTimer();
  virtual ~CGRTimer();
  
  void Reset(); //Resets The Timer
  void Start(); //Starts The Timer
  void Stop(); //Stop (Or Pause) The Timer
  void Advance(); //Advance The Timer By 0.1 Seconds
  double GetAbsoluteTime(); //Get The Absolute System Time
  double GetTime(); //Get The Current Time
  double GetElapsedTime(); //Get The Time That Elapsed Between GetElapsedTime() Calls
  bool IsStopped(); //Returns True If Timer Stopped
private:
  /*Private Directives*/
protected:
  /*Protected Directives*/
  bool m_bUsingQPF;
  bool m_bTimerStopped;
  LONGLONG m_llQPFTicksPerSec;

  LONGLONG m_llStopTime;
  LONGLONG m_llLastElapsedTime;
  LONGLONG m_llBaseTime;
};
#endif //!defined(AFX_TIMER_H__)

////////////////////////////////////////////////////////////////////////////////
// Global Variables Or Constants
////////////////////////////////////////////////////////////////////////////////
extern CGRDeltaTimer* gr_Timer; //GreenRay Timer Interface Class



Добавлено @ 06:53
Ну вот теперь почти всё готово. Теперь разберём некоторые участки кода в модуле SkyBox.cpp:

Код

...
  if (FAILED(d_pDevice->CreateVertexBuffer(36*sizeof(SKYBOX_VERTEX),0, 
  D3DFVF_SKYBOXVERTEX,D3DPOOL_DEFAULT,&m_pVertexBuffer,NULL))) return E_FAIL;
...


Здесь происходит создание вершинного буфера, он служит для
хранения набора вершин объекта и представляет из себя сплошной
блок памяти, также позволяет вполне компактно хранить и обрабатывать
информацию о вершинах, в качестве параметров здесь указывается формат
вершин (структура хранящая данные о координатах, цвете и нормалях вершин, а
также координаты текстур и многое другое, иными словами называемая ещё 
как FVF (Flexible Vertex Format)) и размер буфера с параметрами размещения 
буфера в памяти.
Как мы видим, для указания формата вершин используется константа 
D3DFVF_SKYBOXVERTEX объявленная в модуле GR_SkyBox.h.

Для получения доступа к данным буфера используется метод Lock интерфейса
m_pVertexBuffer, здесь копируются в адрес Vertexes подготовленные 
описания наших вершин

Код

...
  VOID* pBV;
  if (FAILED(m_pVertexBuffer->Lock(0,sizeof(Vertexes),(void**)&pBV,0))) return E_FAIL;
...



После заполнения вершинного буфера данными необходимо вызвать метод Unlock,
если этого не сделать, то отрисовка SkyBox происходить не будет, 
да это может вызвать и ошибку работы движка, т.к сам буфер мы изначально 
перевели в заблокированное состояние, поэтому после всех манипуляций его 
необходимо разблокировать:

Код

...
  m_pVertexBuffer->Unlock(); //Unlock The Vertex Buffer
...


Создание индексного буфера

Код

...
  d_pDevice->CreateIndexBuffer(36*sizeof(Index),0,D3DFMT_INDEX16,D3DPOOL_DEFAULT,&m_pIndexBuffer,NULL);
...


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

Далее разберём код в рендере самого SkyBox:

Код

...
  d_pDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
  d_pDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
...


Тут задаются параметры текстурного сэмплера, здесь кроется 
ключевой момент в отрисовке и рендеринга текстур самого SkyBox-а.
Режим "сэмплера" CLAMP обеспечивает "затирание" стыков в углах и граней SkyBox, если этого не сделать, то сразу будут бросаться в глаза ярко выраженные линии стыков по углам, от чего вся иллюзия целостности и объемности пространства полностью сойдет на нет.. Но для того, чтобы добиться нормального результата работы данного 
режима "сэмплирования", каждая текстура кубической карты должна быть строго одинакового размера, если допустим у вас размер текстуры кубической карты 256x256 то и размер всех остальных текстур должен быть таким же, иначе может получиться эффект "сползания" текстуры вбок, и как результат некорректное и некрасивое отображение и отрисовка.. Вообще если заметить то стыки на границах "скайбокса" можно было наблюдать достаточно во многих старых играх, я встречал даже и в более новых..

5) В конце не забудьте положить скачанные текстуры SkyBox-а в папку, которая
создаётся после компиляции проекта и называется "Debug" в ней обычно создаётся и хранится сам скомпилированный *.exe-файл проекта GRDebugger.exe, а также файлы объектов *.obj которые создаются в результате компилирования модулей *.cpp и *.h самого GRE.  Эти файлы должны лежать по пути:
 
../GreenRay/GRDebugger/Debug/Textures/SkyBox/GrandCanyon/

Название конечной папки может называться и по другому на ваше усмотрение, в нашем
случае она называется GrandCanyon, в ней должны лежать файлы с именами соответствующими сторонам SkyBox-куба это: xneg.png, xpos.png, yneg.png, ypos.png, zneg.png, zpos.png, т.е всего 6 файлов, форматы файлов могут быть и другими такие как Jpg, Bmp и др. Этот набор файлов необходим для формирования так называемой кубической карты "CubeMap" далее эти текстуры накладываются на внутренние грани самого SkyBox-куба, в определённом порядке в результате чего формируется эффект окружения и 3-х мерное представление какого-либо помещения, мира, ландшафта, космоса и планет. Эти текстуры можно получить или сделать в специализированных программах, или они фотографируются специализированным оборудованием и фотокамерами в определённой проекции, наиболее распространённый метод для 
фотографирования это кубические проекции, снимаются в шести взаимно перпендикулярных направлениях (включая верх и низ), и представляются в виде крестообразной развёртки:

user posted image

Примечание! Не забудьте, если у вас папка будет иметь другое имя и путь,
то необходимо этот путь изменить и в коде движка, иначе текстуры загружаться не 
будут, что приведёт к ошибке и закрытию приложения GRE.
Посмотрим на участок кода в модуле GR_Engine.cpp где происходит создание класса SkyBox:

Код

...
  //Create SkyBox Class
  gr_SkyBox = new CGRSkyBox(m_pDevice); //Construct A CGRSkyBox Class  
  gr_SkyBox->CreateBox(100.0f,100.0f,100.0f); //Create Our SkyBox Model With Size WHD
  gr_SkyBox->SetTextures(TEXT("\Textures\\SkyBox\\GrandCanyon\\zneg.png"),
                     TEXT("\Textures\\SkyBox\\GrandCanyon\\xneg.png"),
             TEXT("\Textures\\SkyBox\\GrandCanyon\\zpos.png"),
             TEXT("\Textures\\SkyBox\\GrandCanyon\\xpos.png"),
             TEXT("\Textures\\SkyBox\\GrandCanyon\\yneg.png"),
             TEXT("\Textures\\SkyBox\\GrandCanyon\\ypos.png"));
...


Здесь создаётся класс "Скайбокса", указываются его размеры в данном случае 100, ну
и соответственно пути к нашим CubeMap-текстурам.

Примечание! Текстуры CubeMap для движка или другие дополнительные текстуры SkyBox можно взять отсюда: www.codemonsters.de/home/content.php?show=cubemaps

2.5. Заключение.
Итак в итоге после компиляции проекта должно получиться как на рисунке представленном ниже:

user posted image

Или ещё вот такой вариант загрузки SkyBox:

user posted image

Также рекомендуется проверить как работает наша игровая камера, если всё в порядке и камера подключилась нормально то мы сможем осмотреться вокруг, вверх и вниз, ну а если при движении мыши ничего не происходит значит устройства ввода не работают, либо неправильно были переданы какие-либо параметры, либо не произошла инициализация библиотеки DirectInput. 

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

До новых встреч! Keep smile! Пока! smile

_________________________________________________________________________
© Digital Dreams Development Inc., 2009 
(С) GR-Engine Technical Documentation.
при поддержке © Polarity Soft Engine Inc.  
Любая публикация изложенного материала только с разрешения автора.

Это сообщение отредактировал(а) php - 5.9.2014, 07:14
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
arilou
Дата 6.7.2009, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 6
Всего: 61



Цитата(php @  6.7.2009,  06:53 Найти цитируемый пост)
© Digital Dreams Development Inc., 2009 
(С) GR-Engine Technical Documentation.
при поддержке © Polarity Soft Engine Inc.  
Любая публикация изложенного материала только с разрешения автора.


оффтоп: многовато копирайтов  smile достаточно было написать "Любая публикация изложенного материала только с разрешения автора", имхо.


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
php
Дата 6.7.2009, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Цитата

многовато копирайтов  smile достаточно было написать "Любая публикация изложенного материала только с разрешения автора", имхо.


 smile Ндаа действительно немного перебор с копирайтами.., ладно в следующий раз вообще их
вписывать не буду, этих достаточно будет.. 
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
nogoody
Дата 15.7.2009, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 12.9.2007
Где: Смоленск

Репутация: нет
Всего: нет



Попробовал пример, единственное ругался на dmusici.h, пришлось закоментить
А так все супер, очень жду продолжения, автору спасибо  smile 

PM MAIL   Вверх
ShellRaiser
Дата 16.7.2009, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


еще чуть и закоммичу
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 20.7.2007
Где: Белaрусь, Гродно

Репутация: 1
Всего: 1



Цитата(ISergeyN @ 22.4.2009,  11:02)
Вот это странный код
Код

  if (m_pDirect3D==NULL)//if (!m_pDirect3D)
  {
    if (m_pDirect3D != NULL) //это зачем ? эсли словие ни когда не сработает!
             m_pDirect3D->Release(); //
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }

php, а ведь он как бы прав=)

я бы написал как по твоим описаниям вот так вот:
Код

  if (m_pDirect3D==NULL)//if (!m_pDirect3D)
  {
    //если нет то создаёшь
    MessageBoxA(NULL,"GR_Engine.cpp: Failed To Create Direct3D Interface..",
    "GreenRay Engine Error",MB_SYSTEMMODAL|MB_ICONERROR);
    m_pResult = E_FAIL;
  }
  else
  {
       m_pDirect3D->Release();//иначе сбрасываешь....
  }

ну ет если логически подумать;)
PM MAIL ICQ Skype   Вверх
N.M.Guard
Дата 18.7.2009, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 19.1.2008

Репутация: нет
Всего: нет



php спасибо большое за статью!!! С удовольствием жду продолжения !!!

P.S. 
Для удобства обсуждения можно каждое продолжение в отдельную тему писать!!! smile

Это сообщение отредактировал(а) N.M.Guard - 18.7.2009, 13:48
PM MAIL ICQ   Вверх
pirat77
  Дата 26.7.2009, 09:15 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 10.11.2008

Репутация: нет
Всего: нет



Так как только ещё учусь C++,обратил внимание на этот урок (за что его создателю спасибо) ,но вот почему то возникла такая проблема при debug'е user posted image и таких 6 окошек с ошибкой к каждой текстуре, но из папки debug всё прекрасно запускается и работает. Как решить данную неувязку?  smile 

Это сообщение отредактировал(а) pirat77 - 26.7.2009, 09:32
PM MAIL   Вверх
php
Дата 27.7.2009, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



pirat77  Данная ошибка показывается самим движком GRE, чтобы удобнее было устранять и узнавать где когда и почему произошла ошибка, эта ошибка, что произошла в 
вашем случае может выводиться по двум причинам: из-за физического отсутствия папки с текстурами на диске или неверно прописанного пути в теле программы, и если текстура не найдена или не загружается, то GRE выводит подобную ошибку, но судя по вашему ответу папка с текстурами у вас всё же существует, в вашем случае можно поступить двумя способами:

1. Скопировать папку Textures в папку где лежит файл проекта .sln по умолчанию он должен лежать в папке GRDebugger, но только учтите, что скоро в движке будут реализовываться модели - сами файлы моделей тоже будут лежать в папке Debug и вам придётся постоянно их "дублировать" если захотите запустить движок в режиме отладки, что на мой взгляд не совсем удобно..

2. Как можно увидеть в движке путь к папке с текстурами указан частично: 
"\Textures\\SkyBox\\Arch\\zneg.png", что из этого следует - он обработает этот путь только из 
текущей папки проекта или откуда был запущен exe-шник самого движка, но можно указать 
путь явным образом, к примеру:
"C:\\GreenRay\\GRDebugger\\Debug\\Textures\\SkyBox\\Arch\\zneg.png", но тут 
опять могут возникнуть проблемы, если вы к примеру принесёте движок к другу и запустите он у него работать не будет если путь будет отличаться от выше приведённого или располагаться в другой папке или диске...

Цитата

Попробовал пример, единственное ругался на dmusici.h, пришлось закоментить


Хм странно, вообще это DirectMusic Interface, нужен будет позже когда будет подключаться
возможность проигрывания файлов mp3 в GRE, и обычно находится а разделе Include DirectX SDK, проверьте может неверно прописаны пути к папке Include или некорректно установлен Сам DX SDK, если не поможет могу выложить этот файл сюда..

Цитата

Для удобства обсуждения можно каждое продолжение в отдельную тему писать!!!


Ок так и сделаем в следущий раз.. smile 


Это сообщение отредактировал(а) php - 27.7.2009, 08:29
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
stuqs
Дата 27.7.2009, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 26.7.2009

Репутация: нет
Всего: нет



Статья интересная спору нет. Но она изложена все же для понимающих людей, кто разбирается в функциях DirectX, что зачем идет и тд. Очень хочется понимать  весь код - поэтому большая просьба выложить название каких-нибудь книг, самоучителей по DirectX на C++ где можно будет разобраться с самого начала. ( а то вставлять чужой код и получать работающие программы интересно, но намного интереснее писать свой код) Гугл в помощь просьба не давать, находил много книг, но устаревших с не актуальной информацией(нет уже таких библиотек или приемы уже не используются теперь такие).
Заранее благодарю.
PM MAIL   Вверх
ISergeyN
Дата 27.7.2009, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



stuqs, а стандартная документация чем плоха?
PM MAIL Skype   Вверх
php
Дата 27.7.2009, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Ну к примеру вот это: http://www.intuit.ru/department/graphics/direct3dhlsl/
довольно неплохо расписано начиная с самых азов и заканчивая шейдерами, 
это не совсем книга конечно это статьи с описанием и картинками, а вообще рекомендую
искать и читать в интернете различные статьи, в книгах бывает порой слишком "мутно"
всё расписано, а здесь допустим ищем конкретно интересующую тему к примеру 
"Работа с освещением в DirectX" читаем обрабатываем статью и уже методом подбора 
в коде меняем те или иные функции, значения, смотрим, что за что отвечает, да вот даже можно взять само DX SDK в папке Samples есть примеры с программным кодом и описанием правда на английском языке..
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
Eviljoker
Дата 28.7.2009, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 27.7.2009

Репутация: нет
Всего: нет



php респек, не так часто подиректу нахожу толковые вещи еще и с таким подробным описанием!
Я щитаю себя новичком... пару книг канешн прочитал и в часности Андре Ламота(ну ет по графике вообще) компиляция и запуск написаного проекта затруднений никаких не вызывает, все скомпилилось с первого раза, впринцыпе как и разбор кода... ваще в нете просто искал статью как SkyBox сделать, хорошо что на етот форум забрел smile 
PM MAIL   Вверх
Kolt007
Дата 24.8.2009, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



скажите кто нить плиз это по первой части урока где надо инициализовать Direct3d я всёправельно сделал как написано но вылетеет вот такая ошибка когда я запускаю
1>***.obj : error LNK2019: ссылка на неразрешенный внешний символ _Direct3DCreate9@4 в функции "long __cdecl CreateDirect3D(struct HWND__ *)" (?CreateDirect3D@@YAJPAUHWND__@@@Z)
1>C:\***\***\Debug\***.exe : fatal error LNK1120: 1 неразрешенных внешних элементов
1>Журнал построения был сохранен в "file://c:\***\****\Debug\BuildLog.htm"

Добавлено через 14 минут и 40 секунд
И ещё один вопрос это будет игровой движок например как blitzt 3d или Quest 3d или уже игра

Это сообщение отредактировал(а) Kolt007 - 24.8.2009, 16:25
PM MAIL   Вверх
Kolt007
Дата 25.8.2009, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



ответ те плиз
PM MAIL   Вверх
php
Дата 28.8.2009, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Цитата

И ещё один вопрос это будет игровой движок например как blitzt 3d или Quest 3d или уже игра


Будем стараться делать полноценную игру, хоть это и будет нелегко..

Цитата

1>***.obj : error LNK2019: ссылка на неразрешенный внешний символ _Direct3DCreate9@4 в функции "long __cdecl CreateDirect3D(struct HWND__ *)" (?CreateDirect3D@@YAJPAUHWND__@@@Z)
1>C:\***\***\Debug\***.exe : fatal error LNK1120: 1 неразрешенных внешних элементов
1>Журнал построения был сохранен в "file://c:\***\****\Debug\BuildLog.htm"


Какая у вас установлена версия DX DSK?

--------------------
Джедаи не пройдут..
PM MAIL   Вверх
Kolt007
Дата 28.8.2009, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



У меня DX 10 
Всмысле это будет не движок на котором можно создавать игры
А сразу игра написаная на c++ 
Ну вот есть unity 3d через него можно создавать игры без c++
а здесь будет так что вся игра будет писатся на с++ да

Это сообщение отредактировал(а) Kolt007 - 28.8.2009, 15:12
PM MAIL   Вверх
Kolt007
Дата 2.9.2009, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



Я вообще не знаю у меня и на dx 9 который здесь используется та же самая ошибка
 smile 

Это сообщение отредактировал(а) Kolt007 - 2.9.2009, 13:44
PM MAIL   Вверх
php
Дата 10.9.2009, 06:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Да игра будет делаться с использованием языка C++ и DirectX,
т.е непосредственно сам движок игры, а то что касается unity 3d то это судя
по описанию игровое SDK уже или конструктор!
Здесь по сути тот же конструктор, но только код и движок игры можно переписывать 
и настраивать на любой лад как хочешь, добавлять, изменять в общем как говорится 
была бы фантазия!!

Кстати, а какая версия VisualStudio у вас используется ?
Проверьте также все ли библиотеки lib правильно прописаны, проверьте пути к модулям
движка может что-то там неправильно прописано, как это делается достаточно подробно 
описано в самом начале статьи!
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
Kolt007
Дата 10.9.2009, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



У меня visual studio 2008 библиотеки вроде норм прописаны
PM MAIL   Вверх
Kolt007
Дата 11.9.2009, 06:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



Эта проблема решена я просто библиотеки для x86 сейчас поставил а было x64 хотя винда 64 , но когда я хочу инициализовать d3d 10 то не получается по тутору в dx не че не понятно но я так понимаю код придётся переписывать
PM MAIL   Вверх
php
Дата 11.9.2009, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Цитата

но когда я хочу инициализовать d3d 10 то не получается по тутору в dx не че не понятно но я так понимаю код придётся переписывать


Не получается потому, что структура и инициализация в DX10 изменена и отличается от DX9,
совершенно верно код придётся полностью переписывать и "портировать" уже под DX10  smile 

Займётесь?  smile 
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
Kolt007
Дата 11.9.2009, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



Займусь , а можно сделать так что бы был и dx 9 и dx 10

Это сообщение отредактировал(а) Kolt007 - 11.9.2009, 16:05
PM MAIL   Вверх
Kolt007
Дата 11.9.2009, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



А переписывать всё или только код где инициализация




PM MAIL   Вверх
ISergeyN
Дата 12.9.2009, 02:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Цитата(Kolt007 @  11.9.2009,  16:32 Найти цитируемый пост)
А переписывать всё или только код где инициализация

С такими вопросами лучше С++ поучить, а не то как игры делать..
PM MAIL Skype   Вверх
php
Дата 12.9.2009, 05:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Цитата

а можно сделать так что бы был и dx 9 и dx 10


Да это можно сделать, вопрос лишь состоит в том как это реализовать,
к примеру можно сделать какой нибудь загрузчик с выбором какую версию DX
мы хотим использовать, допустим перед самой загрузкой движка и графики выбирать
9 или 10 DirectX, по сути таким "макаром" можно и поддержку 8 го туда запихнуть 
ради прикола!  smile 
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
zvad
Дата 29.9.2009, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 29.9.2009

Репутация: нет
Всего: нет



а продолжение будет? smile 
PM MAIL   Вверх
Kolt007
Дата 8.10.2009, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



C инициализацией DX 10 я разобрался, но дальше как сделать камеру и загрузить модель не где не написано в DX 9 хоть .x файлы загружались а здесь какие то SDKMesh что ли
И еще когда выйдет следущая часть урока

PM MAIL   Вверх
SATANAblack
Дата 29.10.2009, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 29.10.2009
Где: Украина

Репутация: нет
Всего: нет



php - большое спасибо за уроки и детальное коментирование. Я щас только вхожу в азы и розбираю семплы на SDK DirectX. Но скоро перейду на ваши уроки.
PM MAIL   Вверх
shuttle
Дата 4.11.2009, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 230
Регистрация: 9.4.2008

Репутация: нет
Всего: нет



Структура которая описывает вершину skybox-а
Код

struct SKYBOX_VERTEX
  {
    FLOAT x,y,z;    //Coordinates
    FLOAT nx,ny,nz; //Normals
    DWORD _Color;   //Vertex Color
    FLOAT tu,tv;    //Textures
  }; //End SkyBox Vertex Formats

Затем создаем массив этих вершин.
Код

 SKYBOX_VERTEX Vertexes[] =
  {    
    { fWidth, 0.0f,    0.0f, 0.0f, 1.0f, },
     ...
  }

Создание нормалей и color-а отсутствуют. Куда они пропали?
--------------------
PM MAIL   Вверх
php
Дата 5.11.2009, 05:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



А зачем вам нормали при создании SkyBox ?
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
shuttle
Дата 5.11.2009, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 230
Регистрация: 9.4.2008

Репутация: нет
Всего: нет



Цитата

А зачем вам нормали при создании SkyBox ?


А они там разьве не нужны? Если же и не нужны то и не и нужно было их в струтуре SKYBOX_VERTEX объявлять.

И самое главное -  нужно продолжение сновного урока - а именно работа с физическим движком.
--------------------
PM MAIL   Вверх
php
Дата 7.11.2009, 07:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Цитата

  Если же и не нужны то и не и нужно было их в струтуре SKYBOX_VERTEX объявлять.


Да это я для отладки и тестов всяких делал давно ещё осталось, думал, что пригодится.. 
Надо будет убрать лишнее всё таки... Спасибо что заметили!  smile 

Продолжение уроков будет обязательно, сейчас только чуть чуть разрулю со своими делами немного, а то у меня параллельно ещё два проекта идёт просто.. smile 
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
Kolt007
Дата 15.11.2009, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 24.8.2009

Репутация: нет
Всего: нет



Помогите со создание SkyBox'a мне пишет ошибки в файле GRSkyBox.cpp:
CGRSkyBox::CGRSkyBox повторное объявление функции не разрешается
CGRSkyBox::~CGRSkyBox повторное объявление функции не разрешается
CGRSkyBox::Release повторное объявление функции не разрешается
{: отсутствует заголовок функции (возможно, используется формальный список старого типа)
CGRSkyBox::SetTextures повторное объявление функции не разрешается
{: отсутствует заголовок функции (возможно, используется формальный список старого типа)
хотя всё сделал правельно как показано

Это сообщение отредактировал(а) Kolt007 - 15.11.2009, 13:11
PM MAIL   Вверх
Rickert
Дата 15.11.2009, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: 6
Всего: 52



Модератор: Если хотите обсудить какой-то вопрос - создавайте тему. Здесь же только статья.

Это сообщение отредактировал(а) Rickert - 15.11.2009, 17:25


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
shuttle
Дата 18.11.2009, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 230
Регистрация: 9.4.2008

Репутация: нет
Всего: нет



Сделал все шаги, что то fps получилось всего ~60 (8400 GS, 512). Вроде как маловато fps, может кто еще измерил, какие у кого значения получились?
--------------------
PM MAIL   Вверх
php
Дата 19.11.2009, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Да счётчик значения там выдаёт не совсем верный результат, точнее идёт некая привязка к частоте развёртки экрана монитора,  к примеру допустим если у вас развёртка стоит 80 Hz то fps уже будет примерно от 80 до 84, если 60 Hz то соответственно 60-65 fps, в общем тут тоже нужна будет переделка счётчика немного не те данные выдаёт..
--------------------
Джедаи не пройдут..
PM MAIL   Вверх
rdmt
  Дата 2.2.2010, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 2.2.2010

Репутация: нет
Всего: нет



всем привет! 
как сделать так чтоб картинки показывались?? 

а то пишет user posted image и ###...

вот решил научится попрогать, а без некоторых картинок, становятца не понятны, не которые моменты :(((( 
PM MAIL   Вверх
Rpahut
Дата 3.2.2010, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


0xdeadbeef
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 9.4.2006

Репутация: 5
Всего: 7



Картинки были загружены год назад и уже, по видимому, сдохли. Попробуйте автору статьи написать.
Вообще там все очнь подробно описано, вполне можно и без картинок повторить.
--------------------
C/C++ GameDevRSS Раздела программирования игрOpenGL - уроки от NeHeКак продать идею?
PM MAIL   Вверх
vkd
Дата 19.2.2010, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 19.2.2010

Репутация: нет
Всего: нет



А продолжения можно ожидать? А то думаю, стоит ли присоединяться к компании....

Сам по книжкам сейчас пытаюсь смастерить движок. Книжки, правда уже устаревшие, на Студии 2008 примеры их 
не собираются, вот и набрел на ваше обсуждение. Смущает, правда, большое количество подключаемых библиотек. Хотелось бы самому все по крупицам собрать. Но если продолжение будет, я с радостью тоже поучаствую в общем деле!
PM MAIL   Вверх
mmmaaaxxx15
Дата 20.7.2011, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 20.7.2011

Репутация: нет
Всего: нет



помогите проблема 

Ошибка    1    error LNK2019: ссылка на неразрешенный внешний символ _Direct3DCreate9@4 в функции "long __cdecl CreateDirect3D(struct HWND__ *)" (?CreateDirect3D@@YAJPAUHWND__@@@Z)    

Ошибка    2    error LNK1120: 1 неразрешенных внешних элементов    

код скопировал как написано !

Это сообщение отредактировал(а) mmmaaaxxx15 - 20.7.2011, 14:10
PM MAIL   Вверх
Чупакабро
Дата 22.7.2011, 16:41 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: 2
Всего: 4



mmmaaaxxx15 
либы подключил к проекту?

Это сообщение отредактировал(а) Чупакабро - 22.7.2011, 16:42
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
php
Дата 2.1.2012, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Статья на доработке..

Это сообщение отредактировал(а) php - 31.5.2013, 15:47
PM MAIL   Вверх
Snake006
Дата 4.2.2012, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



А продолжение будет?
PM MAIL   Вверх
Snake006
Дата 9.3.2012, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Почему, когда я увеличиваю размер скайбокса, начинает появляться темнота, и чем дальше я передвигаюсь, тем темнота больше?
PM MAIL   Вверх
lokod
Дата 9.1.2013, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.2.2012
Где: Красноуральск

Репутация: нет
Всего: -1



А ссылочка на топик?
Я только нашел этот урок  smile  smile 
PM MAIL   Вверх
Ineigo
Дата 7.2.2013, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 7.2.2013

Репутация: нет
Всего: нет



Можно попросить автора перезалить картинки..?

С уважением Михаил!
PM MAIL   Вверх
php
Дата 22.5.2013, 03:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 159
Регистрация: 20.2.2003

Репутация: 3
Всего: 3



Статья на доработке..

Это сообщение отредактировал(а) php - 31.5.2013, 15:47
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование игр, графики и искуственного интеллекта"
Rickert

НА ЗЛОБУ ДНЯ: Дорогие посетители, прошу обратить внимание что новые темы касающиеся новых вопросов создаются кнопкой "Новая тема" а не "Ответить"! Любые оффтопиковые вопросы, заданные в текущих тематических темах будут удалены а их авторы, при рецедиве, забанены.

  • Литературу, связанную с программированием графики, обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы связанные с программированием графики и мультимедии на языках С++ и Delphi
  • Вопросы по реализации алгоритмов рассматриваются здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rickert.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Программирование игр, графики и искусственного интеллекта | Следующая тема »


 




[ Время генерации скрипта: 0.3078 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.