examples/eqPixelBench/channel.cpp

00001 
00002 /* Copyright (c) 2007-2008, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "channel.h"
00019 
00020 #include "config.h"
00021 #include "configEvent.h"
00022 
00023 using namespace std;
00024 using namespace eq::base;
00025 
00026 #ifdef WIN32_API
00027 #  define snprintf _snprintf
00028 #endif
00029 
00030 namespace eqPixelBench
00031 {
00032 namespace
00033 {
00034 #pragma warning(disable: 411) // class defines no constructor to initialize ...
00035 struct EnumMap
00036 {
00037     const char*    formatString;
00038     const char*    typeString;
00039     const uint32_t format;
00040     const uint32_t type;
00041 };
00042 #pragma warning(default: 411)
00043 
00044 #define ENUM_MAP_ITEM( format, type )          \
00045     { #format, #type, format, type }
00046 
00047 static EnumMap _enums[] = {
00048     ENUM_MAP_ITEM( GL_RGBA, GL_UNSIGNED_BYTE ), // initial buffer resize
00049     ENUM_MAP_ITEM( GL_RGBA, GL_UNSIGNED_BYTE ),
00050     ENUM_MAP_ITEM( GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV ),
00051     ENUM_MAP_ITEM( GL_RGBA, GL_HALF_FLOAT ),
00052     ENUM_MAP_ITEM( GL_RGBA, GL_FLOAT ),
00053     ENUM_MAP_ITEM( GL_BGRA, GL_UNSIGNED_BYTE ),
00054     ENUM_MAP_ITEM( GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV ),
00055     ENUM_MAP_ITEM( GL_BGRA, GL_HALF_FLOAT ),
00056     ENUM_MAP_ITEM( GL_BGRA, GL_FLOAT ),
00057     ENUM_MAP_ITEM( GL_RGB,  GL_UNSIGNED_BYTE ),
00058     ENUM_MAP_ITEM( GL_RGB,  GL_UNSIGNED_INT_8_8_8_8_REV),
00059     ENUM_MAP_ITEM( GL_RGB,  GL_HALF_FLOAT ),
00060     ENUM_MAP_ITEM( GL_RGB,  GL_FLOAT ),
00061     ENUM_MAP_ITEM( GL_BGR,  GL_UNSIGNED_BYTE ),
00062     ENUM_MAP_ITEM( GL_BGR,  GL_UNSIGNED_INT_8_8_8_8_REV ),
00063     ENUM_MAP_ITEM( GL_BGR,  GL_HALF_FLOAT ),
00064     ENUM_MAP_ITEM( GL_BGR,  GL_FLOAT ),
00065     ENUM_MAP_ITEM( GL_DEPTH_COMPONENT, GL_FLOAT ),
00066     ENUM_MAP_ITEM( GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ),
00067     ENUM_MAP_ITEM( GL_DEPTH_STENCIL_NV, GL_UNSIGNED_INT_24_8_NV ),
00068     { 0, 0, false, false }};
00069 
00070 #define NUM_IMAGES 8
00071 }
00072 
00073 Channel::Channel( eq::Window* parent )
00074         : eq::Channel( parent )
00075 {
00076     eq::FrameData* frameData = new eq::FrameData;
00077     _frame.setData( frameData );
00078 
00079     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00080         frameData->newImage();
00081 }
00082 
00083 void Channel::frameStart( const uint32_t frameID, const uint32_t frameNumber ) 
00084 {
00085     Config*      config = static_cast< Config* >( getConfig( ));
00086     const Clock* clock  = config->getClock();
00087 
00088     if( clock )
00089     {
00090         ConfigEvent   event;
00091         event.msec = clock->getTimef();
00092 
00093         const string& name  = getName();
00094         if( name.empty( ))    
00095             snprintf( event.data.user.data, 32, "%p", this);
00096         else
00097             snprintf( event.data.user.data, 32, "%s", name.c_str( ));
00098         event.data.user.data[31] = '\0';
00099         event.area.x() = 0;
00100         event.area.y() = 0;
00101 
00102         snprintf( event.formatType, 64, "Latency between app and render start");
00103         event.data.type = ConfigEvent::START_LATENCY;
00104 
00105         config->sendEvent( event );
00106     }
00107 
00108     eq::Channel::frameStart( frameID, frameNumber );
00109 }
00110 
00111 void Channel::frameDraw( const uint32_t frameID )
00112 {
00113     //----- setup GL state
00114     applyBuffer();
00115     applyViewport();
00116 
00117     glMatrixMode( GL_PROJECTION );
00118     glLoadIdentity();
00119 
00120     applyFrustum();
00121 
00122     glMatrixMode( GL_MODELVIEW );
00123     glLoadIdentity();
00124     applyHeadTransform();
00125 
00126     setupAssemblyState();
00127 
00128     _testFormats();
00129     _testTiledOperations();
00130     _testDepthAssemble();
00131 
00132     resetAssemblyState();
00133 }
00134 
00135 ConfigEvent Channel::_createConfigEvent()
00136 {
00137     ConfigEvent   event;
00138     const string& name = getName();
00139 
00140     if( name.empty( ))    
00141         snprintf( event.data.user.data, 32, "%p", this );
00142     else
00143         snprintf( event.data.user.data, 32, "%s", name.c_str( ));
00144 
00145     event.data.user.data[31] = '\0';
00146     return event;
00147 }
00148 
00149 void Channel::_testFormats()
00150 {
00151     //----- setup constant data
00152     const eq::ImageVector& images = _frame.getImages();
00153     eq::Image*             image  = images[ 0 ];
00154     EQASSERT( image );
00155 
00156     eq::Config*              config = getConfig();
00157     const eq::PixelViewport& pvp    = getPixelViewport();
00158     const eq::Vector2i     offset( pvp.x, pvp.y );
00159 
00160     ConfigEvent event = _createConfigEvent();
00161     event.area.x() = pvp.w;
00162 
00163     Clock                      clock;
00164     eq::Window::ObjectManager* glObjects = getObjectManager();
00165 
00166     //----- test all default format/type combinations
00167     glGetError();
00168     for( uint32_t i=0; _enums[i].formatString; ++i )
00169     {
00170         _draw( 0 );
00171 
00172         // setup
00173         snprintf( event.formatType, 64, "%s/%s", 
00174             _enums[i].formatString, _enums[i].typeString );
00175         event.formatType[63] = '\0';
00176         event.data.type = ConfigEvent::READBACK;
00177         event.area.y() = pvp.h;
00178 
00179         image->setFormat( eq::Frame::BUFFER_COLOR, _enums[i].format );
00180         image->setType(   eq::Frame::BUFFER_COLOR, _enums[i].type );
00181         image->clearPixelData( eq::Frame::BUFFER_COLOR );
00182         image->disablePBO();
00183 
00184         // read
00185         clock.reset();
00186         image->startReadback( eq::Frame::BUFFER_COLOR, pvp, eq::Zoom(), 
00187                               glObjects );
00188         image->syncReadback();
00189         event.msec = clock.getTimef();
00190 
00191         GLenum error = glGetError();
00192         if( error != GL_NO_ERROR )
00193             event.msec = - static_cast<float>( error );
00194         config->sendEvent( event );
00195 
00196         _saveImage( image, _enums[i].typeString, _enums[i].formatString,
00197                     "formats" );
00198 
00199         if( error != GL_NO_ERROR )
00200             continue;
00201 
00202         // PBO readback
00203         event.data.type = ConfigEvent::READBACK_PBO;
00204         image->clearPixelData( eq::Frame::BUFFER_COLOR );
00205         image->enablePBO();
00206         
00207         clock.reset();
00208         image->startReadback( eq::Frame::BUFFER_COLOR, pvp, eq::Zoom(),
00209                               glObjects );
00210         image->syncReadback();
00211         event.msec = clock.getTimef();
00212         
00213         error = glGetError();
00214         if( error != GL_NO_ERROR )
00215             event.msec = - static_cast<float>( error );
00216         config->sendEvent( event );
00217         
00218         _saveImage( image, _enums[i].typeString, _enums[i].formatString,
00219                     "formats_PBO" );
00220 
00221         // draw
00222         event.data.type = ConfigEvent::ASSEMBLE;
00223         eq::Compositor::ImageOp op;
00224         op.channel = this;
00225         op.buffers = eq::Frame::BUFFER_COLOR;
00226         op.offset  = offset;
00227 
00228         clock.reset();
00229         eq::Compositor::assembleImage( image, op );
00230         event.msec = clock.getTimef();
00231 
00232         error = glGetError();
00233         if( error != GL_NO_ERROR )
00234             event.msec = - static_cast<float>( error );
00235 
00236         config->sendEvent( event );
00237     }
00238 }
00239 
00240 void Channel::_testTiledOperations()
00241 {
00242     //----- setup constant data
00243     const eq::ImageVector& images = _frame.getImages();
00244     EQASSERT( images[0] );
00245 
00246     eq::Config*              config = getConfig();
00247     const eq::PixelViewport& pvp    = getPixelViewport();
00248     const eq::Vector2i     offset( pvp.x, pvp.y );
00249 
00250     ConfigEvent event = _createConfigEvent();
00251     event.area.x() = pvp.w;
00252 
00253     Clock                      clock;
00254     eq::Window::ObjectManager* glObjects = getObjectManager();
00255 
00256     //----- test tiled assembly algorithms
00257     eq::PixelViewport subPVP = pvp;
00258     subPVP.h /= NUM_IMAGES;
00259 
00260     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00261     {
00262         EQASSERT( images[ i ] );
00263         images[ i ]->setPixelViewport( subPVP );
00264     }
00265 
00266     for( unsigned tiles = 0; tiles < NUM_IMAGES; ++tiles )
00267     {
00268         _draw( 0 );
00269 
00270         event.area.y() = subPVP.h * (tiles+1);
00271 
00272         //---- readback of 'tiles' depth images
00273         event.data.type = ConfigEvent::READBACK;
00274         snprintf( event.formatType, 64, "%d depth tiles", tiles+1 ); 
00275 
00276         event.msec = 0;
00277         for( unsigned j = 0; j <= tiles; ++j )
00278         {
00279             subPVP.y = pvp.y + j * subPVP.h;
00280             eq::Image* image = images[ j ];
00281             image->disablePBO();
00282             image->setFormat( eq::Frame::BUFFER_COLOR, GL_DEPTH_COMPONENT );
00283             image->setType(   eq::Frame::BUFFER_COLOR, GL_UNSIGNED_INT );
00284             image->clearPixelData( eq::Frame::BUFFER_COLOR );
00285 
00286             clock.reset();
00287             image->startReadback( eq::Frame::BUFFER_COLOR, subPVP, eq::Zoom(),
00288                                   glObjects );
00289             image->syncReadback();
00290             event.msec += clock.getTimef();
00291         }
00292 
00293         config->sendEvent( event );
00294 
00295         if( tiles == NUM_IMAGES-1 )
00296             for( unsigned j = 0; j <= tiles; ++j )
00297                 _saveImage( images[j],
00298                             "GL_DEPTH_COMPONENT","GL_UNSIGNED_INT","tiles" );
00299 
00300 
00301         event.data.type = ConfigEvent::READBACK_PBO;
00302 
00303         for( unsigned j = 0; j <= tiles; ++j )
00304         {
00305             eq::Image* image = images[ j ];
00306             image->enablePBO();
00307             image->setFormat( eq::Frame::BUFFER_COLOR, GL_DEPTH_COMPONENT );
00308             image->setType(   eq::Frame::BUFFER_COLOR, GL_UNSIGNED_INT );
00309             image->clearPixelData( eq::Frame::BUFFER_COLOR );
00310         }
00311         clock.reset();
00312         for( unsigned j = 0; j <= tiles; ++j )
00313         {
00314             subPVP.y = pvp.y + j * subPVP.h;
00315             images[ j ]->startReadback( eq::Frame::BUFFER_COLOR, subPVP,
00316                                         eq::Zoom(), glObjects );
00317         }
00318 
00319         for( unsigned j = 0; j <= tiles; ++j )
00320             images[ j ]->syncReadback();
00321 
00322         event.msec = clock.getTimef();
00323         config->sendEvent( event );
00324 
00325         if( tiles == NUM_IMAGES-1 )
00326             for( unsigned j = 0; j <= tiles; ++j )
00327               _saveImage(images[j],
00328                             "GL_DEPTH_COMPONENT","GL_UNSIGNED_INT","tiles_PBO");
00329 
00330 
00331         //---- readback of 'tiles' color images
00332         event.data.type = ConfigEvent::READBACK;
00333         snprintf( event.formatType, 64, "%d color tiles", tiles+1 );
00334 
00335         event.msec = 0;
00336         for( unsigned j = 0; j <= tiles; ++j )
00337         {
00338             subPVP.y = pvp.y + j * subPVP.h;
00339             eq::Image* image = images[ j ];
00340             image->disablePBO();
00341             image->setFormat( eq::Frame::BUFFER_COLOR, GL_BGRA );
00342             image->setType(   eq::Frame::BUFFER_COLOR, GL_UNSIGNED_BYTE );
00343             image->clearPixelData( eq::Frame::BUFFER_COLOR );
00344 
00345             clock.reset();
00346             image->startReadback( eq::Frame::BUFFER_COLOR, subPVP, eq::Zoom(),
00347                                   glObjects );
00348             image->syncReadback();
00349             event.msec += clock.getTimef();
00350         }
00351 
00352         config->sendEvent( event );
00353 
00354         if( tiles == NUM_IMAGES-1 )
00355             for( unsigned j = 0; j <= tiles; ++j )
00356                 _saveImage( images[j],"GL_BGRA","GL_UNSIGNED_BYTE","tiles" );
00357 
00358 
00359         event.data.type = ConfigEvent::READBACK_PBO;
00360 
00361         for( unsigned j = 0; j <= tiles; ++j )
00362         {
00363             eq::Image* image = images[ j ];
00364             image->enablePBO();
00365             image->setFormat( eq::Frame::BUFFER_COLOR, GL_BGRA );
00366             image->setType(   eq::Frame::BUFFER_COLOR, GL_UNSIGNED_BYTE );
00367             image->clearPixelData( eq::Frame::BUFFER_COLOR );
00368         }
00369         clock.reset();
00370         for( unsigned j = 0; j <= tiles; ++j )
00371         {
00372             subPVP.y = pvp.y + j * subPVP.h;
00373             images[ j ]->startReadback( eq::Frame::BUFFER_COLOR, subPVP,
00374                                         eq::Zoom(), glObjects );
00375         }
00376 
00377         for( unsigned j = 0; j <= tiles; ++j )
00378             images[ j ]->syncReadback();
00379 
00380         event.msec = clock.getTimef();
00381         config->sendEvent( event );
00382 
00383         if( tiles == NUM_IMAGES-1 )
00384             for( unsigned j = 0; j <= tiles; ++j )
00385                 _saveImage(images[j],"GL_BGRA","GL_UNSIGNED_BYTE","tiles_PBO" );
00386 
00387 
00388         //---- benchmark assembly operations
00389         subPVP.y = pvp.y + tiles * subPVP.h;
00390 
00391         eq::Compositor::ImageOp op;
00392         op.channel = this;
00393         op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
00394         op.offset  = offset;
00395 
00396         // fixed-function
00397         event.data.type = ConfigEvent::ASSEMBLE;
00398         snprintf( event.formatType, 64, 
00399                   "Tiled assembly (GL1.1) of %d images", tiles+1 ); 
00400 
00401         clock.reset();
00402         for( unsigned j = 0; j <= tiles; ++j )
00403             eq::Compositor::assembleImage( images[j], op );
00404 
00405         event.msec = clock.getTimef();
00406         config->sendEvent( event );
00407 
00408         // CPU
00409         snprintf( event.formatType, 64,
00410                   "Tiled assembly (CPU)   of %d images", tiles+1 ); 
00411 
00412         std::vector< eq::Frame* > frames;
00413         frames.push_back( &_frame );
00414 
00415         clock.reset();
00416         eq::Compositor::assembleFramesCPU( frames, this );
00417         event.msec = clock.getTimef();
00418         config->sendEvent( event );            
00419     }
00420 }
00421 
00422 void Channel::_testDepthAssemble()
00423 {
00424     //----- setup constant data
00425     const eq::ImageVector& images = _frame.getImages();
00426     eq::Image*             image  = images[ 0 ];
00427     EQASSERT( image );
00428 
00429     eq::Config*              config = getConfig();
00430     const eq::PixelViewport& pvp    = getPixelViewport();
00431     const eq::Vector2i     offset( pvp.x, pvp.y );
00432 
00433     ConfigEvent event = _createConfigEvent();
00434     event.area.x() = pvp.w;
00435 
00436     Clock                      clock;
00437     eq::Window::ObjectManager* glObjects = getObjectManager();
00438 
00439 
00440     //----- test depth-based assembly algorithms
00441     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00442     {
00443         image = images[ i ];
00444         EQASSERT( image );
00445         image->setPixelViewport( pvp );
00446     }
00447 
00448     event.area.y() = pvp.h;
00449 
00450     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00451     {
00452         _draw( i );
00453 
00454         // fill depth & color image
00455         image = images[ i ];
00456         image->setFormat( eq::Frame::BUFFER_COLOR, GL_BGRA );
00457         image->setType(   eq::Frame::BUFFER_COLOR, GL_UNSIGNED_BYTE );
00458         image->setFormat( eq::Frame::BUFFER_DEPTH, GL_DEPTH_COMPONENT );
00459         image->setType(   eq::Frame::BUFFER_DEPTH, GL_UNSIGNED_INT );
00460         image->clearPixelData( eq::Frame::BUFFER_COLOR );
00461         image->clearPixelData( eq::Frame::BUFFER_DEPTH );
00462 
00463         image->startReadback( eq::Frame::BUFFER_COLOR | 
00464                               eq::Frame::BUFFER_DEPTH, pvp, eq::Zoom(),
00465                               glObjects );
00466         image->syncReadback();
00467 
00468         if( i == NUM_IMAGES-1 )
00469             _saveImage( image,"GL_BGRA","GL_UNSIGNED_BYTE","depthAssemble" );
00470 
00471         // benchmark
00472         eq::Compositor::ImageOp op;
00473         op.channel = this;
00474         op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
00475         op.offset  = offset;
00476 
00477         // fixed-function
00478         event.data.type = ConfigEvent::ASSEMBLE;
00479         snprintf( event.formatType, 64, 
00480                   "Depth-based assembly (GL1.1) of %d images", i+1 ); 
00481 
00482         clock.reset();
00483         for( unsigned j = 0; j <= i; ++j )
00484             eq::Compositor::assembleImageDB_FF( images[j], op );
00485 
00486         event.msec = clock.getTimef();
00487         config->sendEvent( event );            
00488 
00489         // GLSL
00490         if( GLEW_VERSION_2_0 )
00491         {
00492             snprintf( event.formatType, 64,
00493                       "Depth-based assembly (GLSL)  of %d images", i+1 ); 
00494 
00495             clock.reset();
00496             for( unsigned j = 0; j <= i; ++j )
00497                 eq::Compositor::assembleImageDB_GLSL( images[j], op );
00498             event.msec = clock.getTimef();
00499             config->sendEvent( event );
00500         }
00501 
00502         // CPU
00503         snprintf( event.formatType, 64, 
00504                   "Depth-based assembly (CPU)   of %d images", i+1 ); 
00505 
00506         std::vector< eq::Frame* > frames;
00507         frames.push_back( &_frame );
00508 
00509         clock.reset();
00510         eq::Compositor::assembleFramesCPU( frames, this );
00511         event.msec = clock.getTimef();
00512         config->sendEvent( event );            
00513     }
00514 }
00515 
00516 void Channel::_saveImage( const eq::Image* image,
00517                           const char*      type,
00518                           const char*      format,
00519                           const char*      info    )
00520 {
00521     return;
00522 
00523     static uint32_t counter = 0;
00524     ostringstream stringstream;
00525     stringstream << "Image_" << ++counter << "_"
00526                  << type << "_" << format << "_" << info;
00527     image->writeImages( stringstream.str( ));
00528 }
00529 
00530 
00531 void Channel::_draw( const uint32_t spin )
00532 {
00533     glPushAttrib( GL_ALL_ATTRIB_BITS );
00534 
00535     eq::Channel::frameDraw( spin );
00536 
00537     glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
00538     glEnable( GL_DEPTH_TEST );
00539 
00540 #ifdef _0
00541     setNearFar( 0.5f, 5.0f );
00542     const GLfloat lightPosition[]    = {5.0f, 0.0f, 5.0f, 0.0f};
00543     const GLfloat lightDiffuse[]     = {0.8f, 0.8f, 0.8f, 1.0f};
00544 
00545     const GLfloat materialDiffuse[]  = {0.8f, 0.8f, 0.8f, 1.0f};
00546 
00547     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00548     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00549 
00550     glMaterialfv( GL_FRONT, GL_DIFFUSE,   materialDiffuse );
00551 
00552     eq::Matrix4f rotation;
00553     eq::Vector3f translation;
00554 
00555     translation   = eq::Vector3f::ZERO;
00556     translation.z = -2.f;
00557     rotation = eq::Matrix4f::IDENTITY;
00558     rotation.rotate_x( static_cast<float>( -M_PI_2 ));
00559     rotation.rotate_y( static_cast<float>( -M_PI_2 ));
00560 
00561     glTranslatef( translation.x, translation.y, translation.z );
00562     glMultMatrixf( rotation.ml );
00563 
00564     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00565     glColor3f( 1.f, 1.f, 0.f );
00566     glNormal3f( 1.f, -1.f, 0.f );
00567     glBegin( GL_TRIANGLE_STRIP );
00568         glVertex3f(  1.f, 10.f,  2.5f );
00569         glVertex3f( -1.f, 10.f,  2.5f );
00570         glVertex3f(  1.f,-10.f, -2.5f );
00571         glVertex3f( -1.f,-10.f, -2.5f );
00572     glEnd();
00573 
00574 #else
00575 
00576     const float lightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f };
00577     glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
00578 
00579     const float lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
00580     glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
00581 
00582     // rotate scene around the origin
00583     glRotatef( static_cast< float >( spin + 3 ) * 10, 1.0f, 0.5f, 0.25f );
00584 
00585     // render six axis-aligned colored quads around the origin
00586     //  front
00587     glColor3f( 1.0f, 0.5f, 0.5f );
00588     glNormal3f( 0.0f, 0.0f, 1.0f );
00589     glBegin( GL_TRIANGLE_STRIP );
00590     glVertex3f(  .7f,  .7f, -1.0f );
00591     glVertex3f( -.7f,  .7f, -1.0f );
00592     glVertex3f(  .7f, -.7f, -1.0f );
00593     glVertex3f( -.7f, -.7f, -1.0f );
00594     glEnd();
00595 
00596     //  bottom
00597     glColor3f( 0.5f, 1.0f, 0.5f );
00598     glNormal3f( 0.0f, 1.0f, 0.0f );
00599     glBegin( GL_TRIANGLE_STRIP );
00600     glVertex3f(  .7f, -1.0f,  .7f );
00601     glVertex3f( -.7f, -1.0f,  .7f );
00602     glVertex3f(  .7f, -1.0f, -.7f );
00603     glVertex3f( -.7f, -1.0f, -.7f );
00604     glEnd();
00605 
00606     //  back
00607     glColor3f( 0.5f, 0.5f, 1.0f );
00608     glNormal3f( 0.0f, 0.0f, -1.0f );
00609     glBegin( GL_TRIANGLE_STRIP );
00610     glVertex3f(  .7f,  .7f, 1.0f );
00611     glVertex3f( -.7f,  .7f, 1.0f );
00612     glVertex3f(  .7f, -.7f, 1.0f );
00613     glVertex3f( -.7f, -.7f, 1.0f );
00614     glEnd();
00615 
00616     //  top
00617     glColor3f( 1.0f, 1.0f, 0.5f );
00618     glNormal3f( 0.f, -1.f, 0.f );
00619     glBegin( GL_TRIANGLE_STRIP );
00620     glVertex3f(  .7f, 1.0f,  .7f );
00621     glVertex3f( -.7f, 1.0f,  .7f );
00622     glVertex3f(  .7f, 1.0f, -.7f );
00623     glVertex3f( -.7f, 1.0f, -.7f );
00624     glEnd();
00625 
00626     //  right
00627     glColor3f( 1.0f, 0.5f, 1.0f );
00628     glNormal3f( -1.f, 0.f, 0.f );
00629     glBegin( GL_TRIANGLE_STRIP );
00630     glVertex3f( 1.0f,  .7f,  .7f );
00631     glVertex3f( 1.0f, -.7f,  .7f );
00632     glVertex3f( 1.0f,  .7f, -.7f );
00633     glVertex3f( 1.0f, -.7f, -.7f );
00634     glEnd();
00635 
00636     //  left
00637     glColor3f( 0.5f, 1.0f, 1.0f );
00638     glNormal3f( 1.f, 0.f, 0.f );
00639     glBegin( GL_TRIANGLE_STRIP );
00640     glVertex3f( -1.0f,  .7f,  .7f );
00641     glVertex3f( -1.0f, -.7f,  .7f );
00642     glVertex3f( -1.0f,  .7f, -.7f );
00643     glVertex3f( -1.0f, -.7f, -.7f );
00644     glEnd();
00645 
00646 #endif
00647 
00648     glPopAttrib( );
00649 }
00650 
00651 
00652 }
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8