420 likes | 531 Views
GraphGame gg003- Egg. OO framework , Egg util library László Szécsi. Mi a baj azzal ahogy eddig csináltuk?. Projektek nem osztoznak semmilyen kódon DXUT mindegyikben effect bet öltés, mesh betöltés, GUI mindegyikbe ugyanúgy kell majd
E N D
GraphGamegg003-Egg OO framework, Egg utillibrary LászlóSzécsi
Mi a baj azzal ahogy eddig csináltuk? • 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)
Mi a baj azzal ahogy eddig csináltuk? • 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
Mi a baj azzal ahogy eddig csináltuk? • Erőforrások kezelése • workingdirectory : solutionfolder • ez jó ha a közös fx vagy mediafolderbő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 .fxfileról van szó
Feladatok • 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 filebanmegkülönböztetni • #include"valami.fx" – $(ProjectDir)/fx -benkeres • #include<valami.fx> – $(SolutionDir)/fx -benkeres • EffectInclude: public ID3DInclude
String reprezentáció • char* – 8bites 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
Unicode API • D3DX11CompileFromFile • D3DX11CompileFromFileA – char* paraméterek • D3DX11CompileFromFileW – wchar_t* paraméterek • A mi kódunk mindenhol widechart 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
Egg project létrehozása • Start Menu/DirectX SDK (June 2010)/DirectX Sample Browser • install EmptyProject11 • a GraphGame/Projectsfolderbe • project neve: Egg • nem kellenek az slnfileok, törölhetők • nem kell a vs2008-as projectfile, törölhető
Egg hozzáadása a GraphGame-hez • solutionexplorer/GraphGame/Add/Existing Project • nem kell az Egg.cpp és az EmptyProject9.cpp • remove/delete • Egg/Properties/Configurationproperties/General • Configurationtype: Static library (.lib) • Egg/Properties/Configurationproperties/output, intermediate dir: másoljuk ki valamelyik meglevő projectből
Egg fordítása • GraphGame\Bin\Debug\Projects\Egg\Egg.lib • egyelőre csak a DXUT van benne
Effects11 referencia és include • ugyanúgy, ahogy a gg002-Effect projectben • additionalinclude • $(SolutionDir)/Projects/Effects11/Inc • commonproperties/add newreference: Effects11
Osztályok hozzáadása • Hozzunk létre egy Egg/Appfoldert a filerendszerben és egy Egg/App filtert a solutionexplorerben • TárgyhonlaprólEggLibSrc.zip letöltése • Kibontás az Egg/Appfolderbe • Egg/App/Add existingitem • összes forrásfile hozzáadása az Egg/App-ból
Unicode kezelés • convertutf.h, .c – hivatalos Unicode konvertáló • UtfConversion.h, .cpp – stdstringeket használó wrapper a fentihez • a .c fileon jobb klikk/properties/C/C++/Precompiledheaders/Precompiledheader= not using precompiled headers
#10.0 UtfConverter.h namespace Egg{ class UtfConverter { public: static std::wstringutf8to16( const std::string& utf8string); static std::string utf16to8( const std::wstring&widestring); }; }
toString, fromString • atoi, itoa, printf, scanf C megoldás, nem C++ • C++ megoldás: stringstream • wide char verzió • toWString • fromWString
#10.0 stdConversions.h template<class T> inline std::string toString( const T& t ) { std::ostringstreamss; ss << t; return ss.str(); } //std::string s = toString<int>(3);
Parancssoriparaméterek • C-ben: constchar** • ebből kiszedni hogy milyen kapcsolók, paraméterek voltak az nehéz • pakoljuk be őket egy ilyenbe • std::map<std::wstring, std::vector<std::wstring> > paraméter neve értékek listája valami.exe --parambool:on--paramint:3 --parampath:"D:\akarmi";"D:\masik"
Solution és Project dir parancssori paraméterként • 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/ConfigurationProperties/Debugging/CommandArguments --solutionPath:"$(SolutionDir)" --projectPath:"$(ProjectDir)"
#10.0 SystemEnvironment.cpp std::string commandLine( GetCommandLineA() ); escaped_list_separator<char> sep("", " \t:,;", "\""); tokenizer< escaped_list_separator<char>, std::string::const_iterator, std::string > tokens(commandLine, sep); BOOST_FOREACH(std::string t, tokens){ ... }
Boost lib include • A SystemEnvironment.cpp-ben a Boost-othasználjuk stringtokenizálásra • Project properties/Configuration/C/C++/General/Additional include directories • C:\Program Files\boost\boost_1_52\
SystemEnvironment használata • 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 akarunkincludeolni egy effectet a fő effectfileunkba • ha < >, akkor a $(SolutionDir)/fxfolderben • ha " ", akkor a $(ProjectDir)/fxfolderben
#10.0 SystemEnvironment.h std::string resolveMediaPath(std::string filename); std::string resolveEffectPath(std::string filename, boolprojectLocal);
EffectInclude • Effect file betöltésénél meg lehet adni egy include-kezelőt, aki beolvassa az includefilet • D3DX11CompileFromFile3. paraméter • ID3DInclude* • ID3DInclude-ból kell származtatni • Open metódust megvalósítani • IncludeType paraméter: < > vagy " " • a SystemEnvironment::resolveEffectPath-t fogjahasználni
App alaposztály • 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
App alaposztály • 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
Egglib fordítható • 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)
Gyártsunk egy ezt használó projectet! – gg003-Egg • g002-Effect • egészfoldercopy-paste • gg002-Effect - Copy • átnevezni: gg003-Egg • .vcxproj és .filters • gg002-Effect cserélése gg003-Egg –re • solution/add exiting project
Munkakönyvtár, parancssori paraméterek • working dir: $(SolutionDir) • Project Properties/ConfigurationProperties/Debugging/CommandArguments --solutionPath:"$(SolutionDir)" --projectPath:"$(ProjectDir)"
gg003-Egg méretre szabása • project átnevezése a solutionexplorerben 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.cppproperties/C/C++/Precompiledheaders/Precompiledheader: Create
gg003-Egg függőségek • properties/common/references/add new:Egg • additionalinclude • $(SolutionDir)/Projects/Egg;$(SolutionDir)/Projects/Egg/App;$(SolutionDir)/Projects/Egg/DXUT/Core; $(SolutionDir)/Projects/Egg/DXUT/Optional • sima DXUT\Core, DXUT\Optional meg már kidobható • setasstartup project
Ikon • egg.ico letöltése • Projects/Egg/Media –bategyükbe • gg.rc / Viewcode • az iconfilet cseréljük le • DXUT\\Core\\directx.ico helyett (ilyen most nincs a projectben) • Media\\egg.ico
Használjuk az Egg-et a projectben • kell egy Egg::App-ból származó osztály • legyen a neve Game ;) • ugyanazt fogja csinálni mint eddig, háromszöget rajzolni –fxfileból szedett shaderekkel • de ha az Egg (lesz) az engine, akkorez (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
Gameclass • gg003-Egg • add Class… • C++ class • Classname: Game • Base class: Egg::App • Egg::App not found in the project • nembaj, az Egg libben van • Game.h -ba: #include "App/App.h"
Game tagváltozók • 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, nemkell még egy • ID3DX11Effect* effect;
Implementálandó metódusok • 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
Megjegyzések • 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
#10.0 Game.cpp 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();
main.cpp • #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
#10.0 main.cpp HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { app = new Game(pd3dDevice); return app->createResources(); }
#10.0 main.cpp void CALLBACK OnD3D11DestroyDevice( void* pUserContext ) { app->releaseResources(); delete app; }
#10.0 main.cpp void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext ) { if(app) app-> render(pd3dImmediateContext); }
Kész • 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