bool UniformHandler::isVisibleSphere(const PVRTVec3& v3Centre, const VERTTYPE fRadius) { // get in view space PVRTVec4 v4TransCentre = m_mWorldView * PVRTVec4(v3Centre,f2vt(1.0f)); // find clip space coord for centre v4TransCentre = m_mProjection * v4TransCentre; VERTTYPE fRadX,fRadY; // scale radius according to perspective if(m_bRotate) { fRadX = PVRTABS(VERTTYPEMUL(fRadius,m_mProjection(0,1))); fRadY = PVRTABS(VERTTYPEMUL(fRadius,m_mProjection(1,0))); } else { fRadX = PVRTABS(VERTTYPEMUL(fRadius,m_mProjection(0,0))); fRadY = PVRTABS(VERTTYPEMUL(fRadius,m_mProjection(1,1))); } VERTTYPE fRadZ = PVRTABS(VERTTYPEMUL(fRadius,m_mProjection(2,2))); // check if inside frustums // X if(v4TransCentre.x+fRadX<-v4TransCentre.w) { // 'right' side out to 'left' def out return false; } if(v4TransCentre.x-fRadX>v4TransCentre.w) { // 'left' side out to 'right' def out return false; } // Y if(v4TransCentre.y+fRadY<-v4TransCentre.w) { // 'up' side out to 'top' def out return false; } if(v4TransCentre.y-fRadY>v4TransCentre.w) { // 'down' side out to 'bottom' def out return false; } // Z if(v4TransCentre.z+fRadZ<-v4TransCentre.w) { // 'far' side out to 'back' def out return false; } if(v4TransCentre.z-fRadZ>v4TransCentre.w) { // 'near' side out to 'front' def out return false; } return true; }
/*!*************************************************************************** @Function PVRTMatrixQuaternionToAxisAngleX @Input qIn Quaternion to transform @Output vAxis Axis of rotation @Output fAngle Angle of rotation @Description Convert a quaternion to an axis and angle. Expects a unit quaternion. *****************************************************************************/ void PVRTMatrixQuaternionToAxisAngleX( const PVRTQUATERNIONx &qIn, PVRTVECTOR3x &vAxis, int &fAngle) { int fCosAngle, fSinAngle; int temp; /* Compute some values */ fCosAngle = qIn.w; temp = PVRTF2X(1.0f) - PVRTXMUL(fCosAngle, fCosAngle); fAngle = PVRTXMUL(PVRTXACOS(fCosAngle), PVRTF2X(2.0f)); fSinAngle = PVRTF2X(((float)sqrt(PVRTX2F(temp)))); /* This is to avoid a division by zero */ if (PVRTABS(fSinAngle)<PVRTF2X(0.0005f)) { fSinAngle = PVRTF2X(1.0f); } /* Get axis vector */ vAxis.x = PVRTXDIV(qIn.x, fSinAngle); vAxis.y = PVRTXDIV(qIn.y, fSinAngle); vAxis.z = PVRTXDIV(qIn.z, fSinAngle); }
/*!*************************************************************************** @Function PVRTMatrixQuaternionNormalizeX @Modified quat Vector to normalize @Description Normalize quaternion. Original quaternion is scaled down prior to be normalized in order to avoid overflow issues. *****************************************************************************/ void PVRTMatrixQuaternionNormalizeX(PVRTQUATERNIONx &quat) { PVRTQUATERNIONx qTemp; int f, n; /* Scale vector by uniform value */ n = PVRTABS(quat.w) + PVRTABS(quat.x) + PVRTABS(quat.y) + PVRTABS(quat.z); qTemp.w = PVRTXDIV(quat.w, n); qTemp.x = PVRTXDIV(quat.x, n); qTemp.y = PVRTXDIV(quat.y, n); qTemp.z = PVRTXDIV(quat.z, n); /* Compute quaternion magnitude */ f = PVRTXMUL(qTemp.w, qTemp.w) + PVRTXMUL(qTemp.x, qTemp.x) + PVRTXMUL(qTemp.y, qTemp.y) + PVRTXMUL(qTemp.z, qTemp.z); f = PVRTXDIV(PVRTF2X(1.0f), PVRTF2X(sqrt(PVRTX2F(f)))); /* Multiply vector components by f */ quat.x = PVRTXMUL(qTemp.x, f); quat.y = PVRTXMUL(qTemp.y, f); quat.z = PVRTXMUL(qTemp.z, f); quat.w = PVRTXMUL(qTemp.w, f); }
/*!*************************************************************************** @Function PVRTMatrixVec3NormalizeX @Output vOut Normalized vector @Input vIn Vector to normalize @Description Normalizes the supplied vector. The square root function is currently still performed in floating-point. Original vector is scaled down prior to be normalized in order to avoid overflow issues. ****************************************************************************/ void PVRTMatrixVec3NormalizeX( PVRTVECTOR3x &vOut, const PVRTVECTOR3x &vIn) { int f, n; PVRTVECTOR3x vTemp; /* Scale vector by uniform value */ n = PVRTABS(vIn.x) + PVRTABS(vIn.y) + PVRTABS(vIn.z); vTemp.x = PVRTXDIV(vIn.x, n); vTemp.y = PVRTXDIV(vIn.y, n); vTemp.z = PVRTXDIV(vIn.z, n); /* Calculate x2+y2+z2/sqrt(x2+y2+z2) */ f = PVRTMatrixVec3DotProductX(vTemp, vTemp); f = PVRTXDIV(PVRTF2X(1.0f), PVRTF2X(sqrt(PVRTX2F(f)))); /* Multiply vector components by f */ vOut.x = PVRTXMUL(vTemp.x, f); vOut.y = PVRTXMUL(vTemp.y, f); vOut.z = PVRTXMUL(vTemp.z, f); }
/*!*************************************************************************** @Function PVRTMatrixInverseF @Output mOut Inversed matrix @Input mIn Original matrix @Description Compute the inverse matrix of mIn. The matrix must be of the form : A 0 C 1 Where A is a 3x3 matrix and C is a 1x3 matrix. *****************************************************************************/ void PVRTMatrixInverseF( PVRTMATRIXf &mOut, const PVRTMATRIXf &mIn) { PVRTMATRIXf mDummyMatrix; double det_1; double pos, neg, temp; /* Calculate the determinant of submatrix A and determine if the the matrix is singular as limited by the double precision floating-point data representation. */ pos = neg = 0.0; temp = mIn.f[ 0] * mIn.f[ 5] * mIn.f[10]; if (temp >= 0.0) pos += temp; else neg += temp; temp = mIn.f[ 4] * mIn.f[ 9] * mIn.f[ 2]; if (temp >= 0.0) pos += temp; else neg += temp; temp = mIn.f[ 8] * mIn.f[ 1] * mIn.f[ 6]; if (temp >= 0.0) pos += temp; else neg += temp; temp = -mIn.f[ 8] * mIn.f[ 5] * mIn.f[ 2]; if (temp >= 0.0) pos += temp; else neg += temp; temp = -mIn.f[ 4] * mIn.f[ 1] * mIn.f[10]; if (temp >= 0.0) pos += temp; else neg += temp; temp = -mIn.f[ 0] * mIn.f[ 9] * mIn.f[ 6]; if (temp >= 0.0) pos += temp; else neg += temp; det_1 = pos + neg; /* Is the submatrix A singular? */ if ((det_1 == 0.0) || (PVRTABS(det_1 / (pos - neg)) < 1.0e-15)) { /* Matrix M has no inverse */ _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n"); return; } else { /* Calculate inverse(A) = adj(A) / det(A) */ det_1 = 1.0 / det_1; mDummyMatrix.f[ 0] = ( mIn.f[ 5] * mIn.f[10] - mIn.f[ 9] * mIn.f[ 6] ) * (float)det_1; mDummyMatrix.f[ 1] = - ( mIn.f[ 1] * mIn.f[10] - mIn.f[ 9] * mIn.f[ 2] ) * (float)det_1; mDummyMatrix.f[ 2] = ( mIn.f[ 1] * mIn.f[ 6] - mIn.f[ 5] * mIn.f[ 2] ) * (float)det_1; mDummyMatrix.f[ 4] = - ( mIn.f[ 4] * mIn.f[10] - mIn.f[ 8] * mIn.f[ 6] ) * (float)det_1; mDummyMatrix.f[ 5] = ( mIn.f[ 0] * mIn.f[10] - mIn.f[ 8] * mIn.f[ 2] ) * (float)det_1; mDummyMatrix.f[ 6] = - ( mIn.f[ 0] * mIn.f[ 6] - mIn.f[ 4] * mIn.f[ 2] ) * (float)det_1; mDummyMatrix.f[ 8] = ( mIn.f[ 4] * mIn.f[ 9] - mIn.f[ 8] * mIn.f[ 5] ) * (float)det_1; mDummyMatrix.f[ 9] = - ( mIn.f[ 0] * mIn.f[ 9] - mIn.f[ 8] * mIn.f[ 1] ) * (float)det_1; mDummyMatrix.f[10] = ( mIn.f[ 0] * mIn.f[ 5] - mIn.f[ 4] * mIn.f[ 1] ) * (float)det_1; /* Calculate -C * inverse(A) */ mDummyMatrix.f[12] = - ( mIn.f[12] * mDummyMatrix.f[ 0] + mIn.f[13] * mDummyMatrix.f[ 4] + mIn.f[14] * mDummyMatrix.f[ 8] ); mDummyMatrix.f[13] = - ( mIn.f[12] * mDummyMatrix.f[ 1] + mIn.f[13] * mDummyMatrix.f[ 5] + mIn.f[14] * mDummyMatrix.f[ 9] ); mDummyMatrix.f[14] = - ( mIn.f[12] * mDummyMatrix.f[ 2] + mIn.f[13] * mDummyMatrix.f[ 6] + mIn.f[14] * mDummyMatrix.f[10] ); /* Fill in last row */ mDummyMatrix.f[ 3] = 0.0f; mDummyMatrix.f[ 7] = 0.0f; mDummyMatrix.f[11] = 0.0f; mDummyMatrix.f[15] = 1.0f; } /* Copy contents of dummy matrix in pfMatrix */ mOut = mDummyMatrix; }
/*!**************************************************************************** @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 OGLES2ChameleonMan::RenderScene() { // Clear the color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Use shader program glUseProgram(m_SkinnedShaderProgram.uiId); if(PVRShellIsKeyPressed(PVRShellKeyNameACTION1)) { m_bEnableDOT3 = !m_bEnableDOT3; glUniform1i(m_SkinnedShaderProgram.auiLoc[ebUseDot3], m_bEnableDOT3); } /* 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(iTime > m_iTimePrev) { float fDelta = (float) (iTime - m_iTimePrev); m_fFrame += fDelta * g_fDemoFrameRate; // Increment the counters to make sure our animation works m_fLightPos += fDelta * 0.0034f; m_fWallPos += fDelta * 0.00027f; m_fBackgroundPos += fDelta * -0.000027f; // Wrap the Animation back to the Start if(m_fLightPos >= PVRT_TWO_PI) m_fLightPos -= PVRT_TWO_PI; if(m_fWallPos >= PVRT_TWO_PI) m_fWallPos -= PVRT_TWO_PI; if(m_fBackgroundPos <= 0) m_fBackgroundPos += 1.0f; if(m_fFrame > m_Scene.nNumFrame - 1) m_fFrame = 0; } m_iTimePrev = iTime; // Set the scene animation to the current frame m_Scene.SetFrame(m_fFrame); // Set up camera PVRTVec3 vFrom, vTo, vUp(0.0f, 1.0f, 0.0f); PVRTMat4 mView, mProjection; PVRTVec3 LightPos; float fFOV; int i; bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); // Get the camera position, target and field of view (fov) if(m_Scene.pCamera[0].nIdxTarget != -1) // Does the camera have a target? fFOV = m_Scene.GetCameraPos( vFrom, vTo, 0); // vTo is taken from the target node else fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, 0); // vTo is calculated from the rotation fFOV *= bRotate ? (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight) : (float)PVRShellGet(prefHeight)/(float)PVRShellGet(prefWidth); /* 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 mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate); // Update Light Position and related VGP Program constant LightPos.x = 200.0f; LightPos.y = 350.0f; LightPos.z = 200.0f * PVRTABS(sin((PVRT_PI / 4.0f) + m_fLightPos)); glUniform3fv(m_SkinnedShaderProgram.auiLoc[eLightPos], 1, LightPos.ptr()); // Set up the View * Projection Matrix PVRTMat4 mViewProjection; mViewProjection = mProjection * mView; glUniformMatrix4fv(m_SkinnedShaderProgram.auiLoc[eViewProj], 1, GL_FALSE, mViewProjection.ptr()); // Enable the vertex attribute arrays for(i = 0; i < eNumAttribs; ++i) glEnableVertexAttribArray(i); // Draw skinned meshes for(unsigned int i32NodeIndex = 0; i32NodeIndex < 3; ++i32NodeIndex) { // Bind correct texture switch(i32NodeIndex) { case eBody: glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, m_ui32TexHeadNormalMap); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_ui32TexHeadBody); break; case eLegs: glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, m_ui32TexLegsNormalMap); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_ui32TexLegs); break; default: glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, m_ui32TexBeltNormalMap); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_ui32TexBelt); break; } DrawSkinnedMesh(i32NodeIndex); } // Safely disable the vertex attribute arrays for(i = 0; i < eNumAttribs; ++i) glDisableVertexAttribArray(i); // Draw non-skinned meshes glUseProgram(m_DefaultShaderProgram.uiId); // Enable the vertex attribute arrays for(i = 0; i < eNumDefaultAttribs; ++i) glEnableVertexAttribArray(i); for(unsigned int i32NodeIndex = 3; i32NodeIndex < m_Scene.nNumMeshNode; ++i32NodeIndex) { SPODNode& Node = m_Scene.pNode[i32NodeIndex]; SPODMesh& Mesh = m_Scene.pMesh[Node.nIdx]; // bind the VBO for the mesh glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[Node.nIdx]); // bind the index buffer, won't hurt if the handle is 0 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[Node.nIdx]); // Get the node model matrix PVRTMat4 mWorld; mWorld = m_Scene.GetWorldMatrix(Node); // Setup the appropriate texture and transformation (if needed) switch(i32NodeIndex) { case eWall: glBindTexture(GL_TEXTURE_2D, m_ui32TexWall); // Rotate the wall mesh which is circular mWorld *= PVRTMat4::RotationY(m_fWallPos); glUniform1f(m_DefaultShaderProgram.auiLoc[eDefaultUOffset], 0); break; case eBackground: glBindTexture(GL_TEXTURE_2D, m_ui32TexSkyLine); glUniform1f(m_DefaultShaderProgram.auiLoc[eDefaultUOffset], m_fBackgroundPos); break; case eLights: { glBindTexture(GL_TEXTURE_2D, m_ui32TexLamp); PVRTMat4 mWallWorld = m_Scene.GetWorldMatrix(m_Scene.pNode[eWall]); mWorld = mWallWorld * PVRTMat4::RotationY(m_fWallPos) * mWallWorld.inverse() * mWorld; glUniform1f(m_DefaultShaderProgram.auiLoc[eDefaultUOffset], 0); } break; default: break; }; // Set up shader uniforms PVRTMat4 mModelViewProj; mModelViewProj = mViewProjection * mWorld; glUniformMatrix4fv(m_DefaultShaderProgram.auiLoc[eDefaultMVPMatrix], 1, GL_FALSE, mModelViewProj.ptr()); // Set the vertex attribute offsets glVertexAttribPointer(DEFAULT_VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sVertex.nStride, Mesh.sVertex.pData); glVertexAttribPointer(DEFAULT_TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, Mesh.psUVW[0].nStride, Mesh.psUVW[0].pData); // Indexed Triangle list glDrawElements(GL_TRIANGLES, Mesh.nNumFaces*3, GL_UNSIGNED_SHORT, 0); } // Safely disable the vertex attribute arrays for(i = 0; i < eNumAttribs; ++i) glDisableVertexAttribArray(i); // unbind the VBOs glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Display the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools const char * pDescription; if(m_bEnableDOT3) pDescription = "Skinning with DOT3 Per Pixel Lighting"; else pDescription = "Skinning with Vertex Lighting"; m_Print3D.DisplayDefaultTitle("Chameleon Man", pDescription, ePVRTPrint3DSDKLogo); m_Print3D.Flush(); 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 OGLESPolybump::RenderScene() { if(PVRShellIsKeyPressed(PVRShellKeyNameACTION1)) m_bDrawWithDot3 = !m_bDrawWithDot3; PVRTVec4 LightVector; PVRTMat4 mRotateY, mModelView; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); LightVector.x = PVRTSIN(m_i32Frame / 40.0f); LightVector.y = 0.0f; LightVector.z = -PVRTABS(PVRTCOS(m_i32Frame / 40.0f)); LightVector.w = 0.0f; PVRTTransformBack(&LightVector, &LightVector, &m_mView); // Normalize light vector in case it is not LightVector.normalize(); if(m_bDrawWithDot3) { // Setup texture blend modes // First layer (Dot3) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_ui32CloneMap); if(m_bCombinersPresent) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); } else if(m_bIMGTextureFFExtPresent) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DOT3_RGBA); } // Second layer (modulate) glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_ui32DiffuseMap); if(m_bCombinersPresent) { glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); } else if (m_bIMGTextureFFExtPresent) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } // Calculate Dot3 light direction CalculateDot3LightDirection(LightVector); } else { glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_ui32DiffuseMap); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); LightVector.z = -LightVector.z; glLightfv(GL_LIGHT0, GL_POSITION, &LightVector.x); } glMatrixMode(GL_MODELVIEW); // Render mesh SPODNode& Node = m_Scene.pNode[0]; // Rotate the mesh around a point mModelView = m_mView * PVRTMat4::RotationY((float) sin(m_i32Frame * 0.003f) - PVRT_PI_OVER_TWOf); glLoadMatrixf(mModelView.f); DrawMesh(Node.nIdx); // Disable the second layer of texturing if(m_bDrawWithDot3) { glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); } else glDisable(GL_LIGHTING); // Display info text m_Print3D.DisplayDefaultTitle("PolyBump", m_bDrawWithDot3 ? m_pDescription : "Standard GL lighting" , ePVRTPrint3DSDKLogo); m_Print3D.Flush(); // Increase frame counter ++m_i32Frame; return true; }