/*!**************************************************************************** @Function HandleInput @Description Handles user input and updates live variables accordingly. ******************************************************************************/ bool OGLES2ProceduralTextures::HandleInput() { static unsigned long prevTime = PVRShellGetTime(); unsigned long curTime = PVRShellGetTime(); unsigned long deltaTime = curTime - prevTime; if (m_bDemoMode && deltaTime > 2500) { prevTime = curTime; m_uiVisualisation++; if (m_uiVisualisation == NUM_VISUALISATIONS) { m_uiVisualisation = 0; m_uiGenerator = (m_uiGenerator + 1) % NUM_GENERATORS; } return GenerateFnTexture(); } else if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT) || (m_bDemoMode && deltaTime > 5000)) { m_uiGenerator = (m_uiGenerator + 1) % NUM_GENERATORS; return GenerateFnTexture(); } else if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT)) { if (m_uiGenerator > 0) { m_uiGenerator = (m_uiGenerator - 1) % NUM_GENERATORS; } else { m_uiGenerator = NUM_GENERATORS - 1; } return GenerateFnTexture(); } else if (PVRShellIsKeyPressed(PVRShellKeyNameUP)) { m_uiVisualisation = (m_uiVisualisation + 1) % NUM_VISUALISATIONS; } else if (PVRShellIsKeyPressed(PVRShellKeyNameDOWN)) { if (m_uiVisualisation > 0) { m_uiVisualisation--; } else { m_uiVisualisation = NUM_VISUALISATIONS - 1; } } else if (PVRShellIsKeyPressed(PVRShellKeyNameACTION1)) { m_Scalars[m_uiGenerator] *= 0.95f; GenerateFnTexture(); } else if (PVRShellIsKeyPressed(PVRShellKeyNameACTION2)) { m_Scalars[m_uiGenerator] *= 1.05f; GenerateFnTexture(); } return true; }
/*!**************************************************************************** @Function InitApplication @Return bool true if no error occurred @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 dependent on it (e.g. external modules, loading meshes, etc.) If the rendering context is lost, InitApplication() will not be called again. ******************************************************************************/ bool OGLES2ProceduralTextures::InitApplication() { PVRShellSet(prefApiMajorVersion, 3); PVRShellSet(prefApiMinorVersion, 1); m_FnTexture = 0; // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); m_Width = TEXTURE_SIZE; m_Height = TEXTURE_SIZE; m_uiGenerator = EUCLID; m_uiVisualisation = FN1_MINUS_FN0; m_bDemoMode = true; m_Scalars[EUCLID] = 0.26448223f; m_Scalars[CHESSBOARD] = 0.284799f; m_Scalars[MANHATTAN] = 0.134101f; m_pProceduralTextures = new ProceduralTextures(); srand(PVRShellGetTime()); 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 OGLES2ParticleSystem::InitApplication() { m_pParticleSystem = 0; // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); // Load the scene if(m_Scene.ReadFromFile(c_szSphereModelFile) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Couldn't load the sphere.pod file\n"); return false; } srand((unsigned int) PVRShellGetTime()); PVRShellSet(prefSwapInterval, 0); return true; }
/*!**************************************************************************** @Function InitApplication @Return bool true if no error occurred @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 dependent on it (e.g. external modules, loading meshes, etc.) If the rendering context is lost, InitApplication() will not be called again. ******************************************************************************/ bool OGLES3PhantomMask::InitApplication() { // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); // Load the scene if(m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n"); return false; } // The cameras are stored in the file. We check it contains at least one. if(m_Scene.nNumCamera == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera. Please add one and re-export.\n"); return false; } // Initialise variables used for the animation m_ulTimePrev = PVRShellGetTime(); 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 OGLES2EdgeDetection::InitApplication() { #ifdef SHOW_MAX_FPS // Disable v-sync PVRShellSet(prefSwapInterval,0); #endif // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); /* Loads the scene from the .pod file into a CPVRTModelPOD object. We could also export the scene as a header file and load it with ReadFromMemory(). */ if(m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) { CPVRTString ErrorStr = "ERROR: Couldn't load '" + CPVRTString(c_szSceneFile) + "'."; PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } //Initialises the time variables. m_ulCurrentTime = PVRShellGetTime(); m_ulPreviousTimeAngle = m_ulCurrentTime; m_ulPreviousTimeFPS = m_ulCurrentTime; return true; }
/******************************************************************************* * Function Name : InitView * Inputs : uWidth, uHeight * Returns : true if no error occured * Description : Code in InitView() will be called by the Shell upon a change * in the rendering context. * Used to initialise variables that are dependent on the rendering * context (e.g. textures, vertex buffers, etc.) *******************************************************************************/ bool CTransforms::InitView() { // Create paths CreatePaths(); // Create paint m_vgPaint = vgCreatePaint(); vgSetParameteri(m_vgPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetColor(m_vgPaint, PVRTRGBA(255, 255, 170, 255)); vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND); vgSetf(VG_STROKE_LINE_WIDTH, 2.5f / PVRShellGet(prefHeight)); /* The clear colour will be used whenever calling vgClear(). The colour is given as non-premultiplied sRGBA. */ VGfloat afClearColour[] = { 0.6f, 0.8f, 1.0f, 1.0f }; vgSetfv(VG_CLEAR_COLOR, 4, afClearColour); // Initialise custom text drawing m_PrintVG.Initialize(PVRShellGet(prefWidth), PVRShellGet(prefHeight)); m_ui32StartTime = PVRShellGetTime(); 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 OGLESIntroducingPFX::InitApplication() { // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Load the scene if (m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n"); return false; } // The cameras are stored in the file. We check it contains at least one. if(m_Scene.nNumCamera == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera\n"); return false; } // Ensure that all meshes use an indexed triangle list for(unsigned int i = 0; i < m_Scene.nNumMesh; ++i) { if(m_Scene.pMesh[i].nNumStrips || !m_Scene.pMesh[i].sFaces.pData) { PVRShellSet(prefExitMessage, "ERROR: The meshes in the scene should use an indexed triangle list\n"); return false; } } // Initialize variables used for the animation m_fFrame = 0; m_iTimePrev = PVRShellGetTime(); return true; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occurred @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 dependent on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLESPVRScopeRemote::InitView() { CPPLProcessingScoped PPLProcessingScoped(m_psSPSCommsData, __FUNCTION__, static_cast<unsigned int>(strlen(__FUNCTION__)), m_i32FrameCounter); CPVRTString ErrorStr; /* Initialize Print3D */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Sets the clear color glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // Enables texturing glEnable(GL_TEXTURE_2D); // Initialize VBO data if(!LoadVbos(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } /* Load textures */ if(!LoadTextures(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } /* Calculate the projection and view matrices */ m_mProjection = PVRTMat4::PerspectiveFovRH(PVRT_PIf/6, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), CAM_NEAR, CAM_FAR, PVRTMat4::OGL, bRotate); m_mView = PVRTMat4::LookAtRH(PVRTVec3(0, 0, 75.0f), PVRTVec3(0, 0, 0), PVRTVec3(0, 1, 0)); // Enable the depth test glEnable(GL_DEPTH_TEST); // Enable culling glEnable(GL_CULL_FACE); // Initialise variables used for the animation m_fFrame = 0; m_iTimePrev = PVRShellGetTime(); return true; }
/*!**************************************************************************** @Function UpdateFramerateCounter @Description Updates and keeps track of the frames rendered per second. ******************************************************************************/ float OGLES2ParticleSystem::UpdateFramerateCounter() { static long lOldPerf = PVRShellGetTime(); static int i32Frame = 0; static float fFPS = 60.0f; long m_lPerf = PVRShellGetTime(); ++i32Frame; if((m_lPerf - lOldPerf) >= 1000l) { fFPS = i32Frame * 1000.0f / (float)(m_lPerf - lOldPerf); i32Frame = 0; lOldPerf = m_lPerf; } return fFPS; }
/*!**************************************************************************** @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 OGLES2ChameleonMan::InitView() { CPVRTString ErrorStr; /* Initialize VBO data */ LoadVbos(); /* 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; } /* Initialize Print3D */ // Is the screen rotated? bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } /* Set OpenGL ES render states needed for this training course */ // Enable backface culling and depth test glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); // Use black as our clear colour glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Initialise variables used for the animation m_iTimePrev = PVRShellGetTime(); 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 OGLES3TextureStreaming::InitApplication() { m_i32Frame = 0; m_puiVbo = 0; m_puiIndexVbo = 0; m_ulGlowTime = 0; m_iNoiseCoordIdx = 0; m_uiTVScreen = -1; m_bGlowState = false; /* CPVRTResourceFile is a resource file helper class. Resource files can be placed on disk next to the executable or in a platform dependent read path. We need to tell the class where that read path is. Additionally, it is possible to wrap files into cpp modules and link them directly into the executable. In this case no path will be used. Files on disk will override "memory files". */ // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); // Load the scene if(m_Scene.ReadFromFile(c_pszSceneFile) != PVR_SUCCESS) { CPVRTString ErrorStr = "ERROR: Couldn't load '" + CPVRTString(c_pszSceneFile) + "'.\n"; PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // The cameras are stored in the file. We check it contains at least one. if(m_Scene.nNumCamera == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera. Please add one and re-export.\n"); return false; } // We also check that the scene contains at least one light if(m_Scene.nNumLight == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light. Please add one and re-export.\n"); return false; } // Initialize variables used for the animation. m_fFrame = 0.0f; m_fBandScroll = -c_fBandWidth; m_ulTimePrev = PVRShellGetTime(); 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. Will also manage relevent OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES3TextureStreaming::RenderScene() { // Clears the color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Time based animation and locks the app to 60 FPS. // Uses the shell function PVRShellGetTime() to get the time in milliseconds. unsigned long ulTime = PVRShellGetTime(); unsigned long ulDeltaTime = ulTime - m_ulTimePrev; m_ulTimePrev = ulTime; m_fFrame += (float)ulDeltaTime * (60.0f/1000.0f); m_fBandScroll += (float)ulDeltaTime * (60.0f/1000.0f) * c_fBandScrollSpeed; if(m_fFrame > m_Scene.nNumFrame - 1) m_fFrame = 0.0f; if(m_fBandScroll > 1.0f) m_fBandScroll = -c_fBandWidth; bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); m_Scene.SetFrame(m_fFrame); // Setup the main camera PVRTVec3 vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f); float fFOV; // Camera nodes are after the mesh and light nodes in the array int i32CamID = m_Scene.pNode[m_Scene.nNumMeshNode + m_Scene.nNumLight + c_ui32Camera].nIdx; // Get the camera position, target and field of view (fov) if(m_Scene.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target? fFOV = m_Scene.GetCameraPos( vFrom, vTo, c_ui32Camera); // vTo is taken from the target node else fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, c_ui32Camera); // vTo is calculated from the rotation float fTargetAspect = 960.0f/640.0f; float fAspect = (float)PVRShellGet(prefWidth) / (float)PVRShellGet(prefHeight); fFOV *= fTargetAspect / fAspect; PVRTMat4 mView = PVRTMat4::LookAtRH(vFrom, vTo, vUp); PVRTMat4 mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), c_fCameraNear, c_fCameraFar, PVRTMat4::OGL, bRotate); PVRTMat4 mViewProjection = mProjection * mView; DrawPODScene(mViewProjection); // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools m_Print3D.DisplayDefaultTitle("Texture Streaming", c_pszDescription, ePVRTPrint3DSDKLogo); m_Print3D.Flush(); ++m_i32Frame; return true; }
/******************************************************************************* * Function Name : RenderScene * Returns : true if no error occured * Description : Main rendering loop function of the program. The shell will * call this function every frame. *******************************************************************************/ bool CTransforms::RenderScene() { m_ui32AbsTime = PVRShellGetTime(); // Clear the screen with clear color. vgClear(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight)); // Set fill paint vgSetPaint(m_vgPaint, VG_FILL_PATH); unsigned int ui32TimeSinceStart = PVRShellGetTime() - m_ui32StartTime; // toggle segment type every 3 seconds int ui32ActiveTransform = (ui32TimeSinceStart % (3000 * 7)) / 3000; switch(ui32ActiveTransform) { case 0: DoTranslate(); break; case 1: DoScaleCentered(); break; case 2: DoScaleOrigin(); break; case 3: DoRotateCentered(); break; case 4: DoRotateOrigin(); break; case 5: DoShearCentered(); break; case 6: DoShearOrigin(); break; } // Draw user interface static char* apszTransforms[] = { "Translation", "Scaling (centered on object)", "Scaling (from origin)", "Rotate (centered on object)", "Rotate (around origin)", "Shear (centered on object)", "Shear (from origin)", }; m_PrintVG.DisplayDefaultTitle("Transforms", apszTransforms[ui32ActiveTransform], ePVRTPrint3DLogoIMG); return true; }
/*!**************************************************************************** @Function UpdateParticles @Description Updates particle positions and attributes, e.g. lifespan. ******************************************************************************/ void OGLES2ParticleSystem::UpdateParticles() { static long lastTime = PVRShellGetTime(); long nowTime = PVRShellGetTime(); long elapsedTime = nowTime - lastTime; float step = elapsedTime / 140.0f; lastTime = nowTime; static float rot_angle = 0.0f; rot_angle += step / 2.0f; float el_angle = ((float) sin(rot_angle / 4.0f) + 1.0f) * 0.2f + 0.2f; PVRTMat4 rot = PVRTMat4::RotationY(rot_angle); PVRTMat4 skew = PVRTMat4::RotationZ(el_angle); Emitter sEmitter; sEmitter.mTransformation = rot * skew; sEmitter.fHeight = 2.0f; sEmitter.fRadius = 0.35f; m_pParticleSystem->SetEmitter(sEmitter); m_pParticleSystem->Update(step); }
/*!**************************************************************************** @Function Update @Description Handles user input and updates all timing data. ******************************************************************************/ void OGLES3ShadowMapping::Update() { if (PVRShellIsKeyPressed(PVRShellKeyNameSELECT)) m_bDebug = !m_bDebug; if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT)) m_fBias *= 0.9f; if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT)) m_fBias *= 1.1f; // Calculates the frame number to animate in a time-based manner. // Uses the shell function PVRShellGetTime() to get the time in milliseconds. static unsigned long ulTimePrev = PVRShellGetTime(); unsigned long ulTime = PVRShellGetTime(); unsigned long ulDeltaTime = ulTime - ulTimePrev; ulTimePrev = ulTime; static float fFrame = 0; if (!m_bDebug) fFrame += (float)ulDeltaTime * 0.05f; if (fFrame > m_Scene.nNumFrame-1) fFrame = 0; // Update the animation data m_Scene.SetFrame(fFrame); PVRTVec3 vFrom, vTo, vUp; float fFOV = m_Scene.GetCamera(vFrom, vTo, vUp, 0) * 0.75f; m_mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), m_Scene.pCamera[0].fNear, m_Scene.pCamera[0].fFar, PVRTMat4::OGL, m_bRotate); m_mView = PVRTMat4::LookAtRH(vFrom, vTo, vUp); m_Scene.GetLight(m_vLightPosition, m_vLightDirection, 0); PVRTVec3 lightFrom, lightTo, lightUp; m_Scene.GetCamera(lightFrom, lightTo, lightUp, 1); m_mLightView = PVRTMat4::LookAtRH(lightFrom, lightTo, lightUp); m_mLightProjection = PVRTMat4::PerspectiveFovRH(PVRT_PI_OVER_TWO, 1.0f, m_Scene.pCamera[1].fNear, m_Scene.pCamera[1].fFar, PVRTMat4::OGL, m_bRotate); }
/*!**************************************************************************** @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. Will also manage relevent OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES2RenderToTexture::RenderScene() { /* vary the branch angles on the fractal sinusoidally */ m_fAngle = (float)(sin(0.25*PVRT_PIf*(float)(m_ui32Framenum)/256.0f))* 70.0f; /* largeish prime number in the angular frequency here, so the motion's not obviously periodic */ m_fAngle2 = (float)(sin((79.0f/256.0f)*2.0*PVRT_PIf*(float)(m_ui32Framenum)/256.0f))*100.0f + 30.0f; /* Convert the angles to radians. */ m_fAngle *= 0.017453f; m_fAngle2 *= 0.017453f; /* Increase the frame count */ if(PVRShellGetTime() - m_ui32Time > 10) { m_ui32Time = PVRShellGetTime(); m_ui32Framenum += 2; if(m_ui32Framenum > 20000) m_ui32Framenum = 0; } // Disable depth test and culling as we don't need it glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Draw the RenderToTexture if(!DrawScreen()) return false; // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools m_Print3D.DisplayDefaultTitle("Render to Texture", "Using FBO", ePVRTPrint3DLogoIMG); m_Print3D.Flush(); return true; }
// --------------------------------------------------------------- bool MyPVRDemo::RenderScene() { // --- Work out DT unsigned long ulPrevTime = m_ulCurrTime; m_ulCurrTime = PVRShellGetTime(); m_fDT = ((float)m_ulCurrTime - (float)ulPrevTime) * 0.001f; // Calculate a new light matrix PVRTVec3 vLightPos = PVRTVec4(m_vLightPos, 1.0f) * PVRTMat4::RotationY(m_fLightAngle); m_mxLightView = PVRTMat4::LookAtRH(vLightPos, PVRTVec3(0,25,0), PVRTVec3(0,1,0)); // --- Render the scene from the light's POV RenderShadowScene(); // --- Clear buffers glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight)); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); PVRTMat4 mxCam = m_mxCam * PVRTMat4::RotationY(m_fAngleY); PVRTMat4 mxModel = PVRTMat4::Identity(); // --- Draw the Statue glUseProgram(m_StatueShader.uiID); glBindTexture(GL_TEXTURE_2D, m_tex[enumTEXTURE_StatueNormals]); RenderStatue(mxModel, mxCam, vLightPos, &m_StatueShader); // --- Draw the Statue reflected glCullFace(GL_FRONT); PVRTMat4 mxModelRefl = PVRTMat4::Scale(1,-1,1) * mxModel; RenderStatue(mxModelRefl, mxCam, vLightPos, &m_StatueShader); glCullFace(GL_BACK); // --- Draw the Floor (with shadow) RenderCurch(mxCam); // --- Render the bloom effect RenderBloom(mxModel, mxCam, vLightPos); // --- Increment the camera angle m_fAngleY += 0.5f * m_fDT; // --- Increment the light angle m_fLightAngle += 0.5f * m_fDT; return true; }
void OGLES2FilmTV::CalcMiniCameraView() { float fValue = PVRShellGetTime() * 0.001f * 2.0f * PVRT_PIf; float fZ = 1.0f + (2.40f * (float)sin(fValue * 1.0f / g_ui32CameraLoopSpeed)); float fX = 0.50f * (float)cos(fValue * 2.0f / g_ui32CameraLoopSpeed); float fCamRot = 0.16f * (float)sin(fValue * 1.0f / g_ui32CameraLoopSpeed) - 0.17f; m_MiniCamView = PVRTMat4::RotationX((float)atan2(fX, 10.0f)); m_MiniCamView *= PVRTMat4::RotationY(fCamRot); m_MiniCamView *= PVRTMat4::RotationZ((float)atan2(fZ, 10.0f)); // Setup the mini camera's view projection matrix PVRTMat4 mProjection = PVRTMat4::PerspectiveFovRH(70.0f * (PVRT_PIf / 180.0f), 1, g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, false); m_MiniCamViewProj = mProjection * m_MiniCamView; }
/*!**************************************************************************** @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 OGLES3Skinning::InitApplication() { m_puiVbo = 0; m_puiIndexVbo = 0; // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); // Load the scene if (m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n"); return false; } // The cameras are stored in the file. We check it contains at least one. if (m_Scene.nNumCamera == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera\n"); return false; } // Check the scene contains at least one light if (m_Scene.nNumLight == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light\n"); return false; } // Initialise variables used for the animation m_fFrame = 0; m_iTimePrev = PVRShellGetTime(); m_Transform = PVRTMat4::Identity(); m_fAngle = 0.0f; m_fDistance = 0.0f; 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 OGLES3IntroducingPFX::InitApplication() { // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Get and set the load/release functions for loading external files. // In the majority of cases the PVRShell will return NULL function pointers implying that // nothing special is required to load external files. CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc)); // Load the scene if (m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n"); return false; } // The cameras are stored in the file. We check it contains at least one. if(m_Scene.nNumCamera == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera\n"); return false; } // Ensure that all meshes use an indexed triangle list for(unsigned int i = 0; i < m_Scene.nNumMesh; ++i) { if(m_Scene.pMesh[i].nNumStrips || !m_Scene.pMesh[i].sFaces.pData) { PVRShellSet(prefExitMessage, "ERROR: The meshes in the scene should use an indexed triangle list\n"); return false; } } // Initialize variables used for the animation m_fFrame = 0; m_ulTimePrev = PVRShellGetTime(); 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. Will also manage relevent OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES2ParticleSystem::RenderScene() { HandleInput(); UpdateParticles(); UpdateFramerateCounter(); float time_delta = PVRShellGetTime() / 10000.0f; PVRTVec3 vFrom = PVRTVec3((float) sin(time_delta) * 50.0f, 30.0f, (float) cos(time_delta) * 50.0f); m_mView = PVRTMat4::LookAtRH(vFrom, PVRTVec3(0.0f, 5.0f, 0.0f), PVRTVec3(0.0f, 1.0f, 0.0f)); m_mViewProjection = m_mProjection * m_mView; // Clear colour and depth buffers glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Enables depth testing glEnable(GL_DEPTH_TEST); // Render floor RenderFloor(); for (unsigned int i=0; i < g_cuiNumSpheres; i++) RenderSphere(g_caSpheres[i].aPosition, g_caSpheres[i].fRadius); // Render particles RenderParticles(); // Display info text. char lower_buffer[64]; unsigned int numParticles = m_pParticleSystem->GetNumberOfParticles(); sprintf(lower_buffer, "No. of Particles: %d", numParticles); m_Print3D.DisplayDefaultTitle("Particle System", NULL, ePVRTPrint3DSDKLogo); m_Print3D.Print3D(2.0f, 90.0f, 1.0f, 0xFFFFFFFF, "No. of Particles: %d", numParticles); m_Print3D.Flush(); return true; }
/*!**************************************************************************** @Function UpdateScene @Description Moves the scene. ******************************************************************************/ void OGLES2Glass::UpdateScene() { // Fetch current time and make sure the previous time isn't greater unsigned long ulCurrentTime = PVRShellGetTime(); if (ulCurrentTime < m_ulTime) m_ulTime = ulCurrentTime; // Calculate the time difference unsigned long ulTimeDifference = ulCurrentTime - m_ulTime; // Store the current time for the next frame m_ulTime = ulCurrentTime; m_afAngles[0] += ulTimeDifference * 0.0002f; m_afAngles[1] -= ulTimeDifference * 0.00008f; float fRise = sin(m_afAngles[0] * 3.0f); // Rotate the camera m_mView = PVRTMat4::LookAtRH(PVRTVec3(0, 0, -10), PVRTVec3(0, 0, 0), PVRTVec3(0, 1, 0)) * PVRTMat4::RotationY(m_afAngles[0] * 0.2f); // Rotate the balloon model matrices m_mModels[0] = PVRTMat4::RotationY(m_afAngles[0]) * PVRTMat4::Translation(120.0f, fRise * 20.0f, 0.0f) * PVRTMat4::Scale(3.0f, 3.0f, 3.0f); m_mModels[1] = PVRTMat4::RotationY(m_afAngles[1]) * PVRTMat4::Translation(-180.0f, -fRise * 20.0f, 0.0f) * PVRTMat4::Scale(3.0f, 3.0f, 3.0f); }
/*!**************************************************************************** @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 OGLES2IntroducingPOD::InitApplication() { m_puiVbo = 0; m_puiIndexVbo = 0; m_puiTextureIDs = 0; // Get and set the read path for content files CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath)); // Load the scene if(m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n"); return false; } // The cameras are stored in the file. We check it contains at least one. if(m_Scene.nNumCamera == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera. Please add one and re-export.\n"); return false; } // We also check that the scene contains at least one light if(m_Scene.nNumLight == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light. Please add one and re-export.\n"); return false; } // Initialize variables used for the animation m_fFrame = 0; m_iTimePrev = PVRShellGetTime(); return true; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occurred @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 OGLES3EdgeDetection::InitView() { // Store width and height of the viewport. m_i32WinWidth = PVRShellGet(prefWidth); m_i32WinHeight = PVRShellGet(prefHeight); // Set our texture dimensions to be the same as our windows m_i32TexWidth = m_i32WinWidth; m_i32TexHeight = m_i32WinHeight; /* Get the current frame buffer object. As the program hasn't set it yet, this is the default buffer. On most platforms this just gives 0, but there are exceptions. */ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFramebuffer); // Create string for error codes. CPVRTString ErrorStr; // Checks to see if the screen is rotated or not. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); // Initialize VBO data if(!LoadVbos(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Initialise Print3D if(m_Print3D.SetTextures(0,m_i32WinWidth,m_i32WinHeight,bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Load external textures and create internal ones. 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; } // Creates and checks FBO creation if (!CreateFBO(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } SetupView(bRotate); //Initialises the time variables. m_ulCurrentTime = PVRShellGetTime(); m_ulPreviousTimeAngle = m_ulCurrentTime; m_ulPreviousTimeFPS = m_ulCurrentTime; return true; }
/*!**************************************************************************** @Function RenderScene @Return bool true if no error occurred @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. Will also manage relevant OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES3Skybox2::RenderScene() { unsigned int i, j; // Clears the colour and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Calculates the frame number to animate in a time-based manner. Uses the shell function PVRShellGetTime() to get the time in milliseconds. */ unsigned long iTime = PVRShellGetTime(); if(!bPause) { // Calculate the model view matrix turning around the balloon ComputeViewMatrix(); if(iTime > m_iTimePrev) { float fDelta = (float) (iTime - m_iTimePrev) * g_fFrameRate; m_fFrame += fDelta; fDemoFrame += fDelta; fBurnAnim += fDelta * 0.02f; if(fBurnAnim >= 1.0f) fBurnAnim = 1.0f; } } m_iTimePrev = iTime; /* KeyBoard input processing */ if(PVRShellIsKeyPressed(PVRShellKeyNameACTION1)) bPause=!bPause; if(PVRShellIsKeyPressed(PVRShellKeyNameACTION2)) fBurnAnim = 0.0f; /* Keyboard Animation and Automatic Shader Change over time */ if(!bPause && (fDemoFrame > 500 || (m_i32Effect == 2 && fDemoFrame > 80))) { if(++m_i32Effect >= (int) g_ui32NoOfEffects) { m_i32Effect = 1; m_fFrame = 0.0f; } fDemoFrame = 0.0f; fBurnAnim = 0.0f; } /* Change Shader Effect */ if(PVRShellIsKeyPressed(PVRShellKeyNameRIGHT)) { if(++m_i32Effect >= (int) g_ui32NoOfEffects) m_i32Effect = 1; fDemoFrame = 0.0f; fBurnAnim = 0.0f; m_fFrame = 0.0f; } if(PVRShellIsKeyPressed(PVRShellKeyNameLEFT)) { if(--m_i32Effect < 1) m_i32Effect = g_ui32NoOfEffects - 1; fDemoFrame = 0.0f; fBurnAnim = 0.0f; m_fFrame = 0.0f; } /* Change Skybox Texture */ if(PVRShellIsKeyPressed(PVRShellKeyNameUP)) { for(i = 0; i < g_ui32NoOfEffects; ++i) ChangeSkyboxTo(m_ppEffects[i], m_ui32TextureIDs[4]); fBurnAnim = 0.0f; } if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN)) { for(i = 0; i < g_ui32NoOfEffects; ++i) ChangeSkyboxTo(m_ppEffects[i], m_ui32TextureIDs[3]); fBurnAnim = 0.0f; } /* Setup Shader and Shader Constants */ int location; glDisable(GL_CULL_FACE); DrawSkybox(); glEnable(GL_CULL_FACE); m_ppEffects[m_i32Effect]->Activate(); for(i = 0; i < m_Scene.nNumMeshNode; i++) { SPODNode* pNode = &m_Scene.pNode[i]; // Gets pMesh referenced by the pNode SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx]; // Gets the node model matrix PVRTMat4 mWorld, mWORLDVIEW; mWorld = m_Scene.GetWorldMatrix(*pNode); mWORLDVIEW = m_mView * mWorld; glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]); const CPVRTArray<SPVRTPFXUniform>& Uniforms = m_ppEffects[m_i32Effect]->GetUniformArray(); for(j = 0; j < Uniforms.GetSize(); ++j) { switch(Uniforms[j].nSemantic) { case ePVRTPFX_UsPOSITION: { glVertexAttribPointer(Uniforms[j].nLocation, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData); glEnableVertexAttribArray(Uniforms[j].nLocation); } break; case ePVRTPFX_UsNORMAL: { glVertexAttribPointer(Uniforms[j].nLocation, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData); glEnableVertexAttribArray(Uniforms[j].nLocation); } break; case ePVRTPFX_UsUV: { glVertexAttribPointer(Uniforms[j].nLocation, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData); glEnableVertexAttribArray(Uniforms[j].nLocation); } break; case ePVRTPFX_UsWORLDVIEWPROJECTION: { PVRTMat4 mMVP; /* Passes the model-view-projection matrix (MVP) to the shader to transform the vertices */ mMVP = m_mProjection * mWORLDVIEW; glUniformMatrix4fv(Uniforms[j].nLocation, 1, GL_FALSE, mMVP.f); } break; case ePVRTPFX_UsWORLDVIEW: { glUniformMatrix4fv(Uniforms[j].nLocation, 1, GL_FALSE, mWORLDVIEW.f); } break; case ePVRTPFX_UsWORLDVIEWIT: { PVRTMat4 mWORLDVIEWI, mWORLDVIEWIT; mWORLDVIEWI = mWORLDVIEW.inverse(); mWORLDVIEWIT= mWORLDVIEWI.transpose(); PVRTMat3 WORLDVIEWIT = PVRTMat3(mWORLDVIEWIT); glUniformMatrix3fv(Uniforms[j].nLocation, 1, GL_FALSE, WORLDVIEWIT.f); } break; case ePVRTPFX_UsVIEWIT: { PVRTMat4 mViewI, mViewIT; mViewI = m_mView.inverse(); mViewIT = mViewI.transpose(); PVRTMat3 ViewIT = PVRTMat3(mViewIT); glUniformMatrix3fv(Uniforms[j].nLocation, 1, GL_FALSE, ViewIT.f); } break; case ePVRTPFX_UsLIGHTDIREYE: { PVRTVec4 vLightDirectionEyeSpace; // Passes the light direction in eye space to the shader vLightDirectionEyeSpace = m_mView * PVRTVec4(1.0,1.0,-1.0,0.0); glUniform3f(Uniforms[j].nLocation, vLightDirectionEyeSpace.x, vLightDirectionEyeSpace.y, vLightDirectionEyeSpace.z); } break; case ePVRTPFX_UsTEXTURE: { // Set the sampler variable to the texture unit glUniform1i(Uniforms[j].nLocation, Uniforms[j].nIdx); } break; } } location = glGetUniformLocation(m_ppEffects[m_i32Effect]->GetProgramHandle(), "myEyePos"); if(location != -1) glUniform3f(location, vCameraPosition.x, vCameraPosition.y, vCameraPosition.z); //set animation location = glGetUniformLocation(m_ppEffects[m_i32Effect]->GetProgramHandle(), "fAnim"); if(location != -1) glUniform1f(location, fBurnAnim); location = glGetUniformLocation(m_ppEffects[m_i32Effect]->GetProgramHandle(), "myFrame"); if(location != -1) glUniform1f(location, m_fFrame); if(g_bBlendShader[m_i32Effect]) { glEnable(GL_BLEND); // Correct render order for alpha blending through culling // Draw Back faces glCullFace(GL_FRONT); location = glGetUniformLocation(m_ppEffects[m_i32Effect]->GetProgramHandle(), "bBackFace"); glUniform1i(location, 1); DrawMesh(pMesh); glUniform1i(location, 0); glCullFace(GL_BACK); } else { location = glGetUniformLocation(m_ppEffects[m_i32Effect]->GetProgramHandle(), "bBackFace"); if(location != -1) glUniform1i(location, 0); glDisable(GL_BLEND); } /* Everything should now be setup, therefore draw the mesh*/ DrawMesh(pMesh); glBindBuffer(GL_ARRAY_BUFFER, 0); for(j = 0; j < Uniforms.GetSize(); ++j) { switch(Uniforms[j].nSemantic) { case ePVRTPFX_UsPOSITION: { glDisableVertexAttribArray(Uniforms[j].nLocation); } break; case ePVRTPFX_UsNORMAL: { glDisableVertexAttribArray(Uniforms[j].nLocation); } break; case ePVRTPFX_UsUV: { glDisableVertexAttribArray(Uniforms[j].nLocation); } break; } } } // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools if(!bPause) m_Print3D.DisplayDefaultTitle("Skybox2", "", ePVRTPrint3DSDKLogo); else m_Print3D.DisplayDefaultTitle("Skybox2", "Paused", ePVRTPrint3DSDKLogo); m_Print3D.Flush(); return true; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occurred @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 dependent on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLES3Skybox2::InitView() { // Sets the clear colour glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // Enables depth test using the z-buffer glEnable(GL_DEPTH_TEST); CPVRTString ErrorStr; /* Load textures */ if(!LoadTextures(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } /*********************/ /* Create the Skybox */ /*********************/ float* skyboxVertices; float* skyboxUVs; PVRTCreateSkybox( 500.0f, true, 512, &skyboxVertices, &skyboxUVs ); glGenBuffers(1, &m_iSkyVboID); glBindBuffer(GL_ARRAY_BUFFER, m_iSkyVboID); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 24, &skyboxVertices[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); PVRTDestroySkybox(skyboxVertices, skyboxUVs); /**********************/ /* Create the Effects */ /**********************/ { // Parse the file m_pEffectParser = new CPVRTPFXParser(); if(m_pEffectParser->ParseFromFile(g_pszEffectFileName, &ErrorStr) != PVR_SUCCESS) { delete m_pEffectParser; PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } m_ppEffects = new CPVRTPFXEffect*[g_ui32NoOfEffects]; memset(m_ppEffects, 0, sizeof(CPVRTPFXEffect*) * g_ui32NoOfEffects); // Skybox shader if(!LoadEffect(&m_ppEffects[0], "skybox_effect", g_pszEffectFileName)) { delete m_pEffectParser; delete[] m_ppEffects; return false; } // The Balloon Shaders if(!LoadEffect(&m_ppEffects[1], "balloon_effect1", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[2], "balloon_effect2", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[3], "balloon_effect3", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[4], "balloon_effect4", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[5], "balloon_effect5", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[6], "balloon_effect6", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[7], "balloon_effect7", g_pszEffectFileName)) { delete m_pEffectParser; delete[] m_ppEffects; return false; } } // Create Geometry Buffer Objects. m_aiVboID = new GLuint[m_Scene.nNumMeshNode]; glGenBuffers(m_Scene.nNumMeshNode, m_aiVboID); for(unsigned int i = 0; i < m_Scene.nNumMeshNode ; ++i) { SPODNode* pNode = &m_Scene.pNode[i]; // Gets pMesh referenced by the pNode SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx]; // Genereta a vertex buffer and set the interleaved vertex datas. glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]); glBufferData(GL_ARRAY_BUFFER, pMesh->sVertex.nStride*pMesh->nNumVertex, pMesh->pInterleaved, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } /********************** ** Projection Matrix ** **********************/ /* Projection */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); m_mProjection = PVRTMat4::PerspectiveFovRH(PVRT_PI / 6, (float) PVRShellGet(prefWidth) / (float) PVRShellGet(prefHeight), 4.0f, 1000.0f, PVRTMat4::OGL, bRotate); // Calculate the model view matrix turning around the balloon ComputeViewMatrix(); /* Init Values */ bPause = false; fDemoFrame = 0.0; fBurnAnim = 0.0f; m_i32Effect = 1; // Initialise Print3D if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Initialise variables used for the animation m_iTimePrev = PVRShellGetTime(); return true; }
/*!**************************************************************************** @Function DoAnimation @Description Calculate the duck and camera animation as well as the cloud and water. ******************************************************************************/ void OGLESFur::DoAnimation() { PVRTMat4 mCamera, mTmp; PVRTVec3 pvPlane[5]; unsigned long ui32Time; float fDeltaTime; int i; if(!m_bPause) { ui32Time = PVRShellGetTime(); fDeltaTime = (float) (ui32Time < m_ui32PrevTime ? m_ui32PrevTime - ui32Time : ui32Time - m_ui32PrevTime) + 0.1f; if(fDeltaTime > 50.0f) // Cap delta time fDeltaTime = 50.0f; m_ui32PrevTime = ui32Time; m_fCameraRot += 0.00006f * fDeltaTime; fDeltaTime = fDeltaTime * 0.001f; } else fDeltaTime = 0.0f; if(m_bViewMode) { // Viewing duck alone mCamera = PVRTMat4::Translation(0, 0, 160.0f); mTmp = PVRTMat4::RotationX(0.35f * (float) sin(0.0003f * m_ui32PrevTime) + 0.2f); mCamera = mTmp * mCamera; mTmp = PVRTMat4::RotationY(m_fCameraRot); mCamera = mTmp * mCamera; mTmp = PVRTMat4::Translation(m_mDuckWorld.f[12], m_mDuckWorld.f[13], m_mDuckWorld.f[14]); mCamera = mTmp * mCamera; m_vCamFrom.x += fDeltaTime * (mCamera.f[12] - m_vCamFrom.x); m_vCamFrom.y += fDeltaTime * (mCamera.f[13] - m_vCamFrom.y); m_vCamFrom.z += fDeltaTime * (mCamera.f[14] - m_vCamFrom.z); m_vCamTo.x += fDeltaTime * (m_mDuckWorld.f[12] - m_vCamTo.x); m_vCamTo.y += fDeltaTime * (m_mDuckWorld.f[13] + 25.0f - m_vCamTo.y); m_vCamTo.z += fDeltaTime * (m_mDuckWorld.f[14] - m_vCamTo.z); // Build view matrix m_mView = PVRTMat4::LookAtRH(m_vCamFrom, m_vCamTo, c_vUp); } else { // Viewing duck in a wee river m_fDuckRot -= 0.1f * fDeltaTime; // Duck world transform m_mDuckWorld = PVRTMat4::Translation(140.0f, 0, 0); mTmp = PVRTMat4::RotationY(m_fDuckRot); m_mDuckWorld = mTmp * m_mDuckWorld; PVRTVec3 vFrom, vTo; // We can get the camera position, target with GetCameraPos() m_Scene.GetCameraPos(vFrom, vTo, 0); // Position camera mCamera = PVRTMat4::Translation(vFrom.x, vFrom.y, vFrom.z); mTmp = PVRTMat4::RotationY(m_fCameraRot); mCamera = mTmp * mCamera; m_vCamFrom.x += fDeltaTime * (mCamera.f[12] - m_vCamFrom.x); m_vCamFrom.y += fDeltaTime * (mCamera.f[13] - m_vCamFrom.y); m_vCamFrom.z += fDeltaTime * (mCamera.f[14] - m_vCamFrom.z); m_vCamTo.x += fDeltaTime * (2.0f * (m_mDuckWorld.f[12] - m_vCamTo.x)); m_vCamTo.y += fDeltaTime * (2.0f * (m_mDuckWorld.f[13] + 25.0f - m_vCamTo.y)); m_vCamTo.z += fDeltaTime * (2.0f * (m_mDuckWorld.f[14] - m_vCamTo.z)); // Build view matrix m_mView = PVRTMat4::LookAtRH(m_vCamFrom, m_vCamTo, c_vUp); // Calc ViewProjInv matrix mTmp = m_mProj * m_mView; mTmp = mTmp.inverseEx(); // Calculate the ground plane m_i32WaterPlaneNo = PVRTMiscCalculateInfinitePlane(&pvPlane->x, sizeof(*pvPlane), &c_vPlaneWater, &mTmp, &m_vCamFrom, g_fFar); for(i = 0; i < m_i32WaterPlaneNo; ++i) { m_pvPlaneWater[i].x = pvPlane[i].x; m_pvPlaneWater[i].y = pvPlane[i].y; m_pvPlaneWater[i].z = pvPlane[i].z; m_pvPlaneWater[i].nx = c_vPlaneWater.x; m_pvPlaneWater[i].ny = c_vPlaneWater.y; m_pvPlaneWater[i].nz = c_vPlaneWater.z; m_pvPlaneWater[i].tu = pvPlane[i].x * 0.005f; m_pvPlaneWater[i].tv = pvPlane[i].z * 0.005f; } // Calculate the Cloud plane m_i32CloudPlaneNo = PVRTMiscCalculateInfinitePlane(&pvPlane->x, sizeof(*pvPlane), &c_vPlaneCloud, &mTmp, &m_vCamFrom, g_fFar); for(i = 0; i < m_i32CloudPlaneNo; ++i) { m_pvPlaneCloud[i].x = pvPlane[i].x; m_pvPlaneCloud[i].y = pvPlane[i].y; m_pvPlaneCloud[i].z = pvPlane[i].z; m_pvPlaneCloud[i].nx = c_vPlaneCloud.x; m_pvPlaneCloud[i].ny = c_vPlaneCloud.y; m_pvPlaneCloud[i].nz = c_vPlaneCloud.z; m_pvPlaneCloud[i].tu = pvPlane[i].x * ((1.0f / 100.0f) + m_ui32PrevTime * 0.0002f); m_pvPlaneCloud[i].tv = pvPlane[i].z * (1.0f / 100.0f); } } }
/*!**************************************************************************** @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. Will also manage relevent OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES3IntroducingPOD::RenderScene() { // Clear the color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Use shader program glUseProgram(m_ShaderProgram.uiId); /* Calculates the frame number to animate in a time-based manner. Uses the shell function PVRShellGetTime() to get the time in milliseconds. */ unsigned long ulTime = PVRShellGetTime(); if(m_ulTimePrev > ulTime) m_ulTimePrev = ulTime; unsigned long ulDeltaTime = ulTime - m_ulTimePrev; m_ulTimePrev = ulTime; m_fFrame += (float)ulDeltaTime * g_fDemoFrameRate; if (m_fFrame > m_Scene.nNumFrame - 1) m_fFrame = 0; // Sets the scene animation to this frame m_Scene.SetFrame(m_fFrame); /* Get the direction of the first light from the scene. */ PVRTVec4 vLightDirection; vLightDirection = m_Scene.GetLightDirection(0); // For direction vectors, w should be 0 vLightDirection.w = 0.0f; /* Set up the view and projection matrices from the camera */ PVRTMat4 mView, mProjection; PVRTVec3 vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f); float fFOV; // Setup the camera // Camera nodes are after the mesh and light nodes in the array int i32CamID = m_Scene.pNode[m_Scene.nNumMeshNode + m_Scene.nNumLight + g_ui32Camera].nIdx; // Get the camera position, target and field of view (fov) if(m_Scene.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target? fFOV = m_Scene.GetCameraPos( vFrom, vTo, g_ui32Camera); // vTo is taken from the target node else fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, g_ui32Camera); // vTo is calculated from the rotation // We can build the model view matrix from the camera position, target and an up vector. // For this we use PVRTMat4::LookAtRH() mView = PVRTMat4::LookAtRH(vFrom, vTo, vUp); // Calculate the projection matrix bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate); /* A scene is composed of nodes. There are 3 types of nodes: - MeshNodes : references a mesh in the pMesh[]. These nodes are at the beginning of the pNode[] array. And there are nNumMeshNode number of them. This way the .pod format can instantiate several times the same mesh with different attributes. - lights - cameras To draw a scene, you must go through all the MeshNodes and draw the referenced meshes. */ for (unsigned int i = 0; i < m_Scene.nNumMeshNode; ++i) { SPODNode& Node = m_Scene.pNode[i]; // Get the node model matrix PVRTMat4 mWorld; mWorld = m_Scene.GetWorldMatrix(Node); // Pass the model-view-projection matrix (MVP) to the shader to transform the vertices PVRTMat4 mModelView, mMVP; mModelView = mView * mWorld; mMVP = mProjection * mModelView; glUniformMatrix4fv(m_ShaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.f); // Pass the light direction in model space to the shader PVRTVec4 vLightDir; vLightDir = mWorld.inverse() * vLightDirection; PVRTVec3 vLightDirModel = *(PVRTVec3*)&vLightDir; vLightDirModel.normalize(); glUniform3fv(m_ShaderProgram.uiLightDirLoc, 1, &vLightDirModel.x); // Load the correct texture using our texture lookup table GLuint uiTex = 0; if(Node.nIdxMaterial != -1) uiTex = m_puiTextureIDs[Node.nIdxMaterial]; glBindTexture(GL_TEXTURE_2D, uiTex); /* Now that the model-view matrix is set and the materials are ready, call another function to actually draw the mesh. */ DrawMesh(i); } // Display the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools m_Print3D.DisplayDefaultTitle("IntroducingPOD", "", ePVRTPrint3DSDKLogo); m_Print3D.Flush(); 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. Will also manage relevent OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLESIntroducingPFX::RenderScene() { // Clears the color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Use the loaded effect m_pEffect->Activate(); /* Calculates the frame number to animate in a time-based manner. Uses the shell function PVRShellGetTime() to get the time in milliseconds. */ int iTime = PVRShellGetTime(); int iDeltaTime = iTime - m_iTimePrev; m_iTimePrev = iTime; m_fFrame += (float)iDeltaTime * DEMO_FRAME_RATE; if (m_fFrame > m_Scene.nNumFrame-1) m_fFrame = 0; // Sets the scene animation to this frame m_Scene.SetFrame(m_fFrame); { PVRTVec3 vFrom, vTo, vUp; VERTTYPE fFOV; vUp.x = 0.0f; vUp.y = 1.0f; vUp.z = 0.0f; // We can get the camera position, target and field of view (fov) with GetCameraPos() fFOV = m_Scene.GetCameraPos(vFrom, vTo, 0) * 0.4f; /* We can build the world view matrix from the camera position, target and an up vector. For this we use PVRTMat4LookAtRH(). */ m_mView = PVRTMat4::LookAtRH(vFrom, vTo, vUp); // Calculates the projection matrix bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); m_mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), CAM_NEAR, CAM_FAR, PVRTMat4::OGL, bRotate); } /* A scene is composed of nodes. There are 3 types of nodes: - MeshNodes : references a mesh in the pMesh[]. These nodes are at the beginning of the pNode[] array. And there are nNumMeshNode number of them. This way the .pod format can instantiate several times the same mesh with different attributes. - lights - cameras To draw a scene, you must go through all the MeshNodes and draw the referenced meshes. */ for (int i=0; i<(int)m_Scene.nNumMeshNode; i++) { SPODNode* pNode = &m_Scene.pNode[i]; // Gets pMesh referenced by the pNode SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx]; glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]); // Gets the node model matrix PVRTMat4 mWorld; mWorld = m_Scene.GetWorldMatrix(*pNode); PVRTMat4 mWorldView; mWorldView = m_mView * mWorld; for(unsigned int j = 0; j < m_nUniformCnt; ++j) { switch(m_psUniforms[j].nSemantic) { case eUsPOSITION: { glVertexAttribPointer(m_psUniforms[j].nLocation, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData); glEnableVertexAttribArray(m_psUniforms[j].nLocation); } break; case eUsNORMAL: { glVertexAttribPointer(m_psUniforms[j].nLocation, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData); glEnableVertexAttribArray(m_psUniforms[j].nLocation); } break; case eUsUV: { glVertexAttribPointer(m_psUniforms[j].nLocation, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData); glEnableVertexAttribArray(m_psUniforms[j].nLocation); } break; case eUsWORLDVIEWPROJECTION: { PVRTMat4 mWVP; /* Passes the world-view-projection matrix (WVP) to the shader to transform the vertices */ mWVP = m_mProjection * mWorldView; glUniformMatrix4fv(m_psUniforms[j].nLocation, 1, GL_FALSE, mWVP.f); } break; case eUsWORLDVIEWIT: { PVRTMat4 mWorldViewI, mWorldViewIT; /* Passes the inverse transpose of the world-view matrix to the shader to transform the normals */ mWorldViewI = mWorldView.inverse(); mWorldViewIT = mWorldViewI.transpose(); PVRTMat3 WorldViewIT = PVRTMat3(mWorldViewIT); glUniformMatrix3fv(m_psUniforms[j].nLocation, 1, GL_FALSE, WorldViewIT.f); } break; case eUsLIGHTDIREYE: { // Reads the light direction from the scene. PVRTVec4 vLightDirection; PVRTVec3 vPos; vLightDirection = m_Scene.GetLightDirection(0); vLightDirection.x = -vLightDirection.x; vLightDirection.y = -vLightDirection.y; vLightDirection.z = -vLightDirection.z; /* Sets the w component to 0, so when passing it to glLight(), it is considered as a directional light (as opposed to a spot light). */ vLightDirection.w = 0; // Passes the light direction in eye space to the shader PVRTVec4 vLightDirectionEyeSpace; vLightDirectionEyeSpace = m_mView * vLightDirection; glUniform3f(m_psUniforms[j].nLocation, vLightDirectionEyeSpace.x, vLightDirectionEyeSpace.y, vLightDirectionEyeSpace.z); } break; case eUsTEXTURE: { // Set the sampler variable to the texture unit glUniform1i(m_psUniforms[j].nLocation, m_psUniforms[j].nIdx); } break; } } /* Now that the model-view matrix is set and the materials ready, call another function to actually draw the mesh. */ DrawMesh(pMesh); glBindBuffer(GL_ARRAY_BUFFER, 0); for(unsigned int j = 0; j < m_nUniformCnt; ++j) { switch(m_psUniforms[j].nSemantic) { case eUsPOSITION: { glDisableVertexAttribArray(m_psUniforms[j].nLocation); } break; case eUsNORMAL: { glDisableVertexAttribArray(m_psUniforms[j].nLocation); } break; case eUsUV: { glDisableVertexAttribArray(m_psUniforms[j].nLocation); } break; } } } // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools m_Print3D.DisplayDefaultTitle("IntroducingPFX", "", ePVRTPrint3DLogoIMG); m_Print3D.Flush(); 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 and relevant OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES3EdgeDetection::RenderScene() { // Declares world orientation variables. PVRTMat4 mWorld, mMVP; // Updates the current time. m_ulCurrentTime=PVRShellGetTime(); #ifdef SHOW_MAX_FPS //Updates and checks framerate. m_iFrameCount+=1; if (m_ulCurrentTime-m_ulPreviousTimeFPS>=1000) { m_fFPS=(GLfloat)m_iFrameCount/(GLfloat)(m_ulCurrentTime-m_ulPreviousTimeFPS)*1000.0f; m_ulPreviousTimeFPS=m_ulCurrentTime; m_iFrameCount=0; } // Display fps data m_Print3D.Print3D(2.0f, 10.0f, 0.75f, 0xff0000ff, "%i fps", (int)m_fFPS); #endif // Time dependant updates for the rotational velocity of the scene. m_fAngleY += 0.0002f*PVRT_PI*(m_ulCurrentTime-m_ulPreviousTimeAngle); m_ulPreviousTimeAngle=PVRShellGetTime(); // Render to our texture (bracketed for viewing convenience) { // Use the first shader program to perform the initial render of the mask. glUseProgram(m_PreShader.uiId); // Bind render-to-texture frame buffer and set the viewPort glBindFramebuffer(GL_FRAMEBUFFER, m_uiFramebufferObject); if(m_i32TexWidth != m_i32WinWidth || m_i32TexHeight != m_i32WinHeight) glViewport(0, 0, m_i32TexWidth, m_i32TexHeight); #if defined(__PALMPDK__) // Enable writing to the alpha channel again as usually it is disabled so // we don't blend with the video layer on webOS devices. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); #endif // Clear the color and depth buffer of our FBO glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Rotates the scene and sets the model-view-projection matrix mWorld = PVRTMat4::RotationY(m_fAngleY); mMVP = m_mR2TProjection * m_mR2TView * mWorld; // Send the view matrix information to the shader. glUniformMatrix4fv(m_PreShader.auiLoc[eMVPMatrix], 1, GL_FALSE, mMVP.f); // Enable vertex attribute array glEnableVertexAttribArray(eVERTEX_ARRAY); //Enable depth testing and culling. glEnable(GL_DEPTH_TEST); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // Draw our models by looping through each mesh as defined by nNumMesh. for (unsigned int i=0; i<m_Scene.nNumMeshNode; i++) { DrawMesh(i); } // Unbind the VBO and index buffer. glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); //Invalidate the framebuffer attachments we don't need to avoid unnecessary copying to system memory const GLenum attachment = GL_DEPTH_ATTACHMENT; glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &attachment); } // Bind the original frame buffer to draw to screen and set the Viewport. glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFramebuffer); if(m_i32TexWidth != m_i32WinWidth || m_i32TexHeight != m_i32WinHeight) glViewport(0, 0, m_i32WinWidth, m_i32WinHeight); // Clear the color and depth buffers for the screen. glClear(GL_COLOR_BUFFER_BIT); // Uses PVRShell input handling to update the line width in the edge detection shaders. if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT)) { m_fLineWidth++; if (m_fLineWidth>10) m_fLineWidth=10; } if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT)) { m_fLineWidth--; if (m_fLineWidth<1) m_fLineWidth=1; } // Uses PVRShell input to choose which post shader program to use for post processing. // Loops through all shaders defined in EPostShaders if (PVRShellIsKeyPressed(PVRShellKeyNameUP)) { if (m_uiShaderID==eNumPostShaders-1) m_uiShaderID=0; else m_uiShaderID++; } else if (PVRShellIsKeyPressed(PVRShellKeyNameDOWN)) { if (m_uiShaderID==0) m_uiShaderID=eNumPostShaders-1; else m_uiShaderID--; } // Sets the shader based on the shader ID value, and sets the line width each frame (as it can change); glUseProgram(m_PostShaders[m_uiShaderID].uiId); glUniform2f(m_PostShaders[m_uiShaderID].auiLoc[ePixelSize],m_fLineWidth/(float)m_i32TexWidth,m_fLineWidth/(float)m_i32TexHeight); /* Note: We do not need to pass any projection data to these shaders as they are used only to render a texture to a full screen quad which is parallel with the viewport. The model meshes have already been positioned in the previous shader and now only exist as a 2D image.*/ // Enable texture attribute array glEnableVertexAttribArray(eTEXCOORD_ARRAY); // Draw the fullscreen quad to render the screen to. DrawQuad(); // Disable the vertex and texture attribute arrays glDisableVertexAttribArray(eTEXCOORD_ARRAY); glDisableVertexAttribArray(eVERTEX_ARRAY); // Print the demo title, current post shader's name and the line width if applicable m_Print3D.DisplayDefaultTitle("Edge Detection", "", ePVRTPrint3DSDKLogo); m_Print3D.Print3D(5,80,1,0xff885500,g_aszPostShaderNames[m_uiShaderID]); if (!strcmp(c_aszPostShaderDefines[m_uiShaderID][0],"EDGE_DETECTION")) m_Print3D.Print3D(5,90,0.7f,0xff000055,"Line Width = %i", (int)m_fLineWidth); m_Print3D.Flush(); return true; }