17b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/****************************************************************************** 27b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 37b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @File OGLES2ChameleonMan.cpp 47b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 57b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Title OGLES2ChameleonMan 67b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 77b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Version 87b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 97b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Copyright Copyright (c) Imagination Technologies Limited. 107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Platform Independent 127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Shows how to perform skinning combined with Dot3 lighting 147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens#include "PVRShell.h" 177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens#include "OGLES2Tools.h" 187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/****************************************************************************** 207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Constants 217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// Camera constants used to generate the projection matrix 247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst float g_fCameraNear = 4.0f; 257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst float g_fCameraFar = 30000.0f; 267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst float g_fDemoFrameRate = 0.02f; 287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/****************************************************************************** 307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens shader attributes 317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// Skinned 347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// vertex attributes 367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensenum EVertexAttrib { 377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens VERTEX_ARRAY, NORMAL_ARRAY, TANGENT_ARRAY, BINORMAL_ARRAY, TEXCOORD_ARRAY, BONEWEIGHT_ARRAY, BONEINDEX_ARRAY, eNumAttribs }; 387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char* g_aszAttribNames[] = { 397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens "inVertex", "inNormal", "inTangent", "inBiNormal", "inTexCoord", "inBoneWeight", "inBoneIndex" }; 407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// shader uniforms 427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensenum ESkinnnedUniform { 437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eViewProj, eLightPos, eBoneCount, eBoneMatrices, eBoneMatricesIT, ebUseDot3, eNumSkinnedUniforms }; 447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char* g_aszSkinnedUniformNames[] = { 457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens "ViewProjMatrix", "LightPos", "BoneCount", "BoneMatrixArray[0]", "BoneMatrixArrayIT[0]", "bUseDot3" }; 467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// Default 487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// vertex attributes 507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensenum EDefaultVertexAttrib { 517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens DEFAULT_VERTEX_ARRAY, DEFAULT_TEXCOORD_ARRAY, eNumDefaultAttribs }; 527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char* g_aszDefaultAttribNames[] = { 537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens "inVertex", "inTexCoord"}; 547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// shader uniforms 567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensenum EDefaultUniform { 577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eDefaultMVPMatrix, eDefaultUOffset, eNumDefaultUniforms }; 587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char* g_aszDefaultUniformNames[] = { 597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens "MVPMatrix", "fUOffset" }; 607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/****************************************************************************** 627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Content file names 637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// Source and binary shaders 667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szSkinnedFragShaderSrcFile[] = "SkinnedFragShader.fsh"; 677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szSkinnedFragShaderBinFile[] = "SkinnedFragShader.fsc"; 687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szSkinnedVertShaderSrcFile[] = "SkinnedVertShader.vsh"; 697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szSkinnedVertShaderBinFile[] = "SkinnedVertShader.vsc"; 707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szDefaultFragShaderSrcFile[] = "DefaultFragShader.fsh"; 717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szDefaultFragShaderBinFile[] = "DefaultFragShader.fsc"; 727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szDefaultVertShaderSrcFile[] = "DefaultVertShader.vsh"; 737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szDefaultVertShaderBinFile[] = "DefaultVertShader.vsc"; 747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// Base Textures 767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szFinalChameleonManHeadBodyTexFile[] = "FinalChameleonManHeadBody.pvr"; 777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szFinalChameleonManLegsTexFile[] = "FinalChameleonManLegs.pvr"; 787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szLampTexFile[] = "lamp.pvr"; 797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szChameleonBeltTexFile[] = "ChameleonBelt.pvr"; 807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szSkylineTexFile[] = "skyline.pvr"; 827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szWallDiffuseBakedTexFile[] = "Wall_diffuse_baked.pvr"; 837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// Tangent Space BumpMap Textures 857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szTang_space_BodyMapTexFile[] = "Tang_space_BodyMap.pvr"; 867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szTang_space_LegsMapTexFile[] = "Tang_space_LegsMap.pvr"; 877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szTang_space_BeltMapTexFile[] = "Tang_space_BeltMap.pvr"; 887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens// POD scene files 907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensconst char c_szSceneFile[] = "ChameleonScene.pod"; 917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/**************************************************************************** 937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens ** Enums ** 947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens ****************************************************************************/ 957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensenum EMeshes 967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eBody, 987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eLegs, 997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eBelt, 1007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eWall, 1017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eBackground, 1027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eLights 1037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens}; 1047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/**************************************************************************** 1067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens** Structures 1077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens****************************************************************************/ 1087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 1107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Class implementing the PVRShell functions. 1117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 1127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensclass OGLES2ChameleonMan : public PVRShell 1137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 1147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Print3D class used to display text 1157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens CPVRTPrint3D m_Print3D; 1167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // 3D Model 1187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens CPVRTModelPOD m_Scene; 1197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Model transformation variables 1217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens float m_fWallPos; 1227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens float m_fBackgroundPos; 1237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens float m_fLightPos; 1247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // OpenGL handles for shaders and VBOs 1267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_uiSkinnedVertShader; 1277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_uiDefaultVertShader; 1287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_uiSkinnedFragShader; 1297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_uiDefaultFragShader; 1307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint* m_puiVbo; 1317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint* m_puiIndexVbo; 1327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Texture IDs 1347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexHeadBody; 1357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexLegs; 1367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexBeltNormalMap; 1377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexHeadNormalMap; 1387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexLegsNormalMap; 1397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexSkyLine; 1407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexWall; 1417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexLamp; 1427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint m_ui32TexBelt; 1437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Group shader programs and their uniform locations together 1457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens struct 1467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 1477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint uiId; 1487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint auiLoc[eNumSkinnedUniforms]; 1497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 1507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_SkinnedShaderProgram; 1517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens struct 1537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 1547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint uiId; 1557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens GLuint auiLoc[eNumDefaultUniforms]; 1567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 1577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_DefaultShaderProgram; 1587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens bool m_bEnableDOT3; 1607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Variables to handle the animation in a time-based manner 1627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens unsigned long m_iTimePrev; 1637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens float m_fFrame; 1647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capenspublic: 1667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens OGLES2ChameleonMan() : m_fWallPos(0), 1677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fBackgroundPos(0), 1687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fLightPos(0), 1697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_puiVbo(0), 1707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_puiIndexVbo(0), 1717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_bEnableDOT3(true), 1727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_iTimePrev(0), 1737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fFrame(0) 1747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 1757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 1767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens virtual bool InitApplication(); 1787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens virtual bool InitView(); 1797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens virtual bool ReleaseView(); 1807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens virtual bool QuitApplication(); 1817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens virtual bool RenderScene(); 1827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens bool LoadTextures(CPVRTString* pErrorStr); 1847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens bool LoadShaders(CPVRTString* pErrorStr); 1857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens void LoadVbos(); 1867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens void DrawSkinnedMesh(int i32NodeIndex); 1887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens}; 1897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 1907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 1917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function LoadTextures 1927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Output pErrorStr A string describing the error on failure 1937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 1947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Loads the textures required for this training course 1957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 1967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::LoadTextures(CPVRTString* const pErrorStr) 1977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 1987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Load Textures 1997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szFinalChameleonManHeadBodyTexFile, &m_ui32TexHeadBody) != PVR_SUCCESS) 2007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load texture for Upper Body.\n"); 2027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szFinalChameleonManLegsTexFile, &m_ui32TexLegs) != PVR_SUCCESS) 2067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load texture for Legs.\n"); 2087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szTang_space_BodyMapTexFile, &m_ui32TexHeadNormalMap) != PVR_SUCCESS) 2127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load normalmap texture for Upper Body.\n"); 2147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szTang_space_LegsMapTexFile, &m_ui32TexLegsNormalMap) != PVR_SUCCESS) 2187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load normalmap texture for Legs.\n"); 2207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szTang_space_BeltMapTexFile, &m_ui32TexBeltNormalMap) != PVR_SUCCESS) 2247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load normalmap texture for Belt.\n"); 2267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szSkylineTexFile, &m_ui32TexSkyLine) != PVR_SUCCESS) 2307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load texture for SkyLine.\n"); 2327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szWallDiffuseBakedTexFile, &m_ui32TexWall) != PVR_SUCCESS) 2367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load texture for Wall.\n"); 2387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szLampTexFile, &m_ui32TexLamp) != PVR_SUCCESS) 2427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load texture for Lamps.\n"); 2447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTTextureLoadFromPVR(c_szChameleonBeltTexFile, &m_ui32TexBelt) != PVR_SUCCESS) 2487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens *pErrorStr = CPVRTString("ERROR: Failed to load texture for Belt.\n"); 2507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 2547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 2557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 2577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function LoadShaders 2587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Output pErrorStr A string describing the error on failure 2597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 2607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Loads and compiles the shaders and links the shader programs 2617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens required for this training course 2627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 2637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::LoadShaders(CPVRTString* pErrorStr) 2647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 2657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens int i; 2667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 2687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Load and compile the shaders from files. 2697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Binary shaders are tried first, source shaders 2707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens are used as fallback. 2717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 2727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Create the skinned program 2757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTShaderLoadFromFile( 2767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens c_szSkinnedVertShaderBinFile, c_szSkinnedVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiSkinnedVertShader, pErrorStr) != PVR_SUCCESS) 2777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTShaderLoadFromFile( 2827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens c_szSkinnedFragShaderBinFile, c_szSkinnedFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiSkinnedFragShader, pErrorStr) != PVR_SUCCESS) 2837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTCreateProgram(&m_SkinnedShaderProgram.uiId, m_uiSkinnedVertShader, m_uiSkinnedFragShader, g_aszAttribNames, eNumAttribs, pErrorStr) != PVR_SUCCESS) 2887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, pErrorStr->c_str()); 2907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 2917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Store the location of uniforms for later use 2947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(i = 0; i < eNumSkinnedUniforms; ++i) 2957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 2967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_SkinnedShaderProgram.auiLoc[i] = glGetUniformLocation(m_SkinnedShaderProgram.uiId, g_aszSkinnedUniformNames[i]); 2977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 2987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 2997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1i(m_SkinnedShaderProgram.auiLoc[ebUseDot3], m_bEnableDOT3); 3007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set the sampler2D uniforms to corresponding texture units 3027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1i(glGetUniformLocation(m_SkinnedShaderProgram.uiId, "sTexture"), 0); 3037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1i(glGetUniformLocation(m_SkinnedShaderProgram.uiId, "sNormalMap"), 1); 3047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Create the non-skinned program 3067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTShaderLoadFromFile( 3077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens c_szDefaultVertShaderBinFile, c_szDefaultVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiDefaultVertShader, pErrorStr) != PVR_SUCCESS) 3087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 3097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 3107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 3117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTShaderLoadFromFile( 3137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens c_szDefaultFragShaderBinFile, c_szDefaultFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiDefaultFragShader, pErrorStr) != PVR_SUCCESS) 3147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 3157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 3167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 3177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRTCreateProgram(&m_DefaultShaderProgram.uiId, m_uiDefaultVertShader, m_uiDefaultFragShader, g_aszDefaultAttribNames, eNumDefaultAttribs, pErrorStr) != PVR_SUCCESS) 3197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 3207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, pErrorStr->c_str()); 3217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 3227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 3237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Store the location of uniforms for later use 3257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(i = 0; i < eNumDefaultUniforms; ++i) 3267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 3277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_DefaultShaderProgram.auiLoc[i] = glGetUniformLocation(m_DefaultShaderProgram.uiId, g_aszDefaultUniformNames[i]); 3287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 3297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set the sampler2D uniforms to corresponding texture units 3317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1i(glGetUniformLocation(m_DefaultShaderProgram.uiId, "sTexture"), 0); 3327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 3347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 3357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 3377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function LoadVbos 3387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Loads the mesh data required for this training course into 3397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens vertex buffer objects 3407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 3417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensvoid OGLES2ChameleonMan::LoadVbos() 3427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 3437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (!m_puiVbo) m_puiVbo = new GLuint[m_Scene.nNumMesh]; 3447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (!m_puiIndexVbo) m_puiIndexVbo = new GLuint[m_Scene.nNumMesh]; 3457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 3477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Load vertex data of all meshes in the scene into VBOs 3487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens The meshes have been exported with the "Interleave Vectors" option, 3507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens so all data is interleaved in the buffer at pMesh->pInterleaved. 3517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Interleaving data improves the memory access pattern and cache efficiency, 3527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens thus it can be read faster by the hardware. 3537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 3547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glGenBuffers(m_Scene.nNumMesh, m_puiVbo); 3567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for (unsigned int i = 0; i < m_Scene.nNumMesh; ++i) 3587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 3597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Load vertex data into buffer object 3607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens SPODMesh& Mesh = m_Scene.pMesh[i]; 3617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride; 3627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]); 3647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW); 3657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Load index data into buffer object if available 3677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_puiIndexVbo[i] = 0; 3687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (Mesh.sFaces.pData) 3707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 3717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glGenBuffers(1, &m_puiIndexVbo[i]); 3727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort); 3737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]); 3747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW); 3757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 3767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 3777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ARRAY_BUFFER, 0); 3797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 3807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 3817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 3837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function InitApplication 3847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 3857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Code in InitApplication() will be called by PVRShell once per 3867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens run, before the rendering context is created. 3877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Used to initialize variables that are not dependant on it 3887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens (e.g. external modules, loading meshes, etc.) 3897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens If the rendering context is lost, InitApplication() will 3907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens not be called again. 3917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 3927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::InitApplication() 3937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 3947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Get and set the read path for content files 3957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); 3967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 3977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Get and set the load/release functions for loading external files. 3987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // In the majority of cases the PVRShell will return NULL function pointers implying that 3997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // nothing special is required to load external files. 4007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); 4017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Load the scene 4037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) 4047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 4057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n"); 4067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 4077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 4087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // The cameras are stored in the file. We check it contains at least one. 4107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (m_Scene.nNumCamera == 0) 4117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 4127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera\n"); 4137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 4147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 4157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Check the scene contains at least one light 4177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (m_Scene.nNumLight == 0) 4187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 4197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light\n"); 4207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 4217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 4227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 4237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 4247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 4267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function QuitApplication 4277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 4287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Code in QuitApplication() will be called by PVRShell once per 4297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens run, just before exiting the program. 4307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens If the rendering context is lost, QuitApplication() will 4317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens not be called. 4327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 4337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::QuitApplication() 4347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 4357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Free the memory allocated for the scene 4367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_Scene.Destroy(); 4377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens delete [] m_puiVbo; 4397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens delete [] m_puiIndexVbo; 4407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 4427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 4437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 4457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function InitView 4467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 4477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Code in InitView() will be called by PVRShell upon 4487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens initialization or after a change in the rendering context. 4497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Used to initialize variables that are dependant on the rendering 4507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens context (e.g. textures, vertex buffers, etc.) 4517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 4527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::InitView() 4537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 4547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens CPVRTString ErrorStr; 4557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 4577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Initialize VBO data 4587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 4597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens LoadVbos(); 4607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 4627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Load textures 4637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 4647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (!LoadTextures(&ErrorStr)) 4657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 4667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, ErrorStr.c_str()); 4677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 4687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 4697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 4717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Load and compile the shaders & link programs 4727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 4737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if (!LoadShaders(&ErrorStr)) 4747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 4757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, ErrorStr.c_str()); 4767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 4777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 4787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 4807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Initialize Print3D 4817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 4827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Is the screen rotated? 4847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); 4857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) 4877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 4887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); 4897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return false; 4907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 4917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 4937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Set OpenGL ES render states needed for this training course 4947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 4957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Enable backface culling and depth test 4967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glCullFace(GL_BACK); 4977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glEnable(GL_CULL_FACE); 4987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 4997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glEnable(GL_DEPTH_TEST); 5007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Use black as our clear colour 5027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 5037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Initialise variables used for the animation 5057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_iTimePrev = PVRShellGetTime(); 5067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 5087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 5097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 5117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function ReleaseView 5127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 5137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Code in ReleaseView() will be called by PVRShell when the 5147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens application quits or before a change in the rendering context. 5157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 5167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::ReleaseView() 5177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 5187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Delete textures 5197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexLegs); 5207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexBeltNormalMap); 5217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexHeadNormalMap); 5227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexLegsNormalMap); 5237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexSkyLine); 5247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexWall); 5257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexLamp); 5267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteTextures(1, &m_ui32TexBelt); 5277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Delete program and shader objects 5297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteProgram(m_SkinnedShaderProgram.uiId); 5307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteProgram(m_DefaultShaderProgram.uiId); 5317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteShader(m_uiSkinnedVertShader); 5337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteShader(m_uiDefaultVertShader); 5347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteShader(m_uiSkinnedFragShader); 5357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteShader(m_uiDefaultFragShader); 5367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Delete buffer objects 5387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteBuffers(m_Scene.nNumMesh, m_puiVbo); 5397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDeleteBuffers(m_Scene.nNumMesh, m_puiIndexVbo); 5407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Release Print3D Textures 5427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_Print3D.ReleaseTextures(); 5437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 5457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 5467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 5487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function RenderScene 5497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return bool true if no error occured 5507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Main rendering loop function of the program. The shell will 5517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens call this function every frame. 5527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens eglSwapBuffers() will be performed by PVRShell automatically. 5537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRShell will also manage important OS events. 5547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Will also manage relevent OS events. The user has access to 5557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens these events through an abstraction layer provided by PVRShell. 5567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 5577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensbool OGLES2ChameleonMan::RenderScene() 5587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 5597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Clear the color and depth buffer 5607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 5617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Use shader program 5637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUseProgram(m_SkinnedShaderProgram.uiId); 5647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(PVRShellIsKeyPressed(PVRShellKeyNameACTION1)) 5667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 5677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_bEnableDOT3 = !m_bEnableDOT3; 5687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1i(m_SkinnedShaderProgram.auiLoc[ebUseDot3], m_bEnableDOT3); 5697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 5707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 5727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Calculates the frame number to animate in a time-based manner. 5737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens Uses the shell function PVRShellGetTime() to get the time in milliseconds. 5747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 5757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens unsigned long iTime = PVRShellGetTime(); 5767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(iTime > m_iTimePrev) 5787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 5797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens float fDelta = (float) (iTime - m_iTimePrev); 5807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fFrame += fDelta * g_fDemoFrameRate; 5817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Increment the counters to make sure our animation works 5837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fLightPos += fDelta * 0.0034f; 5847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fWallPos += fDelta * 0.00027f; 5857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fBackgroundPos += fDelta * -0.000027f; 5867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Wrap the Animation back to the Start 5887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_fLightPos >= PVRT_TWO_PI) 5897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fLightPos -= PVRT_TWO_PI; 5907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_fWallPos >= PVRT_TWO_PI) 5927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fWallPos -= PVRT_TWO_PI; 5937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_fBackgroundPos <= 0) 5957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fBackgroundPos += 1.0f; 5967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 5977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_fFrame > m_Scene.nNumFrame - 1) 5987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_fFrame = 0; 5997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 6007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_iTimePrev = iTime; 6027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set the scene animation to the current frame 6047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_Scene.SetFrame(m_fFrame); 6057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set up camera 6077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTVec3 vFrom, vTo, vUp(0.0f, 1.0f, 0.0f); 6087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat4 mView, mProjection; 6097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTVec3 LightPos; 6107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens float fFOV; 6117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens int i; 6127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); 6147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Get the camera position, target and field of view (fov) 6167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_Scene.pCamera[0].nIdxTarget != -1) // Does the camera have a target? 6177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens fFOV = m_Scene.GetCameraPos( vFrom, vTo, 0); // vTo is taken from the target node 6187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens else 6197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, 0); // vTo is calculated from the rotation 6207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens fFOV *= bRotate ? (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight) : (float)PVRShellGet(prefHeight)/(float)PVRShellGet(prefWidth); 6227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 6247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens We can build the model view matrix from the camera position, target and an up vector. 6257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens For this we use PVRTMat4::LookAtRH(). 6267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 6277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mView = PVRTMat4::LookAtRH(vFrom, vTo, vUp); 6287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Calculate the projection matrix 6307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate); 6317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Update Light Position and related VGP Program constant 6337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens LightPos.x = 200.0f; 6347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens LightPos.y = 350.0f; 6357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens LightPos.z = 200.0f * PVRTABS(sin((PVRT_PI / 4.0f) + m_fLightPos)); 6367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform3fv(m_SkinnedShaderProgram.auiLoc[eLightPos], 1, LightPos.ptr()); 6387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set up the View * Projection Matrix 6407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat4 mViewProjection; 6417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mViewProjection = mProjection * mView; 6437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniformMatrix4fv(m_SkinnedShaderProgram.auiLoc[eViewProj], 1, GL_FALSE, mViewProjection.ptr()); 6447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Enable the vertex attribute arrays 6467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(i = 0; i < eNumAttribs; ++i) glEnableVertexAttribArray(i); 6477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Draw skinned meshes 6497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(unsigned int i32NodeIndex = 0; i32NodeIndex < 3; ++i32NodeIndex) 6507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 6517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Bind correct texture 6527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens switch(i32NodeIndex) 6537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 6547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens case eBody: 6557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glActiveTexture(GL_TEXTURE1); 6567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexHeadNormalMap); 6577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glActiveTexture(GL_TEXTURE0); 6587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexHeadBody); 6597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 6607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens case eLegs: 6617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glActiveTexture(GL_TEXTURE1); 6627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexLegsNormalMap); 6637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glActiveTexture(GL_TEXTURE0); 6647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexLegs); 6657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 6667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens default: 6677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glActiveTexture(GL_TEXTURE1); 6687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexBeltNormalMap); 6697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glActiveTexture(GL_TEXTURE0); 6707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexBelt); 6717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 6727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 6737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens DrawSkinnedMesh(i32NodeIndex); 6757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 6767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Safely disable the vertex attribute arrays 6787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(i = 0; i < eNumAttribs; ++i) glDisableVertexAttribArray(i); 6797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Draw non-skinned meshes 6817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUseProgram(m_DefaultShaderProgram.uiId); 6827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Enable the vertex attribute arrays 6847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(i = 0; i < eNumDefaultAttribs; ++i) glEnableVertexAttribArray(i); 6857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(unsigned int i32NodeIndex = 3; i32NodeIndex < m_Scene.nNumMeshNode; ++i32NodeIndex) 6877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 6887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens SPODNode& Node = m_Scene.pNode[i32NodeIndex]; 6897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens SPODMesh& Mesh = m_Scene.pMesh[Node.nIdx]; 6907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // bind the VBO for the mesh 6927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[Node.nIdx]); 6937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // bind the index buffer, won't hurt if the handle is 0 6957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[Node.nIdx]); 6967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 6977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Get the node model matrix 6987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat4 mWorld; 6997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mWorld = m_Scene.GetWorldMatrix(Node); 7007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Setup the appropriate texture and transformation (if needed) 7027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens switch(i32NodeIndex) 7037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 7047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens case eWall: 7057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexWall); 7067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Rotate the wall mesh which is circular 7087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mWorld *= PVRTMat4::RotationY(m_fWallPos); 7097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1f(m_DefaultShaderProgram.auiLoc[eDefaultUOffset], 0); 7117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 7137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens case eBackground: 7147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexSkyLine); 7157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1f(m_DefaultShaderProgram.auiLoc[eDefaultUOffset], m_fBackgroundPos); 7177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 7187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens case eLights: 7197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 7207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindTexture(GL_TEXTURE_2D, m_ui32TexLamp); 7217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat4 mWallWorld = m_Scene.GetWorldMatrix(m_Scene.pNode[eWall]); 7237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mWorld = mWallWorld * PVRTMat4::RotationY(m_fWallPos) * mWallWorld.inverse() * mWorld; 7247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1f(m_DefaultShaderProgram.auiLoc[eDefaultUOffset], 0); 7267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 7277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 7287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens default: 7297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens break; 7307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens }; 7317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set up shader uniforms 7337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat4 mModelViewProj; 7347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens mModelViewProj = mViewProjection * mWorld; 7357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniformMatrix4fv(m_DefaultShaderProgram.auiLoc[eDefaultMVPMatrix], 1, GL_FALSE, mModelViewProj.ptr()); 7367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set the vertex attribute offsets 7387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(DEFAULT_VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sVertex.nStride, Mesh.sVertex.pData); 7397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(DEFAULT_TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, Mesh.psUVW[0].nStride, Mesh.psUVW[0].pData); 7407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Indexed Triangle list 7427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDrawElements(GL_TRIANGLES, Mesh.nNumFaces*3, GL_UNSIGNED_SHORT, 0); 7437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 7447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Safely disable the vertex attribute arrays 7467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(i = 0; i < eNumAttribs; ++i) glDisableVertexAttribArray(i); 7477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7487b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // unbind the VBOs 7497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ARRAY_BUFFER, 0); 7507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 7517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Display the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools 7537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens const char * pDescription; 7547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(m_bEnableDOT3) 7567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens pDescription = "Skinning with DOT3 Per Pixel Lighting"; 7577b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens else 7587b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens pDescription = "Skinning with Vertex Lighting"; 7597b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7607b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_Print3D.DisplayDefaultTitle("Chameleon Man", pDescription, ePVRTPrint3DSDKLogo); 7617b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens m_Print3D.Flush(); 7627b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7637b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return true; 7647b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 7657b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7667b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 7677b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function DrawSkinnedMesh 7687b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Input i32NodeIndex Node index of the mesh to draw 7697b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description Draws a SPODMesh after the model view matrix has been set and 7707b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens the meterial prepared. 7717b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 7727b21f276fa91ad62fd2055844688b07829f12205Nicolas Capensvoid OGLES2ChameleonMan::DrawSkinnedMesh(int i32NodeIndex) 7737b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 7747b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens SPODNode& Node = m_Scene.pNode[i32NodeIndex]; 7757b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens SPODMesh& Mesh = m_Scene.pMesh[Node.nIdx]; 7767b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7777b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // bind the VBO for the mesh 7787b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[Node.nIdx]); 7797b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // bind the index buffer, won't hurt if the handle is 0 7807b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[Node.nIdx]); 7817b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7827b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set the vertex attribute offsets 7837b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sVertex.nStride, Mesh.sVertex.pData); 7847b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sNormals.nStride, Mesh.sNormals.pData); 7857b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(TANGENT_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sTangents.nStride, Mesh.sTangents.pData); 7867b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(BINORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sBinormals.nStride, Mesh.sBinormals.pData); 7877b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, Mesh.psUVW[0].nStride, Mesh.psUVW[0].pData); 7887b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(BONEINDEX_ARRAY, Mesh.sBoneIdx.n, GL_UNSIGNED_BYTE, GL_FALSE, Mesh.sBoneIdx.nStride, Mesh.sBoneIdx.pData); 7897b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glVertexAttribPointer(BONEWEIGHT_ARRAY, Mesh.sBoneWeight.n, GL_UNSIGNED_BYTE, GL_TRUE, Mesh.sBoneWeight.nStride, Mesh.sBoneWeight.pData); 7907b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7917b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(int i32Batch = 0; i32Batch < Mesh.sBoneBatches.nBatchCnt; ++i32Batch) 7927b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 7937b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 7947b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens If the current mesh has bone index and weight data then we need to 7957b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens set up some additional variables in the shaders. 7967b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 7977b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 7987b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Set the number of bones that will influence each vertex in the mesh 7997b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniform1i(m_SkinnedShaderProgram.auiLoc[eBoneCount], Mesh.sBoneIdx.n); 8007b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8017b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Go through the bones for the current bone batch 8027b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat4 amBoneWorld[8]; 8037b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens PVRTMat3 afBoneWorldIT[8], mBoneIT; 8047b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8057b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens int i32Count = Mesh.sBoneBatches.pnBatchBoneCnt[i32Batch]; 8067b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8077b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens for(int i = 0; i < i32Count; ++i) 8087b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens { 8097b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Get the Node of the bone 8107b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens int i32NodeID = Mesh.sBoneBatches.pnBatches[i32Batch * Mesh.sBoneBatches.nBatchBoneMax + i]; 8117b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8127b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Get the World transformation matrix for this bone and combine it with our app defined 8137b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // transformation matrix 8147b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens amBoneWorld[i] = m_Scene.GetBoneWorldMatrix(Node, m_Scene.pNode[i32NodeID]); 8157b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8167b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Calculate the inverse transpose of the 3x3 rotation/scale part for correct lighting 8177b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens afBoneWorldIT[i] = PVRTMat3(amBoneWorld[i]).inverse().transpose(); 8187b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 8197b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8207b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniformMatrix4fv(m_SkinnedShaderProgram.auiLoc[eBoneMatrices], i32Count, GL_FALSE, amBoneWorld[0].ptr()); 8217b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glUniformMatrix3fv(m_SkinnedShaderProgram.auiLoc[eBoneMatricesIT], i32Count, GL_FALSE, afBoneWorldIT[0].ptr()); 8227b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8237b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens /* 8247b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens As we are using bone batching we don't want to draw all the faces contained within pMesh, we only want 8257b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens to draw the ones that are in the current batch. To do this we pass to the drawMesh function the offset 8267b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens to the start of the current batch of triangles (Mesh.sBoneBatches.pnBatchOffset[i32Batch]) and the 8277b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens total number of triangles to draw (i32Tris) 8287b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens */ 8297b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens int i32Tris; 8307b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens if(i32Batch+1 < Mesh.sBoneBatches.nBatchCnt) 8317b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens i32Tris = Mesh.sBoneBatches.pnBatchOffset[i32Batch+1] - Mesh.sBoneBatches.pnBatchOffset[i32Batch]; 8327b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens else 8337b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens i32Tris = Mesh.nNumFaces - Mesh.sBoneBatches.pnBatchOffset[i32Batch]; 8347b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8357b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens // Draw the mesh 8367b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens size_t offset = sizeof(GLushort) * 3 * Mesh.sBoneBatches.pnBatchOffset[i32Batch]; 8377b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens glDrawElements(GL_TRIANGLES, i32Tris * 3, GL_UNSIGNED_SHORT, (void*) offset); 8387b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens } 8397b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 8407b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8417b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/*!**************************************************************************** 8427b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Function NewDemo 8437b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Return PVRShell* The demo supplied by the user 8447b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens @Description This function must be implemented by the user of the shell. 8457b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens The user should return its PVRShell object defining the 8467b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens behaviour of the application. 8477b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 8487b21f276fa91ad62fd2055844688b07829f12205Nicolas CapensPVRShell* NewDemo() 8497b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens{ 8507b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens return new OGLES2ChameleonMan(); 8517b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens} 8527b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 8537b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens/****************************************************************************** 8547b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens End of file (OGLES2ChameleonMan.cpp) 8557b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens******************************************************************************/ 8567b21f276fa91ad62fd2055844688b07829f12205Nicolas Capens 857