
\part{Klientská část}

\section{Úvod}

\subsection{ Instalace }
Klient je napsaný v jazyce $C++$ ve vývojovém prostředí Visual Studio 2010. Nejaktuálnější verzi zdrojových kódů klienta je možné stáhnout z následující adresy.
 
 
\begin{center}
\begin{tabular}{|c|}
\hline
\textbf{Url}: http://xp-dev.com/svn/DivergentTerritory \\
\textbf{Login}: AnonimniUzivatel \\
\textbf{Heslo}: aa4Smn1N \\
\hline
\end{tabular}
\end{center}


Kromě standardních C++ knihoven využívá klient také dvě externí knihovny: Qt a Cg. Tyto knihovny je potřeba na začátku ručně  doinstalovat.

\subsubsection{ Qt knihovna}
Klient disponuje velkým množstvím widgetů jako například okna, panely, tabulky nebo tlačítka.
Proto jsme se rozhodli použít knihovnu usnadňující GUI programování. Knihovnu Qt jsme potom vybrali z několika hlavních důvodů.

\begin{enumerate}

\item Multiplatformnost: klient je v současné verzi kompatibilní pouze s PC vybaveným operačním systémem  Windows. Případná portace na jiný OS nebo platformu by však s ohledem na použité knihovny neměla představovat zásadnější problém.

\item Stylovatelnost: GUI prvky v Qt je možné jednoduše měnit pomocí tzv. Stylesheets. Ty umožňují kompletně předefinovat vzhled jednotlivých grafických komponent a tím dodat aplikaci originální grafický styl.

\end{enumerate}

V našem projektu používáme Qt ve verzi 4.7.1, nicméně problém by neměl nastat ani s vyššími verzemi knihovny. 
Knihovnu Qt je možné stáhnout z těchto stránek.

\url{ http://qt.nokia.com/products/ }

Staženou knihovnu je nakonec potřeba  nainstalovat a zkompilovat.
Podrobnější informace o kompilaci je možné najít například na níže uvedených stránkách.

\url{ http://thomasstockx.blogspot.com/2011/03/qt-472-in-visual-studio-2010.html }

\subsubsection{ Cg knihovna }
Cg je knihovna pro práci s shadery. Shadery jsou krátké programy běžící přímo na grafické kartě. To nám mimo jiné umožňuje programování pokročilých grafických efektů prostřednicvím  vertex a pixel shaderů.
Knihovnu Cg je možné stáhnout z uvedeného odkazu níže.

\url{ http://developer.nvidia.com/cg-toolkit }.


\subsection{Hardwarové požadavky klienta}

\begin{center}
\begin{tabular}{|c|}
\hline
512 MB RAM\\
1 GHz procesor\\
Grafická karta s alespoň 256 MB VRAM a podporou
OpenGL 2.0 \\
DVD mechanika\\
Windows 2000 nebo novější\\
disk 100 MB instalace\\
\hline
\end{tabular}
\end{center}

\paragraph{}
Poznámka: Uvedená sestava představuje minimální hardwarové požadavky pro úspěšné spuštění hry. Pro plynulé hraní za každé situace může být vyžadována konfigurace podstatně výkonnější.

\subsection{Testovací sestavy}
Klient byl úspěšně otestován na následujících hardwarových konfiguracích.


\begin{center}
\begin{tabular}{ | l | l | l | p{4cm} |}
\hline
CPU & RAM & GPU & OS \\ \hline
Intel Core 2 Q6600 & 4GB & NVidia GTX470 & Windows7 64bit \\ \hline

Intel Core i3 330M  & 4GB & ATI Mobility Radeon HD5470 & Windows7 32bit \\ \hline

Intel Core 2 Q6600 & 4GB & NVidia 8800GTX & Windows Vista 32bit  \\ \hline 

AMD Athlon II X4 620 & 4GB & NVidia 8800GTS &  Windows XP SP3
\\ \hline


Intel Core 2 Q9550 & 4GB & NVidia 9800GT &  Windows XP SP3
\\ \hline

%TODO presny model CPU a GPU !!!
Intel Core 2 ??? & 2GB & ??? &  Windows XP SP3 \\ \hline

AMD Athlon 64 3000+ & 2GB & Ati Radeon HD 2600XT & Windows XP SP2  \\ \hline


\hline
\end{tabular}
\end{center}


\section{Matematematické knihovny}

\subsection{ Matice }

\dspFuncName{Matrix4x4<T>} je třída určená pro práci s 4x4 maticemi. Uspořádání prvků matice je sloupcově dominantní:

$
 Matrix4x4<T> =
 \begin{pmatrix}
 a_0 & a_4 & a_8 	 & a_{12} \\
 a_1 & a_5 & a_9 	 & a_{13}  \\
 a_2 & a_6 & a_{10} & a_{14}  \\
 a_3 & a_7 & a_{11} & a_{15}
 \end{pmatrix}
$.


Prvky $a_{12}$, $a_{13}$ a $a_{14}$ definují posun na osách x,y,z. Rozložení prvků v matici tak můžeme napsat jako:

$
 Matrix4x4<T> =
 \begin{pmatrix}
  a_0 & a_4 & a_8 	 & posunX \\
  a_1 & a_5 & a_9 	 & posunY  \\
  a_2 & a_6 & a_{10} & posunZ  \\
  a_3 & a_7 & a_{11} & a_{15}
 \end{pmatrix}
$.  

Reprezentace matice je plně kompatibilní s OpenGL maticemi a třídami \dspFuncName{Point\_3<T>} a \dspFuncName{Vector\_3<T>}, které lze maticemi jednoduše transformovat.

Třída dále nabízí základní binární maticové operace 
jako je sčítání, odečítání a násobení. Matici můžeme také vynásobit sloupcovým nebo řádkovým vektorem a získat tak vektor přetransformovaný danou maticí.
K dispozici jsou dále metody pro nahrání nulové, jednotkové, translační, rotační a měřítkové (scale) matice. Implementovány jsou i jejich zakladní operace: rotace, posun a změna měřítka.

\begin{itemize}
\item 
$
 identita =
 \begin{pmatrix}
  1 & 0 & 0 & 0 \\
  0 & 1 & 0 & 0  \\
  0 & 0 & 1 & 0  \\
  0 & 0 & 0 & 1
 \end{pmatrix}
$

\item 
$
 posun =
 \begin{pmatrix}
  1 & 0 & 0 & posunX \\
  0 & 1 & 0 & posunY  \\
  0 & 0 & 1 & posunZ  \\
  0 & 0 & 0 & 1
 \end{pmatrix}
$

\item 
$
 rotace =
 \begin{pmatrix}
  rotaceXX & rotaceYX & rotaceZX & 0 \\
  rotaceXY & rotaceYY & rotaceZY & 0  \\
  rotaceXZ & rotaceYZ & rotaceZZ & 0  \\
  0 & 0 & 0 & 1
 \end{pmatrix}
$

\item 
$
 \text{měřítko} =
 \begin{pmatrix}
  \text{měřítkoX} & 0 & 0 & 0 \\
  0 & \text{měřítkoY} & 0 & 0  \\
  0 & 0 & \text{měřítkoZ} & 0  \\
  0 & 0 & 0 & 1
 \end{pmatrix}
$
\end{itemize}

\subsection{ Vektor }
\dspFuncName{Vector\_3 <T>} je třída obsahující metody pro práci s vektory ve 3-rozměrném euklidovském prostoru. 
Obsahuje pomocné metody pro operace typu vektor-vektor i typu vektor-skalár. 
Dva vektory tak lze sčítat a odečítat, počítat skalární i vektorový součin nebo úhel, který spolu dva vektory svírají.
K vektoru je dále možné přičítat a odečítat skaláry, případně ho násobit nebo dělit skalárem.
Vektor je můžeme také rotovat, počítat jeho velikost nebo ho normalizovat na vektor jednotkové délky.


\subsection{ Bod }
\dspFuncName{Point\_3<T>} je třída obsahující metody pro práci s body v 3-rozměrném euklidovském prostoru.
Třída obsahuje metody pro operace typu bod-bod a bod-vektor. 
Mezi 2 body je tak možné například počítat euklidovskou vzdálenost, odečíst je od sebe a tím získat 
vektor rozdílu a další. K bodu můžeme přičítat nebo odečítat vektor a tím bod posouvat ve směru vektoru .

\subsection{ Vektor vs Bod }
Třídy \dspFuncName{Point\_3<T>} a \dspFuncName{Vector\_3<T>} jsou si poměrně podobné a mají společnou část implementace. Hlavní rozdíl
je v pojmenování metod a koncepci, ke které jsou určeny.
Zatímco například sčítání 2 vektorů je dobře definovaná operace, sčítat 2 body nelze. 
Podobně je například možné určit velikost vektoru nebo vektor normalizovat, kdežto s body tyto operace nemají rozumnou interpretaci a smysl.
Tento systém rozdělení je výhodný zejména ze dvou důvodů: 

\begin{enumerate}
\item  Poskytuje zvýšenou typovou bezpečnost, vektory a body jsou odlišného typu.
\item Umožňuje intuitivnější náhled na problém. Uvedeným typovým odlišením je na první pohled zřejmé, zda na proměnnou nahlížet jako na bod nebo vektor.
\end{enumerate}

 
Interně jsou body a vektory implementovány čtveřicí atributů ( x,y,z,w ). 
Složky x,y,z udávají pozici nebo směr na jednotlivých osách. Poslední atribut w je pro body roven 1, pro vektory roven 0 a slouží pro rozšířené maticové operace tak, jak jsou definovány v OpenGL.


$
 Point\_3<T> = ( x, y, z, 1 )
$


$
 Vector\_3<T> = ( x, y, z, 0 )
$



Násobení translační 4x4 matice vektorem zanechá vektor beze změny. 


$
\begin{pmatrix} 
 	1 & 0 & 0 & posunX \\
  	0 & 1 & 0 & posunY  \\
  	0 & 0 & 1 & posunZ  \\
  	0 & 0 & 0 & 1
\end{pmatrix} \cdot \begin{pmatrix}
  						x \\
  						y \\
  						z \\
  						0
 					\end{pmatrix} =  ( x, y, z, 0 )  
$


Násobení bodu stejnou tranformační maticí způsobí posun bodu v závislosti na použité translační matici.


$
\begin{pmatrix} 
 	1 & 0 & 0 & posunX \\
  	0 & 1 & 0 & posunY  \\
  	0 & 0 & 1 & posunZ  \\
  	0 & 0 & 0 & 1
\end{pmatrix}  \cdot \begin{pmatrix}
  						x \\
  						y \\
  						z \\
  						1
 					\end{pmatrix} = ( x + posunX, y + posunY, z + posunZ, 1)
$


Mezi vektory a body je samozřejmě možné provádět explicitní konverzi v případě, že je taková operace potřeba.



\section{ Podpora pro vykreslovaní }

\subsection{ Proces vykreslovaní }
Rendering je poměrně složitý a komplexní proces. Kompletní postup od inicializace, zobrazení až po uvolnění použitých prostředků můžeme rozdělit na několik částí. 

\begin{enumerate}
\item inicializace OpenGL
\item nahrání textur na GPU
\item nahrání geometrie na GPU
\item nastavení kamery, světel a objektů scény
\item render scény (odkazuje se na data nahraná na GPU )
\item zobrazení vyrenderované scény v přednastaveném okně
\item smazání GPU dat
\item uvolnění ostatních OpenGL prostředků
\end{enumerate}


% TODO, tohle pripadne trochu zvelebit, rozepsat a zformatovat
%-model ma matici -> ta transformuje geometrii, rika kam %vykreslit
%-model ma MeshObject
%	1.	VBOid ( kterou geometrii ulozenou na GPU pouzit )
%	2.	Material ptr  ( vlastnosti materialu ktery na geometrii %aplikovat )
%	3.	TextureId array ( ktere textury ulozene na GPU na %geometrii aplikovat )


\subsection{ Render třídy }
\subsubsection{ AbstractRender }
\dspFuncName{AbstractRender} je abstraktní bázová třída zajišťující render. 
Primárně je třída navržena pro použití s GPU renderem.
Rozhraní je tak přednostně uzpůsobeno možnostem a logice grafických karet.
\dspFuncName{AbstractRender} definuje základ společného rozhraní, které musí všechny odvozené renderovací třídy implementovat.
Logiku a postup při vykreslování můžeme shrnout do následujícího seznamu. 

\begin{enumerate}
\item nastavení parametrů třídy ( kam a jak renderovat )

\item zahájení renderu nového snímku zavoláním metody \dspFuncName{beginFrame()}
 
\item kreslení geometrie scény

\item ukončení renderu snímku a zobrazení výsledného obrázku zavoláním metody \dspFuncName{endFrame()}

  
\end{enumerate}

\subsubsection{ Render }
\dspFuncName{Render} třída je odvozena od \dspFuncName{AbstractRender}, je navržena pro perspektivní rendering a 
implementována prostřednictvím OpenGL.
Kromě základního rozhraní předepsaného třídou \dspFuncName{AbstractRender} poskytuje třída velké množství dalších funkcí. 
Můžeme tak renderovat základní geometrické tvary jako je čára, kružnice, koule nebo třeba polygon.
Dále je možné renderovat komplexnější geometrii jako například 
modely, částice, billboardy, obrázky nebo bitmapový text.
Před začátkem renderu každého nového snímku je navíc možné nastavovat parametry kamery, z jejíž pohledu se scéna bude renderovat.

\subsubsection{ GLPhongRender }
Rozšiřuje možnosti třídy \dspFuncName{Render} o osvětlování geometrie prostřednictvím Phongova světelného modelu.
Tento výpočet je prováděn per-pixel pomocí dodáváného shaderu.
Shader kompatibilní s touto třídou je uložen v adresáři \dspFuncName{kodiak/shaders/phongShaderSoftProj.cg}.

\subsubsection{ SoftProjRender }
Render třída odvozená od předešlého \dspFuncName{GLPhongRender}, obsahuje další pomocné kreslící funkce napsané na míru potřebám hry.

\subsection{ Vertex Buffer Object správce }
\dspFuncName{VBOmanager} je správce dat pro práci s grafickými primitivy 
uloženými přímo v paměti grafické karty. Prostřednictvím této třídy
může uživatel nahrávat na grafickou kartu geometrii: pole vertexů, 
normál a texturovacích koordinátů. K nim lze poté prostřednictvím
vrácených OpenGL identifikátorů přistupovat. 
Tyto identifikátory jsou ukládány společně s uživatelem 
definovaným názvem do databáze. Prostřednictvím zadaného názvu je možné získat data uložená v databázi a dále s nimi potom pracovat.

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=1.2]{./VBOmanager.eps}
	\caption{Vertex Buffer Object: nahrání nové geometrie. }
\end{center}					
\end{figure}

\subsection{ Textury }
\dspFuncName{TextureManager} je singleton třída sloužící ke správě OpenGL textur. 
\dspFuncName{TextureManager} umožňuje nahrávat textury, mazat je a dále s nimi pracovat.
Po vložení textury dojde k jejímu nahrání do paměti grafické karty.
S nahranou texturou potom můžeme pracovat pouze nepřímo pomocí navráceného OpenGL identifikátoru.
Tento identifikátor spolu s uživatelsky definovaným názvem textury se ukládá v databázi. K texturovým OpenGL identifikátorům tak můžeme s pomocí databáze přistupovat i pod uživatelem zadaným názvem a s texturami tak pohodlně pracovat.

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=1.2]{./textureManager.eps}
	\caption{Texture manager: práce s texturou. }
\end{center}					
\end{figure}


\subsection{ Materiály }
Třída \dspFuncName{Material} je abstraktní bázová třída každého materiálu. 
Od ní je odvozena třída \dspFuncName{PhongMaterial}. Ta obsahuje následující atributy materiálu.

\begin{itemize}
\item float ambient[3]
	\\ RGB trojice ambientní složky materiálu.
\item float diffuse[3]
	\\ RGB trojice difůzní složky materiálu.
	
\item float specular[3]
	\\ RGB trojice glossy složky materiálu.
\item float exponent
	\\ exponent určující chování lesklého materiálu.
\end{itemize}

Tyto parametry jsou potřebné pro výpočet osvětlení pomocí Phongova osvětlovacího modelu, který bude popsán v jedné z následujících částí.


\subsection{ Phongův světelný model }
Phongův světelný model aproximuje osvětlení ve scéně rozdělením na 3 části.

\begin{enumerate}
  	\item ambientní složka
	\item difůzní  složka
	\item lesklá (glossy) složka
\end{enumerate}


Ambientní osvětlení spočteme jako: $Final_{ambient} = C_{a} \cdot I_{a}$, kde
\begin{itemize}
\item $C_{a}$ je ambientní složka materiálu
\item $I_{a}$ je ambientní složka světla
\end{itemize}
.

Difůzní složku osvětlení spočteme jako: $Final_{diffuse} = C_{d} \cdot I_{d} \cdot (N \cdot L)$, kde
\begin{itemize}
\item $C_{d}$ je difůzní složka materiálu
\item $I_{d}$ je difůzni složka světla
\item $N$ je normála povrchu
\item $L$ je vektor světla
\end{itemize}
.

Glossy složka je určena vztahem: $Final_{glossy} = C_s \cdot I_s \cdot (V \cdot R)^n$, kde
\begin{itemize}
\item $C_s$ je lesklá složka materiálu
\item $I_s$ je lesklá složka světla
\item V je vektor pohledu
\item R je vektor ideálního odrazu dopadajícího světla
\item n je exponent určující další nastavení lesklosti
\end{itemize}.

Výsledné osvětlení nakonec spočteme součtem všech tří uvedených komponent: 
$Final_{radiance} = Final_{ambient} + Final_{diffuse} + Final_{glossy}$.


\begin{figure}[H]
\begin{center}
	\includegraphics[scale=0.7]{./phongPicture.eps}
	\caption{Phongův světelný model }
\end{center}					
\end{figure}


\subsection{Načítání geometrie z externích souborů}
Program podporuje načítání geometrie ze dvou externích formátů: výškové mapy a OBJ souboru.

\subsubsection{ Výšková mapa }
Výšková mapa je obvykle reprezentovaná ve formě textury. Pozice texelu společně s jeho hodnotou udává souřadnice vrcholu. Konverzi takového vstupu na vertexy, normály a texturové koordináty zajišťuje třída \dspFuncName{HeightMapImporter}. Vrácená a zpracovaná data je potom možné nahrát prostřednictvím třídy \dspFuncName{VBOmanager} do paměti grafické karty.

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=1.2]{./heightMap.eps}
	\caption{Schéma: data zdrojové textury vlevo a vpravo výsledná geometrie }
\end{center}					
\end{figure}

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=0.6]{./example0Part0.eps}
	\caption{Ukázka výškové textury... }
\end{center}					
\end{figure}


\begin{figure}[H]
\begin{center}	
		\includegraphics[scale=0.85]{./example0Part1.eps}
	\caption{...a z ní vygerenované geometrie. }
	
\end{center}					
\end{figure}



\paragraph{Skriptování}
Hlavní výhodou výškových map je jejich jednoduchost. Práce s nimi je intuitivní a lze pomocí nich vytvářet rychle geometrii terénu. My jsme tento systém rozšířili ještě o systém operátorů, kdy lze výškové mapy dále upravovat. K dispozici jsou operace typu výšková mapa - výšková mapa i výšková mapa - skalár. Můžeme tak například sečíst 2 výškové mapy, výdělit jejich součet dvěma a tím získat zprůměrovanou výškovou mapu apd.
Systém operátorů je doplněn o jednoduchý matematický parser, prostřednictvím kterého lze skriptovat geometrii ( viz soubory \dspFuncName{MathParser.h} a \dspFuncName{MathTextureParser.h} \dspFuncName{TextureOperationParser.h}.

\pagebreak[4] 
Ukázka skriptu:
\begin{lstlisting}
geometryScript "tex1.tga"+( 0.5 * "tex2.tga" )
\end{lstlisting}

	\begin{figure}[H]
	\begin{center}	
		\includegraphics[scale=0.5]{tex1.eps}
		\caption{ tex1.tga }
	\end{center}					
	\end{figure}

	\begin{figure}[H]
	\begin{center}	
		\includegraphics[scale=0.5]{tex2.eps}
		\caption{ tex2.tga }
	\end{center}					
	\end{figure}

	\begin{figure}[H]
	\begin{center}	
		\includegraphics[scale=0.5]{tex2_div2.eps}
		\caption{  0.5 * tex2.tga }
	\end{center}					
	\end{figure}


	\begin{figure}[H]
	\begin{center}	
		\includegraphics[scale=0.5]{tex3.eps}
		\caption{ tex1.tga + ( 0.5 * tex2.tga ) }
	\end{center}					
	\end{figure}


\subsubsection{ OBJ a MTL formát }

\paragraph{OBJ}
OBJ je  poměrně oblíbený grafický formát, který je podporován většinou modelovacích nástrojů jako například 3D Studio Max nebo Maya. Formální specifikace formátu je k dispozici například na  \url{ http://paulbourke.net/dataformats/obj/ }.
K načítání tohoto formátu slouží třída \dspFuncName{ModelOBJ<T>}. Ta přečte a naparsuje data ze souboru a vrátí zpracovaná data k dalšímu použití. Ty můžeme dále opět s pomocí třídy \dspFuncName{VBOmanager} uložit na grafickou kartu.

\paragraph{ MTL }
S OBJ formátem velmi úzce souvisí MTL formát. Ten definuje materiály a geometrie specifikovná v OBJ formátu se do tohoto souboru odkazuje. Parsování obstarává třída \dspFuncName{MTLreader} a správu materiálů potom třída \dspFuncName{MaterialManager<T>}
 Podrobnosti k formátu je možné získat zde  \url{ http://paulbourke.net/dataformats/mtl/ }.
Materiál kromě atributů popisující jeho vlastnosti ( viz třída \dspFuncName{Material} ) může obsahovat i názvy textur, které používá. Textury jsou podobně jako geometrie uložena ve VRAM paměti, odkud je možné s nimi při kreslení rychleji pracovat ( viz výše popsaný \dspFuncName{TextureManager} ).


\begin{figure}[H]
\begin{center}
	\includegraphics[scale=1.5]{OBJ_MTL_process.eps}
	\caption{Proces zpracovaní *.obj a *.mtl souborů. }
\end{center}					
\end{figure}



\begin{figure}[H]
\begin{center}
	 %\setlength{\evensidemargin}{-.8in}
	\includegraphics[scale=1.9]{ModelOBJ.eps}
	\caption{ModelOBJ objekt }
\end{center}					
\end{figure}


\subsection{Model}
Třída \dspFuncName{Model} slouží k reprezentaci komplexních objektů v 3-rozměrném prostoru. 
Pozice, velikost a orientace objektu je definována pomocí matice třídy \dspFuncName{Matrix4x4<T>}, 
kterou jsme popsali v jedné z předchozích částí dokumentace. 
Každý model se dále skládá z jedné nebo více homogenních částí, tak zvaných Meshů.
Mesh je skupina polygonů používající společnou sadu vertexů, 
texturovacích koordinátů, normál, materiálů a textur. 
Mesh reprezentujeme prostřednictvím třídy \dspFuncName{MeshObject}. 
\dspFuncName{MeshObject} obsahuje informace o použitých texturách, materiálu a geometrii objektu.

\pagebreak[4] 
\begin{lstlisting}
class Model
{
private:
	Matrix4X4<float> modelMatrix;
	vector<MeshObject> meshes;

public:
	...
};
\end{lstlisting}


\subsection{Kamera}
Třída \dspFuncName{Camera<T>} slouží k práci s kamerou v 3-rozměrném prostoru. Nastavovat můžeme pozici nebo směr pohledu kamery a tím měnit pohled na scénu. Pro pohodlnější práci s kamerou nabízí třída řadu pomocných metod jako například posun kamery ve směru pohledu, otáčení kamery a další. 
Konfigurace kamery je určena následujícími atributy.
\begin{itemize}
\item $Point\_3<T> pos$		
	\\Určuje umístění kamery.
\item $Vector\_3<T> look$		
	\\Určuje směr, kterým se kamera dívá.
\item $Vector\_3<T> right$		
	\\Určuje kde je z pohledu kamery pravá strana.
	
\item $Vector\_3<T> up$		
	\\Určuje kterým směrem je z pohledu kamery vzhůru. Dopočítává se automaticky jako kolmice na look a right vektor.
\end{itemize}


\begin{figure}[H]
\begin{center}
	\includegraphics[scale=0.8]{camera.eps}
	\caption{Kamera }
\end{center}					
\end{figure}

\subsection{ Proces zpracování a zobrazení geometrie}

\begin{enumerate}
\item Načtení geometrie. 
Nejprve je potřeba načíst a rozparsovat geometrii modelu ze souboru.
Načítat lze geometrii ve formě výškové mapy nebo ve formátu OBJ.


\item Zpracování geometrie.
Načtenou geometrii v další části převádíme do podoby kompatibilní s OpenGL Vertex Array a tu pak ukládáme prostřednictvím OpenGL VBO do paměti grafické karty. Tím, že máme geometrii uloženou přímo na GPU výrazně snižujeme objem dat, která je potřeba během renderingu přenášet mezi CPU a GPU. Tím zásadním způsobem urychlujeme kreslení geometrie.

\item Načtení materiálů a textur.
V další části je potřeba načíst a zpracovat materiály a textury, které geometrie používá. Program podporuje načítání materiálů ve formátu MTL.

\item Tvorba modelu. V této chvíli máme načtenou a zpracovanou geometrii a materiály modelu. Odkazy na geometrii a materiály máme uloženy ve správci geometrie a materiálu. Můžeme tak jednoduše vytvořit model používající
uloženou geometrii a materiály ( viz dříve popsaná třída \dspFuncName{Model} ).

\item Kreslení modelu. Na závěr můžeme vytvořený model jednoduše vykreslit prostřednictvím dříve popsané třídy \dspFuncName{Render}.

\end{enumerate}

\subsection{ Částicový systém}
Grafický engine je vybaven také podporou částicových systémů. Částicový systém je rozdělen na 2 části: částice a správce částic.

\subsubsection{ Částice }
Částice je jednoduchý objekt s jehož pomocí se simulují různé objekty bez pevně dané struktury jako například kouř, sníh, tryskající voda a další.

\paragraph{ \dspFuncName{BasicParticle} }
Je základní třída reprezentující částici. Třída obsahuje následující atributy.

\begin{itemize}
\item \dspFuncName{Vector\_3<float>} velocity	\\
	Udává rychlost a směr pohybu částice.

\item float acceleration			\\
	Udává zrychlení částice ve směru pohybu.
	
\item 	float lifeTime		\\
	Životnost částice.

\item 	\dspFuncName{Point\_3<float>} position		\\
	Pozice částice.

\end{itemize}

Třída dále obsahuje metodu \dspFuncName{simulate()}, která pomocí nastavených atributů částice provádí simulaci. K simulaci používáme Eulerovskou diskrétní metodu prvního řádu.

\pagebreak[4]
\begin{lstlisting}
void BasicParticle::simulate( float dt )
{
   this->velocity += this->acceleration * dt;
   this->position += this->velocity * dt;
   this->lifeTime -= dt;
}
\end{lstlisting}

\paragraph{ \dspFuncName{GraphicParticle}}
Je pokročilá částicová třída odvozená od \dspFuncName{BasicParticle}.
Obsahuje navíc atributy popisující částici z grafického hlediska.

\begin{itemize}
\item float colorOffset[4]	\\
		Určuje, jak se bude měnit barva částice během simulace.
		
\item	float sizeOffset	\\
		Určuje, jak se bude měnit velikost částice během simulace.


\item	float color[4]		\\		
		Určuje aktuální barvu částice.
		
\item	float size			\\
		Určuje aktuální velikost částice. Částice je vždy čtvercová o délce strany size.
		
\item	unsigned int textureID	\\
		Identifikátor textury, která se má na částici namapovat.

\end{itemize}

\dspFuncName{GraphicParticle} rozšiřuje metodu \dspFuncName{simulate()} o simulaci nově přidaných atributů. Dále potom přidává metodu \dspFuncName{render()}. Ta zajišťuje vykreslení částice podle jejích parametrů do aktuálního OpenGL kontextu.


\subsubsection{ Správce částic }
Emitor je objekt, který spravuje existující částice. Základ tvoří třída \dspFuncName{BasicEmittor}.
Ta obsahuje metody \dspFuncName{simulate()} a \dspFuncName{garbageRequest()}.

Metoda \dspFuncName{simulate()} iteruje polem částic a na každou částici volá její metodu \dspFuncName{simulate()}, kterou každá částice obsahuje.
Metoda \dspFuncName{garbageRequest()} odstraní staré, neaktivní částice.

Další metody jako například \dspFuncName{emitNewParticles()} a jiné, je nutné dodefinovat v odvozené třídě v závislosti na konkrétních potřebách emitoru.

     
\section{Vlastní hra}     
\subsection{Hvězdná mapa} 
Hvězdná mapa zobrazuje vesmír v okolí aktivní lodě. Hvězdná mapa je rozdělena do dvou logických částí, režim makro a mikro mapy.

\subsubsection{Mikro mapa} 
Zobrazuje detailní náhled na nejbližší okolí hráčovy lodě. V tomto režimu jsou vidět jednotlivé lodě a planety. Mikro mapa je spravována prostřednictvím třídy 
\dspFuncName{ MapFunctionality }. Ta ve spolupráci s třídou \dspFuncName{ SoftProjRender } zajišťuje renderování okolního vesmíru, jehož komponenty si v krátkosti popíšeme.

\begin{itemize}

\item Lodě \\
Reprezentujeme je třídou \dspFuncName{SpaceShip}. Ta obsahuje atributy potřebné pro zobrazování a simulaci lodi. Grafiku lodi zajišťuje objekt \dspFuncName{Model}, jenž je součástí třídy.

\item Planety \\
Jsou reprezentovány třídou \dspFuncName{BasicPlanet}. Třída obsahuje parametry potřebné pro zobrazování a simulaci. Geometrií planety je vždy koule a můžeme proto jednoduše generovat geometrii procedurálně. To nám umožňuje používat tzv. 
Progressive Level of Detail: V závislosti na vzdálenosti planety od pozorovatele měníme kvalitu geometrie \footnote{Použité obrázky viz \url{http://www.search.com/reference/Level_of_detail}}.
Tím efektivně snižujeme počet renderovaných polygonů a tím šetříme čas GPU.

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=0.2]{sphereLow.eps}
	\caption{ Hrubá aproximace koule ~140 vrcholů }
\end{center}					
\end{figure}

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=0.2]{sphereMedium.eps}
	\caption{Normální koule ~670 vrcholů }
\end{center}					
\end{figure}

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=0.2]{sphereHigh.eps}
	\caption{Detailní koule ~5500 vrcholů }
\end{center}					
\end{figure}


\item Rakety \\
Rakety jsou střely lítající mezi nepřátelskými loděmi během souboje.
Reprezentuje je třída \dspFuncName{SpaceMissile}. Podobně jako v případě lodí obsahuje třídu \dspFuncName{Model}, která spravuje modely střel + atributy potřebné pro jejich fyzikální simulaci.

\item Částice \\
Lodě a rakety generují částice, ty byly obecně popsány v sekci Částicový systém. Pro účely aplikace bylo implementováno několik emitorů částic ( pro každý typ lodi jiný ), viz soubor \dspFuncName{ShipEmittor.h}.

\item Exploze \\
Exploze jsou tvořeny sekvencí obrázků utvářející plynulou animaci výbuchu.
Tyto animace realizuje třída \dspFuncName{AnimationEffect}.

\begin{figure}[H]
\begin{center}
	\includegraphics[scale=1.0]{explosion.eps}
	\caption{Série střídajících se obrázků tvořící animaci }
\end{center}					
\end{figure}

\end{itemize}

\subsubsection{Makro mapa} 
Zobrazuje prozkoumané části vesmíru. Objevené sluneční soustavy jsou symbolizovány 2D obrázkem, podobně jako lodě v okolí.
Funkce makro mapy zajišťuje třída \dspFuncName{RadarMapGame}.



\subsection{Komunikace} 

Veškerá komunikace klienta s herním serverem probíhá přes třídy CommandClient a SocketClient. Vysokoúrovňovou komunikaci zajišťuje třída CommandClient, která je zodpovědná za posílání požadavků na server a přijímání odpovědí a aktualizací od serveru. Všechny tyto požadavky a odpovědi mají již formát herních dat a komunikace je pro klienta přes CommandClient transparentní v tom smyslu, že se nemusí starat o vytváření textových zpráv, které se ve skutečnosti na server posílají. Pro komunikaci směrem na server tedy CommandClient přijímá skutečná herní data a stará se o jejich zakódování do textového formátu, při komunikaci směrem od serveru naopak rozkódovává textové zprávy a plní herní struktury, které pak předává dále hlavní třídě MainWindow. CommandClient se tedy nikdy nestará o další akce s herní strukturou, o práci s GUI, nebo libovolné jiné rozhodování. Pouze provede dekódování a o další práci už se stará třída MainWindow. CommandClient pouze ví, jakou metodu MainWindow má volat pro který druh zprávy. Na jednu zprávu totiž může klient reagovat více způsoby, v závislosti na svém stavu, který se však v CommandClient nijak neukládá, o to vše se již stará třída MainWindow.

Veškeré požadavky klienta na server, které CommandClient přijímá, mají formu veřejných metod, protože je klient používá k vytváření svých požadavků na server. Naproti tomu všechny metody pro přijímání odpovědí od serveru jsou privátní, protože tyto metody klient nikdy nevolá sám. Metody pro odpovědi volá sám CommandClient vždy, když od něj klient požaduje další zprávu.

Jakou privátní metodu na dekodování zprávy má CommandClient zavolat se rozhoduje podle jejího jména. K tomu slouží třída HandlerWrapper, která mapuje jména zpráv na metody, které je dekódují. CommandClient vždy pracuje pouze v pevném intervalu, který je defaultně nastavený na 500ms a může se přenastavit metodou setTimeLimitForProcessing. Po dobu tohoto intervalu vždy vyzvedne jednu  zprávu z fronty připravených zpráv, podívá se na její jméno a najde pomocí třídy HandlerWrapper odpovídající metodu na dekódování, která provede převod zprávy do herních struktur. Po dekódování zprávy CommandClient zavolá odpovídající metodu na MainWindow a předá ji dekodovaná herní data. Pokud stihne zpracovat zprávy ve frontě dřív, tak skončí aktuální zpracování až do dalšího intervalu.

Komunikace má tři hlavní vrstvy: Nejvyšší vrstvu CommandClient, která pracuje přímo s herními strukturami, střední vrstvu SocketClient, která pracuje s textovými zprávami a třídu client, která provádí skutečné zasílání a přijímání zpráv a zapouzdřuje práci se sockety. Důvod, proč je mezi třídou client a CommandClient ještě třída SocketClient, která nemá v porovnání s ostatními dvěma třídami zdaleka tolik práce je ten, že chceme maximální odstínění třídy pro práci se sockety a synchronizací a nejvyšší vrstvy, která pracuje s herními daty. Třída client díky tomu zná pouze třídu SocketClient, které zprávy předává a nebo je od ní přijímá. 


\subsubsection{Směr na server}

CommandClient zasílá zprávy přes třídu SocketClient, která se stará o komunikaci na nižší úrovni. ClientCommand se tedy nestará o skutečné posílání zpráv, pouze zprávy zakóduje do textového formátu a předá třídě SocketClient. K tomu využívá třídu protocolWriter, která zapisuje herní struktury do textové formy zprávy, vždy jako název parametru a jeho hodnotu. ProtocolWriter však nezapisuje herní struktury jako celek, protože dokáže zapisovat jenom primitivní datové typy. Zakódování herní struktury tedy provádí CommandClient, který bere jednotlivé primitivní datové položky herní struktury a předává je třídě protocolWriter, která provede skutečné zapsání. Pokud herní struktura obsahuje složené datové typy, zapisují se opět pouze jejich primitivní datové položky. Pole a kolekce se zapisují pomocí přidávání indexů k parametrům, pro vnořené třídy se používá prefix a následně se vypisují její primitivní datové typy.

Pro zapsání zprávy přes protocolWriter využívá CommandClient především funkci beginMessage, která zahájí tvorbu zprávy a které jako typ zprávy vždy předá hodnotu messageType::MT\_REQUEST, protože se jedná o požadavek na server. Dále jí předá jméno zprávy, které reprezentuje jméno požadavku na server a také se shoduje s názvem příslušné odpovědi. Následně zapisuje jednotlivé položky herních struktur pomocí metody writeValue, která vždy dostane název parametru a jeho hodnotu. Po skončení zápisu zavolá metodu endMessage a dá jí vždy příznak true, což znamená, že se jedná o nechybovou zprávu. 

Ve skutečnosti nepoužívá CommandClient protocolWriter přímo, ale používá ještě nad ním třídu requestWriter, která pro každý požadavek obsahuje vlastní metodu, která provede skutečné zakódování do textové podoby. Díky tomu je CommandClient přehlednější, protože se stará převážně o vysokoúrovňové kódování zpráv a komunikaci s MainWindow, zatímco samotné kódování provádí třída pod ním.

Vytvořenou zprávu následně CommandClient zašle na server pomocí nižší třídy SocketClient. SocketClient pouze předá zprávu nižší třídě client a uvolní alokovanou paměť pro vytvořenou zprávu.

\subsubsection{Směr od serveru}

Veškeré metody, které představují metody na dekódování odpovědí od serveru, mají prefix process a zbytek jejich jména se vždy shoduje s daným požadavkem na server, pokud jim nějaký odpovídá. Ne všechny zprávy od serveru totiž musí být posílány jako reakce na klienta, například serverová oznámení, že si klient má aktualizovat aktuální stav zobrazené sekce. Metody vždy přijímají ukazatel na objekt třídy message, která představuje prostřední vrstvu mezi textovým formátem a herními strukturami. Jedná se třídy obsahující mapu, která uchovává textové dvojice název – hodnota. CommandClient čte tyto zprávy a plní z nich herní struktury. Vytvoření zprávy v tomto meziformátu má na starosti třída protocolReader, která je vytváří přímo z textové podoby zprávy. CommandClient tedy nečte skutečnou textovou zprávu, ale využívá metodu translate třídy protocolWriter, aby získal rovnou meziformát, ze kterého pak pouze čte jako z mapy hodnot. 

Ke čtení meziformátu využívá CommandClient třídy ValueReader. To je užitečné především k tomu, aby nemusel CommandClient opakovaně konvertovat řetězce, které jsou v mapě uložené, na skutečný datový typ, který má odpovídající parametr mít. Zároveň poskytuje metody pro čtení indexovaných hodnot, takže CommandClient zadá pouze název parametru a index a ValueReader už provede převod na skutečné jméno parametru včetně zahrnutí indexu ve standardním tvaru, čímž zamezuje vzniku chyb, který by jinak mohl vznikout při opakování stejného kódu. ValueReader se vždy vytváří na zásobníku a přijímá zprávy v meziformátu. CommandClient pak na něm volá přístupové metody, které ValueReader pouze deleguje na meziformát k získání textové hodnoty parametru a následně provede přetypování a vrátí skutečnou hodnotu.

Zprávy přijímá CommandClient od nižší vrstvy, třídy SocketClient, která využívá třídu client, která pouze zapouzdřuje práci se sockety a představuje tedy nejnižší vrstvu komunikace. Má na starosti synchronizaci při práci se sockety a odstiňuje od ní vyšší vrstvy. K tomu využívá dvě vlákna, jedno pro přijímání zpráv ze socketu a druhé pro posílání zpráv do socketu. Při odesílání zprávy jí třída CommandClient pouze předá zprávu v textové podobě pomocí metody send. O její odeslání se už se postará třída client, která ji nemusí odeslat hned, ale může si ji nejprve zařadit do fronty. Stejně při přijmu zprávy třída client zavolá metodu receiveMessage třídy SocketClient a tím ji upozorní, že dorazila nová zpráva. Čekání na socketu na příjem zprávy tedy provádí pouze třída client a vyšší vrstvy jsou na zprávu upozorňovány v momentě, kdy nějaká dorazí. 

Při přijmu zprávy tedy volá client metodu receiveMessage třídy socketClient. Předtím ji však rozkoduje do meziformátu a třídě SocketClient předá rovnou tento meziformát. SocketClient si  vzniklou zprávu pouze zařadí do fronty zpráv a dál se zprávou nic nedělá. Pro správné zařazení do fronty musí na frontu nejprve získat mutex zámek, aby nedošlo k porušení synchronozace. Ve chvíli, kdy CommandClient začne pracovat v rámci svého pracovního intervalu čtení zpráv, řekne si sám třídě SocketClient o další zprávu ve frontě. V tuto chvíli opět musí nejprve získat mutex zámek na frontu. 

Následně se CommandClient podívá na název požadavku a najde odpovídající metodu na rozkodování do herní struktury. Narozdíl od kódování, kde využíval třídu requestWriter, zde provádí dekódování přímo sama třída CommandClient. 

Po dekódování volá metodu třídy MainWindow, která pak dále s herní strukturou pracuje.

Kroky komunikace při aktualizaci dat:
\begin{enumerate}
\item Uživatel zadá příkaz na aktualizaci dat nějakého widgetu, například kliknutím myší na nějaké tlačítko, nebo zadá příkaz na některou herní akci, která se musí zaslat na server, například chce postavit nový předmět v hangárech.

\item Příslušný widget vygeneruje signál, kterým signalizuje žádost o aktualizaci dat a v němž zároveň předá příslušné datové struktury, které jsou k požadavku potřebné.

\item MainWindow zachytí vygenerovaný signál do slotu, který obsluhuje daný signál. 

\item MainWindow zvolí a zavolá metodu pro daný požadavek na třídě CommandClient a předá jí herní strukturu, která se k požadavku vztahuje.

\item CommandClient zavolá metodu pro daný požadavek na třídě requestWriter a předá jí herní datovou strukturu, kterou chce zakódovat.

\item RequestWriter zakóduje požadavek do textové podoby a výsledek vrátí třídě CommandClient. Pokud požadavek obsahuje nějaká data pro server, provede také jejich zakodování.

\item CommandClient zavolá metodu sendAndFreeMessage třídy SocketClient a předá ji vytvořenou textovou zprávu. 

\item SocketClient zavolá metodu send třídy client, který odešle zprávu přes socket na server. Následně odstraní zadanou zprávu z paměti

\end{enumerate}


Kroky komunikace směrem od serveru:
\begin{enumerate}
\item  Server zašle klientovi textovou zprávu, například pro aktualizaci dat některé herní sekce.

\item  Třída client stále čeká ve svém vlastním pracovním vlákně na socketu. Při příjmu zprávy ze socketu ji dekóduje pomocí třídy protocolReader a získá tak meziformát zprávy s mapou hodnot.

\item  Třída client zavolá metodu acceptMessage na třídě SocketClient, která si zprávu zařadí do fronty zpráv.

\item  CommandClient v rámci svého pracovního intervalu vyzvedne zprávu z fronty a podle jejího jména nalezne odpovídající metodu pro zpracování pomocí třídy HandlerWrapper.

\item  CommandClient dekóduje zprávy z meziformátu do herní struktury tak, že čte jednotlivé parametry z mapy hodnot zprávy.

\item  CommandClient zavolá pevně danou metodu třídy MainWindow, určenou pro zpracování dané zprávy a předá jí vyplněnou herní strukturu.


\end{enumerate}



\subsection{GUI}
Hlavní třídou GUI je třída MainWindow, která zastřešuje veškeré klientské widgety, koordinuje jejich práci a zajišťuje pro ně veškerou komunikaci se serverem. Žádný widget totiž nemůže komunikovat se serverem přímo, ale musí vždy požadavky posílat přes třídu MainWindow. Stejně tak odpovědi dostává pouze od třídy MainWindow, což je užitečné zejména proto, že pouze MainWndow udržuje herní stav klienta a může proto rozhodnout, jak s obdrženou zprávou od serveru naložit. 

Například při příjmu zprávy se seznamem lodí záleží na herním stavu klienta, jak s přijatými daty naloží. Například pokud je ve stavu obchodování, předá seznam widgetu pro obchodování, pokud je ve stavu bojování, předá data widgetu pro bojování. Také může přijadá data zcela odmítnout a zahodit, pokud je v takovém stavu, ve kterém daná data nepožaduje. To se může stát, pokud například zažádá o aktualizační data v jednom widgetu, ale ještě než dostane od serveru odpověď, přepne se hráč do jiného widgetu. V takovém případě jsou přijatá data zbytečná a zahodí se.

Pro widgety probíhá komunikace se serverem většinou asynchronně, což znamená, že widgety zašlou požadavek přes MainWindow a na odpověď už přímo nečekají. Při příjmu zprávy jim pak MainWindow předá aktualizační data a widgety se podle nich aktualizují. Ve většině případů si proto widgety žádný stav uchovávat nemusí a pouze na zprávy od serveru reagují a podle nich se aktualizují. V některých případech to však je přesto nutné – například při obchodování, nebo bojování.

Pro zpracování odpovědí od serveru používá MainWindow privátní metody, které jsou označeny prefixem answer a zbytek jména odpovídá názvu příslušného požadavku. Díky tomu CommandClient ví, jakou metodu má zavolat, když naplní herní data ze zprávy od serveru. 

Mnoho widgetů reprezentuje celou herní sekci, například sekci lodních štítů, zbraní, nebo větší herní sekce jako obchodování, bojování, nebo budování. Takové widgety se skládají často z dalších podwidgetů. Budeme je dále nazývat hlavní herní widgety, protože jsou mnohem komplexnější než různé menší podpůrné widgety.

Všechny takové widgety se aktualizují vždy, když uživatel vstoupí do nějaké herní sekce, kterou widget reprezentuje. Díky tomu jsou data vždy poměrně aktuální. Většina widgetů používá na svou aktualizaci jen jeden požadavek na server, který aktualizuje rovnou celý widget. Některé větší widgety, jako například obchodování, budování nebo bojování, zasílají požadavků více, protože obsahují ještě další vnořené widgety, které se mouhou aktualizovat nezávisle na ostatních widgetech, nebo proto, že není možné kvůli velikosti zasílat rovnou celý možný stav widgetu – například při souboji, kde chceme znát všechny hráčovy lodě a zároveň pro každou jeho loď také lodě v dosahu střelby. V takovém případě by bylo zbytečně náročné posílat pro všechny hráče všechny okolní lodě, protože hráč má stejně vždy vybranou jen jednu aktivní loď. Navíc by taková obrovská data rychle ztrácela na aktuálnosti. Proto se data o lodích v okolí zasílají až pro aktivní vybranou loď.

Pro aktualizaci využívají jednotlivé widgety, které reprezentují hlavní herní sekce, téměř vždy jednu aktualizační strukturu, ve které dostávají potřebná data od serveru. Podle ní aktualizují svůj stav a strukturu si uloží do té doby, než provedou další aktualizaci, což je užitečné k tomu, že mohou provádět průběžnou aktualizaci některých údajů, které se časem mění poměrně pravidělně, aniž by museli pořád se serverem komunikovat – stačí když si pamatují rychlost změny a původní stav a z něj již mohou dopočítat nový stav. To platí například u počtu surovin, nabíjení energíí do některých zařízení, nebo při stavbě předmětu či lodě v hangáru, kde chceme zobrazovat postup výroby. 

%\subsubsection{ \dspFuncName{ClientSynchronizer}} 
%Dostává rozparsovaná data lodí a planet od třídy \dspFuncName{CommandClient}.
%\dspFuncName{ClientSynchronizer} při každé synchronizaci porovnává informace od serveru %s lokálními daty na klientu a provádí jejich synchronizaci.
%Pokud přijdou od serveru informace o nové lodi nebo planetě, která na klientu dosud není uložena, tak objekt vytvoří a vloží do lokálních datových struktur. Data přimo související s Makro mapou se ukládájí do \dspFuncName{RadarData}.
%Data Mikro mapy jsou potom uchovávány v  \dspFuncName{GalaxyPart} objektu.

%\begin{figure}[H]
%\begin{center}
%	\includegraphics[scale=1.6]{ClientSynchronizer.eps}
%	\caption{Proces synchronizace lodí a planet }
%\end{center}					
%\end{figure}

%\subsection{GUI} 

             
