123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482 |
- /******************************************************************************
- @File OGLES2Navigation3D.cpp
- @Title Navigation
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform Independent
- @Description Demonstrates a method of rendering a 3D navigation application
- using OpenGL ES 2.0 and various culling techniques
- ******************************************************************************/
- #include "PVRShell.h"
- #include "OGLES2Tools.h"
- #include <stddef.h>
- /******************************************************************************
- Defines
- ******************************************************************************/
- #ifdef _DEBUG
- #define ENABLE_CULLING_OPTIONS
- #define ENABLE_ADVANCED_OUTPUT
- #endif
- // Index the attributes that are bound to vertex shaders
- #define VERTEX_ARRAY 0
- #define NORMAL_ARRAY 1
- #define TEXCOORD_ARRAY 2
- /****************************************************************************
- ** Structures
- ****************************************************************************/
- /*!***********************************************************************
- * @Struct PVRTModelVertex
- ************************************************************************/
- struct PVRTModelVertex
- {
- PVRTVec3 position;
- PVRTVec3 normal;
- PVRTVec2 texcoord;
- };
- /*!***********************************************************************
- * @Struct PVRTBoundingBox2D
- * @Brief Structure describing a 2D bounding box. Supports all kind of
- * set operations and provides higher level functionality.
- ************************************************************************/
- struct PVRTBoundingBox2D
- {
- // Min and max coordinates
- PVRTVec2 minCoords;
- PVRTVec2 maxCoords;
- };
- /*!**************************************************************************
- * @Struct ModelTileObjectSet
- ****************************************************************************/
- struct ModelTileObjectSet
- {
- PVRTBoundingBox2D boundingbox;
- size_t numSubObjects;
- unsigned int *pNodeIdx;
- unsigned int *paNumIndices;
- unsigned int *paIndexOffsets;
- GLuint *pauiTextures;
- };
- /*!**************************************************************************
- * @Struct ModelTileLod
- * @Brief A model tile LOD stores the filename of the POD file and various
- * attributes like the number of (parent) objects it contains.
- * Furthermore it stores two OpenGL buffer object identifiers, one
- * for the vertex and another one for the index data.
- * The last members keep a list of visible nodes which are determined
- * in a seperate visibility update pass.
- ****************************************************************************/
- struct ModelTileLod
- {
- char *pszFilename;
- size_t numObjects;
- ModelTileObjectSet *paObjects;
- GLuint vbos[2];
- unsigned int *paVisibleNodes;
- unsigned int numVisibleNodes;
- bool bLoaded;
- };
- /*!**************************************************************************
- * @Struct ModelTile
- * @Brief A model tile is a container for all models located within a certain
- * region of the city defined by the bounding box. There can be several
- * levels of detail for each model tile.
- ****************************************************************************/
- struct ModelTile
- {
- PVRTBoundingBox2D boundingbox;
- size_t numLod;
- ModelTileLod *paLod;
- };
- /*!**************************************************************************
- * @Struct PositionOcclusionData
- * @Brief TODO
- ****************************************************************************/
- struct PositionOcclusionData
- {
- PVRTVec3 position;
- unsigned int numRefObjects;
- unsigned int *pRefTile;
- unsigned int *pNumRefObject;
- unsigned int **ppRefObjects;
- };
- /*!**************************************************************************
- * @Struct ShaderDescription
- * @Brief This structure describes a shader program and is just used to
- * conveniently store each available shader.
- ****************************************************************************/
- struct ShaderDescription
- {
- const char *pszVertShaderSrcFile;
- const char *pszVertShaderBinFile;
- const char *pszFragShaderSrcFile;
- const char *pszFragShaderBinFile;
- const unsigned int ui32NumAttributes;
- const char **pszAttributes;
- };
- /******************************************************************************
- Content file names
- ******************************************************************************/
- const char *g_pszAttributes[] = { "inVertex", "inNormal", "inTexCoord" };
- const ShaderDescription BuildingShaderDescription = { "BuildingVertShader.vsh", "BuildingVertShader.vsc", "BuildingFragShader.fsh", "BuildingFragShader.fsc", 3, (const char**)g_pszAttributes };
- const ShaderDescription SkyboxShaderDescription = { "SkyboxVertShader.vsh", "SkyboxVertShader.vsc", "SkyboxFragShader.fsh", "SkyboxFragShader.fsc", 1, (const char**)g_pszAttributes };
- // Textures
- const char c_szTextureNameSkybox[] = "Skybox.pvr";
- // Scene files
- const char c_szTrackFile[] = "cameratrack.pod";
- const char c_szModelIndexFilename[] = "modelindex.nav";
- const char c_szOcclusionDataFilename[] = "occlusiondata.nav";
- // Texture files required for the city model
- const char *c_paszTextures[] = { "006_RUS.PNG", "007_RUG.PNG", "008_RUG.PNG", "009_RUG.PNG", "011_GIE.PNG", "012_RSR.PNG", "016_FOC.PNG", "016_RTR.PNG", "017_FOD.PNG",
- "018_FOD.PNG", "019_FOC.PNG", "019_GOC.PNG", "019_RZG.PNG", "020_FOC.PNG", "021_FOC.PNG", "022_FOC.PNG", "022_RUG.PNG",
- "023_FOB.PNG", "023_RUG.PNG", "024_FOB.PNG", "025_FOC.PNG", "025_RUW.PNG", "026_FOD.PNG", "026_RUW.PNG", "027_FOD.PNG",
- "027_RUW.PNG", "028_GOF.PNG", "029_GCC.PNG", "030_GOC.PNG", "031_GOD.PNG", "032_FOC.PNG", "032_GOC.PNG", "033_FOA.PNG",
- "033_GOA.PNG", "034_FOC.PNG", "034_GOC.PNG", "035_FOC.PNG", "035_GOC.PNG", "036_FOC.PNG", "036_GOC.PNG", "037_FOC.PNG",
- "037_GOC.PNG", "041_FRB.PNG", "041_GRB.PNG", "044_GRC.PNG", "046_GRC.PNG", "055_GRC.PNG", "056_GRC.PNG", "060_FRC.PNG", "063_GRC.PNG",
- "064_GRC.PNG", "066_FCB.PNG", "066_GCB.PNG", "067_FCC.PNG", "067_GCC.PNG", "068_GCD.PNG", "069_FCA.PNG", "069_GCA.PNG",
- "070_GOD.PNG", "071_FRC.PNG", "072_FRC.PNG", "073_FRC.PNG", "074_FRC.PNG", "075_FRC.PNG", "076_FRC.PNG", "077_FRC.PNG",
- "080_GCB.PNG", "083_FRC.PNG", "085_GRC.PNG", "086_FOF.PNG", "086_GOF.PNG", "087_FCA.PNG", "087_GCA.PNG", "087_GCC.PNG",
- "054_GRC.PNG", "059_FRC.PNG", "061_FRD.PNG", "082_FCD.PNG", "088_FRC.PNG", "089_FRC.PNG", "092_GCA.PNG", "094_FOD.PNG", "095_FOD.PNG",
- "US_IL_CHICAGO_MMART_L.PNG", "US_IL_13443_CHICAGO_35EAST_L.PNG", "US_IL_13444_CHICAGO_LEOBURNETT_L.PNG",
- "US_IL_13447_CHICAGO_REIDMURDOCH_L.PNG", "US_IL_13448_CHICAGO_CARBIDE_L.PNG", "US_IL_13449_CHICAGO_CROWNFOUNTAIN_L.PNG",
- "US_IL_13451_CHICAGO_CULTURAL_L.PNG", "US_IL_13453_CHICAGO_PRUDENTIAL_PART1_L.PNG", "US_IL_13454_CHICAGO_UNITED_L.PNG",
- "US_IL_13458_CHICAGO_SMURFIT_L.PNG", "US_IL_13459_CHICAGO_LASALLE_L.PNG", "US_IL_13461_CHICAGO_UNITRIN_L.PNG", "US_IL_13462_CHICAGO_WILLOUGHBY_L.PNG",
- "US_IL_13490_CHICAGO_PRUDENTIAL_PART2_L.PNG", "US_IL_CHICAGO_AONCENTER_L.PNG", "US_IL_CHICAGO_ARTINSTITUTE_L.PNG", "US_IL_CHICAGO_BOARDOFTHETRADE_L.PNG",
- "US_IL_CHICAGO_BOEINGBUILDING_L.PNG", "US_IL_CHICAGO_CHICAGOTHEATRE_L.PNG", "US_IL_CHICAGO_CITYHALL_L.PNG", "US_IL_CHICAGO_DALEY_L.PNG",
- "US_IL_CHICAGO_HILTON_L.PNG", "US_IL_CHICAGO_JAMESTHOMPSON_L.PNG", "US_IL_CHICAGO_LIBRARY_L.PNG", "US_IL_CHICAGO_MILLENIUMPARK1_L.PNG",
- "US_IL_CHICAGO_MILLENIUMPARK2_L.PNG", "US_IL_CHICAGO_OGILVIE_L.PNG", "US_IL_CHICAGO_SEARSTOWER_L.PNG", "US_L_CONCRETE-COLOUR.PNG",
- "US_L_CONCRETE-DETAIL.PNG", "US_L_PARK-COLOUR.PNG", "US_L_WATER-COLOUR.PNG", "US_R_CONCRETE.PNG", "US_R_STREET-DASHED.PNG", "US_R_STREET-INNER-SHOULDER.PNG",
- "US_R_STREET-LANE-FILLER.PNG", "US_R_STREET-SOLID.PNG", "US_R_STREET-UNMARKED.PNG", "US_R_WALKWAY-SOLID.PNG", "US_R_WALKWAY-UNMARKED.PNG", "US_T_RAILROAD.PNG",
- "US_R_HIGHWAY-SOLID.PNG", "US_IL_CHICAGO_UNIONSTATION_L.PNG", "US_IL_13460_CHICAGO_TRUMP_L.PNG", "US_IL_13456_CHICAGO_SEVENTEENTH_L.PNG" };
- /*!****************************************************************************
- Class declarations
- ******************************************************************************/
- /*!***********************************************************************
- * @Class OGLES2Navigation3D
- * @Brief Navigation demo main class.
- ************************************************************************/
- class OGLES2Navigation3D : public PVRShell
- {
- // Print3D class used to display text
- CPVRTPrint3D m_Print3D;
- // Camera attributes
- CPVRTModelPOD m_CameraPod;
- unsigned int m_ActiveCameraTrack;
- float m_fFOV;
- float m_fAspectRatio;
- float m_fNearClipPlane;
- float m_fFarClipPlane;
- PVRTVec3 m_vCameraFrom;
- PVRTVec3 m_vCameraTo;
- PVRTVec3 m_vCameraUp;
-
- // Viewing matrices
- PVRTMat4 m_mViewMatrix;
- PVRTMat4 m_mProjectionMatrix;
- PVRTMat4 m_mViewProjectionMatrix;
- // 3D Models
- unsigned int m_uiNumModelTiles;
- ModelTile *m_paModelTiles;
- unsigned int *m_pauiVisibleTiles;
- unsigned int m_uiNumVisibleTiles;
- float m_afLodDistances[2];
- float m_afSquaredLodDistances[2];
- // Occlusion data
- PositionOcclusionData *m_paPositionOcclusionData;
- unsigned int m_uiNumOcclusionData;
- // Skybox
- GLuint m_uiSkyboxVBO;
- GLuint m_uiTextureIdSkybox;
- // Textures
- unsigned int m_uiNumTextures;
- GLuint *m_pauiTextureIds;
- // Shader objects
- struct Shader
- {
- GLuint uiId;
- GLuint uiVertexShaderId;
- GLuint uiFragmentShaderId;
- GLuint uiModelViewProjMatrixLoc;
- }
- m_SkyboxShader;
- struct ModelShader : Shader
- {
- GLuint uiLightDirectionLoc;
- }
- m_BuildingShader;
-
- // Time variables
- float m_fCameraAnimation;
- float m_fDebugTimeMultiplier;
- // General options
- bool m_bUseOcclusionData;
- bool m_bViewFrustumCulling;
- bool m_bPause;
- bool m_bRotate;
- public:
- virtual bool InitApplication();
- virtual bool InitView();
- virtual bool ReleaseView();
- virtual bool QuitApplication();
- virtual bool RenderScene();
- bool LoadTextures(CPVRTString* pErrorStr);
- bool LoadShader(CPVRTString* pErrorStr, const ShaderDescription &descr, Shader &shader);
- bool LoadShaders(CPVRTString* pErrorStr);
- bool ReleaseShader(Shader &shader);
- unsigned int UpdateTimer();
- void Update3dModelWorkingset();
- void HandleInput();
- void Render3dModels();
- void Render3dModelsOcclusion();
- void RenderSkyBox();
- void CreateModelVbo(const unsigned int tile, const unsigned int lod);
- void ReleaseModelVbo(const unsigned int tile, const unsigned int lod);
-
- void CalculateCameraMatrices();
- void GetCameraFrame(PVRTVec3 &from, PVRTVec3 &to, PVRTVec3 &up, float time);
- void ExtractViewFrustumPlanes(PVRTVec4 &left, PVRTVec4 &right, PVRTVec4 &front, PVRTVec4 &back) const;
- bool BoundingBoxIntersectsFrustum(const PVRTBoundingBox2D &bbox, const PVRTVec4 planes[4]) const;
-
- bool Load3dModelIndex(const char *pszFilename, CPVRTString* pErrorStr);
- void Release3dModelIndex();
- void Cache3dModelData();
- bool LoadOcclusionData(const char *pszFilename, CPVRTString* pErrorStr);
- void ReleaseOcclusionData();
- };
- /*!****************************************************************************
- @Function LoadTextures
- @Output pErrorStr A string describing the error on failure
- @Return bool true if no error occured
- @Description Loads the textures required for this training course
- ******************************************************************************/
- bool OGLES2Navigation3D::LoadTextures(CPVRTString* const pErrorStr)
- {
- if (PVRTTextureLoadFromPVR(c_szTextureNameSkybox, &m_uiTextureIdSkybox) != PVR_SUCCESS)
- {
- *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + c_szTextureNameSkybox;
- return false;
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- m_uiNumTextures = sizeof(c_paszTextures)/sizeof(c_paszTextures[0]);
- m_pauiTextureIds = new GLuint[m_uiNumTextures];
- char buffer[512];
- for (unsigned int i=0; i < m_uiNumTextures; i++)
- {
- strcpy(buffer, c_paszTextures[i]);
- strcat(buffer, ".pvr");
- if (PVR_SUCCESS == PVRTTextureLoadFromPVR(buffer, &m_pauiTextureIds[i]))
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- else
- {
- PVRShellOutputDebug("Failed to load texture: %s\n", buffer);
- }
- }
-
- return true;
- }
- /*!****************************************************************************
- @Function LoadShader
- @Output pErrorStr A string describing the error on failure
- @Input descr A struct containing all necessary information to
- load and build the shader
- @Output shader A struct containing all shader object identifiers
- @Return bool true if no error occured
- @Description Loads and compiles a shader and links it into a shader program
- ******************************************************************************/
- bool OGLES2Navigation3D::LoadShader(CPVRTString* pErrorStr, const ShaderDescription &descr, Shader &shader)
- {
- if (PVRTShaderLoadFromFile(descr.pszVertShaderBinFile, descr.pszVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &shader.uiVertexShaderId, pErrorStr) != PVR_SUCCESS)
- {
- *pErrorStr = descr.pszVertShaderSrcFile + CPVRTString(":\n") + *pErrorStr;
- return false;
- }
- if (PVRTShaderLoadFromFile(descr.pszFragShaderBinFile, descr.pszFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &shader.uiFragmentShaderId, pErrorStr) != PVR_SUCCESS)
- {
- *pErrorStr = descr.pszFragShaderSrcFile + CPVRTString(":\n") + *pErrorStr;
- return false;
- }
- // Set up and link to the shader program
- if (PVRTCreateProgram(&shader.uiId, shader.uiVertexShaderId, shader.uiFragmentShaderId, descr.pszAttributes, descr.ui32NumAttributes, pErrorStr))
- {
- *pErrorStr = descr.pszFragShaderSrcFile + CPVRTString(":\n") + *pErrorStr;
- return false;
- }
- return true;
- }
- /*!****************************************************************************
- @Function LoadShaders
- @Output pErrorStr A string describing the error on failure
- @Return bool true if no error occured
- @Description Loads and compiles shaders and links them to shader programs
- ******************************************************************************/
- bool OGLES2Navigation3D::LoadShaders(CPVRTString* pErrorStr)
- {
- // Load and compile the shaders from files.
- // Binary shaders are tried first, source shaders are used as fallback.
- // CityModelShader
- //
- if (!LoadShader(pErrorStr, BuildingShaderDescription, m_BuildingShader))
- {
- PVRShellSet(prefExitMessage, pErrorStr->c_str());
- return false;
- }
-
- m_BuildingShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_BuildingShader.uiId, "ModelViewProjMatrix");
- m_BuildingShader.uiLightDirectionLoc = glGetUniformLocation(m_BuildingShader.uiId, "LightDirection");
- glUniform1i(glGetUniformLocation(m_BuildingShader.uiId, "sTexture"), 0);
- // SkyboxShader
- //
- if (!LoadShader(pErrorStr, SkyboxShaderDescription, m_SkyboxShader))
- {
- PVRShellSet(prefExitMessage, pErrorStr->c_str());
- return false;
- }
- m_SkyboxShader.uiModelViewProjMatrixLoc = glGetUniformLocation(m_SkyboxShader.uiId, "ModelViewProjMatrix");
- glUniform1i(glGetUniformLocation(m_SkyboxShader.uiId, "sCubeMap"), 0);
- return true;
- }
- /*!****************************************************************************
- @Function InitApplication
- @Return bool true if no error occured
- @Description Code in InitApplication() will be called by PVRShell once per
- run, before the rendering context is created.
- Used to initialize variables that are not dependant on it
- (e.g. external modules, loading meshes, etc.)
- If the rendering context is lost, InitApplication() will
- not be called again.
- ******************************************************************************/
- bool OGLES2Navigation3D::InitApplication()
- {
- m_bPause = false;
- m_bUseOcclusionData = true;
- m_bViewFrustumCulling = true;
-
- m_paModelTiles = 0;
- m_pauiVisibleTiles = 0;
- m_paPositionOcclusionData = 0;
- m_pauiTextureIds = 0;
- m_uiNumTextures = 0;
- m_uiNumModelTiles = 0;
- m_uiNumVisibleTiles = 0;
- m_uiNumOcclusionData = 0;
-
- // Get and set the read path for content files
- CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
- CPVRTString errorStr;
- if (!Load3dModelIndex(c_szModelIndexFilename, &errorStr))
- {
- PVRShellOutputDebug(errorStr.c_str());
- return false;
- }
- if (!LoadOcclusionData(c_szOcclusionDataFilename, &errorStr))
- {
- PVRShellOutputDebug(errorStr.c_str());
- return false;
- }
-
- m_pauiVisibleTiles = new unsigned int[m_uiNumModelTiles];
- if (PVR_SUCCESS != m_CameraPod.ReadFromFile("cameratrack.pod"))
- {
- PVRShellSet(prefExitMessage, "Error: Failed to parse POD cameratrack.\n");
- return false;
- }
- m_ActiveCameraTrack = 0;
- m_fNearClipPlane = m_CameraPod.pCamera->fNear;
- m_fFarClipPlane = m_CameraPod.pCamera->fFar;
- m_fFOV = m_CameraPod.pCamera->fFOV;
- const int cmdargs = PVRShellGet(prefCommandLineOptNum);
- const SCmdLineOpt *pCmdLine = (const SCmdLineOpt *)PVRShellGet(prefCommandLineOpts);
- for (int i=0; i < cmdargs; i++)
- {
- if (strcmp(pCmdLine[i].pArg, "-far") == 0)
- {
- PVRShellOutputDebug("Info: Changing far clip plane from %.0f to %s\n", m_fFarClipPlane, pCmdLine[i].pVal);
- m_fFarClipPlane = (float)atoi(pCmdLine[i].pVal);
- }
- if (strcmp(pCmdLine[i].pArg, "-near") == 0)
- {
- PVRShellOutputDebug("Info: Changing near clip plane from %.0f to %s\n", m_fNearClipPlane, pCmdLine[i].pVal);
- m_fNearClipPlane = (float)atoi(pCmdLine[i].pVal);
- }
- }
- m_afLodDistances[0] = (m_CameraPod.pCamera->fFar + m_CameraPod.pCamera->fNear) * 0.5f;
- m_afLodDistances[1] = m_CameraPod.pCamera->fFar;
- m_afSquaredLodDistances[0] = m_afLodDistances[0] * m_afLodDistances[0];
- m_afSquaredLodDistances[1] = m_afLodDistances[1] * m_afLodDistances[1];
-
- // Set timer variables
- m_fCameraAnimation = 0.0f;
- m_fDebugTimeMultiplier = 0.015f;
- return true;
- }
- /*!****************************************************************************
- @Function QuitApplication
- @Return bool true if no error occured
- @Description Code in QuitApplication() will be called by PVRShell once per
- run, just before exiting the program.
- If the rendering context is lost, QuitApplication() will
- not be called.
- ******************************************************************************/
- bool OGLES2Navigation3D::QuitApplication()
- {
- Release3dModelIndex();
- ReleaseOcclusionData();
- delete [] m_pauiTextureIds;
- delete [] m_pauiVisibleTiles;
- return true;
- }
- /*!****************************************************************************
- @Function InitView
- @Return bool true if no error occured
- @Description Code in InitView() will be called by PVRShell upon
- initialization or after a change in the rendering context.
- Used to initialize variables that are dependant on the rendering
- context (e.g. textures, vertex buffers, etc.)
- ******************************************************************************/
- bool OGLES2Navigation3D::InitView()
- {
- m_fAspectRatio = PVRShellGet(prefWidth) / (float)PVRShellGet(prefHeight);
- CPVRTString ErrorStr;
- // Load textures
- if (!LoadTextures(&ErrorStr))
- {
- PVRShellSet(prefExitMessage, ErrorStr.c_str());
- return false;
- }
- // Load and compile the shaders & link programs
- if (!LoadShaders(&ErrorStr))
- {
- PVRShellSet(prefExitMessage, ErrorStr.c_str());
- return false;
- }
- // Is the screen rotated?
- m_bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
- #ifdef _WIN32
- if (PVRShellGet(prefWidth) < PVRShellGet(prefHeight))
- m_bRotate = true;
- #endif
- // Initialize Print3D
- if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), m_bRotate) != PVR_SUCCESS)
- {
- PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
- return false;
- }
- Cache3dModelData();
- // Generate the skybox VBO
- GLfloat *pSkyboxVertices, *pSkyboxTexCoords;
- PVRTCreateSkybox(10.0f, true, 512, &pSkyboxVertices, &pSkyboxTexCoords);
- glGenBuffers(1, &m_uiSkyboxVBO);
- glBindBuffer(GL_ARRAY_BUFFER, m_uiSkyboxVBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*24, pSkyboxVertices, GL_STATIC_DRAW);
- PVRTDestroySkybox(pSkyboxVertices, pSkyboxTexCoords);
-
- // No stencil test required
- glDisable(GL_STENCIL_TEST);
- // Disable blending by default
- glDisable(GL_BLEND);
-
- // Paint it black
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- // Texture channel 0 will always be active
- glActiveTexture(GL_TEXTURE0);
- // Setup the viewport for the whole window
- glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
-
- return true;
- }
- /*!****************************************************************************
- @Function ReleaseShader
- @Return bool true if no error occured
- @Description Releases a shader program including the individual shader objects.
- ******************************************************************************/
- bool OGLES2Navigation3D::ReleaseShader(Shader &shader)
- {
- glDeleteProgram(shader.uiId);
- glDeleteShader(shader.uiVertexShaderId);
- glDeleteShader(shader.uiFragmentShaderId);
- return true;
- }
- /*!****************************************************************************
- @Function ReleaseView
- @Return bool true if no error occured
- @Description Code in ReleaseView() will be called by PVRShell when the
- application quits or before a change in the rendering context.
- ******************************************************************************/
- bool OGLES2Navigation3D::ReleaseView()
- {
- // Delete textures
- glDeleteTextures(1, &m_uiTextureIdSkybox);
- glDeleteTextures(m_uiNumTextures, m_pauiTextureIds);
-
- // Delete program and shader objects
- ReleaseShader(m_BuildingShader);
- ReleaseShader(m_SkyboxShader);
- glDeleteBuffers(1, &m_uiSkyboxVBO);
-
- // Release Print3D Textures
- m_Print3D.ReleaseTextures();
- return true;
- }
- /*!****************************************************************************
- @Function RenderScene
- @Return bool true if no error occured
- @Description Main rendering loop function of the program. The shell will
- call this function every frame.
- eglSwapBuffers() will be performed by PVRShell automatically.
- PVRShell will also manage important OS events.
- The user has access to these events through an abstraction
- layer provided by PVRShell.
- ******************************************************************************/
- bool OGLES2Navigation3D::RenderScene()
- {
- // Handle user input and update the timer based variables
- HandleInput();
- unsigned int fps = UpdateTimer();
- // Update the camera interpolation and extract required matrices
- CalculateCameraMatrices();
- // Clear the color and depth buffer
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Disable depth test to render the skybox
- glDisable(GL_DEPTH_TEST);
- RenderSkyBox();
- // Enable depth test and render buildings
- glEnable(GL_DEPTH_TEST);
- if (m_bUseOcclusionData)
- Render3dModelsOcclusion();
- else
- Render3dModels();
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- // Displays the demo name and other information using the Print3D tool.
- // For a detailed explanation, see the training course IntroducingPVRTools
- m_Print3D.DisplayDefaultTitle("Navigation", NULL, ePVRTPrint3DLogoIMG);
- #ifdef ENABLE_ADVANCED_OUTPUT
- m_Print3D.Print3D(0.05f, 81.0f, 1.0f, 0xFFFFFFFF, "%dx%d FPS: %d", PVRShellGet(prefWidth), PVRShellGet(prefHeight), fps);
- #endif
- #ifdef ENABLE_CULLING_OPTIONS
- m_Print3D.Print3D(0.05f, 88.0f, 1.0f, 0xFFFFFFFF, "Occlusion culling: %s", (m_bUseOcclusionData ? "On" : "Off"));
- m_Print3D.Print3D(0.05f, 95.0f, 1.0f, 0xFFFFFFFF, "Frustum culling: %s", (m_bViewFrustumCulling ? "On" : "Off"));
- #endif
- m_Print3D.Flush();
- return true;
- }
- /*!****************************************************************************
- @Function UpdateTimer
- @Input none
- @Description Updates the values of the current time, previous time, current time
- in seconds, delta time and the FPS counter used in the program
- ******************************************************************************/
- unsigned int OGLES2Navigation3D::UpdateTimer()
- {
- static unsigned int framecounter = 0;
- static unsigned long ulPreviousTime = PVRShellGetTime();
- static unsigned long ulLastUpdate = PVRShellGetTime();
- static unsigned long ulLastFpsUpdate = PVRShellGetTime();
- static unsigned int fps = 60;
- unsigned long ulCurrentTime = PVRShellGetTime();
- unsigned long ulTimeDelta = ulCurrentTime - ulPreviousTime;
- ulPreviousTime = ulCurrentTime;
- // Update the visible object four times per second
- if (ulCurrentTime - ulLastUpdate > 100)
- {
- ulLastUpdate = ulCurrentTime;
- Update3dModelWorkingset();
- }
- if (ulCurrentTime - ulLastFpsUpdate > 1000)
- {
- ulLastFpsUpdate = ulCurrentTime;
- fps = framecounter;
- framecounter = 0;
- }
- else
- framecounter++;
- // Advance camera animation when not paused
- if (!m_bPause)
- {
- m_fCameraAnimation += ulTimeDelta * m_fDebugTimeMultiplier;
- // Start from beginning when the end is near
- if (m_fCameraAnimation > (m_CameraPod.nNumFrame - 1))
- {
- m_fCameraAnimation = 0.0f;
- // Jump to next camera track
- m_ActiveCameraTrack = ++m_ActiveCameraTrack % m_CameraPod.nNumCamera;
- }
- }
- return fps;
- }
- /*!****************************************************************************
- @Function Update3dModelWorkingset
- @Input none
- @Description Updates the visible object set based on the camera position and
- the intersections of the view frustum with the global map plane.
- ******************************************************************************/
- void OGLES2Navigation3D::Update3dModelWorkingset()
- {
- PVRTVec4 planes[4];
- ExtractViewFrustumPlanes(planes[0], planes[1], planes[2], planes[3]);
- const PVRTVec2 lodCenter(m_vCameraFrom);
- m_uiNumVisibleTiles = 0;
- // Update the object set for each layer
- for (unsigned int i=0; i < m_uiNumModelTiles; i++)
- {
- const PVRTBoundingBox2D bbox = m_paModelTiles[i].boundingbox;
-
- if (BoundingBoxIntersectsFrustum(bbox, planes))
- {
- const float distToCameraSquared = ((bbox.maxCoords + bbox.minCoords) * 0.5f - lodCenter).lenSqr();
- unsigned int lod = (unsigned int)(m_paModelTiles[i].numLod - 1);
- for (unsigned int j=0; j < m_paModelTiles[i].numLod; j++)
- {
- if (distToCameraSquared < m_afSquaredLodDistances[j])
- {
- lod = j;
- break;
- }
- }
- m_pauiVisibleTiles[m_uiNumVisibleTiles++] = i * 10 + lod;
- }
- }
- // Fine grained culling
- for (unsigned int i=0; i < m_uiNumVisibleTiles; i++)
- {
- const unsigned int model = m_pauiVisibleTiles[i] / 10;
- const unsigned int lod = m_pauiVisibleTiles[i] - model * 10;
- ModelTileLod *pLod = &m_paModelTiles[model].paLod[lod];
- pLod->numVisibleNodes = 0;
- if (m_bViewFrustumCulling)
- {
- // Check each node in each tile against the view frustum and add it to the list
- // of visible nodes if it is visible
- for (unsigned int j=0; j < pLod->numObjects; j++)
- if (BoundingBoxIntersectsFrustum(pLod->paObjects[j].boundingbox, planes))
- pLod->paVisibleNodes[pLod->numVisibleNodes++] = j;
- }
- else
- for (unsigned int j=0; j < pLod->numObjects; j++)
- pLod->paVisibleNodes[pLod->numVisibleNodes++] = j;
- }
- }
- /*!****************************************************************************
- @Function HandleInput
- @Description Handles user input.
- ******************************************************************************/
- void OGLES2Navigation3D::HandleInput()
- {
- // Handle user input
- if (PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
- m_bPause = !m_bPause;
- if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
- m_ActiveCameraTrack = ++m_ActiveCameraTrack % m_CameraPod.nNumCamera;
- #ifdef ENABLE_CULLING_OPTIONS
- if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT))
- m_bViewFrustumCulling = !m_bViewFrustumCulling;
- if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT))
- m_bUseOcclusionData = !m_bUseOcclusionData;
- #endif
- if (PVRShellIsKeyPressed(PVRShellKeyNameACTION1))
- {
- PVRShellOutputDebug("Reloading shader ... \n");
- CPVRTString ErrorStr;
- ReleaseShader(m_BuildingShader);
- if (!LoadShader(&ErrorStr, BuildingShaderDescription, m_BuildingShader))
- PVRShellOutputDebug("Failed to reload shader: %s\n", ErrorStr.c_str());
- else
- PVRShellOutputDebug("Shader reload succesfull.\n");
- }
- #if 0
- if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT))
- m_fDebugTimeMultiplier *= 2.0f;
- if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT))
- m_fDebugTimeMultiplier *= 0.5f;
- #endif
- }
- /*!****************************************************************************
- @Function Render3dModels
- @Description Draws a SPODMesh after the model view matrix has been set and
- the meterial prepared.
- ******************************************************************************/
- void OGLES2Navigation3D::Render3dModels()
- {
- PVRTVec4 planes[4];
- ExtractViewFrustumPlanes(planes[0], planes[1], planes[2], planes[3]);
-
- PVRTVec3 lightdir = PVRTVec3(0.5f, 0.5f, 1.0f).normalize();
- glUseProgram(m_BuildingShader.uiId);
- glUniformMatrix4fv(m_BuildingShader.uiModelViewProjMatrixLoc, 1, GL_FALSE, m_mViewProjectionMatrix.ptr());
- glUniform3fv(m_BuildingShader.uiLightDirectionLoc, 1, lightdir.ptr());
- // Enable the vertex attribute arrays
- glEnableVertexAttribArray(VERTEX_ARRAY);
- glEnableVertexAttribArray(NORMAL_ARRAY);
- glEnableVertexAttribArray(TEXCOORD_ARRAY);
- GLuint prevTexture = 0;
- for (unsigned int i=0; i < m_uiNumVisibleTiles; i++)
- {
- const unsigned int entry = m_pauiVisibleTiles[i];
- const unsigned int model = entry / 10;
- const unsigned int lod = entry - model * 10;
- const ModelTileLod *pLod = &m_paModelTiles[model].paLod[lod];
- if (!pLod->bLoaded)
- continue;
- glBindBuffer(GL_ARRAY_BUFFER, pLod->vbos[0]);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pLod->vbos[1]);
-
- glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(PVRTModelVertex), 0);
- glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(PVRTModelVertex), (const void*)offsetof(PVRTModelVertex, normal));
- glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(PVRTModelVertex), (const void*)offsetof(PVRTModelVertex, texcoord));
- for (unsigned int j=0; j < pLod->numVisibleNodes; j++)
- {
- const ModelTileObjectSet *pObjectSet = &pLod->paObjects[pLod->paVisibleNodes[j]];
-
- // Ignore the object if it is not visible
- if (m_bViewFrustumCulling && !BoundingBoxIntersectsFrustum(pObjectSet->boundingbox, planes))
- continue;
- for (unsigned int k=0; k < pObjectSet->numSubObjects; k++)
- {
- if (pObjectSet->pauiTextures[k] != prevTexture)
- {
- glBindTexture(GL_TEXTURE_2D, pObjectSet->pauiTextures[k]);
- prevTexture = pObjectSet->pauiTextures[k];
- }
- glDrawElements(GL_TRIANGLES, (GLsizei)pObjectSet->paNumIndices[k], GL_UNSIGNED_SHORT, (void *)(pObjectSet->paIndexOffsets[k]*sizeof(GLushort)));
- }
- }
- }
- glDisableVertexAttribArray(VERTEX_ARRAY);
- glDisableVertexAttribArray(NORMAL_ARRAY);
- glDisableVertexAttribArray(TEXCOORD_ARRAY);
- }
- /*!****************************************************************************
- @Function Render3dModelsOcclusion
- @Description Draws a SPODMesh after the model view matrix has been set and
- the meterial prepared.
- ******************************************************************************/
- void OGLES2Navigation3D::Render3dModelsOcclusion()
- {
- // Find the nearest spot containing occlusion data
- unsigned int nearest_pos = 0;
- float nearest_pos_dist = 99999999999.9f;
- for (unsigned int i=0; i < m_uiNumOcclusionData; i++)
- {
- float dist = (m_paPositionOcclusionData[i].position - m_vCameraFrom).lenSqr();
- if (dist < nearest_pos_dist)
- {
- nearest_pos_dist = dist;
- nearest_pos = i;
- }
- }
- PVRTVec4 planes[4];
- ExtractViewFrustumPlanes(planes[0], planes[1], planes[2], planes[3]);
-
- PVRTVec3 lightdir = PVRTVec3(0.5f, 0.5f, 1.0f).normalize();
- glUseProgram(m_BuildingShader.uiId);
- glUniformMatrix4fv(m_BuildingShader.uiModelViewProjMatrixLoc, 1, GL_FALSE, m_mViewProjectionMatrix.ptr());
- glUniform3fv(m_BuildingShader.uiLightDirectionLoc, 1, lightdir.ptr());
-
- // Enable the vertex attribute arrays
- glEnableVertexAttribArray(VERTEX_ARRAY);
- glEnableVertexAttribArray(NORMAL_ARRAY);
- glEnableVertexAttribArray(TEXCOORD_ARRAY);
- GLuint prevTexture = 0;
- PositionOcclusionData *pRefData = &m_paPositionOcclusionData[nearest_pos];
- for (unsigned int i=0; i < pRefData->numRefObjects; i++)
- {
- const unsigned int numRefObjects = pRefData->pNumRefObject[i];
- const unsigned int refTile = pRefData->pRefTile[i];
- const unsigned int *pRefObjects = pRefData->ppRefObjects[i];
-
- const PVRTVec2 lodReferencePosition(m_vCameraFrom);
- const float sqDist = ((m_paModelTiles[refTile].boundingbox.maxCoords + m_paModelTiles[refTile].boundingbox.minCoords) * 0.5f - lodReferencePosition).lenSqr();
- unsigned int lod = (unsigned int)(m_paModelTiles[i].numLod - 1);
- for (unsigned int j=0; j < m_paModelTiles[refTile].numLod; j++)
- {
- if (sqDist < m_afSquaredLodDistances[j])
- {
- lod = j;
- break;
- }
- }
-
- const ModelTileLod *pLod = &m_paModelTiles[refTile].paLod[lod];
- if (!pLod->bLoaded)
- continue;
-
- // Ignore the tile if it is not visible
- if (m_bViewFrustumCulling && !BoundingBoxIntersectsFrustum(m_paModelTiles[refTile].boundingbox, planes))
- continue;
- glBindBuffer(GL_ARRAY_BUFFER, pLod->vbos[0]);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pLod->vbos[1]);
- for (unsigned int j=0; j < numRefObjects; j++)
- {
- const ModelTileObjectSet *pObjectSet = &pLod->paObjects[pRefObjects[j]];
-
- // Ignore the object if it is not visible
- if (m_bViewFrustumCulling && !BoundingBoxIntersectsFrustum(pObjectSet->boundingbox, planes))
- continue;
- for (unsigned int k=0; k < pObjectSet->numSubObjects; k++)
- {
- glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(PVRTModelVertex), 0);
- glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(PVRTModelVertex), (const void*)offsetof(PVRTModelVertex, normal));
- glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(PVRTModelVertex), (const void*)offsetof(PVRTModelVertex, texcoord));
- if (pObjectSet->pauiTextures[k] != prevTexture)
- {
- glBindTexture(GL_TEXTURE_2D, pObjectSet->pauiTextures[k]);
- prevTexture = pObjectSet->pauiTextures[k];
- }
- glDrawElements(GL_TRIANGLES, (GLsizei)pObjectSet->paNumIndices[k], GL_UNSIGNED_SHORT, (void *)(pObjectSet->paIndexOffsets[k]*sizeof(GLushort)));
- }
- }
- }
- glDisableVertexAttribArray(VERTEX_ARRAY);
- glDisableVertexAttribArray(NORMAL_ARRAY);
- glDisableVertexAttribArray(TEXCOORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- /*!****************************************************************************
- @Function RenderSkyBox
- @Description TBD
- ******************************************************************************/
- void OGLES2Navigation3D::RenderSkyBox()
- {
- PVRTMat4 mv_matrix = PVRTMat4::LookAtRH(PVRTVec3(0.0f, 0.0f, -2.5f), m_vCameraTo - m_vCameraFrom + PVRTVec3(0.0f, 0.0f, -2.5f), m_vCameraUp);
- PVRTMat4 mvp_matrix = m_mProjectionMatrix * mv_matrix;
-
- glUseProgram(m_SkyboxShader.uiId);
- glUniformMatrix4fv(m_SkyboxShader.uiModelViewProjMatrixLoc, 1, GL_FALSE, mvp_matrix.ptr());
- glBindBuffer(GL_ARRAY_BUFFER, m_uiSkyboxVBO);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindTexture(GL_TEXTURE_2D, m_uiTextureIdSkybox);
- // Enable the vertex attribute arrays
- glEnableVertexAttribArray(VERTEX_ARRAY);
- glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(PVRTVec3), NULL);
-
- // Draw primitive
- for(int i = 0; i < 6; ++i)
- glDrawArrays(GL_TRIANGLE_STRIP, i*4, 4);
- glDisableVertexAttribArray(VERTEX_ARRAY);
- }
- /*!****************************************************************************
- @Function CreateModelVbo
- @Description Creates vertex buffer objects of
- ******************************************************************************/
- void OGLES2Navigation3D::CreateModelVbo(const unsigned int tile, const unsigned int lod)
- {
- ModelTileLod *pLod = &m_paModelTiles[tile].paLod[lod];
- CPVRTModelPOD model;
- if (PVR_FAIL == model.ReadFromFile(pLod->pszFilename))
- return;
- else
- pLod->bLoaded = true;
- unsigned int totalVertexCount = 0;
- unsigned int totalIndexCount = 0;
- for (unsigned int i=0; i < pLod->numObjects; i++)
- {
- const size_t numSubObjects = pLod->paObjects[i].numSubObjects;
- pLod->paObjects[i].paNumIndices = new unsigned int[numSubObjects];
- pLod->paObjects[i].paIndexOffsets = new unsigned int[numSubObjects];
- pLod->paObjects[i].pauiTextures = new GLuint[numSubObjects];
- for (unsigned int j=0; j < pLod->paObjects[i].numSubObjects; j++)
- {
- const int mesh_index = model.pNode[pLod->paObjects[i].pNodeIdx[j]].nIdx;
- const SPODMesh &mesh = model.pMesh[mesh_index];
-
- totalVertexCount += mesh.nNumVertex;
- totalIndexCount += PVRTModelPODCountIndices(mesh);
- pLod->paObjects[i].paNumIndices[j] = PVRTModelPODCountIndices(mesh);
- if (model.pMaterial)
- {
- const int material_index = model.pNode[pLod->paObjects[i].pNodeIdx[j]].nIdxMaterial;
- const SPODTexture &texture = model.pTexture[model.pMaterial[material_index].nIdxTexDiffuse];
- // Pre-init with invalid texture handle
- pLod->paObjects[i].pauiTextures[j] = 0;
- for (unsigned int k=0; k < m_uiNumTextures; k++)
- {
- if (strcmp(texture.pszName, c_paszTextures[k]) == 0)
- {
- pLod->paObjects[i].pauiTextures[j] = m_pauiTextureIds[k];
- break;
- }
- }
- }
- }
- }
- if (totalVertexCount > 65536)
- {
- PVRShellOutputDebug("Too many vertices to index with ushort in mesh %s!\n", pLod->pszFilename);
- pLod->bLoaded = false;
- return;
- }
- GLushort *pIndices = new GLushort[totalIndexCount];
- PVRTModelVertex *pVertices = new PVRTModelVertex[totalVertexCount];
- unsigned int indexOffset = 0;
- unsigned int vertexOffset = 0;
- for (unsigned int i=0; i < pLod->numObjects; i++)
- {
- for (unsigned int j=0; j < pLod->paObjects[i].numSubObjects; j++)
- {
- const int mesh_index = model.pNode[pLod->paObjects[i].pNodeIdx[j]].nIdx;
- const SPODMesh &mesh = model.pMesh[mesh_index];
-
- const unsigned int numIndices = PVRTModelPODCountIndices(mesh);
- PVRTModelVertex *pSrcVertices = (PVRTModelVertex *)mesh.pInterleaved;
- GLushort *pSrcIndices = (GLushort *)mesh.sFaces.pData;
- pLod->paObjects[i].paIndexOffsets[j] = indexOffset;
- for (unsigned int k=0; k < mesh.nNumVertex; k++)
- {
- const PVRTVec3 normal = pSrcVertices[k].normal;
- pVertices[vertexOffset + k].normal = PVRTVec3(normal.x, -normal.z, normal.y);
- const PVRTVec3 pos = pSrcVertices[k].position;
- pVertices[vertexOffset + k].position = PVRTVec3(pos.x, -pos.z, pos.y);
- pVertices[vertexOffset + k].texcoord = pSrcVertices[k].texcoord;
- }
-
- for (unsigned int k=0; k < numIndices; k++)
- pIndices[indexOffset + k] = (GLushort)(pSrcIndices[k] + vertexOffset);
- vertexOffset += mesh.nNumVertex;
- indexOffset += numIndices;
- }
- }
- glGenBuffers(2, pLod->vbos);
- glBindBuffer(GL_ARRAY_BUFFER, pLod->vbos[0]);
- glBufferData(GL_ARRAY_BUFFER, totalVertexCount * sizeof(PVRTModelVertex), pVertices, GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pLod->vbos[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, totalIndexCount * sizeof(GLushort), pIndices, GL_STATIC_DRAW);
- delete [] pIndices;
- delete [] pVertices;
- }
- /*!****************************************************************************
- @Function ReleaseModelVbo
- @Description TODO
- ******************************************************************************/
- void OGLES2Navigation3D::ReleaseModelVbo(const unsigned int tile, const unsigned int lod)
- {
- ModelTileLod *pLod = &m_paModelTiles[tile].paLod[lod];
- for (unsigned int i=0; i < pLod->numObjects; i++)
- {
- delete [] pLod->paObjects[i].paNumIndices;
- delete [] pLod->paObjects[i].paIndexOffsets;
- delete [] pLod->paObjects[i].pauiTextures;
- pLod->paObjects[i].paNumIndices = 0;
- pLod->paObjects[i].paIndexOffsets = 0;
- pLod->paObjects[i].pauiTextures = 0;
- }
- }
- /*!****************************************************************************
- @Function Cache3dModelData
- @Description Loads all POD files and textures in advance.
- ******************************************************************************/
- void OGLES2Navigation3D::Cache3dModelData()
- {
- for (unsigned int i=0; i < m_uiNumModelTiles; i++)
- for (unsigned int j=0; j < m_paModelTiles[i].numLod; j++)
- CreateModelVbo(i, j);
- }
- /*!****************************************************************************
- @Function GetCameraFrame
- @Description TODO
- ******************************************************************************/
- void OGLES2Navigation3D::GetCameraFrame(PVRTVec3 &from, PVRTVec3 &to, PVRTVec3 &up, float time)
- {
- m_CameraPod.SetFrame(time);
- m_CameraPod.GetCamera(from, to, up, m_ActiveCameraTrack);
- from *= 0.0254f;
- to *= 0.0254f;
- from = PVRTVec3(from.x, -from.z, from.y);
- to = PVRTVec3(to.x, -to.z, to.y);
- up = PVRTVec3(up.x, -up.z, up.y);
- }
- /*!****************************************************************************
- @Function CalculateCameraMatrices
- @Description TODO
- ******************************************************************************/
- void OGLES2Navigation3D::CalculateCameraMatrices()
- {
- float clamped_delta = m_fCameraAnimation + 5.0f;
- if (clamped_delta > (m_CameraPod.nNumFrame - 1))
- clamped_delta -= (m_CameraPod.nNumFrame - 1);
- PVRTVec3 now_from, now_to, now_up;
- GetCameraFrame(now_from, now_to, now_up, m_fCameraAnimation);
- PVRTVec3 next_from, next_to, next_up;
- GetCameraFrame(next_from, next_to, next_up, clamped_delta);
- m_vCameraFrom = now_from;
- m_vCameraTo = now_from + (next_from - now_from).normalized();
- m_vCameraUp = now_up;
- m_mViewMatrix = PVRTMat4::LookAtRH(m_vCameraFrom, m_vCameraTo, m_vCameraUp);
- m_mProjectionMatrix = PVRTMat4::PerspectiveFovRH(m_fFOV, m_fAspectRatio, m_fNearClipPlane, m_fFarClipPlane, PVRTMat4::OGL, m_bRotate);
- m_mViewProjectionMatrix = m_mProjectionMatrix * m_mViewMatrix;
- }
- /*!****************************************************************************
- @Function ExtractViewFrustumPlanes
- @Description Extracts the (left, right, front and back) view frustum planes
- from the camera modelview-projection matrix.
- ******************************************************************************/
- void OGLES2Navigation3D::ExtractViewFrustumPlanes(PVRTVec4 &left, PVRTVec4 &right, PVRTVec4 &front, PVRTVec4 &back) const
- {
- const PVRTMat4 matrix = m_mViewProjectionMatrix;
- left.x = (matrix.f[3] + matrix.f[0]);
- left.y = (matrix.f[7] + matrix.f[4]);
- left.z = (matrix.f[11] + matrix.f[8]);
- left.w = (matrix.f[15] + matrix.f[12]);
- float inv_len = 1.0f / PVRTVec3(left).length();
- left *= inv_len;
- right.x = (matrix.f[3] - matrix.f[0]);
- right.y = (matrix.f[7] - matrix.f[4]);
- right.z = (matrix.f[11] - matrix.f[8]);
- right.w = (matrix.f[15] - matrix.f[12]);
- inv_len = 1.0f / PVRTVec3(right).length();
- right *= inv_len;
- front.x = (matrix.f[3] + matrix.f[2]);
- front.y = (matrix.f[7] + matrix.f[6]);
- front.z = (matrix.f[11] + matrix.f[10]);
- front.w = (matrix.f[15] + matrix.f[14]);
- inv_len = 1.0f / PVRTVec3(front).length();
- front *= inv_len;
- back.x = (matrix.f[3] - matrix.f[2]);
- back.y = (matrix.f[7] - matrix.f[6]);
- back.z = (matrix.f[11] - matrix.f[10]);
- back.w = (matrix.f[15] - matrix.f[14]);
- inv_len = 1.0f / PVRTVec3(back).length();
- back *= inv_len;
- }
- /*!****************************************************************************
- @Function Load3dModelIndex
- @Description Loads the mesh data required for this training course into
- vertex buffer objects
- ******************************************************************************/
- bool OGLES2Navigation3D::Load3dModelIndex(const char *pszFilename, CPVRTString* pErrorStr)
- {
- CPVRTResourceFile file(pszFilename);
- if (!file.IsOpen())
- {
- *pErrorStr = "Error: Could not open 3d model hirarchy file!\n";
- return false;
- }
- const char *pData = (const char *)file.DataPtr();
-
- size_t numTiles;
- memcpy((char *)&numTiles, pData, sizeof(numTiles));
- pData += sizeof(numTiles);
- m_uiNumModelTiles = (unsigned int)numTiles;
- m_paModelTiles = new ModelTile[m_uiNumModelTiles];
- for (unsigned int i=0; i < m_uiNumModelTiles; i++)
- {
- memcpy((char *)&m_paModelTiles[i].boundingbox, pData, sizeof(PVRTBoundingBox2D));
- pData += sizeof(PVRTBoundingBox2D);
- memcpy((char *)&m_paModelTiles[i].numLod, pData, sizeof(size_t));
- pData += sizeof(size_t);
-
- m_paModelTiles[i].paLod = new ModelTileLod[m_paModelTiles[i].numLod];
- for (unsigned int j=0; j < m_paModelTiles[i].numLod; j++)
- {
- m_paModelTiles[i].paLod[j].bLoaded = false;
- size_t namelength;
- memcpy((char *)&namelength, pData, sizeof(size_t));
- pData += sizeof(size_t);
-
- m_paModelTiles[i].paLod[j].pszFilename = new char[namelength+1];
- memcpy((char *)m_paModelTiles[i].paLod[j].pszFilename, pData, sizeof(char) * namelength);
- pData += sizeof(char) * namelength;
- m_paModelTiles[i].paLod[j].pszFilename[namelength] = '\0';
-
- memcpy((char *)&m_paModelTiles[i].paLod[j].numObjects, pData, sizeof(size_t));
- pData += sizeof(size_t);
- m_paModelTiles[i].paLod[j].paObjects = new ModelTileObjectSet[m_paModelTiles[i].paLod[j].numObjects];
- m_paModelTiles[i].paLod[j].paVisibleNodes = new unsigned int[m_paModelTiles[i].paLod[j].numObjects];
- m_paModelTiles[i].paLod[j].numVisibleNodes = 0;
-
- for (unsigned int k=0; k < m_paModelTiles[i].paLod[j].numObjects; k++)
- {
- memcpy((char *)&m_paModelTiles[i].paLod[j].paObjects[k].boundingbox, pData, sizeof(PVRTBoundingBox2D));
- pData += sizeof(PVRTBoundingBox2D);
- memcpy((char *)&m_paModelTiles[i].paLod[j].paObjects[k].numSubObjects, pData, sizeof(size_t));
- pData += sizeof(size_t);
-
- m_paModelTiles[i].paLod[j].paObjects[k].pNodeIdx = new unsigned int[m_paModelTiles[i].paLod[j].paObjects[k].numSubObjects];
- memcpy((char *)m_paModelTiles[i].paLod[j].paObjects[k].pNodeIdx, pData, sizeof(unsigned int) * m_paModelTiles[i].paLod[j].paObjects[k].numSubObjects);
- pData += sizeof(unsigned int) * m_paModelTiles[i].paLod[j].paObjects[k].numSubObjects;
-
- m_paModelTiles[i].paLod[j].paObjects[k].pauiTextures = 0;
- m_paModelTiles[i].paLod[j].paObjects[k].paNumIndices = 0;
- m_paModelTiles[i].paLod[j].paObjects[k].paIndexOffsets = 0;
- }
- }
- }
- return true;
- }
- /*!****************************************************************************
- @Function Release3dModelIndex
- @Description Loads the mesh data required for this training course into
- vertex buffer objects
- ******************************************************************************/
- void OGLES2Navigation3D::Release3dModelIndex()
- {
- for (unsigned int i=0; i < m_uiNumModelTiles; i++)
- {
- for (unsigned int j=0; j < m_paModelTiles[i].numLod; j++)
- {
- for (unsigned int k=0; k < m_paModelTiles[i].paLod[j].numObjects; k++)
- {
- delete [] m_paModelTiles[i].paLod[j].paObjects[k].pNodeIdx;
- delete [] m_paModelTiles[i].paLod[j].paObjects[k].paNumIndices;
- delete [] m_paModelTiles[i].paLod[j].paObjects[k].paIndexOffsets;
- delete [] m_paModelTiles[i].paLod[j].paObjects[k].pauiTextures;
- }
- delete [] m_paModelTiles[i].paLod[j].paObjects;
- delete [] m_paModelTiles[i].paLod[j].paVisibleNodes;
- delete [] m_paModelTiles[i].paLod[j].pszFilename;
- }
- delete [] m_paModelTiles[i].paLod;
- }
- delete [] m_paModelTiles;
- }
- /*!****************************************************************************
- @Function LoadOcclusionData
- @Description TODO
- ******************************************************************************/
- bool OGLES2Navigation3D::LoadOcclusionData(const char *pszFilename, CPVRTString* pErrorStr)
- {
- CPVRTResourceFile file(pszFilename);
- if (!file.IsOpen())
- {
- *pErrorStr = "Error: Could not open occlusion data!\n";
- return false;
- }
- const char *pData = (const char *)file.DataPtr();
- size_t namelen;
- memcpy((char *)&namelen, pData, sizeof(namelen));
- pData += sizeof(namelen);
- // Skip the name
- pData += namelen;
-
- size_t numTiles;
- memcpy((char *)&numTiles, pData, sizeof(numTiles));
- pData += sizeof(numTiles);
- for (unsigned int i=0; i < numTiles; i++)
- {
- memcpy((char *)&namelen, pData, sizeof(namelen));
- pData += sizeof(namelen);
- // Skip the name
- pData += namelen;
- }
- size_t numpositions;
- memcpy((char *)&numpositions, pData, sizeof(numpositions));
- pData += sizeof(numpositions);
- m_uiNumOcclusionData = (unsigned int)numpositions;
- m_paPositionOcclusionData = new PositionOcclusionData[m_uiNumOcclusionData];
-
- for (unsigned int i=0; i < m_uiNumOcclusionData; i++)
- {
- memcpy((char *)&m_paPositionOcclusionData[i].position, pData, sizeof(PVRTVec3));
- pData += sizeof(PVRTVec3);
-
- size_t reftiles;
- memcpy((char *)&reftiles, pData, sizeof(reftiles));
- pData += sizeof(reftiles);
- m_paPositionOcclusionData[i].numRefObjects = (unsigned int)reftiles;
- m_paPositionOcclusionData[i].pRefTile = new unsigned int[reftiles];
- m_paPositionOcclusionData[i].pNumRefObject = new unsigned int[reftiles];
- m_paPositionOcclusionData[i].ppRefObjects = new unsigned int*[reftiles];
- for (unsigned int j=0; j < reftiles; j++)
- {
- size_t tilenum;
- memcpy((char *)&tilenum, pData, sizeof(tilenum));
- pData += sizeof(tilenum);
- m_paPositionOcclusionData[i].pRefTile[j] = (unsigned int)tilenum;
-
- size_t num_ref_models;
- memcpy((char *)&num_ref_models, pData, sizeof(num_ref_models));
- pData += sizeof(num_ref_models);
- m_paPositionOcclusionData[i].pNumRefObject[j] = (unsigned int)num_ref_models;
- m_paPositionOcclusionData[i].ppRefObjects[j] = new unsigned int[num_ref_models];
- memcpy((char *)m_paPositionOcclusionData[i].ppRefObjects[j], pData, sizeof(unsigned int) * num_ref_models);
- pData += sizeof(unsigned int) * num_ref_models;
- }
- }
- return true;
- }
- /*!****************************************************************************
- @Function ReleaseOcclusionData
- @Description TODO
- ******************************************************************************/
- void OGLES2Navigation3D::ReleaseOcclusionData()
- {
- for (unsigned int i=0; i < m_uiNumOcclusionData; i++)
- {
- for (unsigned int j=0; j < m_paPositionOcclusionData[i].numRefObjects; j++)
- delete [] m_paPositionOcclusionData[i].ppRefObjects[j];
- delete [] m_paPositionOcclusionData[i].pNumRefObject;
- delete [] m_paPositionOcclusionData[i].pRefTile;
- delete [] m_paPositionOcclusionData[i].ppRefObjects;
- }
- delete [] m_paPositionOcclusionData;
- }
- /*!****************************************************************************
- @Function BoundingBoxIntersectsFrustum
- @Description TODO
- ******************************************************************************/
- bool OGLES2Navigation3D::BoundingBoxIntersectsFrustum(const PVRTBoundingBox2D &bbox, const PVRTVec4 planes[4]) const
- {
- PVRTVec3 points[4];
- points[0] = PVRTVec3(bbox.minCoords.x, bbox.minCoords.y, 0.0f);
- points[1] = PVRTVec3(bbox.maxCoords.x, bbox.minCoords.y, 0.0f);
- points[2] = PVRTVec3(bbox.maxCoords.x, bbox.maxCoords.y, 0.0f);
- points[3] = PVRTVec3(bbox.minCoords.x, bbox.maxCoords.y, 0.0f);
- // Test the axis-aligned bounding box against each plane;
- // only cull if all points are outside of one the view frustum planes
- for (unsigned int p=0; p < 4; p++)
- {
- unsigned int pointsOut = 0;
- // Test the points against the plane
- for(unsigned int j=0; j < 4; j++)
- if ((planes[p].x * points[j].x + planes[p].y * points[j].y + planes[p].z * points[j].z + planes[p].w) < 0.0f)
- pointsOut++;
- // if all points are outside of a plane we can cull it
- if (pointsOut == 4)
- return false;
- }
- return true;
- }
- /*!****************************************************************************
- @Function NewDemo
- @Return PVRShell* The demo supplied by the user
- @Description This function must be implemented by the user of the shell.
- The user should return its PVRShell object defining the
- behaviour of the application.
- ******************************************************************************/
- PVRShell* NewDemo()
- {
- return new OGLES2Navigation3D();
- }
- /******************************************************************************
- End of file (OGLES2Navigation3D.cpp)
- ******************************************************************************/
|