|
S60 3rd Edition SDK for Symbian OS Example Applications Guide |
00001 /* 00002 * ============================================================================== 00003 * Name : MultiTex.cpp 00004 * Part of : OpenGLEx / MultiTex 00005 * Interface : 00006 * Description : 00007 * Version : 00008 * 00009 * Copyright (c) 2004-2006 Nokia Corporation. 00010 * This material, including documentation and any related 00011 * computer programs, is protected by copyright controlled by 00012 * Nokia Corporation. 00013 * ============================================================================== 00014 */ 00015 00016 00017 // INCLUDE FILES 00018 #include <e32std.h> 00019 #include <e32math.h> 00020 #include "MultiTex.h" 00021 #include "MultiTexContainer.h" // For accessing the contexts etc. 00022 #include "model.h" 00023 00024 // CONSTANTS 00025 00026 /* Define vertice coordinates for the triangles */ 00027 static const GLbyte LightVertices[8 * 3] = 00028 { 00029 -10, 10, 0, 00030 -10, -10, 0, 00031 10, 10, 0, 00032 10, -10, 0, 00033 00034 -10, 10, 0, 00035 -10, -10, 0, 00036 10, 10, 0, 00037 10, -10, 0 00038 }; 00039 00040 00041 /* Macro for changing the input texture coordinate values from 00042 GLubyte [0,255] to GLbyte [-128,127]. See more info below. */ 00043 #define tex(u,v) (GLbyte)( (u) - 128 ) , (GLbyte)( (v) - 128 ) 00044 00045 static const GLbyte LightTexCoords[8 * 2] = 00046 { 00047 // Red light 00048 tex(0,0), 00049 tex(0,255), 00050 tex(127,0), 00051 tex(127,255), 00052 00053 // Green light 00054 tex(127,0), 00055 tex(127,255), 00056 tex(255,0), 00057 tex(255,255) 00058 }; 00059 00060 00061 // ============================= LOCAL FUNCTIONS =============================== 00062 00063 // ----------------------------------------------------------------------------- 00064 // sin 00065 // ----------------------------------------------------------------------------- 00066 GLfloat sin( GLfloat aRad ) 00067 { 00068 TReal trg, src = (TReal)aRad; 00069 if ( Math::Sin(trg, src) == KErrNone ) 00070 { 00071 return (GLfloat)trg; 00072 } 00073 return 0; 00074 } 00075 00076 // ----------------------------------------------------------------------------- 00077 // cos 00078 // ----------------------------------------------------------------------------- 00079 GLfloat cos( GLfloat aRad ) 00080 { 00081 TReal trg, src = (TReal)aRad; 00082 if ( Math::Cos(trg, src) == KErrNone ) 00083 { 00084 return (GLfloat)trg; 00085 } 00086 return 0; 00087 } 00088 00089 00090 // ============================ MEMBER FUNCTIONS =============================== 00091 00092 // ----------------------------------------------------------------------------- 00093 // CMultiTex::NewL 00094 // 00095 // The usual Symbian NewL implementation. 00096 // Creates the object, pushes it to cleanup stack and calls ContructL. 00097 // Returns the contructed object or leaves. 00098 // ----------------------------------------------------------------------------- 00099 // 00100 00101 CMultiTex* CMultiTex::NewL( TUint aWidth, TUint aHeight ) 00102 { 00103 /* Symbian 2-phase constructor. Calls both the default 00104 C++ constructor and Symbian ConstructL methods */ 00105 CMultiTex* self = new (ELeave) CMultiTex( aWidth, aHeight ); 00106 CleanupStack::PushL( self ); 00107 self->ConstructL(); 00108 CleanupStack::Pop(); 00109 00110 return self; 00111 } 00112 00113 // ----------------------------------------------------------------------------- 00114 // CMultiTex::CMultiTex 00115 // 00116 // C++ constructor. Initializes the size instance variables from arguments. 00117 // ----------------------------------------------------------------------------- 00118 // 00119 00120 CMultiTex::CMultiTex( TUint aWidth, TUint aHeight ) : 00121 CFiniteStateMachine(), 00122 iScreenWidth( aWidth ), 00123 iScreenHeight( aHeight ) 00124 { 00125 if ( iScreenHeight != 0 ) 00126 { 00127 iAspectRatio = (GLfloat)iScreenWidth / (GLfloat)iScreenHeight; 00128 } 00129 else 00130 { 00131 iAspectRatio = 1.0; 00132 } 00133 iCameraDistance = 200; 00134 } 00135 00136 // ----------------------------------------------------------------------------- 00137 // CMultiTex::~CMultiTex 00138 // 00139 // C++ destructor. 00140 // ----------------------------------------------------------------------------- 00141 // 00142 00143 CMultiTex::~CMultiTex() 00144 { 00145 } 00146 00147 // ----------------------------------------------------------------------------- 00148 // CMultiTex::ConstructL 00149 // 00150 // 2nd phase constructor. 00151 // ----------------------------------------------------------------------------- 00152 // 00153 00154 void CMultiTex::ConstructL( void ) 00155 { 00156 } 00157 00158 // ----------------------------------------------------------------------------- 00159 // CMultiTex::CalculateEnvLightsL 00160 // 00161 // Texture map consist of two lights: red and green. 00162 // Alpha is calculated so that is gradually goes from 255 to zero starting 00163 // from the center of the spotlight. 00164 // ----------------------------------------------------------------------------- 00165 // 00166 void CMultiTex::CalculateLightsL( void ) 00167 { 00168 // Reserve memory for light texture 00169 iLightTex = new (ELeave) TUint8[64*32*4]; 00170 if ( !iLightTex ) 00171 { 00172 User::LeaveNoMemory(); 00173 } 00174 00175 TInt d = 0; // distance from the center of the spot 00176 GLfloat alpha = 0.f; // alpha value 00177 00178 for ( TInt i = 0; i < 32; i++ ) 00179 { 00180 for ( TInt j = 0; j < 32; j++ ) 00181 { 00182 // distance from the center of spotlight 00183 d = (i-16)*(i-16) + (j-16)*(j-16); 00184 00185 // simple linear attenuation used for alpha 00186 alpha = 255.f*(1.f-(1.f/250.f)*(GLfloat)(d)); 00187 00188 // alpha < 0 corresponds to spotlight cut-off value 00189 if ( alpha < 0.f ) 00190 { 00191 iLightTex[64*4*i+4*j] = 255; //r 00192 iLightTex[64*4*i+4*j+1] = 0; //g 00193 iLightTex[64*4*i+4*j+2] = 0; //b 00194 iLightTex[64*4*i+4*j+3] = 0; //a 00195 00196 iLightTex[64*4*i+4*j+32*4] = 0; //r 00197 iLightTex[64*4*i+4*j+1+32*4] = 255; //g 00198 iLightTex[64*4*i+4*j+2+32*4] = 0; //b 00199 iLightTex[64*4*i+4*j+3+32*4] = 0; //a 00200 } 00201 // inside the cut-off, set alpha as calculated above/ 00202 else 00203 { 00204 iLightTex[64*4*i+4*j] = 255; //r 00205 iLightTex[64*4*i+4*j+1] = 0; //g 00206 iLightTex[64*4*i+4*j+2] = 0; //b 00207 iLightTex[64*4*i+4*j+3] = (GLubyte)(alpha); //a 00208 00209 iLightTex[64*4*i+4*j+32*4] = 0; //r 00210 iLightTex[64*4*i+4*j+1+32*4] = 255; //g 00211 iLightTex[64*4*i+4*j+2+32*4] = 0; //b 00212 iLightTex[64*4*i+4*j+3+32*4] = (GLubyte)(alpha); //a 00213 } 00214 } 00215 } 00216 } 00217 00218 00219 // ----------------------------------------------------------------------------- 00220 // CMultiTex::AppInit 00221 // 00222 // Initializes OpenGL ES, sets the vertex and color arrays and pointers, 00223 // and selects the shading mode. 00224 // ----------------------------------------------------------------------------- 00225 // 00226 00227 void CMultiTex::AppInitL( TAny* aInstance ) 00228 { 00229 00230 CMultiTexContainer* instance = (CMultiTexContainer*) aInstance; 00231 00232 /*=========================================================================*/ 00233 /*===================== Initialize Pbuffer context ========================*/ 00234 /*=========================================================================*/ 00235 00236 /* Bind the pbuffer context to the current rendering thread and surface.*/ 00237 eglMakeCurrent( instance->iEglDisplay, instance->iEglPbufferSurface, 00238 instance->iEglPbufferSurface, instance->iEglPbufferContext ); 00239 00240 /* Create light texture map */ 00241 CalculateLightsL(); 00242 const GLvoid *texPtr = iLightTex; 00243 00244 // Set the screen background color (black). 00245 glClearColor( 0.f, 0.f, 0.f, 1.f ); 00246 00247 // Initialize viewport and projection. 00248 glViewport( 0, 0, 128, 128 ); 00249 glMatrixMode( GL_PROJECTION ); 00250 glFrustumf( -1.f, 1.f, -1.f, 1.f, 3.f, 1000.f ); 00251 00252 /* Initialize appropriate texture matrix. First we have to translate the 00253 input texture coordinate values to be within a range of [0,255]. Hence 00254 we translate the x- and y-coordinate values by 128. Recall that the 00255 values in nokTexCoords are between [-128,127], now they are in a range 00256 of [0,255]. After that we scale the values by 1/255 to make the values 00257 to be in range [0,1]. */ 00258 glMatrixMode( GL_TEXTURE ); 00259 glLoadIdentity(); 00260 glScalef( 1.0f/255.0f, 1.0f/255.0f, 1.0f ); 00261 glTranslatef( 128.0f, 128.0f, 0.0f ); 00262 00263 // Remember to change the matrix mode to modelview. 00264 glMatrixMode( GL_MODELVIEW ); 00265 00266 // Enable back face culling, texturing and blending. 00267 glEnable( GL_CULL_FACE ); 00268 glEnable( GL_TEXTURE_2D ); 00269 glEnable( GL_BLEND ); 00270 glBlendFunc( GL_SRC_ALPHA, GL_ONE ); 00271 00272 // Enable vertex arrays. 00273 glEnableClientState( GL_VERTEX_ARRAY ); 00274 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 00275 00276 // Set array pointers. 00277 glVertexPointer( 3, GL_BYTE, 0, LightVertices ); 00278 glTexCoordPointer( 2, GL_BYTE, 0, LightTexCoords ); 00279 00280 // Set the initial shading mode 00281 glShadeModel( GL_FLAT ); 00282 00283 /* Create texture names */ 00284 glGenTextures( 2, iLightTexObjects ); 00285 00286 // Bind and set the light texture. 00287 glBindTexture( GL_TEXTURE_2D, iLightTexObjects[0] ); 00288 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 32, 00289 0, GL_RGBA, GL_UNSIGNED_BYTE, texPtr ); 00290 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); 00291 00292 /* We can now free the memory reserved for light texture, 00293 since it's loaded inside OpenGL ES */ 00294 delete[] iLightTex; 00295 iLightTex = NULL; 00296 00297 /* Bind and set the environment map texture. We pass NULL as pixels, 00298 since we use glCopyTexImage2D later to initialize the texture memory. */ 00299 glBindTexture( GL_TEXTURE_2D, iLightTexObjects[1] ); 00300 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 00301 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); 00302 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 00303 00304 // Do not use perspective correction 00305 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); 00306 00307 00308 /*=========================================================================*/ 00309 /*====================== Initialize Window context ========================*/ 00310 /*=========================================================================*/ 00311 00312 00313 // Bind the Window context to the current rendering thread and surface. 00314 eglMakeCurrent( instance->iEglDisplay, instance->iEglSurface, 00315 instance->iEglSurface, instance->iEglContext ); 00316 00317 // Set the screen background color. 00318 glClearColor( 0.f, 0.f, 0.4f, 1.f ); 00319 00320 /* Enable depth testing and back face culling. */ 00321 glEnable( GL_DEPTH_TEST ); 00322 glEnable( GL_CULL_FACE ); 00323 glEnable( GL_TEXTURE_2D ); 00324 00325 // Initialize viewport and projection. 00326 glViewport( 0, 0, iScreenWidth, iScreenHeight ); 00327 glMatrixMode( GL_PROJECTION ); 00328 00329 // Calculate the view frustrum 00330 glFrustumf( FRUSTUM_LEFT * iAspectRatio, FRUSTUM_RIGHT * iAspectRatio, 00331 FRUSTUM_BOTTOM, FRUSTUM_TOP, 00332 FRUSTUM_NEAR, FRUSTUM_FAR ); 00333 00334 00335 // Initialize appropriate texture matrix 00336 glMatrixMode( GL_TEXTURE ); 00337 glLoadIdentity(); 00338 glScalef( 1.0f/32767.0f, 1.0f/32767.0f, 1.0f ); 00339 00340 // Remember to change the matrix mode to modelview. 00341 glMatrixMode( GL_MODELVIEW ); 00342 00343 // Set shading mode 00344 glShadeModel( GL_FLAT ); 00345 00346 // Do not use perspective correction 00347 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); 00348 00349 00350 // Construct a texture manager that uses the application's private 00351 // directory as the location for all textures. 00352 iTextureManager = CTextureManager::NewL ( iScreenWidth, iScreenWidth, 00353 iAspectRatio*1.f, iAspectRatio*-1.f, 1.f, -1.f, 3.f, 00354 this ); 00355 00356 // Pushing the textures into the loading queue. 00357 _LIT(KWorldTexture, "world.jpg"); 00358 iTextureManager->RequestToLoad(KWorldTexture, &iWorldTexture ); 00359 00360 //Start to load the textures. 00361 iTextureManager->DoLoadL(); 00362 00363 } 00364 00365 // ------------------------------------------------------------------------------------------------------- 00366 // CBillboard::OnStartLoadingTextures() 00367 // Called for a MTextureLoadingListener by the texture manager when texture loading operation starts 00368 // ------------------------------------------------------------------------------------------------------- 00369 00370 void CMultiTex::OnStartLoadingTexturesL() 00371 { 00372 SetStateL( ELoadingTextures ); 00373 } 00374 00375 // ------------------------------------------------------------------------------------------------------------ 00376 // CBillboard::OnEndLoadingTextures() 00377 // Called for a MTextureLoadingListener by the texture manager when texture loading operation is completed 00378 // ------------------------------------------------------------------------------------------------------------ 00379 void CMultiTex::OnEndLoadingTexturesL() 00380 { 00381 /* TEXTURE0 is used for Marble texture */ 00382 glActiveTexture( GL_TEXTURE0 ); 00383 glClientActiveTexture( GL_TEXTURE0 ); 00384 00385 // Enable texturing 00386 glEnable( GL_TEXTURE_2D ); 00387 00388 // Enable vertex and texture coordinates arrays. 00389 glEnableClientState( GL_VERTEX_ARRAY ); 00390 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 00391 00392 // Set array pointers. 00393 glVertexPointer( 3, GL_SHORT, 0, objVertex ); 00394 glTexCoordPointer( 2, GL_SHORT, 0, objTexCoords ); 00395 00396 /* Bind the marble.jpg texture to iWorldTexture, set the texture 00397 to the texPtr defined above, and set the texture environment. */ 00398 glBindTexture( GL_TEXTURE_2D, iWorldTexture.iID ); 00399 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 00400 00401 /* Texture to TEXTURE1 is taken from Pbuffer 00402 context, i.e, iLightTexObjects[1] */ 00403 glActiveTexture( GL_TEXTURE1 ); 00404 glClientActiveTexture( GL_TEXTURE1 ); 00405 00406 // Enable texturing 00407 glEnable( GL_TEXTURE_2D ); 00408 00409 // Enable vertex and texture coordinates arrays. 00410 glEnableClientState( GL_VERTEX_ARRAY ); 00411 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 00412 00413 // Set array pointers. 00414 glVertexPointer( 3, GL_SHORT, 0, objVertex ); 00415 glTexCoordPointer( 3, GL_SHORT, 0, envNormals ); 00416 00417 /* Bind the environment map texture created with Pbuffer context. 00418 Actual creation and updating is done in AppCycle. */ 00419 glBindTexture( GL_TEXTURE_2D, iLightTexObjects[1] ); 00420 00421 // Set the texture env mode for environment map texture 00422 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); 00423 00424 if ( GetState() == ELoadingTextures ) 00425 { 00426 SetStateL( ERunning ); 00427 } 00428 } 00429 00430 // --------------------------------------------------------- 00431 // CBillboard::OnEnterState( TInt aState ) 00432 // Called by TFiniteStateMachine when the f.s.m enters a new state 00433 // --------------------------------------------------------- 00434 00435 void CMultiTex::OnEnterStateL( TInt /*aState*/ ) 00436 { 00437 // Nothing to do here... 00438 } 00439 00440 // ----------------------------------------------------------------------------- 00441 // CMultiTex::AppExit 00442 // 00443 // Release any allocations made in AppInit. 00444 // ----------------------------------------------------------------------------- 00445 // 00446 00447 void CMultiTex::AppExit( void ) 00448 { 00449 delete iTextureManager; 00450 } 00451 00452 // ----------------------------------------------------------------------------- 00453 // CMultiTex::DrawLight 00454 // 00455 // Draws lights. 00456 // ----------------------------------------------------------------------------- 00457 // 00458 00459 void CMultiTex::DrawLights( TInt iFrame ) 00460 { 00461 // Draw red light 00462 glPushMatrix(); 00463 glTranslatex(( 2 << 16) + (GLint) (sin(iFrame * 0.10f) * 5 * 65536) , (2 << 16) + (GLint) (cos(iFrame * 0.13f) * 5 * 65536) , 0 ); 00464 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); 00465 glPopMatrix(); 00466 00467 // Draw green light 00468 glPushMatrix(); 00469 glTranslatex( (-2 << 16) + (GLint) (sin(iFrame * 0.10f) * 5 * 65536) , (-2 << 16) + (GLint) (cos(iFrame * 0.10f) * 8 * 65536) , 0 ); 00470 glDrawArrays( GL_TRIANGLE_STRIP, 4, 4 ); 00471 glPopMatrix(); 00472 00473 } 00474 00475 // ----------------------------------------------------------------------------- 00476 // CMultiTex::AppCyclePbuffer 00477 // 00478 // Create a dynamic environment map, where two spot lights (red, green) moves 00479 // ----------------------------------------------------------------------------- 00480 // 00481 00482 void CMultiTex::AppCyclePbuffer( TInt iFrame ) 00483 { 00484 glClear( GL_COLOR_BUFFER_BIT ); 00485 00486 // Bind the light texture as current 00487 glBindTexture( GL_TEXTURE_2D, iLightTexObjects[0] ); 00488 00489 /* Animate and draw lights */ 00490 glLoadIdentity(); 00491 glTranslatex( 0 , 0 , -iCameraDistance << 16 ); 00492 glScalex( 2 << 16, 2 << 16, 2 << 16 ); 00493 DrawLights( iFrame ); 00494 00495 // Bind the environment map texture as current 00496 glBindTexture( GL_TEXTURE_2D, iLightTexObjects[1] ); 00497 00498 // Copy the content of the pbuffer to the currently bound texture 00499 glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 128, 128, 0 ); 00500 } 00501 00502 // ----------------------------------------------------------------------------- 00503 // CMultiTex::AppCycleWindow 00504 // 00505 // Draw the sphere with Marble and dynamic environment textures 00506 // ----------------------------------------------------------------------------- 00507 // 00508 00509 void CMultiTex::AppCycleWindow( TInt iFrame ) 00510 { 00511 // Set the TEXTURE1 unit as active (env map texture) 00512 glActiveTexture( GL_TEXTURE1 ); 00513 glClientActiveTexture( GL_TEXTURE1 ); 00514 00515 // Set the correct texture matrix 00516 glMatrixMode( GL_TEXTURE ); 00517 glLoadIdentity(); 00518 glTranslatef( 0.5f, 0.5f, 0.5f ); 00519 glRotatex( 180 << 16, 0, 0, 1 << 16 ); 00520 glRotatex( iFrame << 16, 0, 1 << 16, 0 ); 00521 glScalef( 1.0f/65534.0f, 1.0f/65534.0f, 1.0f/65534.0f ); 00522 00523 glMatrixMode( GL_MODELVIEW ); 00524 00525 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 00526 00527 glLoadIdentity(); 00528 glTranslatex( 0 , 0 , -iCameraDistance << 16 ); 00529 glRotatex( 180 << 16, 0, 0, 1 << 16 ); 00530 glRotatex( iFrame << 16, 0, 1 << 16, 0 ); 00531 00532 // Scale the world model to fit the screen. 00533 glScalex( 1 << 9, 1 << 9, 1 << 9 ); 00534 glDrawElements( GL_TRIANGLES, objFaces * 3, 00535 GL_UNSIGNED_SHORT, objIndices ); 00536 } 00537 00538 // ----------------------------------------------------------------------------- 00539 // CMultiTex::SetScreenSize 00540 // Reacts to the dynamic screen size change during execution of this program. 00541 // ----------------------------------------------------------------------------- 00542 // 00543 void CMultiTex::SetScreenSize( TUint aWidth, TUint aHeight ) 00544 { 00545 iScreenWidth = aWidth; 00546 iScreenHeight = aHeight; 00547 00548 // Notify the texture manager of screen size change 00549 iTextureManager->SetScreenSize( aWidth, aHeight ); 00550 00551 // Reinitialize viewport and projection. 00552 glViewport( 0, 0, iScreenWidth, iScreenHeight ); 00553 00554 // Recalculate the view frustrum 00555 if ( iScreenHeight != 0 ) 00556 { 00557 iAspectRatio = (GLfloat)iScreenWidth / (GLfloat)iScreenHeight; 00558 } 00559 else 00560 { 00561 iAspectRatio = 1.0; 00562 } 00563 00564 glMatrixMode( GL_PROJECTION ); 00565 glLoadIdentity(); 00566 glFrustumf( FRUSTUM_LEFT * iAspectRatio, FRUSTUM_RIGHT * iAspectRatio, 00567 FRUSTUM_BOTTOM, FRUSTUM_TOP, 00568 FRUSTUM_NEAR, FRUSTUM_FAR ); 00569 glMatrixMode( GL_PROJECTION ); 00570 00571 } 00572 00573 00574 // End of File
|
© Nokia 2006 |