/*!*************************************************************************** @Function Name PVRTMatrixRotationZF @Output mOut Rotation matrix @Input fAngle Angle of the rotation @Description Create an Z rotation matrix mOut. *****************************************************************************/ void PVRTMatrixRotationZF( PVRTMATRIXf &mOut, const float fAngle) { float fCosine, fSine; /* Precompute cos and sin */ #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10) fCosine = (float)PVRTFCOS(-fAngle); fSine = (float)PVRTFSIN(-fAngle); #else fCosine = (float)PVRTFCOS(fAngle); fSine = (float)PVRTFSIN(fAngle); #endif /* Create the trigonometric matrix corresponding to Z Rotation */ mOut.f[ 0]=fCosine; mOut.f[ 4]=fSine; mOut.f[ 8]=0.0f; mOut.f[12]=0.0f; mOut.f[ 1]=-fSine; mOut.f[ 5]=fCosine; mOut.f[ 9]=0.0f; mOut.f[13]=0.0f; mOut.f[ 2]=0.0f; mOut.f[ 6]=0.0f; mOut.f[10]=1.0f; mOut.f[14]=0.0f; mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; }
/*!*************************************************************************** @Function PVRTMatrixQuaternionRotationAxisF @Output qOut Rotation quaternion @Input vAxis Axis to rotate around @Input fAngle Angle to rotate @Description Create quaternion corresponding to a rotation of fAngle radians around submitted vector. *****************************************************************************/ void PVRTMatrixQuaternionRotationAxisF( PVRTQUATERNIONf &qOut, const PVRTVECTOR3f &vAxis, const float fAngle) { float fSin, fCos; fSin = (float)PVRTFSIN(fAngle * 0.5f); fCos = (float)PVRTFCOS(fAngle * 0.5f); /* Create quaternion */ qOut.x = vAxis.x * fSin; qOut.y = vAxis.y * fSin; qOut.z = vAxis.z * fSin; qOut.w = fCos; /* Normalise it */ PVRTMatrixQuaternionNormalizeF(qOut); }
/*!**************************************************************************** @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 OGLESParticles::RenderScene() { int i; PVRTMat4 mRotY; // Clear colour and depth buffers myglClearColor(f2vt(0.0f), f2vt(0.0f), f2vt(0.0f), f2vt(1.0f)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Enables depth testing glEnable(GL_DEPTH_TEST); // Modify per-frame variables controlling the particle mouvements. float fSpeedCtrl = (float) (PVRTFSIN(m_fRot*0.01f)+1.0f)/2.0f; float fStopNo = 0.8f; float fStep = 0.1f; if(fSpeedCtrl > fStopNo) fStep = 0.0f; // Generate particles as needed. if((m_i32NumParticles < (int) g_ui32MaxParticles) && (fSpeedCtrl <= fStopNo)) { int num_to_gen = (int) (RandPositiveFloat()*(g_ui32MaxParticles/100.0)); if(num_to_gen == 0) num_to_gen = 1; for(i = 0; (i < num_to_gen) && (m_i32NumParticles < (int) g_ui32MaxParticles); ++i) SpawnParticle(&m_Particles[m_i32NumParticles++]); } // Build rotation matrix around axis Y. mRotY = PVRTMat4::RotationY(f2vt((m_fRot2*PVRT_PIf)/180.0f)); for(i = 0; i < m_i32NumParticles; ++i) { // Transform particle with rotation matrix m_sParticleVTXPSBuf[i].x = VERTTYPEMUL(mRotY.f[ 0], m_Particles[i].m_fPosition.x) + VERTTYPEMUL(mRotY.f[ 4], m_Particles[i].m_fPosition.y) + VERTTYPEMUL(mRotY.f[ 8], m_Particles[i].m_fPosition.z) + mRotY.f[12]; m_sParticleVTXPSBuf[i].y = VERTTYPEMUL(mRotY.f[ 1], m_Particles[i].m_fPosition.x) + VERTTYPEMUL(mRotY.f[ 5], m_Particles[i].m_fPosition.y) + VERTTYPEMUL(mRotY.f[ 9], m_Particles[i].m_fPosition.z) + mRotY.f[13]; m_sParticleVTXPSBuf[i].z = VERTTYPEMUL(mRotY.f[ 2], m_Particles[i].m_fPosition.x) + VERTTYPEMUL(mRotY.f[ 6], m_Particles[i].m_fPosition.y) + VERTTYPEMUL(mRotY.f[10], m_Particles[i].m_fPosition.z) + mRotY.f[14]; m_sParticleVTXPSBuf[i].fSize = m_Particles[i].m_fSize; m_sNormalColour[i].r = vt2b(m_Particles[i].m_fColour.x); m_sNormalColour[i].g = vt2b(m_Particles[i].m_fColour.y); m_sNormalColour[i].b = vt2b(m_Particles[i].m_fColour.z); m_sNormalColour[i].a = (unsigned char)255; m_sReflectColour[i].r = vt2b(VERTTYPEMUL(m_Particles[i].m_fColour.x, g_fFactor)); m_sReflectColour[i].g = vt2b(VERTTYPEMUL(m_Particles[i].m_fColour.y, g_fFactor)); m_sReflectColour[i].b = vt2b(VERTTYPEMUL(m_Particles[i].m_fColour.z, g_fFactor)); m_sReflectColour[i].a = (unsigned char)255; } glBindBuffer(GL_ARRAY_BUFFER, m_i32VertVboID); glBufferData(GL_ARRAY_BUFFER, sizeof(SVtxPointSprite)*m_i32NumParticles, m_sParticleVTXPSBuf,GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, m_i32ColAVboID); glBufferData(GL_ARRAY_BUFFER, sizeof(SColors)*m_i32NumParticles, m_sNormalColour,GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, m_i32ColBVboID); glBufferData(GL_ARRAY_BUFFER, sizeof(SColors)*m_i32NumParticles, m_sReflectColour,GL_DYNAMIC_DRAW); // clean up render states glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); // Draw floor. // Save modelview matrix glMatrixMode(GL_MODELVIEW); glPushMatrix(); myglRotate(f2vt(-m_fRot), f2vt(0.0f), f2vt(1.0f), f2vt(0.0f)); // setup render states glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); // Set texture and texture environment glBindTexture(GL_TEXTURE_2D, m_ui32FloorTexName); glBlendFunc(GL_ONE, GL_ONE); // Render floor RenderFloor(); // clean up render states glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glPopMatrix(); // Render particles reflections. // set up render states glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); myglTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBindTexture(GL_TEXTURE_2D, m_ui32TexName); // Set model view matrix glMatrixMode(GL_MODELVIEW); glPushMatrix(); myglScale(f2vt(1.0f), f2vt(-1.0f), f2vt(1.0f)); myglTranslate(f2vt(0.0f), f2vt(0.01f), f2vt(0.0f)); glEnable(GL_POINT_SPRITE_OES); if(((int)(m_i32NumParticles * 0.5f)) > 0) RenderParticle(((int)(m_i32NumParticles*0.5f)),true); glPopMatrix(); // Render particles. // Sets the model view matrix glMatrixMode(GL_MODELVIEW); glPushMatrix(); if(m_i32NumParticles > 0) RenderParticle(m_i32NumParticles,false); glPopMatrix(); glDisable(GL_POINT_SPRITE_OES); PVRTVec3 Force = PVRTVec3(f2vt(0.0f), f2vt(0.0f), f2vt(0.0f)); Force.x = f2vt(1000.0f*(float)PVRTFSIN(m_fRot*0.01f)); for(i = 0; i < m_i32NumParticles; ++i) { /* Move the particle. If the particle exceeds its lifetime, create a new one in its place. */ if(m_Particles[i].Step(f2vt(fStep), Force)) SpawnParticle(&m_Particles[i]); } // clean up render states glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); // Increase rotation angles m_fRot += 1; m_fRot2 = m_fRot + 36; // Unbinds the vertex buffer if we are using OpenGL ES 1.1 glBindBuffer(GL_ARRAY_BUFFER, 0); // Display info text. m_Print3D.DisplayDefaultTitle("Particles", "Using point sprites", ePVRTPrint3DSDKLogo); m_Print3D.Flush(); return true; }
/*!*************************************************************************** @Function PVRTMatrixQuaternionSlerpF @Output qOut Result of the interpolation @Input qA First quaternion to interpolate from @Input qB Second quaternion to interpolate from @Input t Coefficient of interpolation @Description Perform a Spherical Linear intERPolation between quaternion A and quaternion B at time t. t must be between 0.0f and 1.0f *****************************************************************************/ void PVRTMatrixQuaternionSlerpF( PVRTQUATERNIONf &qOut, const PVRTQUATERNIONf &qA, const PVRTQUATERNIONf &qB, const float t) { float fCosine, fAngle, A, B; /* Parameter checking */ if (t<0.0f || t>1.0f) { _RPT0(_CRT_WARN, "PVRTMatrixQuaternionSlerp : Bad parameters\n"); qOut.x = 0; qOut.y = 0; qOut.z = 0; qOut.w = 1; return; } /* Find sine of Angle between Quaternion A and B (dot product between quaternion A and B) */ fCosine = qA.w*qB.w + qA.x*qB.x + qA.y*qB.y + qA.z*qB.z; if (fCosine < 0) { PVRTQUATERNIONf qi; /* <http://www.magic-software.com/Documentation/Quaternions.pdf> "It is important to note that the quaternions q and -q represent the same rotation... while either quaternion will do, the interpolation methods require choosing one over the other. "Although q1 and -q1 represent the same rotation, the values of Slerp(t; q0, q1) and Slerp(t; q0,-q1) are not the same. It is customary to choose the sign... on q1 so that... the angle between q0 and q1 is acute. This choice avoids extra spinning caused by the interpolated rotations." */ qi.x = -qB.x; qi.y = -qB.y; qi.z = -qB.z; qi.w = -qB.w; PVRTMatrixQuaternionSlerpF(qOut, qA, qi, t); return; } fCosine = PVRT_MIN(fCosine, 1.0f); fAngle = (float)PVRTFACOS(fCosine); /* Avoid a division by zero */ if (fAngle==0.0f) { qOut = qA; return; } /* Precompute some values */ A = (float)(PVRTFSIN((1.0f-t)*fAngle) / PVRTFSIN(fAngle)); B = (float)(PVRTFSIN(t*fAngle) / PVRTFSIN(fAngle)); /* Compute resulting quaternion */ qOut.x = A * qA.x + B * qB.x; qOut.y = A * qA.y + B * qB.y; qOut.z = A * qA.z + B * qB.z; qOut.w = A * qA.w + B * qB.w; /* Normalise result */ PVRTMatrixQuaternionNormalizeF(qOut); }