S60 3rd Edition SDK for Symbian OS
Example Applications Guide

Texture.cpp

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

Back to top