OGLES2Navigation.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601
  1. /******************************************************************************
  2. @File OGLES2Navigation.cpp
  3. @Title Navigation
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independent
  7. @Description Demonstrates a method of rendering a navigation application using
  8. OpenGL ES 2.0
  9. ******************************************************************************/
  10. #include <stddef.h>
  11. #include "PVRShell.h"
  12. #include "OGLES2Tools.h"
  13. /******************************************************************************
  14. Class forward declarations
  15. ******************************************************************************/
  16. class CPVRTWorkingSet;
  17. /******************************************************************************
  18. Defines
  19. ******************************************************************************/
  20. // All indices will be made up of 16 bit unsigned integers
  21. typedef PVRTuint16 index_t;
  22. // Index the attributes that are bound to vertex shaders
  23. #define VERTEX_ARRAY 0
  24. #define TEXCOORD_ARRAY 1
  25. #define WORDINDEX_ARRAY 1
  26. #define ATTRIB_ARRAY 2
  27. #define MAPFILEIO_SECURITYCHECKPOINT 0xFACEBEED
  28. #define MAPFILEIO_VERSION 1
  29. #ifndef DEG2RAD
  30. #define DEG2RAD(x) (0.0174532925199432f * (x))
  31. #endif
  32. /****************************************************************************
  33. ** Enums
  34. ****************************************************************************/
  35. enum RenderMethod
  36. {
  37. RENDER_FLATCOLOURED,
  38. RENDER_ANTIALIASEDLINES,
  39. RENDER_SIGNS,
  40. RENDER_TEXT,
  41. RENDER_BILLBOARD_TEXT,
  42. RENDER_DISABLED
  43. };
  44. /****************************************************************************
  45. ** Structures
  46. ****************************************************************************/
  47. /*!***********************************************************************
  48. * @Struct PVRTBoundingBox2D
  49. * @Brief Structure describing a 2D bounding box. Supports all kind of
  50. * set operations and provides higher level functionality.
  51. ************************************************************************/
  52. struct PVRTBoundingBox2D
  53. {
  54. // Min and max coordinates
  55. PVRTVec2 minCoords;
  56. PVRTVec2 maxCoords;
  57. };
  58. /*!***********************************************************************
  59. * @Struct PVRTBoundingCircle
  60. * @Brief Structure describing a 2D bounding circle.
  61. ************************************************************************/
  62. struct PVRTBoundingCircle
  63. {
  64. PVRTVec2 center;
  65. float radius;
  66. };
  67. /*!***********************************************************************
  68. * @Struct PVRTViewFrustum
  69. * @Brief Structure containing all view frustum corners.
  70. ************************************************************************/
  71. struct PVRTViewFrustum
  72. {
  73. // Encoding:
  74. // n == near, f == far, t == top, b == bottom, l == left, r == right
  75. PVRTVec3 ntl, ntr, nbl, nbr;
  76. PVRTVec3 ftl, ftr, fbl, fbr;
  77. };
  78. /*!***********************************************************************
  79. * @Struct PVRTVertex
  80. * @Brief Stores two-dimensional position and texture coordinates.
  81. ************************************************************************/
  82. struct PVRTVertex
  83. {
  84. PVRTVec2 position;
  85. PVRTVec2 texcoord;
  86. };
  87. /*!***********************************************************************
  88. * @Struct PVRTPivotQuadVertex
  89. * @Brief The PivotQuadVertex structure describes a single vertex within
  90. * a screen-space aligned series of quads. It contains the origin
  91. * position, the word index determining the position of the letter
  92. * within the word, the quad index which determines the position of
  93. * the vertex within the quad and texture coordinates.
  94. ************************************************************************/
  95. struct PVRTPivotQuadVertex
  96. {
  97. PVRTVec2 origin;
  98. PVRTint8 word_index;
  99. PVRTint8 height_index;
  100. PVRTuint8 u;
  101. PVRTuint8 v;
  102. };
  103. /*!***********************************************************************
  104. * @Struct PVRTVertexDataBucket
  105. * @Brief Contains plain data.
  106. ************************************************************************/
  107. struct PVRTVertexDataBucket
  108. {
  109. PVRTBoundingBox2D boundingbox;
  110. size_t size;
  111. char *pData;
  112. };
  113. /*!***********************************************************************
  114. * @Struct PVRTIndexDataBucket
  115. * @Brief A bucket indexset is a regular indexset which is defined within
  116. * a coordinate bucket. The bounding box describes the extents of
  117. * the contained primitives, which are defined by the indexset.
  118. ************************************************************************/
  119. struct PVRTIndexDataBucket
  120. {
  121. unsigned int bucketindex;
  122. PVRTBoundingBox2D boundingbox;
  123. size_t numIndices;
  124. index_t *pIndices;
  125. };
  126. /*!***********************************************************************
  127. * @Struct PVRTMapBucket
  128. * @Brief A map bucket is a regular map layer which has been split up into
  129. * smaller buckets, which contain the vertex and index data.
  130. * The bounding box describes the extents of the whole map layer.
  131. ************************************************************************/
  132. struct PVRTMapBucket
  133. {
  134. PVRTBoundingBox2D boundingbox;
  135. size_t numVertexDataBuckets;
  136. PVRTVertexDataBucket *pVertexDataBuckets;
  137. size_t numIndexDataBuckets;
  138. PVRTIndexDataBucket *pIndexDataBuckets;
  139. };
  140. /*!**************************************************************************
  141. * @Struct RenderCache
  142. * @Brief A rendercache object is a reference counted vertex buffer object.
  143. ****************************************************************************/
  144. struct RenderCache
  145. {
  146. GLuint vbo;
  147. size_t size;
  148. unsigned int references;
  149. RenderCache()
  150. { vbo = 0; size = 0; references = 0; }
  151. };
  152. /*!**************************************************************************
  153. * @Struct RenderLayer
  154. * @Brief The renderlayer is used to keep an index of active indexsets during
  155. * runtime. Furthermore it contains attributes like colour and the
  156. * actual method used to render the data.
  157. ****************************************************************************/
  158. struct RenderLayer
  159. {
  160. PVRTMapBucket mapbucket;
  161. RenderCache *prendercache;
  162. CPVRTWorkingSet *pworkingset;
  163. PVRTVec4 colour;
  164. PVRTVec2 scale;
  165. RenderMethod renderpath;
  166. const char *pszName;
  167. };
  168. /*!**************************************************************************
  169. * @Struct LayerDescription
  170. * @Brief This structure describes a renderlayer and is just used to
  171. * conveniently store each available layer.
  172. ****************************************************************************/
  173. struct LayerDescription
  174. {
  175. const char *pszFilename;
  176. const RenderMethod renderpath;
  177. const PVRTVec4 colour;
  178. const PVRTVec2 scale;
  179. };
  180. /*!**************************************************************************
  181. * @Struct ShaderDescription
  182. * @Brief This structure describes a shader program and is just used to
  183. * conveniently store each available shader.
  184. ****************************************************************************/
  185. struct ShaderDescription
  186. {
  187. const char *pszVertShaderSrcFile;
  188. const char *pszVertShaderBinFile;
  189. const char *pszFragShaderSrcFile;
  190. const char *pszFragShaderBinFile;
  191. const unsigned int ui32NumAttributes;
  192. const char **pszAttributes;
  193. };
  194. /****************************************************************************
  195. ** Consts
  196. ****************************************************************************/
  197. // Serves as a look-ahead value to prevent popping of non-cached geometry
  198. const float g_fBoundingCircleShift = 0.00128f;
  199. // Global scale factor for the size of the billboard signs and letters
  200. const float g_fPivotQuadScale = 0.000256f;
  201. // Orientation of the plane the roads etc. are being drawn onto
  202. const PVRTVec4 g_MapPlane (0.0f, 0.0f, 1.0f, 0.0f);
  203. // Global colour presets
  204. const PVRTVec4 g_BackgroundColour(0.8509f, 0.8392f, 0.6784f, 0.0f);
  205. const PVRTVec4 g_FloorColour (0.9411f, 0.7921f, 0.6078f, 1.0f);
  206. // Individual layers of the map
  207. const LayerDescription layerdescriptions[] =
  208. {
  209. { "LandUseA_meshes.nav", RENDER_FLATCOLOURED, PVRTVec4(0.752f, 0.9411f, 0.6f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  210. { "LandUseB_meshes.nav", RENDER_FLATCOLOURED, PVRTVec4(0.0f, 1.0f, 0.0f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  211. { "Landmark_meshes.nav", RENDER_FLATCOLOURED, PVRTVec4(0.627f, 0.627f, 0.627f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  212. { "WaterSeg_meshes.nav", RENDER_FLATCOLOURED, PVRTVec4(0.7215f, 0.8f, 0.8509f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  213. { "WaterPoly_meshes.nav", RENDER_FLATCOLOURED, PVRTVec4(0.7215f, 0.8f, 0.8509f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  214. // Anti-aliased lines
  215. { "RailRds_meshes.nav", RENDER_ANTIALIASEDLINES, PVRTVec4(1.0f, 1.0f, 0.5f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  216. { "Streets_meshes.nav", RENDER_ANTIALIASEDLINES, PVRTVec4(0.9790f, 0.9672f, 0.9437f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  217. { "SecHwys_meshes.nav", RENDER_ANTIALIASEDLINES, PVRTVec4(0.8509f, 0.6196f, 0.4156f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  218. { "MajHwys_meshes.nav", RENDER_ANTIALIASEDLINES, PVRTVec4(0.8509f, 0.4745f, 0.2549f, 1.0f), PVRTVec2(1.0f, 1.0f) },
  219. { "MajHwyShield_text.nav", RENDER_BILLBOARD_TEXT, PVRTVec4(0.0f, 0.0f, 0.0f, 1.0f), PVRTVec2(0.075f, 0.08f) },
  220. { "SecHwyShield_text.nav", RENDER_BILLBOARD_TEXT, PVRTVec4(0.0f, 0.0f, 0.0f, 1.0f), PVRTVec2(0.075f, 0.08f) },
  221. { "Streets_text.nav", RENDER_TEXT, PVRTVec4(0.0f, 0.0f, 0.0f, 1.0f), PVRTVec2(0.065625f, 0.07f) },
  222. { "Signs_billboards.nav", RENDER_SIGNS, PVRTVec4(1.0f, 1.0f, 1.0f, 1.0f), PVRTVec2(0.4f, 0.475f) },
  223. };
  224. /******************************************************************************
  225. Content file names
  226. ******************************************************************************/
  227. const char *g_pszSimpleAttribs[] = { "inVertex" };
  228. const char *g_pszAttribs[] = { "inVertex", "inTexCoord" };
  229. const char *g_pszPivotQuadAttribs[] = { "inVertex", "inWordIndex", "inTexCoords" };
  230. const ShaderDescription FlatShaderDescription = { "VertShader.vsh", "VertShader.vsc", "FragShader.fsh", "FragShader.fsc", 1, (const char**)g_pszSimpleAttribs };
  231. const ShaderDescription AALinesShaderDescription = { "AntiAliasedLinesVertShader.vsh", "AntiAliasedLinesVertShader.vsc", "AntiAliasedLinesFragShader.fsh", "AntiAliasedLinesFragShader.fsc", 2, (const char**)g_pszAttribs };
  232. const ShaderDescription AlphaMaskShaderDescription = { "AntiAliasedLinesVertShader.vsh", "AntiAliasedLinesVertShader.vsc", "AlphaMaskFragShader.fsh", "AlphaMaskFragShader.fsc", 2, (const char**)g_pszAttribs };
  233. const ShaderDescription PivotQuadShaderDescription = { "PivotQuadVertShader.vsh", "PivotQuadVertShader.vsc", "PivotQuadFragShader.fsh", "PivotQuadFragShader.fsc", 3, (const char**)g_pszPivotQuadAttribs };
  234. const ShaderDescription PivotQuadMaskedShaderDescription = { "PivotQuadVertShader.vsh", "PivotQuadVertShader.vsc", "PivotQuadMaskedFragShader.fsh", "PivotQuadMaskedFragShader.fsc", 3, (const char**)g_pszPivotQuadAttribs };
  235. // Textures
  236. const char c_aszTextureNameStreetSigns[] = "StreetSigns.pvr";
  237. const char c_aszTextureNameRoad[] = "Road.pvr";
  238. const char c_aszTextureNameAlphabet[] = "Alphabet.pvr";
  239. /*!**************************************************************************
  240. Function declarations
  241. ****************************************************************************/
  242. bool ReadPVRTMapBucket(const char *pszFilename, PVRTMapBucket &layer);
  243. /*!****************************************************************************
  244. Class declarations
  245. ******************************************************************************/
  246. /*!***********************************************************************
  247. * @Class OGLES2Navigation
  248. * @Brief Navigation demo main class.
  249. ************************************************************************/
  250. class OGLES2Navigation : public PVRShell
  251. {
  252. // Print3D class used to display text
  253. CPVRTPrint3D m_Print3D;
  254. // Camera attributes
  255. CPVRTModelPOD m_CameraPod;
  256. float m_fFOV;
  257. float m_fAspectRatio;
  258. float m_fNearClipPlane;
  259. float m_fFarClipPlane;
  260. PVRTVec3 m_vCameraOffset;
  261. PVRTVec3 m_vCameraFrom;
  262. PVRTVec3 m_vCameraTo;
  263. PVRTVec3 m_vCameraUp;
  264. PVRTVec3 m_vCameraDirection;
  265. PVRTVec3 m_vCameraRight;
  266. PVRTViewFrustum m_CameraFrustum;
  267. PVRTMat4 m_mProjectionMatrix;
  268. PVRTMat4 m_mViewProjectionMatrix;
  269. PVRTBoundingBox2D m_BoundingBox;
  270. // Map layers
  271. RenderLayer *m_paLayers;
  272. unsigned int m_uiLayerCount;
  273. // Texture objects
  274. GLuint m_uiTextureIdStreetSigns;
  275. GLuint m_uiTextureIdRoad;
  276. GLuint m_uiTextureIdAlphabet;
  277. // Resource tracking objects
  278. GLuint m_uiLastBoundVboId;
  279. GLuint m_uiLastBoundTextureId;
  280. // Shader objects
  281. struct Shader
  282. {
  283. GLuint uiId;
  284. GLuint uiVertexShaderId;
  285. GLuint uiFragmentShaderId;
  286. GLuint uiModelViewProjMatrixLoc;
  287. GLuint uiColourLoc;
  288. }
  289. m_FlatShader, m_AALinesShader, m_AlphaMaskShader;
  290. struct PivotQuadShader : Shader
  291. {
  292. GLuint uiUpVecLoc;
  293. GLuint uiPivotDirectionLoc;
  294. }
  295. m_PivotQuadShader, m_PivotQuadMaskedShader;
  296. // Time variables
  297. unsigned long m_ulPreviousTime, m_ulLastUpdate;
  298. float m_fCameraAnimation;
  299. float m_fDebugTimeMultiplier;
  300. bool m_bPause;
  301. bool m_bRotate;
  302. public:
  303. virtual bool InitApplication();
  304. virtual bool InitView();
  305. virtual bool ReleaseView();
  306. virtual bool QuitApplication();
  307. virtual bool RenderScene();
  308. bool LoadTextures(CPVRTString* pErrorStr);
  309. bool LoadShader(CPVRTString* pErrorStr, const ShaderDescription &descr, Shader &shader);
  310. bool LoadShaders(CPVRTString* pErrorStr);
  311. bool ReleaseShader(Shader &shader);
  312. void UpdateTimer();
  313. void UpdateObjectset();
  314. void HandleInput();
  315. void Render(const RenderLayer *pRenderLayer);
  316. void RenderTriangles(const RenderLayer *pRenderLayer, const Shader &shader);
  317. void RenderPivotQuads(const PivotQuadShader &shader, const RenderLayer *pRenderLayer, GLuint textureId);
  318. void RenderGround();
  319. void CacheBucketIndexSet(RenderLayer *pRenderLayer, const unsigned int bucketindex);
  320. void RemoveBucketIndexSet(RenderLayer *pRenderLayer, const unsigned int bucketindex);
  321. void BindVBO(GLuint vbo);
  322. void BindTexture(GLenum unit, GLuint texture);
  323. void CalculateCameraMatrices();
  324. void CalculateClipPlanes(float &near, float &far);
  325. void CalculateViewFrustumCorners(PVRTViewFrustum &corners) const;
  326. bool CircleIntersectsBoundingBox(const PVRTBoundingBox2D &bbox, const PVRTBoundingCircle &circle);
  327. float CalculateLinePlaneIntersection(const PVRTVec4 &plane, const PVRTVec3 &a, const PVRTVec3 &b) const;
  328. void CalculateCameraBoundingCircle(const PVRTVec4 &plane, const float shift, PVRTBoundingCircle &bcircle);
  329. void ReadData(const char **pSrc, void *pDst, size_t size) const;
  330. bool CheckMarker(const char **pData, unsigned int token) const;
  331. bool LoadPVRTMapBucket(const char *pszFilename, PVRTMapBucket &layer) const;
  332. };
  333. /*!***********************************************************************
  334. * @Class CPVRTWorkingSet
  335. * @Brief Simple set implementation.
  336. ************************************************************************/
  337. class CPVRTWorkingSet
  338. {
  339. private:
  340. unsigned int *m_puiEntries;
  341. unsigned int m_uiMaxEntries;
  342. unsigned int m_uiNumEntries;
  343. public:
  344. CPVRTWorkingSet(const CPVRTWorkingSet &ws)
  345. {
  346. m_puiEntries = new unsigned int[ws.m_uiMaxEntries];
  347. memcpy(m_puiEntries, ws.m_puiEntries, sizeof(unsigned int) * ws.m_uiNumEntries);
  348. m_uiMaxEntries = ws.m_uiMaxEntries;
  349. m_uiNumEntries = ws.m_uiNumEntries;
  350. }
  351. CPVRTWorkingSet(unsigned int maxEntries)
  352. {
  353. m_puiEntries = new unsigned int[maxEntries];
  354. m_uiMaxEntries = maxEntries;
  355. m_uiNumEntries = 0;
  356. }
  357. ~CPVRTWorkingSet()
  358. {
  359. delete [] m_puiEntries;
  360. }
  361. const unsigned int *GetEntries() const
  362. {
  363. return m_puiEntries;
  364. }
  365. unsigned int GetEntry(unsigned int index) const
  366. {
  367. return m_puiEntries[index];
  368. }
  369. bool Contains(unsigned int entry) const
  370. {
  371. for (size_t i=0; i < m_uiNumEntries; i++)
  372. if (m_puiEntries[i] == entry)
  373. return true;
  374. return false;
  375. }
  376. bool Insert(unsigned int entry)
  377. {
  378. if (m_uiMaxEntries > m_uiNumEntries)
  379. {
  380. m_puiEntries[m_uiNumEntries] = entry;
  381. m_uiNumEntries++;
  382. return true;
  383. }
  384. return false;
  385. }
  386. void Clear()
  387. {
  388. m_uiNumEntries = 0;
  389. }
  390. unsigned int Size() const
  391. {
  392. return m_uiNumEntries;
  393. }
  394. unsigned int Capacity() const
  395. {
  396. return m_uiMaxEntries;
  397. }
  398. };
  399. /*!****************************************************************************
  400. @Function LoadTextures
  401. @Output pErrorStr A string describing the error on failure
  402. @Return bool true if no error occured
  403. @Description Loads the textures required for this training course
  404. ******************************************************************************/
  405. bool OGLES2Navigation::LoadTextures(CPVRTString* const pErrorStr)
  406. {
  407. if (PVRTTextureLoadFromPVR(c_aszTextureNameStreetSigns, &m_uiTextureIdStreetSigns) != PVR_SUCCESS)
  408. {
  409. *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + c_aszTextureNameStreetSigns;
  410. return false;
  411. }
  412. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  413. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  414. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  415. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  416. if (PVRTTextureLoadFromPVR(c_aszTextureNameAlphabet, &m_uiTextureIdAlphabet) != PVR_SUCCESS)
  417. {
  418. *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + c_aszTextureNameAlphabet;
  419. return false;
  420. }
  421. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  422. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  423. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  424. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  425. if (PVRTTextureLoadFromPVR(c_aszTextureNameRoad, &m_uiTextureIdRoad) != PVR_SUCCESS)
  426. {
  427. *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + c_aszTextureNameRoad;
  428. return false;
  429. }
  430. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  431. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  432. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  433. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  434. return true;
  435. }
  436. /*!****************************************************************************
  437. @Function LoadShader
  438. @Output pErrorStr A string describing the error on failure
  439. @Input descr A struct containing all necessary information to
  440. load and build the shader
  441. @Output shader A struct containing all shader object identifiers
  442. @Return bool true if no error occured
  443. @Description Loads and compiles a shader and links it into a shader program
  444. ******************************************************************************/
  445. bool OGLES2Navigation::LoadShader(CPVRTString* pErrorStr, const ShaderDescription &descr, Shader &shader)
  446. {
  447. if (PVRTShaderLoadFromFile(descr.pszVertShaderBinFile, descr.pszVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &shader.uiVertexShaderId, pErrorStr) != PVR_SUCCESS)
  448. {
  449. *pErrorStr = descr.pszVertShaderSrcFile + CPVRTString(":\n") + *pErrorStr;
  450. return false;
  451. }
  452. if (PVRTShaderLoadFromFile(descr.pszFragShaderBinFile, descr.pszFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &shader.uiFragmentShaderId, pErrorStr) != PVR_SUCCESS)
  453. {
  454. *pErrorStr = descr.pszFragShaderSrcFile + CPVRTString(":\n") + *pErrorStr;
  455. return false;
  456. }
  457. // Set up and link to the shader program
  458. if (PVRTCreateProgram(&shader.uiId, shader.uiVertexShaderId, shader.uiFragmentShaderId, descr.pszAttributes, descr.ui32NumAttributes, pErrorStr))
  459. {
  460. *pErrorStr = descr.pszFragShaderSrcFile + CPVRTString(":\n") + *pErrorStr;
  461. return false;
  462. }
  463. return true;
  464. }
  465. /*!****************************************************************************
  466. @Function LoadShaders
  467. @Output pErrorStr A string describing the error on failure
  468. @Return bool true if no error occured
  469. @Description Loads and compiles shaders and links them to shader programs
  470. ******************************************************************************/
  471. bool OGLES2Navigation::LoadShaders(CPVRTString* pErrorStr)
  472. {
  473. // Load and compile the shaders from files.
  474. // Binary shaders are tried first, source shaders are used as fallback.
  475. // FlatShader
  476. //
  477. if (!LoadShader(pErrorStr, FlatShaderDescription, m_FlatShader))
  478. {
  479. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  480. return false;
  481. }
  482. m_FlatShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_FlatShader.uiId, "ModelViewProjMatrix");
  483. m_FlatShader.uiColourLoc = glGetUniformLocation(m_FlatShader.uiId, "FlatColour");
  484. // AALinesShader
  485. //
  486. if (!LoadShader(pErrorStr, AALinesShaderDescription, m_AALinesShader))
  487. {
  488. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  489. return false;
  490. }
  491. glUniform1i(glGetUniformLocation(m_AALinesShader.uiId, "sTexture"), 0);
  492. m_AALinesShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_AALinesShader.uiId, "ModelViewProjMatrix");
  493. m_AALinesShader.uiColourLoc = glGetUniformLocation(m_AALinesShader.uiId, "FlatColour");
  494. // PivotQuadShader
  495. //
  496. if (!LoadShader(pErrorStr, PivotQuadShaderDescription, m_PivotQuadShader))
  497. {
  498. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  499. return false;
  500. }
  501. glUniform1i(glGetUniformLocation(m_PivotQuadShader.uiId, "sTexture"), 0);
  502. m_PivotQuadShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_PivotQuadShader.uiId, "ModelViewProjMatrix");
  503. m_PivotQuadShader.uiUpVecLoc = glGetUniformLocation(m_PivotQuadShader.uiId, "Up");
  504. m_PivotQuadShader.uiPivotDirectionLoc = glGetUniformLocation(m_PivotQuadShader.uiId, "PivotDirection");
  505. m_PivotQuadShader.uiColourLoc = glGetUniformLocation(m_PivotQuadShader.uiId, "Colour");
  506. // PivotQuadMaskedShader
  507. //
  508. if (!LoadShader(pErrorStr, PivotQuadMaskedShaderDescription, m_PivotQuadMaskedShader))
  509. {
  510. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  511. return false;
  512. }
  513. glUniform1i(glGetUniformLocation(m_PivotQuadMaskedShader.uiId, "sTexture"), 0);
  514. m_PivotQuadMaskedShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_PivotQuadMaskedShader.uiId, "ModelViewProjMatrix");
  515. m_PivotQuadMaskedShader.uiUpVecLoc = glGetUniformLocation(m_PivotQuadMaskedShader.uiId, "Up");
  516. m_PivotQuadMaskedShader.uiPivotDirectionLoc = glGetUniformLocation(m_PivotQuadMaskedShader.uiId, "PivotDirection");
  517. m_PivotQuadMaskedShader.uiColourLoc = glGetUniformLocation(m_PivotQuadMaskedShader.uiId, "Colour");
  518. // AlphaMaskShader
  519. //
  520. if (!LoadShader(pErrorStr, AlphaMaskShaderDescription, m_AlphaMaskShader))
  521. {
  522. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  523. return false;
  524. }
  525. glUniform1i(glGetUniformLocation(m_AlphaMaskShader.uiId, "sTexture"), 0);
  526. m_AlphaMaskShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_AlphaMaskShader.uiId, "ModelViewProjMatrix");
  527. m_AlphaMaskShader.uiColourLoc = glGetUniformLocation(m_AlphaMaskShader.uiId, "FlatColour");
  528. return true;
  529. }
  530. /*!****************************************************************************
  531. @Function InitApplication
  532. @Return bool true if no error occured
  533. @Description Code in InitApplication() will be called by PVRShell once per
  534. run, before the rendering context is created.
  535. Used to initialize variables that are not dependant on it
  536. (e.g. external modules, loading meshes, etc.)
  537. If the rendering context is lost, InitApplication() will
  538. not be called again.
  539. ******************************************************************************/
  540. bool OGLES2Navigation::InitApplication()
  541. {
  542. m_bPause = false;
  543. m_fFOV = 45.0f;
  544. m_fNearClipPlane = 0.001f;
  545. m_fFarClipPlane = 0.01f;
  546. // Get and set the read path for content files
  547. CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
  548. if (PVR_SUCCESS != m_CameraPod.ReadFromFile("cameratrack.pod"))
  549. {
  550. PVRShellSet(prefExitMessage, "Error: Failed to parse POD cameratrack.\n");
  551. return false;
  552. }
  553. // Load each layer of the map
  554. m_uiLayerCount = sizeof(layerdescriptions) / sizeof(layerdescriptions[0]);
  555. m_paLayers = new RenderLayer[m_uiLayerCount];
  556. for (unsigned int i=0; i < m_uiLayerCount; i++)
  557. {
  558. m_paLayers[i].prendercache = 0;
  559. m_paLayers[i].pworkingset = 0;
  560. m_paLayers[i].renderpath = RENDER_DISABLED;
  561. m_paLayers[i].colour = layerdescriptions[i].colour;
  562. m_paLayers[i].scale = layerdescriptions[i].scale;
  563. m_paLayers[i].pszName = layerdescriptions[i].pszFilename;
  564. if (!LoadPVRTMapBucket(layerdescriptions[i].pszFilename, m_paLayers[i].mapbucket))
  565. {
  566. continue;
  567. }
  568. if ((m_paLayers[i].mapbucket.numVertexDataBuckets > 0) &&
  569. (m_paLayers[i].mapbucket.numIndexDataBuckets > 0))
  570. {
  571. m_paLayers[i].prendercache = new RenderCache[m_paLayers[i].mapbucket.numVertexDataBuckets];
  572. m_paLayers[i].pworkingset = new CPVRTWorkingSet((unsigned int)m_paLayers[i].mapbucket.numIndexDataBuckets);
  573. m_paLayers[i].renderpath = layerdescriptions[i].renderpath;
  574. }
  575. }
  576. // Determine a global bounding box, encompassing all individual bounding boxes
  577. m_BoundingBox = m_paLayers[0].mapbucket.boundingbox;
  578. for (unsigned int i=1; i < m_uiLayerCount; i++)
  579. {
  580. if (m_paLayers[i].renderpath == RENDER_DISABLED)
  581. continue;
  582. m_BoundingBox.minCoords.x = PVRT_MIN(m_BoundingBox.minCoords.x, m_paLayers[i].mapbucket.boundingbox.minCoords.x);
  583. m_BoundingBox.minCoords.y = PVRT_MIN(m_BoundingBox.minCoords.y, m_paLayers[i].mapbucket.boundingbox.minCoords.y);
  584. m_BoundingBox.maxCoords.x = PVRT_MAX(m_BoundingBox.maxCoords.x, m_paLayers[i].mapbucket.boundingbox.maxCoords.x);
  585. m_BoundingBox.maxCoords.y = PVRT_MAX(m_BoundingBox.maxCoords.y, m_paLayers[i].mapbucket.boundingbox.maxCoords.y);
  586. }
  587. m_vCameraOffset = PVRTVec3(m_BoundingBox.minCoords.x, m_BoundingBox.minCoords.y, 0.0f);
  588. // Set timer variables
  589. m_ulPreviousTime = PVRShellGetTime();
  590. m_ulLastUpdate = 0;
  591. m_fCameraAnimation = 0.0f;
  592. m_fDebugTimeMultiplier = 1.0f;
  593. return true;
  594. }
  595. /*!****************************************************************************
  596. @Function QuitApplication
  597. @Return bool true if no error occured
  598. @Description Code in QuitApplication() will be called by PVRShell once per
  599. run, just before exiting the program.
  600. If the rendering context is lost, QuitApplication() will
  601. not be called.
  602. ******************************************************************************/
  603. bool OGLES2Navigation::QuitApplication()
  604. {
  605. for (unsigned int i=0; i < m_uiLayerCount; i++)
  606. {
  607. delete [] m_paLayers[i].prendercache;
  608. delete m_paLayers[i].pworkingset;
  609. PVRTMapBucket &mapbucket = m_paLayers[i].mapbucket;
  610. for (unsigned int j=0; j < mapbucket.numIndexDataBuckets; j++)
  611. delete [] mapbucket.pIndexDataBuckets[j].pIndices;
  612. delete [] mapbucket.pIndexDataBuckets;
  613. for (unsigned int j=0; j < mapbucket.numVertexDataBuckets; j++)
  614. delete [] mapbucket.pVertexDataBuckets[j].pData;
  615. delete [] mapbucket.pVertexDataBuckets;
  616. }
  617. delete [] m_paLayers;
  618. return true;
  619. }
  620. /*!****************************************************************************
  621. @Function InitView
  622. @Return bool true if no error occured
  623. @Description Code in InitView() will be called by PVRShell upon
  624. initialization or after a change in the rendering context.
  625. Used to initialize variables that are dependant on the rendering
  626. context (e.g. textures, vertex buffers, etc.)
  627. ******************************************************************************/
  628. bool OGLES2Navigation::InitView()
  629. {
  630. m_fAspectRatio = PVRShellGet(prefWidth) / (float)PVRShellGet(prefHeight);
  631. CPVRTString ErrorStr;
  632. // Load textures
  633. if (!LoadTextures(&ErrorStr))
  634. {
  635. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  636. return false;
  637. }
  638. // Load and compile the shaders & link programs
  639. if (!LoadShaders(&ErrorStr))
  640. {
  641. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  642. return false;
  643. }
  644. // Is the screen rotated?
  645. m_bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  646. #ifdef _WIN32
  647. if (PVRShellGet(prefWidth) < PVRShellGet(prefHeight))
  648. m_bRotate = true;
  649. #endif
  650. // Initialize Print3D
  651. if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), m_bRotate) != PVR_SUCCESS)
  652. {
  653. PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
  654. return false;
  655. }
  656. // Enable culling and depth test
  657. glCullFace(GL_BACK);
  658. glEnable(GL_CULL_FACE);
  659. // No depth testing when rendering a plain 2D map
  660. glDisable(GL_DEPTH_TEST);
  661. // No stencil test required by default
  662. glDisable(GL_STENCIL_TEST);
  663. // Disable blending by default for now, but set proper blending mode
  664. glDisable(GL_BLEND);
  665. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  666. // Use the ground colour for clearing
  667. glClearColor(g_BackgroundColour.x, g_BackgroundColour.y, g_BackgroundColour.z, 1.0f);
  668. return true;
  669. }
  670. /*!****************************************************************************
  671. @Function ReleaseShader
  672. @Return bool true if no error occured
  673. @Description Releases a shader program including the individual shader objects.
  674. ******************************************************************************/
  675. bool OGLES2Navigation::ReleaseShader(Shader &shader)
  676. {
  677. glDeleteProgram(shader.uiId);
  678. glDeleteShader(shader.uiVertexShaderId);
  679. glDeleteShader(shader.uiFragmentShaderId);
  680. return true;
  681. }
  682. /*!****************************************************************************
  683. @Function ReleaseView
  684. @Return bool true if no error occured
  685. @Description Code in ReleaseView() will be called by PVRShell when the
  686. application quits or before a change in the rendering context.
  687. ******************************************************************************/
  688. bool OGLES2Navigation::ReleaseView()
  689. {
  690. // Delete textures
  691. glDeleteTextures(1, &m_uiTextureIdStreetSigns);
  692. glDeleteTextures(1, &m_uiTextureIdRoad);
  693. // Delete program and shader objects
  694. ReleaseShader(m_FlatShader);
  695. ReleaseShader(m_AALinesShader);
  696. ReleaseShader(m_PivotQuadShader);
  697. ReleaseShader(m_PivotQuadMaskedShader);
  698. ReleaseShader(m_AlphaMaskShader);
  699. // Release Print3D Textures
  700. m_Print3D.ReleaseTextures();
  701. return true;
  702. }
  703. /*!****************************************************************************
  704. @Function RenderScene
  705. @Return bool true if no error occured
  706. @Description Main rendering loop function of the program. The shell will
  707. call this function every frame.
  708. eglSwapBuffers() will be performed by PVRShell automatically.
  709. PVRShell will also manage important OS events.
  710. The user has access to these events through an abstraction
  711. layer provided by PVRShell.
  712. ******************************************************************************/
  713. bool OGLES2Navigation::RenderScene()
  714. {
  715. // Handle user input and update the timer based variables
  716. HandleInput();
  717. UpdateTimer();
  718. // Update the camera interpolation and extract required matrices
  719. CalculateCameraMatrices();
  720. // Initialize id tracking variables
  721. m_uiLastBoundVboId = m_uiLastBoundTextureId = 0;
  722. // Setup the viewport for the whole window
  723. glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
  724. // Clear the color and depth buffer
  725. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  726. // Disable culling and depth testing
  727. glDisable(GL_CULL_FACE);
  728. glDisable(GL_DEPTH_TEST);
  729. // Render ground
  730. RenderGround();
  731. // Render each layer
  732. for (unsigned int i=0; i < m_uiLayerCount; i++)
  733. {
  734. Render(&m_paLayers[i]);
  735. }
  736. // Displays the demo name and other information using the Print3D tool.
  737. // For a detailed explanation, see the training course IntroducingPVRTools
  738. m_Print3D.DisplayDefaultTitle("Navigation", NULL, ePVRTPrint3DLogoIMG);
  739. m_Print3D.Flush();
  740. return true;
  741. }
  742. /*!****************************************************************************
  743. @Function UpdateTimer
  744. @Input none
  745. @Description Updates the values of the current time, previous time, current time
  746. in seconds, delta time and the FPS counter used in the program
  747. ******************************************************************************/
  748. void OGLES2Navigation::UpdateTimer()
  749. {
  750. unsigned long ulCurrentTime = PVRShellGetTime();
  751. unsigned long ulTimeDelta = ulCurrentTime - m_ulPreviousTime;
  752. m_ulPreviousTime = ulCurrentTime;
  753. // Update the visible object four times per second
  754. if (ulCurrentTime - m_ulLastUpdate > 250)
  755. {
  756. m_ulLastUpdate = ulCurrentTime;
  757. UpdateObjectset();
  758. }
  759. // Advance camera animation when not paused
  760. if (!m_bPause)
  761. m_fCameraAnimation += ulTimeDelta * 0.00005f * m_fDebugTimeMultiplier;
  762. }
  763. /*!****************************************************************************
  764. @Function UpdateObjectset
  765. @Input none
  766. @Description Updates the visible object set based on the camera position and
  767. the intersections of the view frustum with the global map plane.
  768. ******************************************************************************/
  769. void OGLES2Navigation::UpdateObjectset()
  770. {
  771. // Calculate the bounding circle based on the camera frustum intersection with the global map plane.
  772. // Shift the resulting bounding circle towards the viewing direction to cache objects ahead.
  773. PVRTBoundingCircle circle;
  774. CalculateCameraBoundingCircle(g_MapPlane, g_fBoundingCircleShift, circle);
  775. // Update the object set for each layer
  776. for (unsigned int i=0; i < m_uiLayerCount; i++)
  777. {
  778. // If we do not render it, skip it
  779. if (m_paLayers[i].renderpath == RENDER_DISABLED)
  780. continue;
  781. RenderLayer *pLayer = &m_paLayers[i];
  782. CPVRTWorkingSet workingset_old(*(pLayer->pworkingset));
  783. pLayer->pworkingset->Clear();
  784. // If the bounding circle does not intersect the bucket layer, skip it
  785. if (CircleIntersectsBoundingBox(pLayer->mapbucket.boundingbox, circle))
  786. {
  787. // Check against each individual bucket-indexset
  788. for (unsigned int i=0; i < pLayer->mapbucket.numIndexDataBuckets; i++)
  789. {
  790. // Skip it if it is empty
  791. if (pLayer->mapbucket.pIndexDataBuckets[i].numIndices == 0)
  792. continue;
  793. if (CircleIntersectsBoundingBox(pLayer->mapbucket.pIndexDataBuckets[i].boundingbox, circle))
  794. pLayer->pworkingset->Insert(i);
  795. }
  796. }
  797. // Check all the old indices agains the new ones and if one entry is not
  798. // in the new one, drop the cache
  799. for (unsigned int j=0; j < workingset_old.Size(); j++)
  800. if (!pLayer->pworkingset->Contains(workingset_old.GetEntry(j)))
  801. RemoveBucketIndexSet(pLayer, workingset_old.GetEntry(j));
  802. // Check all the new indices agains the old ones and if one entry is not
  803. // in the old one, cache it
  804. for (unsigned int j=0; j < pLayer->pworkingset->Size(); j++)
  805. if (!workingset_old.Contains(pLayer->pworkingset->GetEntry(j)))
  806. CacheBucketIndexSet(pLayer, pLayer->pworkingset->GetEntry(j));
  807. }
  808. }
  809. /*!****************************************************************************
  810. @Function HandleInput
  811. @Description Handles user input.
  812. ******************************************************************************/
  813. void OGLES2Navigation::HandleInput()
  814. {
  815. // Handle user input
  816. if (PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  817. m_bPause = !m_bPause;
  818. #ifdef _DEBUG
  819. if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT))
  820. m_fDebugTimeMultiplier *= 2.0f;
  821. if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT))
  822. m_fDebugTimeMultiplier *= 0.5f;
  823. #endif
  824. }
  825. /*!****************************************************************************
  826. @Function Render
  827. @Input pRenderLayer The navigation map layer to render.
  828. @Description Renders
  829. ******************************************************************************/
  830. void OGLES2Navigation::Render(const RenderLayer *pRenderLayer)
  831. {
  832. // Return immediately if there is nothing to render for this layer or
  833. // the rendering has been disabled
  834. if (pRenderLayer->renderpath == RENDER_DISABLED)
  835. return;
  836. // Determine the renderpath
  837. switch (pRenderLayer->renderpath)
  838. {
  839. case RENDER_BILLBOARD_TEXT:
  840. {
  841. glEnable(GL_BLEND);
  842. RenderPivotQuads(m_PivotQuadMaskedShader, pRenderLayer, m_uiTextureIdAlphabet);
  843. break;
  844. }
  845. case RENDER_SIGNS:
  846. {
  847. glEnable(GL_BLEND);
  848. RenderPivotQuads(m_PivotQuadShader, pRenderLayer, m_uiTextureIdStreetSigns);
  849. break;
  850. }
  851. case RENDER_TEXT:
  852. {
  853. glEnable(GL_BLEND);
  854. BindTexture(GL_TEXTURE0, m_uiTextureIdAlphabet);
  855. RenderTriangles(pRenderLayer, m_AlphaMaskShader);
  856. break;
  857. }
  858. case RENDER_ANTIALIASEDLINES:
  859. {
  860. glEnable(GL_BLEND);
  861. BindTexture(GL_TEXTURE0, m_uiTextureIdRoad);
  862. RenderTriangles(pRenderLayer, m_AALinesShader);
  863. break;
  864. }
  865. case RENDER_FLATCOLOURED:
  866. {
  867. glDisable(GL_BLEND);
  868. RenderTriangles(pRenderLayer, m_FlatShader);
  869. break;
  870. }
  871. case RENDER_DISABLED:
  872. default:
  873. {
  874. break;
  875. }
  876. }
  877. }
  878. /*!****************************************************************************
  879. @Function RenderTriangles
  880. @Input pRenderLayer The navigation map layer to render.
  881. @Description Draws a rectangle the size of the maps bounding boxes.
  882. ******************************************************************************/
  883. void OGLES2Navigation::RenderTriangles(const RenderLayer *pRenderLayer, const Shader &shader)
  884. {
  885. //if (pRenderLayer->workingset_sorted.empty())
  886. if (pRenderLayer->pworkingset->Size() == 0)
  887. return;
  888. PVRTVec4 colour = pRenderLayer->colour;
  889. glUseProgram(shader.uiId);
  890. glUniform4fv(shader.uiColourLoc, 1, colour.ptr());
  891. // Enable the vertex attribute arrays
  892. glEnableVertexAttribArray(VERTEX_ARRAY);
  893. glEnableVertexAttribArray(TEXCOORD_ARRAY);
  894. // Iterate over the active object set
  895. //for (unsigned int i=0; i < pRenderLayer->workingset_sorted.size(); i++)
  896. for (unsigned int i=0; i < pRenderLayer->pworkingset->Size(); i++)
  897. {
  898. // Get the index for the bucket
  899. const unsigned int index = pRenderLayer->pworkingset->GetEntry(i);
  900. // Get the bucket-indexset
  901. const PVRTIndexDataBucket &indexdatabucket = pRenderLayer->mapbucket.pIndexDataBuckets[index];
  902. // Go to the next workingset item if no primitives to draw
  903. if (indexdatabucket.numIndices == 0)
  904. continue;
  905. // Move camera according to the min coords of the current bounding box as the data is stored relative to it
  906. PVRTVec2 mincoords = pRenderLayer->mapbucket.pVertexDataBuckets[indexdatabucket.bucketindex].boundingbox.minCoords;
  907. PVRTVec3 offset = PVRTVec3(mincoords.x, mincoords.y, 0.0f);
  908. PVRTMat4 viewmatrix = PVRTMat4::LookAtRH(m_vCameraFrom - offset, m_vCameraTo - offset, m_vCameraUp);
  909. PVRTMat4 mvp = m_mProjectionMatrix * viewmatrix;
  910. glUniformMatrix4fv(shader.uiModelViewProjMatrixLoc, 1, GL_FALSE, mvp.ptr());
  911. // Get the VBO id from the rendercache
  912. const RenderCache &cache = pRenderLayer->prendercache[indexdatabucket.bucketindex];
  913. if (cache.references == 0)
  914. {
  915. PVRShellOutputDebug("Error: Tried to draw non-cached bucket!");
  916. continue;
  917. }
  918. BindVBO(cache.vbo);
  919. // Set the vertex attribute offsets
  920. glVertexAttribPointer(VERTEX_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(PVRTVertex), NULL);
  921. glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_TRUE, sizeof(PVRTVertex), (const void*)offsetof(PVRTVertex, texcoord));
  922. // Draw the triangles
  923. glDrawElements(GL_TRIANGLES, (GLsizei)indexdatabucket.numIndices, GL_UNSIGNED_SHORT, indexdatabucket.pIndices);
  924. }
  925. glDisableVertexAttribArray(VERTEX_ARRAY);
  926. glDisableVertexAttribArray(TEXCOORD_ARRAY);
  927. glBindBuffer(GL_ARRAY_BUFFER, 0);
  928. }
  929. /*!****************************************************************************
  930. @Function RenderPivotQuads
  931. @Description Renders a series of screen-aligned quads
  932. ******************************************************************************/
  933. void OGLES2Navigation::RenderPivotQuads(const PivotQuadShader &shader, const RenderLayer *pRenderLayer, GLuint textureId)
  934. {
  935. if (pRenderLayer->pworkingset->Size() == 0)
  936. return;
  937. // Calculate the scale (product of global and local scale factors)
  938. const PVRTVec2 fontscalars = pRenderLayer->scale * g_fPivotQuadScale;
  939. PVRTVec4 colour = pRenderLayer->colour;
  940. // Get the current camera matrix
  941. PVRTMat4 matrix = m_mViewProjectionMatrix;
  942. // to extract the up and right vectors
  943. PVRTVec3 up = PVRTVec3(matrix.f[1], matrix.f[5], matrix.f[9]) * fontscalars.y;
  944. // and calculate the individual quad offset for the shader
  945. PVRTVec3 pivot_dir = PVRTVec3(matrix.f[0], matrix.f[4], matrix.f[8]) * fontscalars.x;
  946. // Bind the texture
  947. BindTexture(GL_TEXTURE0, textureId);
  948. // Activate shader
  949. glUseProgram(shader.uiId);
  950. // and set the corresponding constants
  951. if (m_bRotate)
  952. {
  953. PVRTVec3 inv_up = -pivot_dir;
  954. glUniform3fv(shader.uiPivotDirectionLoc, 1, up.ptr());
  955. glUniform3fv(shader.uiUpVecLoc, 1, inv_up.ptr());
  956. }
  957. else
  958. {
  959. glUniform3fv(shader.uiUpVecLoc, 1, up.ptr());
  960. glUniform3fv(shader.uiPivotDirectionLoc, 1, pivot_dir.ptr());
  961. }
  962. glUniform4fv(shader.uiColourLoc, 1, colour.ptr());
  963. // Enable the vertex attribute arrays
  964. glEnableVertexAttribArray(VERTEX_ARRAY);
  965. glEnableVertexAttribArray(WORDINDEX_ARRAY);
  966. glEnableVertexAttribArray(ATTRIB_ARRAY);
  967. // Iterate over the object set
  968. //for (unsigned int i=0; i < pRenderLayer->workingset_sorted.size(); i++)
  969. for (unsigned int i=0; i < pRenderLayer->pworkingset->Size(); i++)
  970. {
  971. // Get the current bucket index
  972. //const unsigned int index = pRenderLayer->workingset_sorted[i];
  973. const unsigned int index = pRenderLayer->pworkingset->GetEntry(i);
  974. // Get the contained bucket-indexset
  975. const PVRTIndexDataBucket &indexdatabucket = pRenderLayer->mapbucket.pIndexDataBuckets[index];
  976. // Get the cache
  977. const RenderCache &cache = pRenderLayer->prendercache[indexdatabucket.bucketindex];
  978. if (cache.references == 0)
  979. {
  980. PVRShellOutputDebug("Error: Tried to draw non-cached bucket!");
  981. continue;
  982. }
  983. // Move camera according to the min coords of the current bounding box as the data is stored relative to it
  984. PVRTVec2 mincoords = pRenderLayer->mapbucket.pVertexDataBuckets[indexdatabucket.bucketindex].boundingbox.minCoords;
  985. PVRTVec3 offset = PVRTVec3(mincoords.x, mincoords.y, 0.0f);
  986. PVRTMat4 viewmatrix = PVRTMat4::LookAtRH(m_vCameraFrom - offset, m_vCameraTo - offset, m_vCameraUp);
  987. PVRTMat4 mvp = m_mProjectionMatrix * viewmatrix;
  988. glUniformMatrix4fv(shader.uiModelViewProjMatrixLoc, 1, GL_FALSE, mvp.ptr());
  989. BindVBO(cache.vbo);
  990. // Set the vertex attribute offsets
  991. int stride = sizeof(PVRTPivotQuadVertex);
  992. glVertexAttribPointer(VERTEX_ARRAY, 2, GL_FLOAT, GL_FALSE, stride, 0);
  993. glVertexAttribPointer(WORDINDEX_ARRAY, 2, GL_BYTE, GL_FALSE, stride, (const void *)offsetof(struct PVRTPivotQuadVertex, word_index));
  994. glVertexAttribPointer(ATTRIB_ARRAY, 2, GL_UNSIGNED_BYTE, GL_TRUE, stride, (const void *)offsetof(struct PVRTPivotQuadVertex, u));
  995. // Skip if there is nothing to draw
  996. if (indexdatabucket.numIndices > 0)
  997. {
  998. // Draw the actual pivot quads
  999. glDrawElements(GL_TRIANGLES, (GLsizei)indexdatabucket.numIndices, GL_UNSIGNED_SHORT, indexdatabucket.pIndices);
  1000. }
  1001. }
  1002. glDisableVertexAttribArray(VERTEX_ARRAY);
  1003. glDisableVertexAttribArray(WORDINDEX_ARRAY);
  1004. glDisableVertexAttribArray(ATTRIB_ARRAY);
  1005. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1006. }
  1007. /*!****************************************************************************
  1008. @Function RenderGround
  1009. @Description Draws a rectangle the size of the maps bounding boxes.
  1010. ******************************************************************************/
  1011. void OGLES2Navigation::RenderGround()
  1012. {
  1013. glUseProgram(m_FlatShader.uiId);
  1014. glUniformMatrix4fv(m_FlatShader.uiModelViewProjMatrixLoc, 1, GL_FALSE, m_mViewProjectionMatrix.ptr());
  1015. PVRTVec4 col = g_FloorColour;
  1016. glUniform4fv(m_FlatShader.uiColourLoc, 1, col.ptr());
  1017. // Enable vertex arributes
  1018. PVRTVec2 minCorner = m_BoundingBox.minCoords;
  1019. PVRTVec2 maxCorner = m_BoundingBox.maxCoords;
  1020. const float afVertexData[] = { minCorner.x, minCorner.y, 0.0f, maxCorner.x, minCorner.y, 0.0f,
  1021. minCorner.x, maxCorner.y, 0.0f, maxCorner.x, maxCorner.y, 0.0f };
  1022. glEnableVertexAttribArray(VERTEX_ARRAY);
  1023. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, afVertexData);
  1024. // Kept if adding a texture is wanted
  1025. //const float afTexCoordData[] = { 0, 0, 1, 0, 0, 1, 1, 1 };
  1026. //glEnableVertexAttribArray(TEXCOORD_ARRAY);
  1027. //glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, afTexCoordData);
  1028. // Draw the quad
  1029. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1030. // Safely disable the vertex attribute arrays
  1031. glDisableVertexAttribArray(VERTEX_ARRAY);
  1032. //glDisableVertexAttribArray(TEXCOORD_ARRAY);
  1033. }
  1034. /*!****************************************************************************
  1035. @Function CacheBucketIndexSet
  1036. @Description Creates a VBO of a bucket of coordinates and adds it to the
  1037. cache queue of the map tile or increases reference count if
  1038. already cached.
  1039. ******************************************************************************/
  1040. void OGLES2Navigation::CacheBucketIndexSet(RenderLayer *pRenderLayer, const unsigned int bucketindex)
  1041. {
  1042. // Retrieve referenced rendercache entity
  1043. const unsigned int index = pRenderLayer->mapbucket.pIndexDataBuckets[bucketindex].bucketindex;
  1044. RenderCache &rendercache = pRenderLayer->prendercache[index];
  1045. // If it is already cached do nothing
  1046. if (rendercache.references > 0)
  1047. {
  1048. rendercache.references++;
  1049. return;
  1050. }
  1051. // Not cached, so create VBO now
  1052. PVRTVertexDataBucket &vertexdatabucket = pRenderLayer->mapbucket.pVertexDataBuckets[index];
  1053. rendercache.size = vertexdatabucket.size;
  1054. rendercache.references++;
  1055. glGenBuffers(1, &(rendercache.vbo));
  1056. glBindBuffer(GL_ARRAY_BUFFER, rendercache.vbo);
  1057. glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)rendercache.size, vertexdatabucket.pData, GL_STATIC_DRAW);
  1058. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1059. }
  1060. /*!****************************************************************************
  1061. @Function RemoveBucketIndexSet
  1062. @Description Decreases reference count of VBO and removes VBO if not
  1063. required any longer.
  1064. ******************************************************************************/
  1065. void OGLES2Navigation::RemoveBucketIndexSet(RenderLayer *pRenderLayer, const unsigned int bucketindex)
  1066. {
  1067. const unsigned int index = pRenderLayer->mapbucket.pIndexDataBuckets[bucketindex].bucketindex;
  1068. RenderCache &rendercache = pRenderLayer->prendercache[index];
  1069. if (rendercache.references == 0)
  1070. {
  1071. PVRShellOutputDebug("Error: Tried to remove non-cached element!");
  1072. return;
  1073. }
  1074. rendercache.references--;
  1075. // Remove if reference count reaches zero
  1076. if (rendercache.references == 0)
  1077. {
  1078. glDeleteBuffers(1, &(rendercache.vbo));
  1079. rendercache.size = 0;
  1080. }
  1081. }
  1082. /*!****************************************************************************
  1083. @Function BindVBO
  1084. @Description Checks whether the given VBO is already bound and binds it if
  1085. necessary.
  1086. ******************************************************************************/
  1087. void OGLES2Navigation::BindVBO(GLuint vbo)
  1088. {
  1089. // Only set the VBO if we bind a different one (optimize -> sort for vbos)
  1090. if (vbo != m_uiLastBoundVboId)
  1091. {
  1092. // Bind the current bucket
  1093. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  1094. m_uiLastBoundVboId = vbo;
  1095. }
  1096. }
  1097. /*!****************************************************************************
  1098. @Function BindTexture
  1099. @Description Checks whether the given texture is already bound and binds it if
  1100. necessary. Currently only supports one global texture,
  1101. regardless to which texture unit it is currently bound.
  1102. ******************************************************************************/
  1103. void OGLES2Navigation::BindTexture(GLenum unit, GLuint id)
  1104. {
  1105. glActiveTexture(unit);
  1106. if (m_uiLastBoundTextureId != id)
  1107. {
  1108. glBindTexture(GL_TEXTURE_2D, id);
  1109. m_uiLastBoundTextureId = id;
  1110. }
  1111. }
  1112. /*!****************************************************************************
  1113. @Function CalculateCameraMatrices
  1114. @Description Calculates all required camera matrices.
  1115. ******************************************************************************/
  1116. void OGLES2Navigation::CalculateCameraMatrices()
  1117. {
  1118. // Animate the camera
  1119. if (m_fCameraAnimation > (m_CameraPod.nNumFrame - 2))
  1120. m_fCameraAnimation = 0.0f;
  1121. m_CameraPod.SetFrame(m_fCameraAnimation);
  1122. static PVRTMATRIX rotMatrix;
  1123. m_CameraPod.GetRotationMatrix(rotMatrix, m_CameraPod.pNode[0]);
  1124. int baseFrame = (int)m_fCameraAnimation;
  1125. PVRTVec3 pos0(&m_CameraPod.pNode[0].pfAnimPosition[baseFrame * 3]);
  1126. PVRTVec3 pos1(&m_CameraPod.pNode[0].pfAnimPosition[(baseFrame + 1) * 3]);
  1127. // Offset the camera by a reference coordinate to center it around the origin
  1128. // This should help circumvent floating point precision problems
  1129. pos0 -= m_vCameraOffset;
  1130. pos1 -= m_vCameraOffset;
  1131. float lerp = (m_fCameraAnimation - (float)(baseFrame));
  1132. m_vCameraFrom = pos0 + (pos1 - pos0) * lerp;
  1133. m_vCameraFrom += m_vCameraOffset;
  1134. // Extract camera tripod orientation from rotation matrix
  1135. m_vCameraDirection = PVRTVec3(-rotMatrix[1][0], -rotMatrix[1][1], -rotMatrix[1][2]);
  1136. m_vCameraUp = PVRTVec3(-rotMatrix[2][0], -rotMatrix[2][1], -rotMatrix[2][2]);
  1137. m_vCameraTo = m_vCameraFrom + m_vCameraDirection;
  1138. m_vCameraRight = m_vCameraUp.cross(m_vCameraDirection);
  1139. // Adjust the near and far clip plane for a tight view frustum
  1140. CalculateViewFrustumCorners(m_CameraFrustum);
  1141. //CalculateClipPlanes(m_fNearClipPlane, m_fFarClipPlane);
  1142. PVRTMat4 viewMatrix = PVRTMat4::LookAtRH(m_vCameraFrom, m_vCameraTo, m_vCameraUp);
  1143. m_mProjectionMatrix = PVRTMat4::PerspectiveFovRH(DEG2RAD(m_fFOV), m_fAspectRatio, m_fNearClipPlane, m_fFarClipPlane, PVRTMat4::OGL, m_bRotate);
  1144. m_mViewProjectionMatrix = m_mProjectionMatrix * viewMatrix;
  1145. }
  1146. /*!****************************************************************************
  1147. @Function CalculateClipPlanes
  1148. @Output nearplane The calculated near plane.
  1149. @Output farplane The calculated far plane.
  1150. @Description Calculates optimal clipping planes based on the current camera
  1151. setup and the viewable area.
  1152. ******************************************************************************/
  1153. void OGLES2Navigation::CalculateClipPlanes(float &nearplane, float &farplane)
  1154. {
  1155. // Adjust the clip planes so that the near plane is pushed away as far as possible
  1156. // before intersecting the ground
  1157. PVRTVec3 lowdir = ((m_CameraFrustum.fbl - m_vCameraFrom) + (m_CameraFrustum.fbr - m_vCameraFrom)).normalized();
  1158. PVRTVec3 updir = ((m_CameraFrustum.ftl - m_vCameraFrom) + (m_CameraFrustum.ftr - m_vCameraFrom)).normalized();
  1159. // Calculate the intersections with the global plane
  1160. float u = CalculateLinePlaneIntersection(g_MapPlane, m_vCameraFrom, lowdir + m_vCameraFrom);
  1161. float v = CalculateLinePlaneIntersection(g_MapPlane, m_vCameraFrom, updir + m_vCameraFrom);
  1162. // Project the intersection onto the view direction
  1163. nearplane = (lowdir * u).dot(m_vCameraDirection);
  1164. farplane = (updir * v).dot(m_vCameraDirection);
  1165. }
  1166. /*!********************************************************************************************
  1167. @Function CalculateViewFrustumCorners
  1168. @Output corners The eight vertices defining the viewfrustum shape.
  1169. @Description Calculates the eight viewfrustum vertices based on the current camera setup.
  1170. ***********************************************************************************************/
  1171. void OGLES2Navigation::CalculateViewFrustumCorners(PVRTViewFrustum &corners) const
  1172. {
  1173. const PVRTVec3 nearcenter = m_vCameraFrom + m_vCameraDirection * m_fNearClipPlane;
  1174. const PVRTVec3 farcenter = m_vCameraFrom + m_vCameraDirection * m_fFarClipPlane;
  1175. const float tang = (float)tan(DEG2RAD(m_fFOV) * 0.5f);
  1176. const float nearheight = m_fNearClipPlane * tang;
  1177. const float nearwidth = nearheight * m_fAspectRatio;
  1178. const float farheight = m_fFarClipPlane * tang;
  1179. const float farwidth = farheight * m_fAspectRatio;
  1180. // Near plane frustum corners
  1181. corners.ntl = nearcenter + m_vCameraUp * nearheight - m_vCameraRight * nearwidth;
  1182. corners.ntr = nearcenter + m_vCameraUp * nearheight + m_vCameraRight * nearwidth;
  1183. corners.nbl = nearcenter - m_vCameraUp * nearheight - m_vCameraRight * nearwidth;
  1184. corners.nbr = nearcenter - m_vCameraUp * nearheight + m_vCameraRight * nearwidth;
  1185. // Far plane frustum corners
  1186. corners.ftl = farcenter + m_vCameraUp * farheight - m_vCameraRight * farwidth;
  1187. corners.ftr = farcenter + m_vCameraUp * farheight + m_vCameraRight * farwidth;
  1188. corners.fbl = farcenter - m_vCameraUp * farheight - m_vCameraRight * farwidth;
  1189. corners.fbr = farcenter - m_vCameraUp * farheight + m_vCameraRight * farwidth;
  1190. }
  1191. /*!********************************************************************************************
  1192. @Function CalculateCameraBoundingCircle
  1193. @Input plane The plane which will be intersected with the viewfrustum.
  1194. @Input shift The resulting bounding circle will be shifted along the
  1195. view direction by this amount.
  1196. @Return PVRTBoundingCircle The bounding circle enclosing the intersection primitive.
  1197. @Description Calculates the intersection points of a viewfrustum and a plane. Only the viewfrustum
  1198. side vectors (pointing towards the viewing direction) will be taken into account.
  1199. The resulting intersection points are then used to calculate a bounding circle,
  1200. which will be shifted along the viewing direction.
  1201. ***********************************************************************************************/
  1202. void OGLES2Navigation::CalculateCameraBoundingCircle(const PVRTVec4 &plane, const float shift, PVRTBoundingCircle &circle)
  1203. {
  1204. PVRTVec2 a(m_vCameraFrom + (m_CameraFrustum.fbl - m_vCameraFrom) * CalculateLinePlaneIntersection(plane, m_vCameraFrom, m_CameraFrustum.fbl));
  1205. PVRTVec2 b(m_vCameraFrom + (m_CameraFrustum.fbr - m_vCameraFrom) * CalculateLinePlaneIntersection(plane, m_vCameraFrom, m_CameraFrustum.fbr));
  1206. PVRTVec2 c(m_vCameraFrom + (m_CameraFrustum.ftl - m_vCameraFrom) * CalculateLinePlaneIntersection(plane, m_vCameraFrom, m_CameraFrustum.ftl));
  1207. PVRTVec2 d(m_vCameraFrom + (m_CameraFrustum.ftr - m_vCameraFrom) * CalculateLinePlaneIntersection(plane, m_vCameraFrom, m_CameraFrustum.ftr));
  1208. circle.center = (a + b + c + d) * 0.25f;
  1209. circle.radius = (a - circle.center).length();
  1210. // now add a little shift towards view direction
  1211. circle.center += PVRTVec2(m_vCameraDirection) * shift;
  1212. }
  1213. /*!********************************************************************************************
  1214. @Function CircleIntersectsBoundingBox
  1215. @Input bbox The bounding box.
  1216. @Input circle The bounding circle.
  1217. @Return bool Indicates whether the primitives intersect or not.
  1218. @Description Determines whether a bounding circle and a bounding box intersect or not.
  1219. ***********************************************************************************************/
  1220. bool OGLES2Navigation::CircleIntersectsBoundingBox(const PVRTBoundingBox2D &bbox, const PVRTBoundingCircle &circle)
  1221. {
  1222. // Extremely simple, just add border the same width as radius. Gives false positives at edge cases!
  1223. PVRTBoundingBox2D extbbox;
  1224. extbbox.minCoords = bbox.minCoords - PVRTVec2(circle.radius);
  1225. extbbox.maxCoords = bbox.maxCoords + PVRTVec2(circle.radius);
  1226. if ((circle.center.x >= extbbox.minCoords.x) && (circle.center.y >= extbbox.minCoords.y) &&
  1227. (circle.center.x <= extbbox.maxCoords.x) && (circle.center.y <= extbbox.maxCoords.y))
  1228. return true;
  1229. else
  1230. return false;
  1231. }
  1232. /*!****************************************************************************
  1233. @Function CalculateLinePlaneIntersection
  1234. @Input plane Plane definition in normal plus distance format.
  1235. @Input a First point of line.
  1236. @Input b Second point of line.
  1237. @Return Intersection distance.
  1238. @Description Calculates the intersection of a line and a plane.
  1239. ******************************************************************************/
  1240. float OGLES2Navigation::CalculateLinePlaneIntersection(const PVRTVec4 &plane, const PVRTVec3 &a, const PVRTVec3 &b) const
  1241. {
  1242. PVRTVec3 normal(plane.x, plane.y, plane.z);
  1243. float nom = -(normal.dot(a) + plane.w);
  1244. float denom = normal.dot(b - a);
  1245. if (denom == 0.0f) return 0.0f;
  1246. else return nom / denom;
  1247. }
  1248. /*!****************************************************************************
  1249. @Function ReadData
  1250. @Input pSrc Pointer to pointer to read data from.
  1251. @Input size Amount of data in bytes to copy.
  1252. @Output pDst Destination buffer.
  1253. @Description Copies a defined amount of data from a source pointer and sets
  1254. it after the last read byte.
  1255. ******************************************************************************/
  1256. void OGLES2Navigation::ReadData(const char **pSrc, void *pDst, size_t size) const
  1257. {
  1258. memcpy(pDst, *pSrc, size);
  1259. *pSrc += size;
  1260. }
  1261. /*!****************************************************************************
  1262. @Function CheckMarker
  1263. @Input pData Pointer to data to read the data from.
  1264. @Input token Value of token to check.
  1265. @Return True if the marker is correct, false otherwise.
  1266. @Description Reads a 32-bit token from the data stream and compares it
  1267. against the provided one.
  1268. ******************************************************************************/
  1269. bool OGLES2Navigation::CheckMarker(const char **pData, unsigned int token) const
  1270. {
  1271. unsigned int value = 0;
  1272. ReadData(pData, &value, sizeof(value));
  1273. return (value == token);
  1274. }
  1275. /*!********************************************************************************************
  1276. @Function readPVRTMapBucket
  1277. @Input pszFilename Filename to read the map layer from.
  1278. @Input layer The layer to write.
  1279. @Return bool True if successful, false otherwise.
  1280. @Description Reads a map bucket from a file.
  1281. ***********************************************************************************************/
  1282. bool OGLES2Navigation::LoadPVRTMapBucket(const char *pszFilename, PVRTMapBucket &layer) const
  1283. {
  1284. CPVRTResourceFile file(pszFilename);
  1285. if (!file.IsOpen())
  1286. return false;
  1287. const char *pData = (const char *)file.DataPtr();
  1288. if (!CheckMarker(&pData, MAPFILEIO_VERSION)) return false;
  1289. ReadData(&pData, &layer.boundingbox, sizeof(layer.boundingbox));
  1290. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1291. // Read vertex data
  1292. ReadData(&pData, &layer.numVertexDataBuckets, sizeof(layer.numVertexDataBuckets));
  1293. if (layer.numVertexDataBuckets > 0)
  1294. {
  1295. layer.pVertexDataBuckets = new PVRTVertexDataBucket[layer.numVertexDataBuckets];
  1296. for (unsigned int i=0; i < layer.numVertexDataBuckets; i++)
  1297. {
  1298. ReadData(&pData, &layer.pVertexDataBuckets[i].boundingbox, sizeof(layer.pVertexDataBuckets[i].boundingbox));
  1299. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1300. ReadData(&pData, &layer.pVertexDataBuckets[i].size, sizeof(layer.pVertexDataBuckets[i].size));
  1301. if (layer.pVertexDataBuckets[i].size == 0) return false;
  1302. layer.pVertexDataBuckets[i].pData = new char[layer.pVertexDataBuckets[i].size];
  1303. ReadData(&pData, layer.pVertexDataBuckets[i].pData, layer.pVertexDataBuckets[i].size);
  1304. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1305. }
  1306. }
  1307. else
  1308. layer.pVertexDataBuckets = NULL;
  1309. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1310. ReadData(&pData, &layer.numIndexDataBuckets, sizeof(layer.numIndexDataBuckets));
  1311. if (layer.numIndexDataBuckets > 0)
  1312. {
  1313. layer.pIndexDataBuckets = new PVRTIndexDataBucket[layer.numIndexDataBuckets];
  1314. for (unsigned int i=0; i < layer.numIndexDataBuckets; i++)
  1315. {
  1316. ReadData(&pData, &layer.pIndexDataBuckets[i].bucketindex, sizeof(layer.pIndexDataBuckets[i].bucketindex));
  1317. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1318. ReadData(&pData, &layer.pIndexDataBuckets[i].boundingbox, sizeof(layer.pIndexDataBuckets[i].boundingbox));
  1319. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1320. size_t size;
  1321. ReadData(&pData, &size, sizeof(size_t));
  1322. layer.pIndexDataBuckets[i].numIndices = size / sizeof(index_t);
  1323. if (layer.pIndexDataBuckets[i].numIndices == 0) return false;
  1324. layer.pIndexDataBuckets[i].pIndices = new index_t[layer.pIndexDataBuckets[i].numIndices];
  1325. ReadData(&pData, layer.pIndexDataBuckets[i].pIndices, size);
  1326. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1327. }
  1328. }
  1329. else
  1330. layer.pIndexDataBuckets = NULL;
  1331. if (!CheckMarker(&pData, MAPFILEIO_SECURITYCHECKPOINT)) return false;
  1332. return true;
  1333. }
  1334. /*!****************************************************************************
  1335. @Function NewDemo
  1336. @Return PVRShell* The demo supplied by the user
  1337. @Description This function must be implemented by the user of the shell.
  1338. The user should return its PVRShell object defining the
  1339. behaviour of the application.
  1340. ******************************************************************************/
  1341. PVRShell* NewDemo()
  1342. {
  1343. return new OGLES2Navigation();
  1344. }
  1345. /******************************************************************************
  1346. End of file (OGLES2Navigation.cpp)
  1347. ******************************************************************************/