OO framework, Egg util library László Szécsi
Projektek nem osztoznak semmilyen kódon – DXUT mindegyikben – effect betöltés, mesh betöltés, GUI mindegyikbe ugyanúgy kell majd Megoldás: csináljunk egy lib-et amibe ezeket tesszük (az Effects11-hez hasonlóan)
Globális függvények, globális változók – nem OO – nem túl áttekinthető Megoldás: hozzunk létre egy App osztályt aminek a metódusait hívjuk a globális függvényekből App alaposztály: ami mindig kell (pl. effect file betöltés) Ebből lehet származtatni olyat ami többet tud
Erőforrások kezelése – working directory : solution folder – ez jó ha a közös fx vagy media folderből kell valami – de mi van ha a projectnek vannak privát effektjei? Megoldás – lehessen az elérési utakat parancssori argumentumként megadni – meg lehessen adni hogy most közös vagy saját.fx fileról van szó
Egg (Engine for GraphGame) lib létrehozása Parancssorfeldolgozó osztály: SystemEnvironment globális eseménykezelők helyett App osztály effect file betöltő metódus (App::loadEffect) – az effect fileban megkülönböztetni #include "valami.fx" – $(ProjectDir)/fx -ben keres #include – $(SolutionDir)/fx -ben keres – EffectInclude : public ID3DInclude
char* – 8 bites karakterek, unsafe wchar_t* – 16 bites karakterek, unsafe std::string – 8 bites, safe std::wstring – 16 bites, safe a kódolás nem specifikált, de nálunk – std::string – UTF8 kódolás - ANSI – std::wstring – UTF16 kódolás - Unicode
D3DX11CompileFromFile – D3DX11CompileFromFileA – char* paraméterek – D3DX11CompileFromFileW – wchar_t* paraméterek A mi kódunk mindenhol wide chart használ Kivéve ahol ezt ‘elfelejtették’ – pl. ID3DInclude::Open const char* -ot vár, nincs Unicode verzió – itt konvertálnunk kell UTF8 UFT16
Start Menu/DirectX SDK (June 2010)/DirectX Sample Browser – install EmptyProject11 – a GraphGame/Projects folderbe – project neve: Egg nem kellenek az sln fileok, törölhetők nem kell a vs2008-as projectfile, törölhető
solution explorer/GraphGame/Add/Existing Project nem kell az Egg.cpp és az EmptyProject9.cpp – remove/delete Egg/Properties/Configuration properties/General – Configuration type: Static library (.lib) Egg/Properties/Configuration properties/output, intermediate dir: másoljuk ki valamelyik meglevő projectből
GraphGame\Bin\Debug\Projects\Egg\Egg.lib egyelőre csak a DXUT van benne
ugyanúgy, ahogy a gg002-Effect projectben – additional include $(SolutionDir)/Projects/Effects11/Inc – common properties/add new reference: Effects11
Hozzunk létre egy Egg/App foldert a filerendszerben és egy Egg/App filtert a solution explorerben Tárgyhonlapról EggLibSrc.zip letöltése Kibontás az Egg/App folderbe Egg/App/Add existing item – összes forrásfile hozzáadása az Egg/App-ból
convertutf.h,.c – hivatalos Unicode konvertáló UtfConversion.h,.cpp – std stringeket használó wrapper a fentihez a.c fileon jobb klikk/properties/C/C++/Precompiled headers/Precompiled header = not using precompiled headers
namespace Egg{ class UtfConverter{ public: static std::wstring utf8to16( const std::string& utf8string); static std::string utf16to8( const std::wstring& widestring); }; } #10.0
atoi, itoa, printf, scanf C megoldás, nem C++ C++ megoldás: stringstream wide char verzió – toWString – fromWString
template inline std::string toString( const T& t ) { std::ostringstream ss; ss << t; return ss.str(); } //std::string s = toString (3); #10.0
C-ben: const char** – ebből kiszedni hogy milyen kapcsolók, paraméterek voltak az nehéz pakoljuk be őket egy ilyenbe – std::map > paraméter neveértékek listája valami.exe --parambool:on --paramint:3 --parampath:"D:\akarmi";"D:\masik"
Ha áthelyezzük a projectet akkor is működik A lib persze nem exe, de a libet használó futtatható alkalmazásnál majd a futtatáshoz a parancssort megadhatjuk így: Project Properties/Configuration Properties/Debugging/Command Arguments --solutionPath:"$(SolutionDir)" --projectPath:"$(ProjectDir)"
std::string commandLine( GetCommandLineA() ); escaped_list_separator sep("", " \t:,;", "\""); tokenizer, std::string::const_iterator, std::string > tokens(commandLine, sep); BOOST_FOREACH(std::string t, tokens){... } #10.0
A SystemEnvironment.cpp-ben a Boost-ot használjuk string tokenizálásra Project properties/Configuration/C/C++/General/Addi tional include directories – C:\Program Files\boost\boost_1_52\
Be akarunk tölteni egy modellt, textúrát – tudjuk a file nevét, de a pontos elérési utat nem akarjuk a programba kódolni – meg kell nézni a $(ProjectDir)/Media folderben, ha nincs ott akkor a $(SolutionDir)/Media folderben Be akarunk includeolni egy effectet a fő effectfileunkba – ha, akkor a $(SolutionDir)/fx folderben – ha " ", akkor a $(ProjectDir)/fx folderben
std::string resolveMediaPath(std::string filename); std::string resolveEffectPath(std::string filename, bool projectLocal); #10.0
Effect file betöltésénél meg lehet adni egy include-kezelőt, aki beolvassa az include filet D3DX11CompileFromFile 3. paraméter – ID3DInclude* ID3DInclude-ból kell származtatni – Open metódust megvalósítani IncludeType paraméter: vagy " " a SystemEnvironment::resolveEffectPath-t fogja használni
Segédosztályok készen vannak, jöhet a lényeg Ebből fogunk származtatni saját app osztályt – egy globális példánya lesz – a globális eseménykezelők ennek a metódusait hívják majd (ezeket fogjuk implementálni) OnD3D11CreateDevice → createResources OnD3D11DestroyDevice → releaseResources OnD3D11ResizedSwapChain → createSwapChainResources OnD3D11ReleasingSwapChain → releaseSwapChainResources
OnD3D11FrameRender → render OnFrameMove → animate MsgProc → processMessage Plusz még egy loadEffect metódus – betölti az effectet – az effect file nevét a getMainEffectFilename() metódussal kérdezi le ezt kell a leszármazott osztályban felüldefiniálni és a loadEffectet békén lehet hagyni
kész van, használhatjuk a jövőbeli projectjeinkben de bővíthető, ide rakjuk majd – mesh kezelés – math, vector, matrix – GUI – entitások kezelése – további engine funkciók ebből lesz majd a játékmotor (project a játék)
g002-Effect – egész folder copy-paste gg002-Effect - Copy – átnevezni: gg003-Egg.vcxproj és.filters – gg002-Effect cserélése gg003-Egg –re solution/add exiting project
working dir: $(SolutionDir) Project Properties/Configuration Properties/Debugging/Command Arguments --solutionPath:"$(SolutionDir)" --projectPath:"$(ProjectDir)"
project átnevezése a solution explorerben gg003-Egg -re teljes DXUT könyvtár kidobása, törlése – hiszen az Egg-ben bent van! – plusz a Media folderből is törölhetjük a DXUT dolgait (UI könyvtár) gg002-Effect.cpp átnevezése: main.cpp main.cpp properties/C/C++/Precompiled headers/Precompiled header: Create
properties/common/references/add new:Egg additional include – $(SolutionDir)/Projects/Egg;$(SolutionDir)/Project s/Egg/App;$(SolutionDir)/Projects/Egg/DXUT/Cor e; $(SolutionDir)/Projects/Egg/DXUT/Optional sima DXUT\Core, DXUT\Optional meg már kidobható set as startup project
egg.ico letöltése Projects/Egg/Media –ba tegyük be gg.rc / View code – az icon filet cseréljük le – DXUT\\Core\\directx.ico helyett (ilyen most nincs a projectben) – Media\\egg.ico
kell egy Egg::App-ból származó osztály – legyen a neve Game ;) ugyanazt fogja csinálni mint eddig, háromszöget rajzolni –fx fileból szedett shaderekkel de ha az Egg (lesz) az engine, akkor ez (lesz) a game… main.cpp-ben ennek egy példánya globális függvények ennek a metódusait hívják erőforráslétrehozó, rajzoló funkcionalitás az implementáló metódusokba
gg003-Egg – add Class… – C++ class – Class name: Game – Base class: Egg::App Egg::App not found in the project – nem baj, az Egg libben van Game.h -ba: #include "App/App.h"
ami eddig globális volt, abból tagváltozó lesz – ID3D11Buffer* vertexBuffer; – ID3D11InputLayout* inputLayout; kivéve az effectet mert az már benne van az Egg::App-ban, nem kell még egy – ID3DX11Effect* effect;
konstuktor getMainEffectFilename – adja vissza, hogy "main.fx" createResources – ami eddig a D3DOnCreateDevice-ban volt releaseResources – ami eddig a D3DOnDestroyDevice-ban volt – effect->Release() helyett Egg::App::releaseResources() render – ami eddig a D3DOnFrameRender-ben volt
nem kell, hogy virtuálisak legyenek Game.cpp-ben érdemes implementálni – kivéve a getMainEffectFilename az elég rövid konstruktorparamétert az Egg::App ősosztálynak továbbadni ha HRESULT a visszatérési típus, akkor S_OK-t visszaadni
ID3DBlob* compiledEffect = NULL; D3DX11CompileFromFileW( L"fx/idle.fx", NULL, NULL, NULL, "fx_5_0", 0, 0, NULL, &compiledEffect, NULL, NULL); D3DX11CreateEffectFromMemory( compiledEffect->GetBufferPointer(), compiledEffect->GetBufferSize(), 0, device, &effect); loadEffect(); #10.0
#include "Game.h" Egg::App* app = NULL; – ez a globális app példányunk – azért nem Game*, hogy könnyen cserélhető legyen a pointer mögött a konkrét megvalósítás
HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { app = new Game(pd3dDevice); return app->createResources(); } #10.0
void CALLBACK OnD3D11DestroyDevice( void* pUserContext ) { app->releaseResources(); delete app; } #10.0
void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext ) { if(app) app-> render(pd3dImmediateContext); } #10.0
ugyanazt tudja, mint a múltkori, de van Egg, amibe a közös dolgokat tehetjük konkrétan mit rajzoljunk, milyen erőforrásokkal, milyen shaderrel, az a Game osztályban van