00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "Teddy/Graphics/Device.h"
00026 #include "Teddy/TeddyConfig.h"
00027 #include "Teddy/Graphics/Font.h"
00028 #include "Teddy/Graphics/PsRenderer.h"
00029 #include "Teddy/Graphics/Texture.h"
00030 #include "Teddy/Graphics/View.h"
00031 #include "Teddy/Maths/Matrix.h"
00032 #include "Teddy/PhysicalComponents/WindowManager.h"
00033 #include "Teddy/PhysicalComponents/Style.h"
00034 #include "Teddy/SysSupport/Messages.h"
00035 #include "Teddy/SysSupport/StdSDL.h"
00036 #include "Teddy/SysSupport/StdIO.h"
00037 #ifndef SWIG
00038 #include <cstdlib>
00039 #endif
00040 using namespace Teddy::Maths;
00041 using namespace Teddy::MixIn;
00042 using namespace Teddy::PhysicalComponents;
00043 using namespace Teddy::SysSupport;
00044
00045
00046 namespace Teddy {
00047 namespace Graphics {
00048
00049
00050 View *View::active = NULL;
00051
00052
00053 const int View::OPT_FRAME = (1ul<<1ul);
00054 const int View::OPT_FULLSCREEN = (1ul<<2ul);
00055 const int View::OPT_MULTI_WINDOW = (1ul<<3ul);
00056 const int View::OPT_SEPARATE_SPECULAR_COLOR = (1ul<<4ul);
00057 const int View::OPT_FONT_FIX = (1ul<<5ul);
00058
00059
00061 void View::displayPs( char *filename ){
00062 # if !defined( USE_TINY_GL )
00063
00064 long max_len = 1024*1024;
00065 GLfloat *buffer = new GLfloat[max_len];
00066 glFeedbackBuffer( max_len, GL_3D_COLOR, buffer );
00067 glRenderMode( GL_FEEDBACK );
00068
00069
00070 if( clear == true ){
00071 glClearColor( clear_color.rgba[0], clear_color.rgba[1], clear_color.rgba[2], clear_color.rgba[3] );
00072 glClearDepth( 1 );
00073 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00074 }
00075 current_texture = NULL;
00076 window_manager->draw();
00077
00078
00079 GLint len = glRenderMode( GL_RENDER );
00080 PsRenderer ps;
00081 ps.writePs( filename, buffer, len, true );
00082 delete[] buffer;
00083 # endif
00084 }
00085
00087 void View::display(){
00088
00089 # if !defined( USE_TINY_GL )
00090 if( clear == true ){
00091 # endif
00092 glClearColor( clear_color.rgba[0], clear_color.rgba[1], clear_color.rgba[2], clear_color.rgba[3] );
00093 glClearDepth( 1 );
00094 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00095 # if !defined( USE_TINY_GL )
00096 }
00097 # endif
00098
00099 current_texture = NULL;
00100
00101
00102 window_manager->draw();
00103
00104 # if defined( USE_TINY_GL )
00105 sdl_swgl_SwapBuffers();
00106 # else
00107 SDL_GL_SwapBuffers();
00108 # endif
00109
00110
00111
00112 frames++;
00113 Uint32 clock_time = SDL_GetTicks();
00114
00115
00116
00117
00118
00119
00120 if( (clock_time - last_fps) > 1000 ){
00121 fps = (float)(frames*1000) / (float)(clock_time - last_fps);
00122 frames = 0;
00123 last_fps = clock_time;
00124 }
00125 last_frame = clock_time - last_time;
00126 last_time = clock_time;
00127 }
00128
00129
00130 void View::setClearColor( const Color &clear_color ){
00131 this->clear_color = clear_color;
00132 }
00133
00134
00135 void View::setCull( unsigned long dir ){
00136 if( dir == 0 ){
00137 msg( M_INIT, "setCull back" );
00138 glCullFace ( GL_BACK );
00139 glFrontFace( GL_CW );
00140 }else{
00141 msg( M_INIT, "setCull front" );
00142 glCullFace ( GL_FRONT );
00143 glFrontFace( GL_CW );
00144
00145 }
00146 }
00147
00148
00161 View::View( int width, int height, Options options )
00162 :
00163 options(options)
00164 {
00165 active = this;
00166 clear = true;
00167 clear_color = Color( 0.5f, 0.5, 0.5f, 1.0f );
00168
00169 const SDL_VideoInfo *info = NULL;
00170 int bpp = 0;
00171
00172
00173 info = SDL_GetVideoInfo();
00174 if( info==NULL ){
00175 fmsg( M_GL, "SDL_getVideoInfo() failed" );
00176 }
00177 if( info->vfmt == NULL ){
00178 fmsg( M_GL, "SDL_getVideoInfo() failed - no format?!" );
00179 }
00180
00181 bpp = info->vfmt->BitsPerPixel;
00182
00183 # if defined( USE_TINY_GL )
00184
00185 sdl_surface = SDL_SetVideoMode(width, height, 16, SDL_DOUBLEBUF);
00186 if( sdl_surface == NULL ) {
00187 fmsg( M_GL, "Couldn't set %dx%d video mode: %s", width, height, SDL_GetError() );
00188 }
00189
00190 sdl_swgl_Context *context = sdl_swgl_CreateContext();
00191 sdl_swgl_MakeCurrent( sdl_surface, context );
00192 # else
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 msg( M_INIT, "SDL_GL_SetAttribute..." );
00210 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
00211 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
00212 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
00213 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
00214
00215 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
00216
00217 unsigned long sdl_flags = SDL_OPENGL;
00218 if( options.isDisabled(OPT_FRAME) ){ sdl_flags |= SDL_NOFRAME; }
00219 if( options.isEnabled (OPT_FULLSCREEN) ){ sdl_flags |= SDL_FULLSCREEN; }
00220
00221
00222
00223
00224 msg( M_INIT, "SDL_SetVideoMode( %d, %d, %d, 0x%x )...", width, height, bpp, sdl_flags );
00225 sdl_surface = SDL_SetVideoMode( width, height, bpp, sdl_flags );
00226 if( sdl_surface == 0 ) {
00227
00228
00229
00230
00231
00232 fmsg( M_GL, "Video mode set failed: %s", SDL_GetError() );
00233 }else{
00234 msg( M_INIT, "Video mode ok..." );
00235 }
00236
00237 int gl_depth_size;
00238 SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &gl_depth_size );
00239
00240 msg( M_INIT, "Got %d bits for depth buffer", gl_depth_size );
00241 # endif
00242
00243 SDL_WM_SetCaption( "Teddy", NULL );
00244
00245 if( Font::default_font == &Font::dummy_font ){
00246 if( options.isEnabled (OPT_FONT_FIX) ){
00247 Font::default_font = new Font( "Data/gui/fonts.raw", Font::MODE_NO_BLEND );
00248 }else{
00249 Font::default_font = new Font( "Data/gui/fonts.raw", Font::MODE_NORMAL );
00250 }
00251 }
00252 if( Style::default_style == NULL ){
00253 Style::default_style = new Style();
00254 }
00255
00256
00257
00258 gl_polygon_mode = GL_FILL;
00259 gl_shade_model = GL_FLAT;
00260 gl_blend_source_factor = GL_SRC_ALPHA;
00261 gl_blend_destination_factor = GL_ONE_MINUS_SRC_ALPHA;
00262 gl_fog_mode = GL_LINEAR;
00263 gl_fog_color[0] = 0;
00264 gl_fog_color[1] = 0;
00265 gl_fog_color[2] = 0;
00266 gl_fog_start = 0;
00267 gl_fog_end = 1;
00268 gl_clear_depth = 1;
00269 size = IntVector2( width, height );
00270
00271 dmsg( M_WM, "view::getSize() = %d x %d", size[0], size[1] );
00272
00273 ratio = (float)width/(float)height;
00274 frames = 0;
00275 last_frame = 0;
00276 last_time = 0;
00277 last_fps = 0;
00278 fps = 0;
00279 screen_width = 0;
00280 screen_height = 0;
00281 current_matrix_mode = GL_MODELVIEW;
00282 current_texture = NULL;
00283 current_element = -1;
00284
00285 glMatrixMode( GL_MODELVIEW );
00286
00287 for( int i=0; i<256; i++ ){
00288 gl_feature[i] = false;
00289 }
00290
00291 Color ambient = Color::RED;
00292 Color diffuse = Color::RED;
00293 Color specular = Color::RED;
00294 Color emission = Color::RED;
00295 float shininess = 1.0f;
00296
00297
00298 glColor4f ( 0.5f, 0.5f, 0.5f, 1.0f );
00299 glMaterialfv ( GL_FRONT, GL_AMBIENT, ambient .rgba );
00300 glMaterialfv ( GL_FRONT, GL_DIFFUSE, diffuse .rgba );
00301 glMaterialfv ( GL_FRONT, GL_SPECULAR, specular.rgba );
00302 glMaterialfv ( GL_FRONT, GL_EMISSION, emission.rgba );
00303 glMaterialf ( GL_FRONT, GL_SHININESS, shininess );
00304 glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE );
00305
00306 glHint ( GL_POLYGON_SMOOTH_HINT, GL_FASTEST );
00307
00308 glHint ( GL_LINE_SMOOTH_HINT, GL_FASTEST );
00309 setCull ( 0 );
00310
00311 # if !defined( USE_TINY_GL )
00312 if( hasExtension("GL_EXT_separate_specular_color") ){
00313 if( options.isEnabled(OPT_SEPARATE_SPECULAR_COLOR) ){
00314 glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT );
00315 dmsg( M_INIT, "GL_LIGHT_MODEL_COLOR_CONTROL_EXT set to GL_SEPARATE_SPECULAR_COLOR_EXT" );
00316 }
00317 }
00318
00319
00320
00321
00322 if( hasExtension("GL_ARB_vertex_program" ) ) dmsg( M_INIT, "GL_ARB_vertex_program" );
00323 if( hasExtension("GL_ARB_fragment_program" ) ) dmsg( M_INIT, "GL_ARB_fragment_program" );
00324 if( hasExtension("GL_EXT_vertex_shader" ) ) dmsg( M_INIT, "GL_EXT_vertex_shader" );
00325 if( hasExtension("GL_NV_vertex_program" ) ) dmsg( M_INIT, "GL_NV_vertex_program" );
00326 if( hasExtension("GL_NV_fragment_program" ) ) dmsg( M_INIT, "GL_NV_fragment_program" );
00327 if( hasExtension("GL_ATI_fragment_shader" ) ) dmsg( M_INIT, "GL_ATI_fragment_shader" );
00328
00329 if( hasExtension("GL_EXT_rescale_normal" ) ) dmsg( M_INIT, "GL_EXT_rescale_normal" );
00330 if( hasExtension("GL_EXT_cull_vertex" ) ) dmsg( M_INIT, "GL_EXT_cull_vertex" );
00331 if( hasExtension("SGIX_reference_plane" ) ) dmsg( M_INIT, "SGIX_reference_plane" );
00332 if( hasExtension("GL_SGIX_reference_plane" ) ) dmsg( M_INIT, "GL_SGIX_reference_plane" );
00333 if( hasExtension("GL_IBM_texture_mirrored_repeat" ) ) dmsg( M_INIT, "GL_IBM_texture_mirrored_repeat" );
00334 if( hasExtension("GL_EXT_texture_filter_anisotropic") ) dmsg( M_INIT, "GL_EXT_texture_filter_anisotropic" );
00335 if( hasExtension("GL_ARB_texture_compression" ) ) dmsg( M_INIT, "GL_ARB_texture_compression" );
00336 if( hasExtension("GL_EXT_texture_compression_s3tc" ) ) dmsg( M_INIT, "GL_EXT_texture_compression_s3tc" );
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 dmsg( M_INIT, "OpenGL vendor: %s", getVendor () );
00349 dmsg( M_INIT, "OpenGL renderer: %s", getRenderer () );
00350 dmsg( M_INIT, "OpenGL version: %s", getVersion () );
00351 dmsg( M_INIT, "\nOpenGL extensions: %s\n", getExtensions() );
00352 check();
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE );
00372 glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
00373 setBlendFunc ( GL_ONE, GL_ONE );
00374 # endif
00375 check();
00376 }
00377
00378
00380 void View::displayOne(){
00381 active->display();
00382 }
00383
00384
00389 float View::getRatio(){
00390 return ratio;
00391 }
00392
00393 int View::getFrames(){
00394 return frames;
00395 }
00396
00397
00398 float View::getLastFrame(){
00399 return last_frame;
00400 }
00401
00402
00403 float View::getFps(){
00404 return fps;
00405 }
00406
00407
00408 float View::getLastTime(){
00409 return last_time;
00410 }
00411
00412
00413 int View::getScreenWidth(){
00414 return screen_width;
00415 }
00416
00417
00418 int View::getScreenHeight(){
00419 return screen_height;
00420 }
00421
00422
00424
00425
00426
00427
00428
00429 void View::setState( const int feature, const bool state ){
00430 if( state ){
00431 enable( feature );
00432 }else{
00433 disable( feature );
00434 }
00435 }
00436
00437
00443 void View::setClear( bool clear ){
00444 this->clear = clear;
00445 }
00446
00447
00449 bool View::getClear(){
00450 return this->clear;
00451 }
00452
00453
00454 bool View::getState( const int feature ){
00455 GLenum code = getCode( feature );
00456
00457 # if defined( USE_TINY_GL )
00458 if( gl_feature[feature] == true ){
00459 return true;
00460 }else{
00461 return false;
00462 }
00463 # else
00464
00465 if( glIsEnabled(code) == GL_TRUE ){
00466 if( gl_feature[feature] == true ){
00467 return true;
00468 }else{
00469 dmsg( M_GL, "OpenGL says %s is enabled", feature_to_str(feature) );
00470 dmsg( M_GL, "But I thought it was disabled!" );
00471 dmsg( M_GL, "Check use of attribute stack" );
00472 gl_feature[feature] = true;
00473 return true;
00474 }
00475 }
00476 if( glIsEnabled(code) == GL_FALSE ){
00477 if( gl_feature[feature] == false ){
00478 return false;
00479 }else{
00480 dmsg( M_GL, "OpenGL says %s is disabled", feature_to_str(feature) );
00481 dmsg( M_GL, "But I thought it was enabled!" );
00482 dmsg( M_GL, "Check use of attribute stack" );
00483 gl_feature[feature] = false;
00484 return false;
00485 }
00486 }
00487
00488 # endif
00489
00490 return false;
00491 }
00492
00493
00495 void View::enable( const int feature ){
00496 if( gl_feature[feature] == false ){
00497 gl_feature[feature] = true;
00498 dmsg( M_GL, "%s enabled", feature_to_str(feature) );
00499 GLenum code = getCode( feature );
00500 glEnable( code );
00501 }
00502 }
00503
00504
00506 void View::disable( const int feature ){
00507 if( gl_feature[feature] == true ){
00508 gl_feature[feature] = false;
00509 dmsg( M_GL, "%s disabled", feature_to_str(feature) );
00510 GLenum code = getCode( feature );
00511 glDisable( code );
00512
00513
00514 }
00515 }
00516
00517
00519 void View::reshape( int w, int h ){
00520 glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
00521
00522 ratio = (GLfloat)w/(GLfloat)h;
00523 size = Vector2( w, h );
00524 window_manager->update();
00525 displayOne();
00526 }
00527
00528
00529 const Teddy::Maths::TVector2<int> &View::getSize() const {
00530 dmsg( M_WM, "view::getSize() = %d x %d", size[0], size[1] );
00531 return size;
00532 }
00533
00534
00535 void View::setWindowManager( WindowManager *wm ){
00536 this->window_manager = wm;
00537 }
00538
00539
00540 Matrix View::getOrthoMatrix( float left, float right, float bottom, float top, float nearval, float farval ){
00541 float x;
00542 float y;
00543 float z;
00544 float tx;
00545 float ty;
00546 float tz;
00547 Matrix ortho_matrix;
00548
00549 x = 2 / (right -left );
00550 y = 2 / (top -bottom );
00551 z = -2 / (farval-nearval);
00552 tx = -(right +left ) / (right -left );
00553 ty = -(top +bottom ) / (top -bottom );
00554 tz = -(farval+nearval) / (farval-nearval);
00555
00556 # define M(row,col) ortho_matrix.m[col][row]
00557 M(0,0) = x; M(0,1) = 0; M(0,2) = 0; M(0,3) = tx;
00558 M(1,0) = 0; M(1,1) = y; M(1,2) = 0; M(1,3) = ty;
00559 M(2,0) = 0; M(2,1) = 0; M(2,2) = z; M(2,3) = tz;
00560 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
00561 # undef M
00562
00563 return ortho_matrix;
00564 }
00565
00567 void View::begin2d(){
00568 check();
00569 Matrix om = getOrthoMatrix( 0, size[0], size[1], 0, 0.0f, 1.0f );
00570
00571 disable ( LIGHTING );
00572 disable ( DEPTH_TEST );
00573 disable ( CULL_FACE );
00574 disable ( BLEND );
00575 glViewport ( 0, 0, size[0], size[1] );
00576 color ( C_WHITE );
00577 setPolygonMode ( GL_FILL );
00578 setProjectionMatrix( om );
00579 setModelViewMatrix ( Matrix::IDENTITY );
00580
00581 check();
00582 }
00583
00584
00586 void View::end2d(){
00587 }
00588
00589
00591 void View::begin3d(){
00592 }
00593
00594
00596 void View::end3d(){
00597 }
00598
00599
00601 void View::setPolygonMode( const unsigned int polygon_mode ){
00602 if( gl_polygon_mode != polygon_mode ){
00603 gl_polygon_mode = polygon_mode;
00604
00605 # ifdef GRAPHICS_STATE_DEBUG
00606 if( polygon_mode == GL_FILL ){
00607 dmsg( M_GL, "polygon mode fill" );
00608 }else if( polygon_mode == GL_LINE ){
00609 dmsg( M_GL, "polygon mode line" );
00610 }else if( polygon_mode == GL_POINTS ){
00611 dmsg( M_GL, "polygon mode points" );
00612 }else{
00613 dmsg( M_GL, "unknown polygon mode \d ", (int)(polygon_mode) );
00614 }
00615 # endif
00616
00617 glPolygonMode( GL_FRONT_AND_BACK, polygon_mode );
00618 }
00619 }
00620
00621
00623 void View::setShadeModel( const unsigned int shade_model ){
00624 if( gl_shade_model != shade_model ){
00625 gl_shade_model = shade_model;
00626 glShadeModel( shade_model );
00627 }
00628 }
00629
00630
00632 void View::setBlendFunc( const unsigned int sfactor, const unsigned int dfactor ){
00633 #if !defined( USE_TINY_GL )
00634 if( gl_blend_source_factor != sfactor ||
00635 gl_blend_destination_factor != dfactor )
00636 {
00637 gl_blend_source_factor = sfactor;
00638 gl_blend_destination_factor = dfactor;
00639 glBlendFunc( sfactor, dfactor );
00640 }
00641 #endif
00642 }
00643
00644
00646 void View::setFogMode( const unsigned int mode ){
00647 # if !defined( USE_TINY_GL )
00648 if( gl_fog_mode != mode ){
00649 gl_fog_mode = mode;
00650 glFogi( GL_FOG_MODE, mode );
00651 }
00652 # endif
00653 }
00654
00655
00657 void View::setFogColor( float *color ){
00658 # if !defined( USE_TINY_GL )
00659 glFogfv( GL_FOG_COLOR, color );
00660 # endif
00661 }
00662
00663
00665 void View::setFogStart( float start ){
00666 # if !defined( USE_TINY_GL )
00667 if( gl_fog_start != start ){
00668 gl_fog_start = start;
00669 glFogf( GL_FOG_START, start );
00670 }
00671 # endif
00672 }
00673
00674
00676 void View::setFogEnd( float end ){
00677 # if !defined( USE_TINY_GL )
00678 glFogf( GL_FOG_END, end );
00679 # endif
00680 }
00681
00682
00684 void View::check(){
00685 # if !defined( USE_TINY_GL )
00686 int e;
00687
00688 e = glGetError();
00689 switch( e ){
00690 case GL_NO_ERROR: break;
00691 case GL_INVALID_VALUE: emsg( M_GL, "OpenGL error: Invalid value" ); break;
00692 case GL_INVALID_ENUM: emsg( M_GL, "OpenGL error: Invalid enum" ); break;
00693 case GL_INVALID_OPERATION: emsg( M_GL, "OpenGL error: Invalid operation" ); break;
00694 case GL_STACK_OVERFLOW: emsg( M_GL, "OpenGL error: Stack overflow" ); break;
00695 case GL_STACK_UNDERFLOW: emsg( M_GL, "OpenGL error: Stack underflow" ); break;
00696 case GL_OUT_OF_MEMORY: emsg( M_GL, "OpenGL error: Out of memory" ); break;
00697 default: emsg( M_GL, "Unknown OpenGL error" ); break;
00698 }
00699 # endif
00700 }
00701
00702
00704 SDL_Surface *View::getSurface(){
00705 return sdl_surface;
00706 }
00707
00708
00709 void View::printExtensions(){
00710 }
00711
00713 bool View::hasExtension( const char *ext_name ){
00714 int ext_name_len = strlen( ext_name );
00715 char *p = getExtensions();
00716 if( p == NULL ){
00717 return false;
00718 }
00719 char *end = p + strlen( p );
00720
00721 while( p < end ){
00722 int n = strcspn( p, " " );
00723 if( (ext_name_len == n ) &&
00724 (strncmp(ext_name, p, n) == 0 ) )
00725 {
00726 return true;
00727 }
00728 p += (n + 1);
00729 }
00730 return false;
00731 }
00732
00733
00734 };
00735 };
00736