home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / video / renderer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2008-04-22  |  14.0 KB  |  679 lines

  1. /***************************************************************************
  2.  * renderer.cpp  -  Render Queueing
  3.  *
  4.  * Copyright (C) 2006 - 2008 Florian Richter
  5.  ***************************************************************************/
  6. /*
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14. */
  15.  
  16. #include "../video/renderer.h"
  17. #include "../core/globals.h"
  18. #include "../core/game_core.h"
  19. #include "../core/camera.h"
  20.  
  21. #include <math.h>
  22.  
  23. #ifndef M_PI
  24. #define M_PI 3.14159265358979323846
  25. #endif
  26.  
  27. const float doubled_pi = static_cast<float>(M_PI * 2);
  28. const float hundred_of_double_pi = doubled_pi / 100;
  29.  
  30. /* *** *** *** *** *** *** cRenderRequest *** *** *** *** *** *** *** *** *** *** *** */
  31.  
  32. cRenderRequest :: cRenderRequest( void )
  33. {
  34.     type = REND_NOTHING;
  35.     globalscale = 1;
  36.     no_camera = 1;
  37.  
  38.     pos_z = 0;
  39.     blend_sfactor = GL_SRC_ALPHA;
  40.     blend_dfactor = GL_ONE_MINUS_SRC_ALPHA;
  41.  
  42.     shadow_pos = 0;
  43.     shadow_color = static_cast<Uint8>(0);
  44.  
  45.     combine_type = 0;
  46.     combine_col[0] = 0;
  47.     combine_col[1] = 0;
  48.     combine_col[2] = 0;
  49.  
  50.     render_count = 1;
  51. }
  52.  
  53. cRenderRequest :: ~cRenderRequest( void )
  54. {
  55.  
  56. }
  57.  
  58. void cRenderRequest :: Draw( void )
  59. {
  60.     // virtual
  61. }
  62.  
  63. void cRenderRequest :: Begin_Render( void )
  64. {
  65.     // todo: is there a way to do this once and not for every render request
  66.     glLoadIdentity();
  67.  
  68.     // global scale
  69.     if( globalscale && ( global_upscalex != 1 || global_upscaley != 1 ) )
  70.     {
  71.         glScalef( global_upscalex, global_upscaley, 1 );
  72.     }
  73.  
  74.     // blend factor
  75.     if( blend_sfactor != GL_SRC_ALPHA || blend_dfactor != GL_ONE_MINUS_SRC_ALPHA )
  76.     {
  77.         glBlendFunc( blend_sfactor, blend_dfactor );
  78.     }
  79. }
  80.  
  81. void cRenderRequest :: End_Render( void )
  82. {
  83.     // clear blend factor
  84.     if( blend_sfactor != GL_SRC_ALPHA || blend_dfactor != GL_ONE_MINUS_SRC_ALPHA )
  85.     {
  86.         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  87.     }
  88.  
  89.     // if debug build check for errors
  90. #ifdef _DEBUG
  91.     GLenum error = glGetError();
  92.     if( error != GL_NO_ERROR )
  93.     {
  94.         printf( "RenderRequest : GL Error found : %s\n", gluErrorString( error ) );
  95.     }
  96. #endif
  97. }
  98.  
  99. void cRenderRequest :: Begin_Color_Combine( void )
  100. {
  101.     // Color Combine
  102.     if( combine_type != 0 && ( combine_col[0] != 0 || combine_col[1] != 0 || combine_col[2] != 0 ) )
  103.     {
  104.         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
  105.         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, combine_type );
  106.         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT );
  107.         glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, combine_col );
  108.         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
  109.     }
  110. }
  111.  
  112. void cRenderRequest :: End_Color_Combine( void )
  113. {
  114.     // clear color modifications
  115.     if( combine_type != 0 && ( combine_col[0] != 0 || combine_col[1] != 0 || combine_col[2] != 0 ) )
  116.     {
  117.         float col[3] = { 0.0f, 0.0f, 0.0f };
  118.         glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col );
  119.         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
  120.         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  121.     }
  122. }
  123.  
  124. /* *** *** *** *** *** *** cLineRequest *** *** *** *** *** *** *** *** *** *** *** */
  125.  
  126. cLineRequest :: cLineRequest( void )
  127. : cRenderRequest()
  128. {
  129.     type = REND_LINE;
  130.     color = static_cast<Uint8>(0);
  131.     line = GL_line( 0, 0, 0, 0 );
  132.     line_width = 1;
  133. }
  134.  
  135. cLineRequest :: ~cLineRequest( void )
  136. {
  137.  
  138. }
  139.  
  140. void cLineRequest :: Draw( void )
  141. {
  142.     Begin_Render();
  143.  
  144.     // ## position ##
  145.     // set camera position
  146.     if( !no_camera )
  147.     {
  148.         glTranslatef( -pActive_Camera->x, -pActive_Camera->y, pos_z );
  149.     }
  150.     else
  151.     {
  152.         // only z position
  153.         glTranslatef( 0, 0, pos_z );
  154.     }
  155.  
  156.     Begin_Color_Combine();
  157.  
  158.     // color
  159.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  160.     {
  161.         glColor4ub( color.red, color.green, color.blue, color.alpha );
  162.     }
  163.  
  164.     if( glIsEnabled( GL_TEXTURE_2D ) )
  165.     {
  166.         glDisable( GL_TEXTURE_2D );
  167.     }
  168.  
  169.     if( line_width != 1 )
  170.     {
  171.         glLineWidth( line_width );
  172.     }
  173.  
  174.     glBegin( GL_LINES );
  175.         glVertex2f( line.x1, line.y1 );
  176.         glVertex2f( line.x2, line.y2 );
  177.     glEnd();
  178.  
  179.     // clear line width
  180.     if( line_width != 1 )
  181.     {
  182.         glLineWidth( 1 );
  183.     }
  184.  
  185.     // clear color
  186.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  187.     {
  188.         glColor4ub( 255, 255, 255, 255 );
  189.     }
  190.  
  191.     End_Color_Combine();
  192.     End_Render();
  193. }
  194.  
  195. /* *** *** *** *** *** *** cRectRequest *** *** *** *** *** *** *** *** *** *** *** */
  196.  
  197. cRectRequest :: cRectRequest( void )
  198. : cRenderRequest()
  199. {
  200.     type = REND_RECT;
  201.     color = static_cast<Uint8>(0);
  202.     rect = GL_rect( 0, 0, 0, 0 );
  203.     filled = 1;
  204. }
  205.  
  206. cRectRequest :: ~cRectRequest( void )
  207. {
  208.  
  209. }
  210.  
  211. void cRectRequest :: Draw( void )
  212. {
  213.     Begin_Render();
  214.  
  215.     // set camera position
  216.     if( !no_camera )
  217.     {
  218.         glTranslatef( rect.x - pActive_Camera->x, rect.y - pActive_Camera->y, pos_z );
  219.     }
  220.     // ignore camera position
  221.     else
  222.     {
  223.         glTranslatef( rect.x, rect.y, pos_z );
  224.     }
  225.  
  226.     Begin_Color_Combine();
  227.  
  228.     // color
  229.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  230.     {
  231.         glColor4ub( color.red, color.green, color.blue, color.alpha );
  232.     }
  233.  
  234.     if( glIsEnabled( GL_TEXTURE_2D ) )
  235.     {
  236.         glDisable( GL_TEXTURE_2D );
  237.     }
  238.  
  239.     if( filled )
  240.     {
  241.         glBegin( GL_POLYGON );
  242.     }
  243.     else
  244.     {
  245.         glBegin( GL_LINE_LOOP );
  246.     }
  247.         glVertex2f( 0, 0 );
  248.         glVertex2f( rect.w, 0 );
  249.         glVertex2f( rect.w, rect.h );
  250.         glVertex2f( 0, rect.h );
  251.     glEnd();
  252.  
  253.     
  254.     // clear color
  255.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  256.     {
  257.         glColor4ub( 255, 255, 255, 255 );
  258.     }
  259.  
  260.     End_Color_Combine();
  261.     End_Render();
  262. }
  263.  
  264. /* *** *** *** *** *** *** cGradientRequest *** *** *** *** *** *** *** *** *** *** *** */
  265.  
  266. cGradientRequest :: cGradientRequest( void )
  267. : cRenderRequest()
  268. {
  269.     type = REND_GRADIENT;
  270.     rect = GL_rect( 0, 0, 0, 0 );
  271.     dir = DIR_UNDEFINED;
  272.     color_1 = static_cast<Uint8>(0);
  273.     color_2 = static_cast<Uint8>(0);
  274. }
  275.  
  276. cGradientRequest :: ~cGradientRequest( void )
  277. {
  278.  
  279. }
  280.  
  281. void cGradientRequest :: Draw( void )
  282. {
  283.     Begin_Render();
  284.  
  285.     // set camera position
  286.     if( !no_camera )
  287.     {
  288.         glTranslatef( rect.x - pActive_Camera->x, rect.y - pActive_Camera->y, pos_z );
  289.     }
  290.     // ignore camera position
  291.     else
  292.     {
  293.         glTranslatef( rect.x, rect.y, pos_z );
  294.     }
  295.  
  296.     if( glIsEnabled( GL_TEXTURE_2D ) )
  297.     {
  298.         glDisable( GL_TEXTURE_2D );
  299.     }
  300.  
  301.     Begin_Color_Combine();
  302.  
  303.     if( dir == DIR_VERTICAL )
  304.     {
  305.         glBegin( GL_POLYGON );
  306.             glColor4ub( color_1.red, color_1.green, color_1.blue, color_1.alpha );
  307.             glVertex2f( 0, 0 );
  308.             glVertex2f( rect.w, 0 );
  309.             glColor4ub( color_2.red, color_2.green, color_2.blue, color_2.alpha );
  310.             glVertex2f( rect.w, rect.h );
  311.             glVertex2f( 0, rect.h );
  312.         glEnd();
  313.  
  314.     }
  315.     else if( dir == DIR_HORIZONTAL )
  316.     {
  317.         glBegin( GL_POLYGON );
  318.             glColor4ub( color_1.red, color_1.green, color_1.blue, color_1.alpha );
  319.             glVertex2f( 0, rect.h );
  320.             glVertex2f( 0, 0 );
  321.             glColor4ub( color_2.red, color_2.green, color_2.blue, color_2.alpha );
  322.             glVertex2f( rect.w, 0 );
  323.             glVertex2f( rect.w, rect.h );
  324.         glEnd();
  325.     }
  326.  
  327.     // clear color
  328.     glColor4ub( 255, 255, 255, 255 );
  329.  
  330.     End_Color_Combine();
  331.     End_Render();
  332. }
  333.  
  334. /* *** *** *** *** *** *** cCircleRequest *** *** *** *** *** *** *** *** *** *** *** */
  335.  
  336. cCircleRequest :: cCircleRequest( void )
  337. : cRenderRequest()
  338. {
  339.     type = REND_CIRCLE;
  340.     color = static_cast<Uint8>(0);
  341.     pos = GL_point( 0, 0 );
  342.     radius = 0.1f;
  343.     // default is filled
  344.     line_width = 0;
  345. }
  346.  
  347. cCircleRequest :: ~cCircleRequest( void )
  348. {
  349.  
  350. }
  351.  
  352. void cCircleRequest :: Draw( void )
  353. {
  354.     Begin_Render();
  355.  
  356.     // set camera position
  357.     if( !no_camera )
  358.     {
  359.         glTranslatef( pos.x - pActive_Camera->x, pos.y - pActive_Camera->y, pos_z );
  360.     }
  361.     // ignore camera position
  362.     else
  363.     {
  364.         glTranslatef( pos.x, pos.y, pos_z );
  365.     }
  366.  
  367.     Begin_Color_Combine();
  368.  
  369.     // color
  370.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  371.     {
  372.         glColor4ub( color.red, color.green, color.blue, color.alpha );
  373.     }
  374.  
  375.     if( glIsEnabled( GL_TEXTURE_2D ) )
  376.     {
  377.         glDisable( GL_TEXTURE_2D );
  378.     }
  379.  
  380.     // set step size based on radius
  381.     float step_size = 1 / ( radius * 0.05f );
  382.  
  383.     // minimum step size
  384.     if( step_size > 0.2f )
  385.     {
  386.         step_size = 0.2f;
  387.     }
  388.  
  389.     float angle = 0;
  390.  
  391.     // not filled
  392.     if( line_width )
  393.     {
  394.         // set line width
  395.         glLineWidth( line_width );
  396.  
  397.         glBegin( GL_LINE_STRIP );
  398.     }
  399.     // filled
  400.     else
  401.     {
  402.         glBegin( GL_TRIANGLE_FAN );
  403.  
  404.         // start with center
  405.         glVertex2f( 0, 0 );
  406.     }
  407.  
  408.         while( angle < doubled_pi )
  409.         {
  410.             glVertex2f( radius * sin( angle ), radius * cos( angle ) );
  411.             angle += step_size;
  412.         }
  413.  
  414.         // draw to end
  415.         angle = doubled_pi;
  416.         glVertex2f( radius * sin( angle ), radius * cos( angle ) );
  417.  
  418.     glEnd();
  419.  
  420.     // clear line width
  421.     if( line_width != 1 )
  422.     {
  423.         glLineWidth( 1 );
  424.     }
  425.  
  426.     // clear color
  427.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  428.     {
  429.         glColor4ub( 255, 255, 255, 255 );
  430.     }
  431.  
  432.     End_Color_Combine();
  433.     End_Render();
  434. }
  435.  
  436. /* *** *** *** *** *** *** cSurfaceRequest *** *** *** *** *** *** *** *** *** *** *** */
  437.  
  438. cSurfaceRequest :: cSurfaceRequest( void )
  439. : cRenderRequest()
  440. {
  441.     type = REND_SURFACE;
  442.     texture_id = 0;
  443.  
  444.     pos_x = 0;
  445.     pos_y = 0;
  446.  
  447.     w = 0;
  448.     h = 0;
  449.  
  450.     rotx = 0;
  451.     roty = 0;
  452.     rotz = 0;
  453.  
  454.     scale_x = 1;
  455.     scale_y = 1;
  456.     scale_z = 1;
  457.  
  458.     color = static_cast<Uint8>(255);
  459.  
  460.     delete_texture = 0;
  461. }
  462.  
  463. cSurfaceRequest :: ~cSurfaceRequest( void )
  464. {
  465.     if( delete_texture && glIsTexture( texture_id ) )
  466.     {
  467.         glDeleteTextures( 1, &texture_id );
  468.     }
  469. }
  470.  
  471. void cSurfaceRequest :: Draw( void )
  472. {
  473.     // draw shadow
  474.     if( shadow_pos )
  475.     {
  476.         // shadow position
  477.         pos_x += shadow_pos;
  478.         pos_y += shadow_pos;
  479.         pos_z -= 0.000001f;
  480.  
  481.         // save data
  482.         Color temp_color = color;
  483.         float temp_shadow_pos = shadow_pos;
  484.         GLint temp_combine_type = combine_type;
  485.         float temp_combine_col[3];
  486.         temp_combine_col[0] = combine_col[0];
  487.         temp_combine_col[1] = combine_col[1];
  488.         temp_combine_col[2] = combine_col[2];
  489.  
  490.         // temporarily unset to prevent endless loop
  491.         shadow_pos = 0;
  492.         // shadow as a white texture
  493.         color = black;
  494.         // keep shadow_color alpha
  495.         color.alpha = shadow_color.alpha;
  496.         // combine color
  497.         combine_type = GL_REPLACE;
  498.         combine_col[0] = static_cast<float>(shadow_color.red) / 260;
  499.         combine_col[1] = static_cast<float>(shadow_color.green) / 260;
  500.         combine_col[2] = static_cast<float>(shadow_color.blue) / 260;
  501.  
  502.         // draw shadow
  503.         Draw();
  504.  
  505.         // set back data
  506.         shadow_pos = temp_shadow_pos;
  507.         color = temp_color;
  508.         combine_type = temp_combine_type;
  509.         combine_col[0] = temp_combine_col[0];
  510.         combine_col[1] = temp_combine_col[1];
  511.         combine_col[2] = temp_combine_col[2];
  512.         pos_z += 0.000001f;
  513.  
  514.         // move back to original position
  515.         pos_x -= shadow_pos;
  516.         pos_y -= shadow_pos;
  517.     }
  518.  
  519.     Begin_Render();
  520.  
  521.     // position
  522.     float final_pos_x = pos_x + ( ( w / 2 ) * scale_x );
  523.     float final_pos_y = pos_y + ( ( h / 2 ) * scale_y );
  524.  
  525.     // set camera position
  526.     if( !no_camera )
  527.     {
  528.         final_pos_x -= pActive_Camera->x;
  529.         final_pos_y -= pActive_Camera->y;
  530.     }
  531.  
  532.     glTranslatef( final_pos_x, final_pos_y, pos_z );
  533.  
  534.     // scale
  535.     if( scale_x != 1 || scale_y != 1 || scale_z != 1 )
  536.     {
  537.         glScalef( scale_x, scale_y, scale_z );
  538.     }
  539.  
  540.     // rotation
  541.     if( rotx != 0 )
  542.     {
  543.         glRotatef( rotx, 1, 0, 0 );
  544.     }
  545.     if( roty != 0 )
  546.     {
  547.         glRotatef( roty, 0, 1, 0 );
  548.     }
  549.     if( rotz != 0 )
  550.     {
  551.         glRotatef( rotz, 0, 0, 1 );
  552.     }
  553.  
  554.     Begin_Color_Combine();
  555.  
  556.     // color
  557.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  558.     {
  559.         glColor4ub( color.red, color.green, color.blue, color.alpha );
  560.     }
  561.  
  562.     if( !glIsEnabled( GL_TEXTURE_2D ) )
  563.     {
  564.         glEnable( GL_TEXTURE_2D );
  565.     }
  566.  
  567.     // bind texture id
  568.     GLint last_bind_texture = 0;
  569.     glGetIntegerv( GL_TEXTURE_BINDING_2D, &last_bind_texture );
  570.     // only bind if not the same texture
  571.     if( static_cast<GLuint>(last_bind_texture) != texture_id )
  572.     {
  573.         glBindTexture( GL_TEXTURE_2D, texture_id );
  574.     }
  575.  
  576.     // rectangle
  577.     glBegin( GL_QUADS );
  578.         // top left
  579.         glTexCoord2f( 0, 0 );
  580.         glVertex2f( -w / 2, -h / 2 );
  581.         // top right
  582.         glTexCoord2f( 1, 0 );
  583.         glVertex2f( w / 2, -h / 2 );
  584.         // bottom right
  585.         glTexCoord2f( 1, 1 );
  586.         glVertex2f( w / 2, h / 2 );
  587.         // bottom left
  588.         glTexCoord2f( 0, 1 );
  589.         glVertex2f( -w / 2, h / 2 );
  590.     glEnd();
  591.  
  592.     
  593.     // clear color
  594.     if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
  595.     {
  596.         glColor4ub( 255, 255, 255, 255 );
  597.     }
  598.  
  599.     End_Color_Combine();
  600.     End_Render();
  601. }
  602.  
  603. /* *** *** *** *** *** *** cRenderQueue *** *** *** *** *** *** *** *** *** *** *** */
  604.  
  605. cRenderQueue :: cRenderQueue( unsigned int reserve_items )
  606. {
  607.     renderdata.reserve( reserve_items );
  608. }
  609.  
  610. cRenderQueue :: ~cRenderQueue( void )
  611. {
  612.     Clear();
  613. }
  614.  
  615. void cRenderQueue :: Add( cRenderRequest *obj )
  616. {
  617.     if( !obj )
  618.     {
  619.         return;
  620.     }
  621.  
  622.     // if no type
  623.     if( obj->type == REND_NOTHING )
  624.     {
  625.         delete obj;
  626.         return;
  627.     }
  628.  
  629.     renderdata.push_back( obj );
  630. }
  631.  
  632. void cRenderQueue :: Render( bool clear /* = 1 */ )
  633. {
  634.     // z position sort
  635.     sort( renderdata.begin(), renderdata.end(), zpos_sort() );
  636.  
  637.     // draw
  638.     for( RenderList::iterator itr = renderdata.begin(), itr_end = renderdata.end(); itr != itr_end; ++itr )
  639.     {
  640.         // get object pointer
  641.         cRenderRequest *obj = (*itr);
  642.  
  643.         obj->Draw();
  644.         obj->render_count--;
  645.     }
  646.  
  647.     // clear
  648.     if( clear )
  649.     {
  650.         Clear( 0 );
  651.     }
  652. }
  653.  
  654. void cRenderQueue :: Clear( bool force /* = 1 */ )
  655. {
  656.     for( RenderList::iterator itr = renderdata.begin(); itr != renderdata.end(); )
  657.     {
  658.         // get object pointer
  659.         cRenderRequest *obj = (*itr);
  660.  
  661.         // if forced or finished rendering
  662.         if( force || obj->render_count <= 0 )
  663.         {
  664.             itr = renderdata.erase( itr );
  665.             delete obj;
  666.         }
  667.         // increment
  668.         else
  669.         {
  670.             ++itr;
  671.         }
  672.     }
  673. }
  674.  
  675. /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
  676.  
  677. cRenderQueue *pRenderer = NULL;
  678. cRenderQueue *pRenderer_GUI = NULL;
  679.