OGLES2DisplacementMap.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /******************************************************************************
  2. @File OGLES2DisplacementMap.cpp
  3. @Title Shows how to displace geometry in the vertex shader using a
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independent
  7. @Description Shows how to displace geometry in the vertex shader using a
  8. texture.
  9. ******************************************************************************/
  10. #include <string.h>
  11. #include "PVRShell.h"
  12. #include "OGLES2Tools.h"
  13. /******************************************************************************
  14. Defines
  15. ******************************************************************************/
  16. // Index to bind the attributes to vertex shaders
  17. #define VERTEX_ARRAY 0
  18. #define NORMAL_ARRAY 1
  19. #define TEXCOORD_ARRAY 2
  20. /******************************************************************************
  21. Consts
  22. ******************************************************************************/
  23. // Camera constants. Used for making the projection matrix
  24. const float g_fCameraNear = 4.0f;
  25. const float g_fCameraFar = 2000.0f;
  26. const float g_fDemoFrameRate = 1.0f / 90.0f;
  27. // The camera to use from the pod file
  28. const int g_ui32Camera = 0;
  29. /******************************************************************************
  30. Content file names
  31. ******************************************************************************/
  32. // Source and binary shaders
  33. const char c_szFragShaderSrcFile[] = "FragShader.fsh";
  34. const char c_szFragShaderBinFile[] = "FragShader.fsc";
  35. const char c_szVertShaderSrcFile[] = "VertShader.vsh";
  36. const char c_szVertShaderBinFile[] = "VertShader.vsc";
  37. // POD scene files
  38. const char c_szSceneFile[] = "DisMapScene.pod";
  39. const char c_szDisMapFile[] = "DisMap.pvr";
  40. /*!****************************************************************************
  41. Class implementing the PVRShell functions.
  42. ******************************************************************************/
  43. class OGLES2DisplacementMap : public PVRShell
  44. {
  45. // Print3D class used to display text
  46. CPVRTPrint3D m_Print3D;
  47. // 3D Model
  48. CPVRTModelPOD m_Scene;
  49. // OpenGL handles for shaders, textures and VBOs
  50. GLuint m_uiVertShader;
  51. GLuint m_uiFragShader;
  52. GLuint* m_puiVbo;
  53. GLuint* m_puiIndexVbo;
  54. GLuint* m_puiTextureIDs;
  55. GLuint m_uiDisMapID;
  56. // Group shader programs and their uniform locations together
  57. struct
  58. {
  59. GLuint uiId;
  60. GLuint uiMVPMatrixLoc;
  61. GLuint uiLightDirLoc;
  62. GLuint uiTexture;
  63. GLuint uiDisMap;
  64. GLuint uiDisplacementFactor;
  65. }
  66. m_ShaderProgram;
  67. // Variables to handle the animation in a time-based manner
  68. int m_iTimePrev;
  69. // App variables
  70. PVRTVec4 m_LightDir;
  71. PVRTMat4 m_View, m_Projection;
  72. float m_DisplacementFactor;
  73. bool m_bGrow;
  74. public:
  75. virtual bool InitApplication();
  76. virtual bool InitView();
  77. virtual bool ReleaseView();
  78. virtual bool QuitApplication();
  79. virtual bool RenderScene();
  80. OGLES2DisplacementMap();
  81. bool LoadTextures(CPVRTString* pErrorStr);
  82. bool LoadShaders(CPVRTString* pErrorStr);
  83. bool LoadVbos(CPVRTString* pErrorStr);
  84. void DrawMesh(int i32NodeIndex);
  85. };
  86. /*!****************************************************************************
  87. @Function OGLES2DisplacementMap
  88. @Description Constructor
  89. ******************************************************************************/
  90. OGLES2DisplacementMap::OGLES2DisplacementMap() : m_puiVbo(0),
  91. m_puiIndexVbo(0),
  92. m_puiTextureIDs(0),
  93. m_DisplacementFactor(0),
  94. m_bGrow(false)
  95. {
  96. }
  97. /*!****************************************************************************
  98. @Function LoadTextures
  99. @Return bool true if no error occured
  100. @Description Loads the textures required for this training course
  101. ******************************************************************************/
  102. bool OGLES2DisplacementMap::LoadTextures(CPVRTString* pErrorStr)
  103. {
  104. /*
  105. Load the textures.
  106. For a more detailed explanation, see Texturing and IntroducingPVRTools
  107. */
  108. /*
  109. Initialises an array to lookup the textures
  110. for each material in the scene.
  111. */
  112. m_puiTextureIDs = new GLuint[m_Scene.nNumMaterial];
  113. if(!m_puiTextureIDs)
  114. {
  115. *pErrorStr = "ERROR: Insufficient memory.";
  116. return false;
  117. }
  118. for(int i = 0; i < (int) m_Scene.nNumMaterial; ++i)
  119. {
  120. m_puiTextureIDs[i] = 0;
  121. SPODMaterial* pMaterial = &m_Scene.pMaterial[i];
  122. if(pMaterial->nIdxTexDiffuse != -1)
  123. {
  124. /*
  125. Using the tools function PVRTTextureLoadFromPVR load the textures required by the pod file.
  126. Note: This function only loads .pvr files. You can set the textures in 3D Studio Max to .pvr
  127. files using the PVRTexTool plug-in for max. Alternatively, the pod material properties can be
  128. modified in PVRShaman.
  129. */
  130. CPVRTString sTextureName = m_Scene.pTexture[pMaterial->nIdxTexDiffuse].pszName;
  131. if(PVRTTextureLoadFromPVR(sTextureName.c_str(), &m_puiTextureIDs[i]) != PVR_SUCCESS)
  132. {
  133. *pErrorStr = "ERROR: Failed to load " + sTextureName + ".";
  134. // Check to see if we're trying to load .pvr or not
  135. CPVRTString sFileExtension = PVRTStringGetFileExtension(sTextureName);
  136. if(sFileExtension.toLower() == "pvr")
  137. *pErrorStr += "Note: Can only load pvr files.";
  138. return false;
  139. }
  140. }
  141. }
  142. // Load the texture used for the displacement map
  143. if(PVRTTextureLoadFromPVR(c_szDisMapFile, &m_uiDisMapID) != PVR_SUCCESS)
  144. {
  145. *pErrorStr = "ERROR: Failed to load " + CPVRTString(c_szDisMapFile) + ".";
  146. return false;
  147. }
  148. // Define the wrapping to use for the displacment map
  149. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  150. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  151. return true;
  152. }
  153. /*!****************************************************************************
  154. @Function LoadShaders
  155. @Output pErrorStr A string describing the error on failure
  156. @Return bool true if no error occured
  157. @Description Loads and compiles the shaders and links the shader programs
  158. required for this training course
  159. ******************************************************************************/
  160. bool OGLES2DisplacementMap::LoadShaders(CPVRTString* pErrorStr)
  161. {
  162. /*
  163. Load and compile the shaders from files.
  164. Binary shaders are tried first, source shaders
  165. are used as fallback.
  166. */
  167. if(PVRTShaderLoadFromFile(
  168. c_szVertShaderBinFile, c_szVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiVertShader, pErrorStr) != PVR_SUCCESS)
  169. {
  170. return false;
  171. }
  172. if (PVRTShaderLoadFromFile(
  173. c_szFragShaderBinFile, c_szFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiFragShader, pErrorStr) != PVR_SUCCESS)
  174. {
  175. return false;
  176. }
  177. /*
  178. Set up and link the shader program
  179. */
  180. const char* aszAttribs[] = { "inVertex", "inNormal", "inTexCoord" };
  181. if(PVRTCreateProgram(
  182. &m_ShaderProgram.uiId, m_uiVertShader, m_uiFragShader, aszAttribs, 3, pErrorStr) != PVR_SUCCESS)
  183. {
  184. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  185. return false;
  186. }
  187. // Store the location of uniforms for later use
  188. m_ShaderProgram.uiMVPMatrixLoc = glGetUniformLocation(m_ShaderProgram.uiId, "MVPMatrix");
  189. m_ShaderProgram.uiLightDirLoc = glGetUniformLocation(m_ShaderProgram.uiId, "LightDirection");
  190. m_ShaderProgram.uiDisplacementFactor = glGetUniformLocation(m_ShaderProgram.uiId, "DisplacementFactor");
  191. m_ShaderProgram.uiTexture = glGetUniformLocation(m_ShaderProgram.uiId, "sTexture");
  192. m_ShaderProgram.uiDisMap = glGetUniformLocation(m_ShaderProgram.uiId, "sDisMap");
  193. return true;
  194. }
  195. /*!****************************************************************************
  196. @Function LoadVbos
  197. @Description Loads the mesh data required for this training course into
  198. vertex buffer objects
  199. ******************************************************************************/
  200. bool OGLES2DisplacementMap::LoadVbos(CPVRTString* pErrorStr)
  201. {
  202. if(!m_Scene.pMesh[0].pInterleaved)
  203. {
  204. *pErrorStr = "ERROR: IntroducingPOD requires the pod data to be interleaved. Please re-export with the interleaved option enabled.";
  205. return false;
  206. }
  207. if (!m_puiVbo) m_puiVbo = new GLuint[m_Scene.nNumMesh];
  208. if (!m_puiIndexVbo) m_puiIndexVbo = new GLuint[m_Scene.nNumMesh];
  209. /*
  210. Load vertex data of all meshes in the scene into VBOs
  211. The meshes have been exported with the "Interleave Vectors" option,
  212. so all data is interleaved in the buffer at pMesh->pInterleaved.
  213. Interleaving data improves the memory access pattern and cache efficiency,
  214. thus it can be read faster by the hardware.
  215. */
  216. glGenBuffers(m_Scene.nNumMesh, m_puiVbo);
  217. for (unsigned int i = 0; i < m_Scene.nNumMesh; ++i)
  218. {
  219. // Load vertex data into buffer object
  220. SPODMesh& Mesh = m_Scene.pMesh[i];
  221. unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
  222. glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]);
  223. glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
  224. // Load index data into buffer object if available
  225. m_puiIndexVbo[i] = 0;
  226. if (Mesh.sFaces.pData)
  227. {
  228. glGenBuffers(1, &m_puiIndexVbo[i]);
  229. uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
  230. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]);
  231. glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
  232. }
  233. }
  234. glBindBuffer(GL_ARRAY_BUFFER, 0);
  235. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  236. return true;
  237. }
  238. /*!****************************************************************************
  239. @Function InitApplication
  240. @Return bool true if no error occured
  241. @Description Code in InitApplication() will be called by PVRShell once per
  242. run, before the rendering context is created.
  243. Used to initialize variables that are not dependant on it
  244. (e.g. external modules, loading meshes, etc.)
  245. If the rendering context is lost, InitApplication() will
  246. not be called again.
  247. ******************************************************************************/
  248. bool OGLES2DisplacementMap::InitApplication()
  249. {
  250. // Get and set the read path for content files
  251. CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
  252. // Load the scene
  253. if(m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS)
  254. {
  255. PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
  256. return false;
  257. }
  258. // The cameras are stored in the file. We check it contains at least one.
  259. if(m_Scene.nNumCamera == 0)
  260. {
  261. PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera. Please add one and re-export.\n");
  262. return false;
  263. }
  264. // We also check that the scene contains at least one light
  265. if(m_Scene.nNumLight == 0)
  266. {
  267. PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light. Please add one and re-export.\n");
  268. return false;
  269. }
  270. return true;
  271. }
  272. /*!****************************************************************************
  273. @Function QuitApplication
  274. @Return bool true if no error occured
  275. @Description Code in QuitApplication() will be called by PVRShell once per
  276. run, just before exiting the program.
  277. If the rendering context is lost, QuitApplication() will
  278. not be called.
  279. ******************************************************************************/
  280. bool OGLES2DisplacementMap::QuitApplication()
  281. {
  282. // Free the memory allocated for the scene
  283. m_Scene.Destroy();
  284. delete[] m_puiVbo;
  285. delete[] m_puiIndexVbo;
  286. return true;
  287. }
  288. /*!****************************************************************************
  289. @Function InitView
  290. @Return bool true if no error occured
  291. @Description Code in InitView() will be called by PVRShell upon
  292. initialization or after a change in the rendering context.
  293. Used to initialize variables that are dependant on the rendering
  294. context (e.g. textures, vertex buffers, etc.)
  295. ******************************************************************************/
  296. bool OGLES2DisplacementMap::InitView()
  297. {
  298. CPVRTString ErrorStr;
  299. /*
  300. Initialize VBO data
  301. */
  302. if(!LoadVbos(&ErrorStr))
  303. {
  304. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  305. return false;
  306. }
  307. /*
  308. Load textures
  309. */
  310. if(!LoadTextures(&ErrorStr))
  311. {
  312. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  313. return false;
  314. }
  315. /*
  316. Load and compile the shaders & link programs
  317. */
  318. if(!LoadShaders(&ErrorStr))
  319. {
  320. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  321. return false;
  322. }
  323. /*
  324. Initialize Print3D
  325. */
  326. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  327. if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
  328. {
  329. PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
  330. return false;
  331. }
  332. /*
  333. Set OpenGL ES render states needed for this training course
  334. */
  335. // Enable backface culling and depth test
  336. glCullFace(GL_BACK);
  337. glEnable(GL_CULL_FACE);
  338. glEnable(GL_DEPTH_TEST);
  339. // Use a nice bright blue as clear colour
  340. glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
  341. //Get the direction of the first light from the scene.
  342. m_LightDir = m_Scene.GetLightDirection(0);
  343. // For direction vectors, w should be 0
  344. m_LightDir.w = 0.0f;
  345. // Set up the view and projection matrices from the camera
  346. PVRTVec3 vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f);
  347. float fFOV;
  348. // Setup the camera
  349. // Camera nodes are after the mesh and light nodes in the array
  350. int i32CamID = m_Scene.pNode[m_Scene.nNumMeshNode + m_Scene.nNumLight + g_ui32Camera].nIdx;
  351. // Get the camera position, target and field of view (fov)
  352. if(m_Scene.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target?
  353. fFOV = m_Scene.GetCameraPos( vFrom, vTo, g_ui32Camera); // vTo is taken from the target node
  354. else
  355. fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, g_ui32Camera); // vTo is calculated from the rotation
  356. // We can build the model view matrix from the camera position, target and an up vector.
  357. // For this we usePVRTMat4LookAtRH()
  358. m_View = PVRTMat4::LookAtRH(vFrom, vTo, vUp);
  359. // Calculate the projection matrix
  360. m_Projection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate);
  361. // Initialize variables used for the animation
  362. m_iTimePrev = PVRShellGetTime();
  363. return true;
  364. }
  365. /*!****************************************************************************
  366. @Function ReleaseView
  367. @Return bool true if no error occured
  368. @Description Code in ReleaseView() will be called by PVRShell when the
  369. application quits or before a change in the rendering context.
  370. ******************************************************************************/
  371. bool OGLES2DisplacementMap::ReleaseView()
  372. {
  373. // Deletes the textures
  374. glDeleteTextures(m_Scene.nNumMaterial, &m_puiTextureIDs[0]);
  375. glDeleteTextures(1, &m_uiDisMapID);
  376. // Frees the texture lookup array
  377. delete[] m_puiTextureIDs;
  378. m_puiTextureIDs = 0;
  379. // Delete program and shader objects
  380. glDeleteProgram(m_ShaderProgram.uiId);
  381. glDeleteShader(m_uiVertShader);
  382. glDeleteShader(m_uiFragShader);
  383. // Delete buffer objects
  384. glDeleteBuffers(m_Scene.nNumMesh, m_puiVbo);
  385. glDeleteBuffers(m_Scene.nNumMesh, m_puiIndexVbo);
  386. // Release Print3D Textures
  387. m_Print3D.ReleaseTextures();
  388. return true;
  389. }
  390. /*!****************************************************************************
  391. @Function RenderScene
  392. @Return bool true if no error occured
  393. @Description Main rendering loop function of the program. The shell will
  394. call this function every frame.
  395. eglSwapBuffers() will be performed by PVRShell automatically.
  396. PVRShell will also manage important OS events.
  397. Will also manage relevent OS events. The user has access to
  398. these events through an abstraction layer provided by PVRShell.
  399. ******************************************************************************/
  400. bool OGLES2DisplacementMap::RenderScene()
  401. {
  402. // Clear the color and depth buffer
  403. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  404. // Calculates the the time since the last frame
  405. int iTime = PVRShellGetTime();
  406. int iDeltaTime = iTime - m_iTimePrev;
  407. m_iTimePrev = iTime;
  408. // Use shader program
  409. glUseProgram(m_ShaderProgram.uiId);
  410. // Enable 2D texturing for the first texture.
  411. glActiveTexture(GL_TEXTURE0);
  412. // Set the sampler2D variable to the first texture unit
  413. glUniform1i(m_ShaderProgram.uiTexture, 0);
  414. // Enable 2D texturing for the second texture.
  415. glActiveTexture(GL_TEXTURE1);
  416. // Set the displacement map variable to the second texture unit
  417. glUniform1i(m_ShaderProgram.uiDisMap, 1);
  418. // Calculate and set the displacement factor
  419. if(m_bGrow)
  420. {
  421. m_DisplacementFactor += (float)iDeltaTime * g_fDemoFrameRate;
  422. if(m_DisplacementFactor > 25.0f)
  423. {
  424. m_bGrow = false;
  425. m_DisplacementFactor = 25.0f;
  426. }
  427. }
  428. else
  429. {
  430. m_DisplacementFactor -= (float)iDeltaTime * g_fDemoFrameRate;
  431. if(m_DisplacementFactor < 0.0f)
  432. {
  433. m_bGrow = true;
  434. m_DisplacementFactor = 0.0f;
  435. }
  436. }
  437. glUniform1f(m_ShaderProgram.uiDisplacementFactor, m_DisplacementFactor);
  438. // Bind the displacement map texture
  439. glBindTexture(GL_TEXTURE_2D, m_uiDisMapID);
  440. // Now the displacement map texture is bound set the active texture to texture 0
  441. glActiveTexture(GL_TEXTURE0);
  442. // Draw the scene
  443. // Enable the vertex attribute arrays
  444. glEnableVertexAttribArray(VERTEX_ARRAY);
  445. glEnableVertexAttribArray(NORMAL_ARRAY);
  446. glEnableVertexAttribArray(TEXCOORD_ARRAY);
  447. for(unsigned int i = 0; i < m_Scene.nNumMeshNode; ++i)
  448. {
  449. SPODNode& Node = m_Scene.pNode[i];
  450. // Get the node model matrix
  451. PVRTMat4 mWorld;
  452. mWorld = m_Scene.GetWorldMatrix(Node);
  453. // Pass the model-view-projection matrix (MVP) to the shader to transform the vertices
  454. PVRTMat4 mModelView, mMVP;
  455. mModelView = m_View * mWorld;
  456. mMVP = m_Projection * mModelView;
  457. glUniformMatrix4fv(m_ShaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.f);
  458. // Pass the light direction in model space to the shader
  459. PVRTVec4 vLightDir;
  460. vLightDir = mWorld.inverse() * m_LightDir;
  461. PVRTVec3 vLightDirModel = *(PVRTVec3*) vLightDir.ptr();
  462. vLightDirModel.normalize();
  463. glUniform3fv(m_ShaderProgram.uiLightDirLoc, 1, &vLightDirModel.x);
  464. // Load the correct texture for the mesh using our texture lookup table
  465. GLuint uiTex = 0;
  466. if(Node.nIdxMaterial != -1)
  467. uiTex = m_puiTextureIDs[Node.nIdxMaterial];
  468. glBindTexture(GL_TEXTURE_2D, uiTex);
  469. /*
  470. Now that the model-view matrix is set and the materials ready,
  471. call another function to actually draw the mesh.
  472. */
  473. DrawMesh(i);
  474. }
  475. // Safely disable the vertex attribute arrays
  476. glDisableVertexAttribArray(VERTEX_ARRAY);
  477. glDisableVertexAttribArray(NORMAL_ARRAY);
  478. glDisableVertexAttribArray(TEXCOORD_ARRAY);
  479. glBindBuffer(GL_ARRAY_BUFFER, 0);
  480. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  481. // Display the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools
  482. m_Print3D.DisplayDefaultTitle("DisplacementMapping", "", ePVRTPrint3DSDKLogo);
  483. m_Print3D.Flush();
  484. return true;
  485. }
  486. /*!****************************************************************************
  487. @Function DrawMesh
  488. @Input i32NodeIndex Node index of the mesh to draw
  489. @Description Draws a SPODMesh after the model view matrix has been set and
  490. the meterial prepared.
  491. ******************************************************************************/
  492. void OGLES2DisplacementMap::DrawMesh(int i32NodeIndex)
  493. {
  494. int i32MeshIndex = m_Scene.pNode[i32NodeIndex].nIdx;
  495. SPODMesh* pMesh = &m_Scene.pMesh[i32MeshIndex];
  496. // bind the VBO for the mesh
  497. glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i32MeshIndex]);
  498. // bind the index buffer, won't hurt if the handle is 0
  499. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i32MeshIndex]);
  500. // Set the vertex attribute offsets
  501. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
  502. glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
  503. glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
  504. /*
  505. The geometry can be exported in 4 ways:
  506. - Indexed Triangle list
  507. - Non-Indexed Triangle list
  508. - Indexed Triangle strips
  509. - Non-Indexed Triangle strips
  510. */
  511. if(pMesh->nNumStrips == 0)
  512. {
  513. if(m_puiIndexVbo[i32MeshIndex])
  514. {
  515. // Indexed Triangle list
  516. glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
  517. }
  518. else
  519. {
  520. // Non-Indexed Triangle list
  521. glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
  522. }
  523. }
  524. else
  525. {
  526. int offset = 0;
  527. for(int i = 0; i < (int)pMesh->nNumStrips; ++i)
  528. {
  529. if(m_puiIndexVbo[i32MeshIndex])
  530. {
  531. // Indexed Triangle strips
  532. glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, &((GLshort*)0)[offset]);
  533. }
  534. else
  535. {
  536. // Non-Indexed Triangle strips
  537. glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
  538. }
  539. offset += pMesh->pnStripLength[i]+2;
  540. }
  541. }
  542. }
  543. /*!****************************************************************************
  544. @Function NewDemo
  545. @Return PVRShell* The demo supplied by the user
  546. @Description This function must be implemented by the user of the shell.
  547. The user should return its PVRShell object defining the
  548. behaviour of the application.
  549. ******************************************************************************/
  550. PVRShell* NewDemo()
  551. {
  552. return new OGLES2DisplacementMap();
  553. }
  554. /******************************************************************************
  555. End of file (OGLES2DisplacementMap.cpp)
  556. ******************************************************************************/