S60 3rd Edition SDK for Symbian OS
Example Applications Guide

Shadows.cpp

00001 /*
00002 * ==============================================================================
00003 *  Name        : Shadows.cpp
00004 *  Part of     : OpenGLEx / Shadows
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 // INCLUDES
00017 #include <e32std.h>
00018 #include <e32math.h>
00019 
00020 #include "Shadows.h"
00021 
00022 // LOCAL MACROS
00023 #define MATERIAL_MAX (1 << 16)
00024 #define LIGHT_MAX    (1 << 16)
00025 
00026 #define cameraDistance 150.0
00027 
00028 
00029 #define MATERIALCOLOR(r, g, b, a)    \
00030        (GLfixed)(r * MATERIAL_MAX),   \
00031        (GLfixed)(g * MATERIAL_MAX),   \
00032        (GLfixed)(b * MATERIAL_MAX),   \
00033        (GLfixed)(a * MATERIAL_MAX)    
00034 
00035 #define LIGHTCOLOR(r, g, b, a)       \
00036        (GLfixed)(r * LIGHT_MAX),      \
00037        (GLfixed)(g * LIGHT_MAX),      \
00038        (GLfixed)(b * LIGHT_MAX),      \
00039        (GLfixed)(a * LIGHT_MAX)    
00040 
00041 
00042 // CONSTANTS
00043 /** Vertice coordinates for the ground plane */
00044 static const GLbyte planeVertices[4 * 3] =
00045     {
00046     1,-1,0,
00047     1,1,0,
00048     -1,1,0,
00049     -1,-1,0
00050     };
00051 
00052 /** Indices for drawing the triangles of the ground plane */
00053 static const GLubyte planeTriangles[2 * 3] =
00054     {
00055     0,1,2,
00056     0,2,3
00057     };
00058 
00059 /** Vertice coordinates for the shadow object */
00060 static const GLbyte objVertices[48 * 3] =
00061     {
00062     /* Front */
00063     /* Outer ring */
00064     0,0,0,   // 0
00065     0,10,0,  // 1
00066     0,10,10, // 2
00067     0,0,10,  // 3
00068     /* Inner ring */
00069     0,2,2,   // 4
00070     0,8,2,   // 5
00071     0,8,8,   // 6
00072     0,2,8,   // 7
00073 
00074     /* Right */
00075     /* Outer ring */
00076     0,10,0,    // 8
00077     -10,10,0,  // 9
00078     -10,10,10, // 10
00079     0,10,10,   // 11
00080     /* Inner ring */
00081     -2,10,2,   // 12
00082     -8,10,2,   // 13
00083     -8,10,8,   // 14
00084     -2,10,8,   // 15
00085 
00086     /* Back */
00087     /* Outer ring */
00088     -10,10,0,  // 16
00089     -10,0,0,   // 17
00090     -10,0,10,  // 18
00091     -10,10,10, // 19
00092     /* Inner ring */
00093     -10,8,2,   // 20
00094     -10,2,2,   // 21
00095     -10,2,8,   // 22
00096     -10,8,8,   // 23
00097 
00098     /* Left */
00099     /* Outer ring */
00100     -10,0,0,   // 24  
00101     0,0,0,     // 25
00102     0,0,10,    // 26
00103     -10,0,10,  // 27
00104     /* Inner ring */
00105     -8,0,2,    // 28
00106     -2,0,2,    // 29
00107     -2,0,8,    // 30
00108     -8,0,8,    // 31
00109 
00110     /* Top */
00111     /* Outer ring */
00112     0,0,10,    // 32
00113     0,10,10,   // 33
00114     -10,10,10, // 34
00115     -10,0,10,  // 35
00116     /* Inner ring */
00117     -2,2,10,   // 36
00118     -2,8,10,   // 37
00119     -8,8,10,   // 38
00120     -8,2,10,   // 39
00121 
00122     /* Bottom */
00123     /* Outer ring */
00124     -10,0,0,   // 40
00125     -10,10,0,  // 41
00126     0,10,0,    // 42
00127     0,0,0,     // 43
00128     /* Inner ring */
00129     -8,2,0,    // 44
00130     -8,8,0,    // 45
00131     -2,8,0,    // 46
00132     -2,2,0     // 47
00133     };
00134 
00135 /** Indices for drawing the triangles of the shadow object */
00136 static const GLubyte objTriangles[48 * 3] =
00137     {
00138     /* Front */
00139     0,5,4,
00140     0,1,5,
00141     1,6,5,
00142     1,2,6,
00143     2,7,6,
00144     2,3,7,
00145     3,4,7,
00146     3,0,4,
00147     /* Right */
00148     8,13,12,
00149     8,9,13,
00150     9,14,13,
00151     9,10,14,
00152     10,15,14,
00153     10,11,15,
00154     11,12,15,
00155     11,8,12,
00156     /* Back */
00157     16,21,20,
00158     16,17,21,
00159     17,22,21,
00160     17,18,22,
00161     18,23,22,
00162     18,19,23,
00163     19,20,23,
00164     19,16,20,
00165     /* Left */
00166     24,29,28,
00167     24,25,29,
00168     25,30,29,
00169     25,26,30,
00170     26,31,30,
00171     26,27,31,
00172     27,28,31,
00173     27,24,28,
00174     /* Top */
00175     32,37,36,
00176     32,33,37,
00177     33,38,37,
00178     33,34,38,
00179     34,39,38,
00180     34,35,39,
00181     35,36,39,
00182     35,32,36,
00183     /* Bottom */
00184     40,45,44,
00185     40,41,45,
00186     41,46,45,
00187     41,42,46,
00188     42,47,46,
00189     42,43,47,
00190     43,44,47,
00191     43,40,44
00192 
00193     };
00194 
00195 /** Normals for the shadow object */
00196 static const GLbyte objNormals[48 * 3] =
00197     {
00198     /* Front */
00199     1,0,0,
00200     1,0,0,
00201     1,0,0,
00202     1,0,0,
00203     1,0,0,
00204     1,0,0,
00205     1,0,0,
00206     1,0,0,
00207     /* Right */
00208     0,1,0,
00209     0,1,0,
00210     0,1,0,
00211     0,1,0,
00212     0,1,0,
00213     0,1,0,
00214     0,1,0,
00215     0,1,0,
00216     /* Back */
00217     -1,0,0,
00218     -1,0,0,
00219     -1,0,0,
00220     -1,0,0,
00221     -1,0,0,
00222     -1,0,0,
00223     -1,0,0,
00224     -1,0,0,
00225     /* Left */
00226     0,-1,0,
00227     0,-1,0,
00228     0,-1,0,
00229     0,-1,0,
00230     0,-1,0,
00231     0,-1,0,
00232     0,-1,0,
00233     0,-1,0,
00234     /* Top */
00235     0,0,1,
00236     0,0,1,
00237     0,0,1,
00238     0,0,1,
00239     0,0,1,
00240     0,0,1,
00241     0,0,1,
00242     0,0,1,
00243     /* Bottom */
00244     0,0,-1,
00245     0,0,-1,
00246     0,0,-1,
00247     0,0,-1,
00248     0,0,-1,
00249     0,0,-1,
00250     0,0,-1,
00251     0,0,-1
00252     };
00253 
00254 
00255 /** Diffuse material definition for the shadow object. */
00256 static const GLfixed objDiffuseFront[4]  = { MATERIALCOLOR(1.0, 0.5, 0.0, 1.0) };
00257 /** Ambient material definition for the shadow object. */
00258 static const GLfixed objAmbientFront[4]  = { MATERIALCOLOR(1.0, 0.5, 0.0, 1.0) };
00259 
00260 /** Global ambient light. */
00261 static const GLfixed globalAmbient[4]      = { LIGHTCOLOR(0.2, 0.2, 0.2, 1.0) };
00262 
00263 /** Lamp diffuse parameters. */
00264 static const GLfixed lightDiffuseLamp[4]   = { LIGHTCOLOR(0.7, 0.7, 0.7, 1.0) };
00265 /** Lamp ambient parameters. */
00266 static const GLfixed lightAmbientLamp[4]   = { LIGHTCOLOR(0.3, 0.3, 0.3, 1.0) };
00267 
00268 
00269 // ============================= LOCAL FUNCTIONS ===============================
00270 
00271 // -----------------------------------------------------------------------------
00272 // sin
00273 // -----------------------------------------------------------------------------
00274 /**
00275  * Calculates the sine of the given float.
00276  * @param aRad Angle in radians.
00277  * @return Sine value of the angle.
00278  */
00279 GLfloat sin(GLfloat aRad)
00280     {
00281     TReal trg, src = (TReal)aRad;
00282     if ( Math::Sin(trg, src) == KErrNone )
00283         {
00284         return (GLfloat)trg;
00285         }
00286     return 0;
00287     }
00288 
00289 // -----------------------------------------------------------------------------
00290 // cos
00291 // -----------------------------------------------------------------------------
00292 /**
00293  * Calculates the cosine of the given float.
00294  * @param aRad Angle in radians.
00295  * @return Cosine value of the angle.
00296  */
00297 GLfloat cos(GLfloat aRad)
00298     {
00299     TReal trg, src = (TReal)aRad;
00300     if ( Math::Cos(trg, src) == KErrNone )
00301         {
00302         return (GLfloat)trg;
00303         }
00304     return 0;
00305     }
00306 
00307 
00308 // ============================ MEMBER FUNCTIONS ===============================
00309 
00310 // -----------------------------------------------------------------------------
00311 // CShadows::CShadows
00312 // C++ default constructor can NOT contain any code, that
00313 // might leave.
00314 // -----------------------------------------------------------------------------
00315 //
00316 CShadows::CShadows( TUint aWidth, TUint aHeight )
00317 :iScreenWidth(aWidth), iScreenHeight(aHeight)
00318     {
00319     }
00320 
00321 
00322 // -----------------------------------------------------------------------------
00323 // CShadows::ConstructL
00324 // Symbian 2nd phase constructor can leave.
00325 // -----------------------------------------------------------------------------
00326 //
00327 void CShadows::ConstructL( void )
00328     {
00329     }
00330 
00331 
00332 // -----------------------------------------------------------------------------
00333 // CShadows::NewL
00334 // Two-phased constructor.
00335 // -----------------------------------------------------------------------------
00336 //
00337 CShadows* CShadows::NewL( TUint aWidth, TUint aHeight )
00338     {
00339     /* Symbian 2-phase constructor. Calls both the default 
00340        C++ constructor and Symbian ConstructL methods */
00341     CShadows* self = new (ELeave) CShadows( aWidth, aHeight );
00342     CleanupStack::PushL( self );
00343     self->ConstructL();
00344     CleanupStack::Pop();
00345 
00346     return self;
00347     }
00348 
00349 
00350 // Destructor. 
00351 CShadows::~CShadows()
00352     {
00353     }
00354 
00355 
00356 // -----------------------------------------------------------------------------
00357 // CShadows::AppInit
00358 // Initialize OpenGL ES.
00359 // -----------------------------------------------------------------------------
00360 //
00361 void CShadows::AppInit( void )
00362     {
00363     // Set the screen background color. 
00364     glClearColor( 0.f, 0.4f, 0.7f, 1.f );
00365 
00366     // Enable auto normalization for object's normals. 
00367     glEnable( GL_NORMALIZE  );
00368     
00369     // Initialize viewport and projection. 
00370     glViewport( 0, 0, iScreenWidth, iScreenHeight );
00371     glMatrixMode( GL_PROJECTION );
00372 
00373     // Calculate the view frustrum
00374     GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight);
00375     glFrustumf( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio,
00376                 FRUSTUM_BOTTOM, FRUSTUM_TOP,
00377                 FRUSTUM_NEAR, FRUSTUM_FAR );
00378 
00379     glMatrixMode( GL_MODELVIEW );
00380 
00381     // Enable vertex and  normal arrays. 
00382     glEnableClientState( GL_VERTEX_ARRAY );
00383     glEnableClientState( GL_NORMAL_ARRAY );
00384 
00385     // Set shadow object's front and back materials. 
00386     glMaterialxv( GL_FRONT_AND_BACK, GL_AMBIENT,  objAmbientFront  );
00387     glMaterialxv( GL_FRONT_AND_BACK, GL_DIFFUSE,  objDiffuseFront  );
00388 
00389     // Set the normal pointer. 
00390     glNormalPointer( GL_BYTE, 0, objNormals );
00391 
00392     // Set up global ambient light. 
00393     glLightModelxv( GL_LIGHT_MODEL_AMBIENT, globalAmbient );
00394 
00395     // Do not use perspective correction 
00396     glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
00397 
00398     // Set up lamp. 
00399     glEnable(   GL_LIGHT0 );
00400     glLightxv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuseLamp  );
00401     glLightxv( GL_LIGHT0, GL_AMBIENT,  lightAmbientLamp  );
00402     glLightxv( GL_LIGHT0, GL_SPECULAR, lightDiffuseLamp  );
00403 
00404     glPointSize( 5.0 ); // For drawing the lamp object
00405 
00406     // Initial position of the lamp 
00407     iLightRadius = 10.0;
00408     iLightAngle  = 0.0;
00409     iLightPosX   = iLightRadius * cos(iLightAngle); // 10.0
00410     iLightPosY   = iLightRadius * sin(iLightAngle); // 0.0
00411     iLightPosZ   = 50.0;
00412 
00413     iLightPos[0] = iLightPosX; 
00414     iLightPos[1] = iLightPosY; 
00415     iLightPos[2] = iLightPosZ; 
00416     iLightPos[3] = 0.0;
00417 
00418     iIsLightRotatedLeft  = EFalse;
00419     iIsLightRotatedRight = EFalse;
00420 
00421     }
00422 
00423 
00424 // -----------------------------------------------------------------------------
00425 // CShadows::AppExit
00426 // Release any allocations made in AppInit.
00427 // -----------------------------------------------------------------------------
00428 //
00429 void CShadows::AppExit( void )
00430     {
00431     }
00432 
00433 
00434 // -----------------------------------------------------------------------------
00435 // CShadows::DrawPlane
00436 // Draw the ground plane.
00437 // -----------------------------------------------------------------------------
00438 //
00439 void CShadows::DrawPlane( void )
00440     {
00441     glColor4f( 255.f, 255.f, 255.f, 255.f ); // White
00442     glVertexPointer( 3, GL_BYTE, 0, planeVertices );
00443     glDrawElements( GL_TRIANGLES, 2 * 3, GL_UNSIGNED_BYTE, planeTriangles );
00444     }
00445 
00446 
00447 // -----------------------------------------------------------------------------
00448 // CShadows::DrawLamp
00449 // Draw the lamp.
00450 // -----------------------------------------------------------------------------
00451 //
00452 void CShadows::DrawLamp( void )
00453     {
00454     /* The lamp is drawn using one vertex from the shadow object
00455        vertex list. The lamp is drawn as a single point. */
00456 
00457     glColor4f( 255.f, 255.f, 0.f, 255.f ); // Yellow
00458     glVertexPointer( 3, GL_BYTE, 0, objVertices );
00459     glDrawElements( GL_POINTS, 1, GL_UNSIGNED_BYTE, objTriangles );
00460     }
00461 
00462 
00463 // -----------------------------------------------------------------------------
00464 // CShadows::DrawShadowObject
00465 // Draw shadows.
00466 // -----------------------------------------------------------------------------
00467 //
00468 void CShadows::DrawShadowObject( void )
00469     {
00470     glColor4f( 0.f, 0.f, 0.f, 255.f ); // Black
00471     glVertexPointer( 3, GL_BYTE, 0, objVertices );
00472     glDrawElements( GL_TRIANGLES, 48 * 3, GL_UNSIGNED_BYTE, objTriangles );
00473     }
00474 
00475 
00476 // -----------------------------------------------------------------------------
00477 // CShadows::DrawObject
00478 // Draw the shadow object.
00479 // -----------------------------------------------------------------------------
00480 //
00481 void CShadows::DrawObject( void )
00482     {
00483     glDrawElements( GL_TRIANGLES, 48 * 3, GL_UNSIGNED_BYTE, objTriangles );
00484     }
00485 
00486 
00487 // -----------------------------------------------------------------------------
00488 // CShadows::CalculateProjectionMatrix
00489 // Calculate proper shadow matrix.
00490 // -----------------------------------------------------------------------------
00491 //
00492 void CShadows::CalculateProjectionMatrix( void )
00493     {
00494     /* Shadows are calculated using appropriate projection matrix, which is
00495        defined, e.g., in OpenGL Programming Guide on page 584, or in Jim Blinn's
00496        Corner: A Trip Down the Graphics Pipeline on page 60. The latter also 
00497        includes localized light sources as in our case. The general modelview 
00498        matrix for creating a planar shadow can be expressed as:
00499 
00500        shadowMat = 
00501 
00502        [ dtop-l[0]*g[0],     -l[1]*g[0],     -l[2]*g[0],     -l[3]*g[0],
00503              -l[0]*g[1], dotp-l[1]*g[1],     -l[2]*g[1],     -l[3]*g[1],
00504              -l[0]*g[2],     -l[1]*g[2], dotp-l[2]*g[2],     -l[3]*g[2],
00505          -l[0]*g[3],     -l[1]*g[3],     -l[2]*g[3], dotp-l[3]*g[3] ],
00506 
00507        where l - list(4) - light position
00508              g - list(4) - ground plane equation in form Ax + By + Cz + d = 0
00509          dotp = l[0]*g[0]+l[1]*g[1]+l[2]*g[2]+l[3]*g[3]
00510     
00511        Note that in this example the ground plane is a x-y-plane in origin, i.e.,
00512        the plane equation is g = [0,0,1,0]. Therefore the matrix can be written
00513        using only the light position parameters.
00514 
00515        Note that if you have a local light source, then g[2] = 1. In the case of
00516        directional light g[2] = 0.
00517     */
00518 
00519     GLfloat shadowMat_local[16] = { iLightPosZ,     0.0,        0.0,    0.0, \
00520                                        0.0,      iLightPosZ,    0.0,    0.0, \
00521                                       -iLightPosX, -iLightPosY,    0.0,   -1.0, \
00522                                       0.0,        0.0,         0.0, iLightPosZ };
00523 
00524     for ( int i=0;i<16;i++ ) 
00525         {
00526         iShadowMat[i] = shadowMat_local[i];
00527         }
00528     
00529     }
00530 
00531 
00532 // -----------------------------------------------------------------------------
00533 // CShadows::AppCycle
00534 // Draws and animates the objects.
00535 // -----------------------------------------------------------------------------
00536 //
00537 void CShadows::AppCycle( TInt aFrame )
00538     {
00539     /* The order of rendering in our case is following:
00540        1. Draw all the ground object, i.e., the plane
00541        2. Draw shadows. If we have multiple ground object, each would have
00542           to be rendered separately with each different light sources.
00543        3. Draw the shadow objects. */
00544 
00545     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00546 
00547     // Update light position 
00548     if ( iIsLightRotatedLeft )
00549         {
00550         iLightAngle += (GLfloat)0.1;
00551         }
00552 
00553     if ( iIsLightRotatedRight )
00554         {
00555         iLightAngle -= (GLfloat)0.1;
00556         }
00557     
00558     iLightPosX   = iLightRadius * cos( iLightAngle );
00559     iLightPosY   = iLightRadius * sin( iLightAngle );
00560     iLightPos[0] = iLightPosX;
00561     iLightPos[1] = iLightPosY;
00562 
00563 
00564     // Move camera 
00565     glLoadIdentity();
00566     glTranslatef( 0.0, -20.0, -cameraDistance );
00567     glRotatef( -75.0, 1.0, 0.0, 0.0 );
00568 
00569     glDisable( GL_LIGHTING ); // Plane, lamp, and shadows don't need lighting
00570     glShadeModel( GL_FLAT );  // Plane, lamp, and shadows are single colored 
00571 
00572     // Draw plane 
00573     glPushMatrix();
00574     glScalef( 80.0, 60.0, 1.0 );
00575     DrawPlane();
00576     glPopMatrix();
00577     
00578     // Draw the lamp 
00579     glLightfv( GL_LIGHT0, GL_POSITION, iLightPos ); // Update lamp position
00580     glPushMatrix();
00581     glTranslatef( iLightPosX, iLightPosY, iLightPosZ );
00582     DrawLamp();
00583     glPopMatrix();
00584     
00585     glDisable( GL_DEPTH_TEST );  // Disable depth test while drawing shadows
00586                                  // To ensure that shadows are drawn on top
00587                                  // of the ground plane
00588     CalculateProjectionMatrix(); // Calculate/update shadowMat
00589     glPushMatrix();              // Store the current modelview for drawing 
00590                                  // the actual objects after shadows are drawn
00591                                  // modelview = M_camera
00592     glMultMatrixf( iShadowMat ); // Multiply shadow matrix with current 
00593                                  // modelview after camera xforms and before
00594                                  // model xforms
00595     
00596     // Draw shadows 
00597     glTranslatef( 0.0, 0.0, 30.0 );  // Translate object above the ground plane
00598     glRotatef( float(aFrame), 1.0, 0.0, 0.0 ); // Rotate object
00599     glRotatef( float(aFrame), 0.0, 1.0, 0.0 );
00600     glRotatef( float(aFrame), 0.0, 0.0, 1.0 );
00601     glTranslatef( 5.0, -5.0, -5.0 ); // Move origin to the middle of the 
00602                                      // shadow object
00603     
00604     DrawShadowObject(); // Draw shadows, i.e., draw the shadow object with the
00605                         // correct modelview matrix: 
00606                         // modelview = M_camera * M_shadow * M_object 
00607     glPopMatrix();      // modelview = M_camera
00608 
00609     glEnable( GL_DEPTH_TEST ); // Shadows are drawn -> enable depth test
00610     glEnable( GL_LIGHTING );   // Enable lighting for drawing the objects
00611     glShadeModel( GL_SMOOTH ); // To make the lighting work properly
00612 
00613     // Draw shadow object 
00614     glTranslatef( 0.0, 0.0, 30.0 );
00615     glRotatef( float(aFrame), 1.0, 0.0, 0.0 );
00616     glRotatef( float(aFrame), 0.0, 1.0, 0.0 );
00617     glRotatef( float(aFrame), 0.0, 0.0, 1.0 );
00618     glTranslatef( 5.0, -5.0, -5.0 ); 
00619     DrawObject();
00620     
00621     }
00622 
00623 
00624 //----------------------------------------------------------
00625 // The following methods are called by the CShadowsAppUi 
00626 // class when handling the incoming menu events.
00627 //----------------------------------------------------------
00628 
00629 
00630 // -----------------------------------------------------------------------------
00631 // CShadows::RotateLightLeft
00632 // Rotates light to left.
00633 // -----------------------------------------------------------------------------
00634 //
00635 void CShadows::RotateLightLeft( void )
00636     {
00637     iIsLightRotatedLeft = !iIsLightRotatedLeft;
00638     }
00639 
00640 
00641 // -----------------------------------------------------------------------------
00642 // CShadows::RotateLightRight
00643 // Rotates light to right.
00644 // -----------------------------------------------------------------------------
00645 //
00646 void CShadows::RotateLightRight( void )
00647     {
00648     iIsLightRotatedRight = !iIsLightRotatedRight;
00649     }
00650 
00651 // -----------------------------------------------------------------------------
00652 // CShadows::SetScreenSize
00653 // Reacts to the dynamic screen size change during execution of this program.
00654 // -----------------------------------------------------------------------------
00655 //
00656 void CShadows::SetScreenSize( TUint aWidth, TUint aHeight )
00657     {
00658     iScreenWidth  = aWidth;
00659     iScreenHeight = aHeight;
00660 
00661     // Reinitialize viewport and projection.
00662     glViewport( 0, 0, iScreenWidth, iScreenHeight );
00663 
00664     // Recalculate the view frustrum
00665     glMatrixMode( GL_PROJECTION );
00666     glLoadIdentity();
00667     GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight);
00668     glFrustumf( FRUSTUM_LEFT * aspectRatio, FRUSTUM_RIGHT * aspectRatio,
00669                 FRUSTUM_BOTTOM, FRUSTUM_TOP,
00670                 FRUSTUM_NEAR, FRUSTUM_FAR );
00671     glMatrixMode( GL_MODELVIEW );
00672     }

© Nokia 2006

Back to top