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