|
S60 3rd Edition SDK for Symbian OS Example Applications Guide |
00001 /* 00002 * ============================================================================== 00003 * Name : Texture.cpp 00004 * Part of : OpenGLEx / Texture 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 // INCLUDE FILES 00017 #include <e32std.h> 00018 #include "Texture.h" 00019 00020 // MACROS 00021 #define LIGHT_MAX (1 << 16) 00022 #define LIGHTCOLOR(r, g, b, a) \ 00023 (GLfixed)(r * LIGHT_MAX), \ 00024 (GLfixed)(g * LIGHT_MAX), \ 00025 (GLfixed)(b * LIGHT_MAX), \ 00026 (GLfixed)(a * LIGHT_MAX) 00027 00028 /* Define global ambient light. */ 00029 static const GLfixed globalAmbient[4] = { LIGHTCOLOR(0.0, 0.0, 0.0, 1.0) }; 00030 00031 /* Define lamp parameters. */ 00032 static const GLfixed lightDiffuseLamp[4] = { LIGHTCOLOR(1.0, 1.0, 1.0, 1.0) }; 00033 static const GLfixed lightAmbientLamp[4] = { LIGHTCOLOR(0.3, 0.3, 0.3, 1.0) }; 00034 static const GLfixed lightSpecularLamp[4] = { LIGHTCOLOR(0.5, 0.5, 0.5, 1.0) }; 00035 static const GLfixed lightPositionLamp[4] = { 0, 0, 10, 0 }; 00036 00037 /* Define vertice coordinates for the cube 00038 Duplication of vertices needed for texturing every surface of the cube */ 00039 static const GLbyte vertices[24 * 3] = 00040 { 00041 /* top */ 00042 -1, 1, 1, 00043 1, 1, 1, 00044 1, -1, 1, 00045 -1, -1, 1, 00046 00047 /* front */ 00048 1, 1, 1, 00049 1, 1, -1, 00050 1, -1, -1, 00051 1, -1, 1, 00052 00053 /* right */ 00054 -1, 1, 1, 00055 -1, 1, -1, 00056 1, 1, -1, 00057 1, 1, 1, 00058 00059 /* left */ 00060 1, -1, 1, 00061 1, -1, -1, 00062 -1, -1, -1, 00063 -1, -1, 1, 00064 00065 /* back */ 00066 -1, -1, 1, 00067 -1, -1, -1, 00068 -1, 1, -1, 00069 -1, 1, 1, 00070 00071 /* bottom */ 00072 -1, 1, -1, 00073 1, 1, -1, 00074 1, -1, -1, 00075 -1, -1, -1 00076 }; 00077 00078 /* Define normals for the cube */ 00079 static const GLbyte normals[24 * 3] = 00080 { 00081 /* top */ 00082 0,0,1, 00083 0,0,1, 00084 0,0,1, 00085 0,0,1, 00086 00087 /* front */ 00088 1,0,0, 00089 1,0,0, 00090 1,0,0, 00091 1,0,0, 00092 00093 /* right */ 00094 0,1,0, 00095 0,1,0, 00096 0,1,0, 00097 0,1,0, 00098 00099 /* left */ 00100 0,-1,0, 00101 0,-1,0, 00102 0,-1,0, 00103 0,-1,0, 00104 00105 /* back */ 00106 -1,0,0, 00107 -1,0,0, 00108 -1,0,0, 00109 -1,0,0, 00110 00111 /* bottom */ 00112 0,0,-1, 00113 0,0,-1, 00114 0,0,-1, 00115 0,0,-1 00116 }; 00117 00118 /* Define indices for drawing the triangles ( 5 sides of the cube ) 00119 Nasa Hubble texture is drawn on these sides. */ 00120 static const GLubyte triangles[10 * 3] = 00121 { 00122 /* top */ 00123 1,0,3, 00124 1,3,2, 00125 00126 /* front */ 00127 5,4,7, 00128 5,7,6, 00129 00130 /* right */ 00131 9,8,11, 00132 9,11,10, 00133 00134 /* left */ 00135 13,12,15, 00136 13,15,14, 00137 00138 /* back */ 00139 17,16,19, 00140 17,19,18 00141 }; 00142 00143 00144 /* The 6th side of the cube. 00145 ogles.jpg texture is drawn on this side. */ 00146 static const GLubyte triangles2[2 * 3] = 00147 { 00148 /* bottom */ 00149 21,22,23, 00150 21,23,20 00151 }; 00152 00153 00154 /* Macro for changing the input texture coordinate values from 00155 GLubyte [0,255] to GLbyte [-128,127]. See more info below. */ 00156 #define tex(u,v) (GLbyte)( (u) - 128 ) , (GLbyte)( (v) - 128 ) 00157 00158 00159 /* Input texture coordinates for each of the object vertices. 00160 The coordinates are given in GLbyte [-128,127] format. 00161 Since the texture picture coordinates are between values 00162 [0,255] for both width and height, we have defined a macro 00163 to change the input coordinates into a appropriate form. 00164 It is easier to think the texture coordinates as corresponding 00165 image pixel coordinates. This alone is not enough because 00166 if texture coordinates are not given between values [0,1], 00167 texture wrapping will occur. Therefore we need to 00168 scale the texture coordinates with appropriate texture matrix, 00169 which is defined in AppInit(). */ 00170 static const GLbyte nokTexCoords[24 * 2] = 00171 { 00172 /* top, whole texture nasa_hubble.h */ 00173 tex(0,0), 00174 tex(255,0), 00175 tex(255,255), 00176 tex(0,255), 00177 00178 /* front, spiral with tail */ 00179 tex(0,255), 00180 tex(127,255), 00181 tex(127,127), 00182 tex(0,127), 00183 00184 /* right, red nebulae */ 00185 tex(127,255), 00186 tex(255,255), 00187 tex(255,127), 00188 tex(127,127), 00189 00190 /* left, plasma cloud */ 00191 tex(0,127), 00192 tex(127,127), 00193 tex(127,0), 00194 tex(0,0), 00195 00196 /* back, 2 spirals */ 00197 tex(127,127), 00198 tex(255,127), 00199 tex(255,0), 00200 tex(127,0), 00201 00202 /* bottom, whole texture ogles.jpg */ 00203 tex(255,255), 00204 tex(255,0), 00205 tex(0,0), 00206 tex(0,255) 00207 }; 00208 00209 00210 // ============================ MEMBER FUNCTIONS =============================== 00211 00212 // ----------------------------------------------------------------------------- 00213 // CTexture::CTexture 00214 // C++ default constructor can NOT contain any code, that 00215 // might leave. 00216 // ----------------------------------------------------------------------------- 00217 // 00218 CTexture::CTexture( TUint aWidth, TUint aHeight ): CFiniteStateMachine() 00219 { 00220 iScreenWidth = aWidth; 00221 iScreenHeight = aHeight; 00222 } 00223 00224 00225 // ----------------------------------------------------------------------------- 00226 // CTexture::ConstructL 00227 // Symbian 2nd phase constructor can leave. 00228 // ----------------------------------------------------------------------------- 00229 // 00230 void CTexture::ConstructL( void ) 00231 { 00232 } 00233 00234 00235 // ----------------------------------------------------------------------------- 00236 // CTexture::NewL 00237 // Two-phased constructor. 00238 // ----------------------------------------------------------------------------- 00239 // 00240 CTexture* CTexture::NewL( TUint aWidth, TUint aHeight ) 00241 { 00242 /* Symbian 2-phase constructor. Calls both the default 00243 C++ constructor and Symbian ConstructL methods */ 00244 CTexture* self = new (ELeave) CTexture( aWidth, aHeight ); 00245 CleanupStack::PushL( self ); 00246 self->ConstructL(); 00247 CleanupStack::Pop(); 00248 00249 return self; 00250 } 00251 00252 00253 // Destructor 00254 CTexture::~CTexture() 00255 { 00256 } 00257 00258 00259 // ----------------------------------------------------------------------------- 00260 // CTexture::AppInit 00261 // OpenGL ES initialization code. Set the required OpenGL ES state 00262 // ----------------------------------------------------------------------------- 00263 // 00264 void CTexture::AppInitL() 00265 { 00266 /* Set the screen background color. */ 00267 glClearColor( 0.f, 0.f, 0.f, 1.f ); 00268 00269 /* Enable back face culling, texturing, and normalization. */ 00270 glEnable( GL_CULL_FACE ); 00271 glEnable( GL_TEXTURE_2D ); 00272 glEnable( GL_NORMALIZE ); 00273 00274 /* Initialize viewport, texture matrix scaling, and projection. */ 00275 glViewport( 0, 0, iScreenWidth, iScreenHeight ); 00276 glMatrixMode( GL_PROJECTION ); 00277 00278 // Calculate the view frustrum 00279 GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight); 00280 glFrustumf( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio, 00281 FRUSTUM_BOTTOM, FRUSTUM_TOP, 00282 FRUSTUM_NEAR, FRUSTUM_FAR ); 00283 00284 /* Initialize appropriate texture matrix. First we have to translate the 00285 input texture coordinate values to be within a range of [0,255]. Hence 00286 we translate the x- and y-coordinate values by 128. Recall that the 00287 values in nokTexCoords are between [-128,127], now they are in a range 00288 of [0,255]. After that we scale the values by 1/255 to make the values 00289 to be in range [0,1]. */ 00290 glMatrixMode( GL_TEXTURE ); 00291 glLoadIdentity(); 00292 glScalef( 1.0f/255.0f, 1.0f/255.0f, 1.0f ); 00293 glTranslatef( 128.0f, 128.0f, 0.0f ); 00294 00295 /* Remember to change the matrix mode to modelview. */ 00296 glMatrixMode( GL_MODELVIEW ); 00297 00298 /* Enable vertex and texture arrays. */ 00299 glEnableClientState( GL_VERTEX_ARRAY ); 00300 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 00301 glEnableClientState( GL_NORMAL_ARRAY ); 00302 00303 /* Set array pointers. */ 00304 glVertexPointer( 3, GL_BYTE, 0, vertices ); 00305 glTexCoordPointer( 2, GL_BYTE, 0, nokTexCoords ); 00306 glNormalPointer( GL_BYTE, 0, normals ); 00307 00308 /* Set up global ambient light. */ 00309 glLightModelxv( GL_LIGHT_MODEL_AMBIENT, globalAmbient ); 00310 00311 /* Set up lamp. */ 00312 glEnable( GL_LIGHT0 ); 00313 glLightxv( GL_LIGHT0, GL_DIFFUSE, lightDiffuseLamp ); 00314 glLightxv( GL_LIGHT0, GL_AMBIENT, lightAmbientLamp ); 00315 glLightxv( GL_LIGHT0, GL_SPECULAR, lightSpecularLamp ); 00316 glLightxv( GL_LIGHT0, GL_POSITION, lightPositionLamp ); 00317 00318 /* Set shading mode*/ 00319 glShadeModel( GL_FLAT ); 00320 00321 /* Set the blending function for translucency. */ 00322 glBlendFunc( GL_ONE, GL_ONE ); 00323 00324 /* Do not use perspective correction, can be enabled from the menu */ 00325 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); 00326 00327 /* Symbian menu item initialization. See CTextureAppUi.cpp for more. */ 00328 iPerspectiveCorrEnabled = EFalse; // no texture perspective correction 00329 iTextureWrapEnabled = EFalse; // no texture wrapping 00330 iLightingEnabled = EFalse; // no lighting 00331 iBlendingEnabled = EFalse; // no blending 00332 00333 // Construct a texture manager that uses the application's private 00334 // directory as the location for all textures. 00335 iTextureManager = CTextureManager::NewL ( iScreenWidth, iScreenWidth, 00336 FRUSTUM_TOP, FRUSTUM_BOTTOM, FRUSTUM_RIGHT, FRUSTUM_LEFT, FRUSTUM_NEAR, 00337 this ); 00338 00339 // Pushing the textures into the loading queue. 00340 _LIT(KHubbleTexture, "nasa_hubble.jpg"); 00341 _LIT(KOGLESTexture, "ogles.jpg"); 00342 iTextureManager->RequestToLoad(KHubbleTexture, &iNasaHubble ); 00343 iTextureManager->RequestToLoad(KOGLESTexture, &iOpenGLES ); 00344 00345 //Start to load the textures. 00346 iTextureManager->DoLoadL(); 00347 } 00348 00349 00350 // ----------------------------------------------------------------------------- 00351 // CTexture::AppExit 00352 // Relase any allocations made in AppInit 00353 // ----------------------------------------------------------------------------- 00354 // 00355 void CTexture::AppExit( void ) 00356 { 00357 delete iTextureManager; 00358 } 00359 00360 00361 // ----------------------------------------------------------------------------- 00362 // CTexture::AppCycle 00363 // OpenGL ES main rendering loop. 00364 // ----------------------------------------------------------------------------- 00365 // 00366 void CTexture::AppCycle( TInt aFrame ) 00367 { 00368 #define cameraDistance 120 00369 00370 glClear( GL_COLOR_BUFFER_BIT ); 00371 00372 /* Animate and draw the cube. */ 00373 glLoadIdentity(); 00374 glTranslatex( 0 , 0 , -cameraDistance << 16 ); 00375 glRotatex( aFrame << 16, 1 << 16, 0 , 0 ); 00376 glRotatex( aFrame << 15, 0 , 1 << 16, 0 ); 00377 glRotatex( aFrame << 14, 0 , 0 , 1 << 16 ); 00378 00379 /* Scale the cube coordinates to fit the screen. */ 00380 glScalex( 20 << 16, 20 << 16, 20 << 16 ); 00381 00382 /* Draw the first 5 sides of the cube with the texture Nasa Hubble. */ 00383 glBindTexture( GL_TEXTURE_2D, iNasaHubble.iID ); 00384 glDrawElements( GL_TRIANGLES, 10 * 3, GL_UNSIGNED_BYTE, triangles ); 00385 00386 /* Draw the remaining side of the cube with the ogles.jpg texture. */ 00387 glBindTexture( GL_TEXTURE_2D, iOpenGLES.iID ); 00388 glDrawElements( GL_TRIANGLES, 2 * 3, GL_UNSIGNED_BYTE, triangles2 ); 00389 } 00390 00391 // ------------------------------------------------------------------------------------------------------- 00392 // CBillboard::OnStartLoadingTextures() 00393 // Called for a MTextureLoadingListener by the texture manager when texture loading operation starts 00394 // ------------------------------------------------------------------------------------------------------- 00395 00396 void CTexture::OnStartLoadingTexturesL() 00397 { 00398 SetStateL( ELoadingTextures ); 00399 } 00400 00401 // ------------------------------------------------------------------------------------------------------------ 00402 // CBillboard::OnEndLoadingTextures() 00403 // Called for a MTextureLoadingListener by the texture manager when texture loading operation is completed 00404 // ------------------------------------------------------------------------------------------------------------ 00405 void CTexture::OnEndLoadingTexturesL() 00406 { 00407 if ( GetState() == ELoadingTextures ) 00408 { 00409 SetStateL( ERunning ); 00410 } 00411 } 00412 00413 // --------------------------------------------------------- 00414 // CBillboard::OnEnterState( TInt aState ) 00415 // Called by TFiniteStateMachine when the f.s.m enters a new state 00416 // --------------------------------------------------------- 00417 00418 void CTexture::OnEnterStateL( TInt /*aState*/ ) 00419 { 00420 // Nothing to do here... 00421 } 00422 00423 //---------------------------------------------------------- 00424 // The following methods are called by the CTextureAppUi 00425 // class when handling the incoming menu events. 00426 //---------------------------------------------------------- 00427 00428 00429 // ----------------------------------------------------------------------------- 00430 // CTexture::TogglePerspective 00431 // User defines whether or not to use perspective correction when rendering 00432 // ----------------------------------------------------------------------------- 00433 // 00434 void CTexture::TogglePerspective( void ) 00435 { 00436 if( iPerspectiveCorrEnabled) 00437 { 00438 iPerspectiveCorrEnabled = EFalse; 00439 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); 00440 } 00441 else 00442 { 00443 iPerspectiveCorrEnabled = ETrue; 00444 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); 00445 } 00446 } 00447 00448 /** 00449 * Enable/Disable texture wrapping. 00450 */ 00451 // ----------------------------------------------------------------------------- 00452 // CTexture::ToggleWrapping 00453 // Implement texture wrapping by changing the texture matrix scale 00454 // ----------------------------------------------------------------------------- 00455 // 00456 void CTexture::ToggleWrapping( void ) 00457 { 00458 if( iTextureWrapEnabled ) 00459 { 00460 iTextureWrapEnabled = EFalse; 00461 glMatrixMode( GL_TEXTURE ); 00462 glLoadIdentity(); 00463 glScalef( 1.0f/255.0f, 1.0f/255.0f, 1.0f ); 00464 glTranslatef( 128.0f, 128.0f, 1.0f ); 00465 glMatrixMode( GL_MODELVIEW ); 00466 } 00467 /* Texture wrapping is implemented here simply by changing the scale of 00468 texture matrix. Now the coordinate values are between [0,2], which 00469 causes the texture to wrap one time. */ 00470 else 00471 { 00472 iTextureWrapEnabled = ETrue; 00473 glMatrixMode( GL_TEXTURE ); 00474 glLoadIdentity(); 00475 glScalef( 1.0f/128.0f, 1.0f/128.0f, 1.0f ); 00476 glTranslatef( 128.0f, 128.0f, 1.0f ); 00477 glMatrixMode( GL_MODELVIEW ); 00478 } 00479 } 00480 00481 /** 00482 * Enable/Disable lighting. 00483 */ 00484 // ----------------------------------------------------------------------------- 00485 // CTexture::ToggleLighting 00486 // When using textures with lights the texenv must be set to GL_MODULATE, 00487 // and shade model must be GL_SMOOTH. 00488 // ----------------------------------------------------------------------------- 00489 // 00490 void CTexture::ToggleLighting( void ) 00491 { 00492 // If texture loading is still going on, return from this method without doing anything. 00493 if ( GetState() == ELoadingTextures ) 00494 { 00495 return; 00496 } 00497 00498 if( iLightingEnabled ) 00499 { 00500 iLightingEnabled = EFalse; 00501 glShadeModel( GL_FLAT ); // Don't need smooth shading when no lights 00502 glDisable( GL_LIGHTING ); // Disable lighting 00503 00504 /* Set both textures environments to GL_REPLACE. */ 00505 glBindTexture( GL_TEXTURE_2D, iNasaHubble.iID ); 00506 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 00507 00508 glBindTexture( GL_TEXTURE_2D, iOpenGLES.iID ); 00509 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 00510 } 00511 else 00512 { 00513 iLightingEnabled = ETrue; 00514 glShadeModel( GL_SMOOTH ); // For the lighting to work properly 00515 glEnable( GL_LIGHTING ); // Enable lighting 00516 00517 /* Set both textures environments to GL_MODULATE. */ 00518 glBindTexture( GL_TEXTURE_2D, iNasaHubble.iID ); 00519 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00520 00521 glBindTexture( GL_TEXTURE_2D, iOpenGLES.iID ); 00522 glTexEnvx( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00523 } 00524 } 00525 00526 00527 // ----------------------------------------------------------------------------- 00528 // CTexture::ToggleBlending 00529 // User defines whether or not blending is enabled from the menu. 00530 // ----------------------------------------------------------------------------- 00531 // 00532 void CTexture::ToggleBlending( void ) 00533 { 00534 if( iBlendingEnabled ) 00535 { 00536 // Blending was enabled, disable blending 00537 iBlendingEnabled = EFalse; 00538 glDisable( GL_BLEND ); 00539 glEnable( GL_CULL_FACE ); 00540 } 00541 else 00542 { 00543 // Blending was disabled, enable blending 00544 iBlendingEnabled = ETrue; 00545 glEnable( GL_BLEND ); 00546 glDisable( GL_CULL_FACE ); 00547 } 00548 } 00549 00550 // ----------------------------------------------------------------------------- 00551 // CTexture::SetScreenSize 00552 // Reacts to the dynamic screen size change during execution of this program. 00553 // ----------------------------------------------------------------------------- 00554 // 00555 void CTexture::SetScreenSize( TUint aWidth, TUint aHeight ) 00556 { 00557 iScreenWidth = aWidth; 00558 iScreenHeight = aHeight; 00559 00560 // Notify the texture manager of screen size change 00561 iTextureManager->SetScreenSize( aWidth, aHeight ); 00562 00563 // Reinitialize viewport and projection. 00564 glViewport( 0, 0, iScreenWidth, iScreenHeight ); 00565 00566 // Recalculate the view frustrum 00567 glMatrixMode( GL_PROJECTION ); 00568 glLoadIdentity(); 00569 GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight); 00570 glFrustumf( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio, 00571 FRUSTUM_BOTTOM, FRUSTUM_TOP, 00572 FRUSTUM_NEAR, FRUSTUM_FAR ); 00573 glMatrixMode( GL_MODELVIEW ); 00574 }
|
© Nokia 2006 |