home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * renderer.cpp - Render Queueing
- *
- * Copyright (C) 2006 - 2008 Florian Richter
- ***************************************************************************/
- /*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include "../video/renderer.h"
- #include "../core/globals.h"
- #include "../core/game_core.h"
- #include "../core/camera.h"
-
- #include <math.h>
-
- #ifndef M_PI
- #define M_PI 3.14159265358979323846
- #endif
-
- const float doubled_pi = static_cast<float>(M_PI * 2);
- const float hundred_of_double_pi = doubled_pi / 100;
-
- /* *** *** *** *** *** *** cRenderRequest *** *** *** *** *** *** *** *** *** *** *** */
-
- cRenderRequest :: cRenderRequest( void )
- {
- type = REND_NOTHING;
- globalscale = 1;
- no_camera = 1;
-
- pos_z = 0;
- blend_sfactor = GL_SRC_ALPHA;
- blend_dfactor = GL_ONE_MINUS_SRC_ALPHA;
-
- shadow_pos = 0;
- shadow_color = static_cast<Uint8>(0);
-
- combine_type = 0;
- combine_col[0] = 0;
- combine_col[1] = 0;
- combine_col[2] = 0;
-
- render_count = 1;
- }
-
- cRenderRequest :: ~cRenderRequest( void )
- {
-
- }
-
- void cRenderRequest :: Draw( void )
- {
- // virtual
- }
-
- void cRenderRequest :: Begin_Render( void )
- {
- // todo: is there a way to do this once and not for every render request
- glLoadIdentity();
-
- // global scale
- if( globalscale && ( global_upscalex != 1 || global_upscaley != 1 ) )
- {
- glScalef( global_upscalex, global_upscaley, 1 );
- }
-
- // blend factor
- if( blend_sfactor != GL_SRC_ALPHA || blend_dfactor != GL_ONE_MINUS_SRC_ALPHA )
- {
- glBlendFunc( blend_sfactor, blend_dfactor );
- }
- }
-
- void cRenderRequest :: End_Render( void )
- {
- // clear blend factor
- if( blend_sfactor != GL_SRC_ALPHA || blend_dfactor != GL_ONE_MINUS_SRC_ALPHA )
- {
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- }
-
- // if debug build check for errors
- #ifdef _DEBUG
- GLenum error = glGetError();
- if( error != GL_NO_ERROR )
- {
- printf( "RenderRequest : GL Error found : %s\n", gluErrorString( error ) );
- }
- #endif
- }
-
- void cRenderRequest :: Begin_Color_Combine( void )
- {
- // Color Combine
- if( combine_type != 0 && ( combine_col[0] != 0 || combine_col[1] != 0 || combine_col[2] != 0 ) )
- {
- glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
- glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, combine_type );
- glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT );
- glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, combine_col );
- glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
- }
- }
-
- void cRenderRequest :: End_Color_Combine( void )
- {
- // clear color modifications
- if( combine_type != 0 && ( combine_col[0] != 0 || combine_col[1] != 0 || combine_col[2] != 0 ) )
- {
- float col[3] = { 0.0f, 0.0f, 0.0f };
- glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col );
- glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
- glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
- }
- }
-
- /* *** *** *** *** *** *** cLineRequest *** *** *** *** *** *** *** *** *** *** *** */
-
- cLineRequest :: cLineRequest( void )
- : cRenderRequest()
- {
- type = REND_LINE;
- color = static_cast<Uint8>(0);
- line = GL_line( 0, 0, 0, 0 );
- line_width = 1;
- }
-
- cLineRequest :: ~cLineRequest( void )
- {
-
- }
-
- void cLineRequest :: Draw( void )
- {
- Begin_Render();
-
- // ## position ##
- // set camera position
- if( !no_camera )
- {
- glTranslatef( -pActive_Camera->x, -pActive_Camera->y, pos_z );
- }
- else
- {
- // only z position
- glTranslatef( 0, 0, pos_z );
- }
-
- Begin_Color_Combine();
-
- // color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( color.red, color.green, color.blue, color.alpha );
- }
-
- if( glIsEnabled( GL_TEXTURE_2D ) )
- {
- glDisable( GL_TEXTURE_2D );
- }
-
- if( line_width != 1 )
- {
- glLineWidth( line_width );
- }
-
- glBegin( GL_LINES );
- glVertex2f( line.x1, line.y1 );
- glVertex2f( line.x2, line.y2 );
- glEnd();
-
- // clear line width
- if( line_width != 1 )
- {
- glLineWidth( 1 );
- }
-
- // clear color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( 255, 255, 255, 255 );
- }
-
- End_Color_Combine();
- End_Render();
- }
-
- /* *** *** *** *** *** *** cRectRequest *** *** *** *** *** *** *** *** *** *** *** */
-
- cRectRequest :: cRectRequest( void )
- : cRenderRequest()
- {
- type = REND_RECT;
- color = static_cast<Uint8>(0);
- rect = GL_rect( 0, 0, 0, 0 );
- filled = 1;
- }
-
- cRectRequest :: ~cRectRequest( void )
- {
-
- }
-
- void cRectRequest :: Draw( void )
- {
- Begin_Render();
-
- // set camera position
- if( !no_camera )
- {
- glTranslatef( rect.x - pActive_Camera->x, rect.y - pActive_Camera->y, pos_z );
- }
- // ignore camera position
- else
- {
- glTranslatef( rect.x, rect.y, pos_z );
- }
-
- Begin_Color_Combine();
-
- // color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( color.red, color.green, color.blue, color.alpha );
- }
-
- if( glIsEnabled( GL_TEXTURE_2D ) )
- {
- glDisable( GL_TEXTURE_2D );
- }
-
- if( filled )
- {
- glBegin( GL_POLYGON );
- }
- else
- {
- glBegin( GL_LINE_LOOP );
- }
- glVertex2f( 0, 0 );
- glVertex2f( rect.w, 0 );
- glVertex2f( rect.w, rect.h );
- glVertex2f( 0, rect.h );
- glEnd();
-
-
- // clear color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( 255, 255, 255, 255 );
- }
-
- End_Color_Combine();
- End_Render();
- }
-
- /* *** *** *** *** *** *** cGradientRequest *** *** *** *** *** *** *** *** *** *** *** */
-
- cGradientRequest :: cGradientRequest( void )
- : cRenderRequest()
- {
- type = REND_GRADIENT;
- rect = GL_rect( 0, 0, 0, 0 );
- dir = DIR_UNDEFINED;
- color_1 = static_cast<Uint8>(0);
- color_2 = static_cast<Uint8>(0);
- }
-
- cGradientRequest :: ~cGradientRequest( void )
- {
-
- }
-
- void cGradientRequest :: Draw( void )
- {
- Begin_Render();
-
- // set camera position
- if( !no_camera )
- {
- glTranslatef( rect.x - pActive_Camera->x, rect.y - pActive_Camera->y, pos_z );
- }
- // ignore camera position
- else
- {
- glTranslatef( rect.x, rect.y, pos_z );
- }
-
- if( glIsEnabled( GL_TEXTURE_2D ) )
- {
- glDisable( GL_TEXTURE_2D );
- }
-
- Begin_Color_Combine();
-
- if( dir == DIR_VERTICAL )
- {
- glBegin( GL_POLYGON );
- glColor4ub( color_1.red, color_1.green, color_1.blue, color_1.alpha );
- glVertex2f( 0, 0 );
- glVertex2f( rect.w, 0 );
- glColor4ub( color_2.red, color_2.green, color_2.blue, color_2.alpha );
- glVertex2f( rect.w, rect.h );
- glVertex2f( 0, rect.h );
- glEnd();
-
- }
- else if( dir == DIR_HORIZONTAL )
- {
- glBegin( GL_POLYGON );
- glColor4ub( color_1.red, color_1.green, color_1.blue, color_1.alpha );
- glVertex2f( 0, rect.h );
- glVertex2f( 0, 0 );
- glColor4ub( color_2.red, color_2.green, color_2.blue, color_2.alpha );
- glVertex2f( rect.w, 0 );
- glVertex2f( rect.w, rect.h );
- glEnd();
- }
-
- // clear color
- glColor4ub( 255, 255, 255, 255 );
-
- End_Color_Combine();
- End_Render();
- }
-
- /* *** *** *** *** *** *** cCircleRequest *** *** *** *** *** *** *** *** *** *** *** */
-
- cCircleRequest :: cCircleRequest( void )
- : cRenderRequest()
- {
- type = REND_CIRCLE;
- color = static_cast<Uint8>(0);
- pos = GL_point( 0, 0 );
- radius = 0.1f;
- // default is filled
- line_width = 0;
- }
-
- cCircleRequest :: ~cCircleRequest( void )
- {
-
- }
-
- void cCircleRequest :: Draw( void )
- {
- Begin_Render();
-
- // set camera position
- if( !no_camera )
- {
- glTranslatef( pos.x - pActive_Camera->x, pos.y - pActive_Camera->y, pos_z );
- }
- // ignore camera position
- else
- {
- glTranslatef( pos.x, pos.y, pos_z );
- }
-
- Begin_Color_Combine();
-
- // color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( color.red, color.green, color.blue, color.alpha );
- }
-
- if( glIsEnabled( GL_TEXTURE_2D ) )
- {
- glDisable( GL_TEXTURE_2D );
- }
-
- // set step size based on radius
- float step_size = 1 / ( radius * 0.05f );
-
- // minimum step size
- if( step_size > 0.2f )
- {
- step_size = 0.2f;
- }
-
- float angle = 0;
-
- // not filled
- if( line_width )
- {
- // set line width
- glLineWidth( line_width );
-
- glBegin( GL_LINE_STRIP );
- }
- // filled
- else
- {
- glBegin( GL_TRIANGLE_FAN );
-
- // start with center
- glVertex2f( 0, 0 );
- }
-
- while( angle < doubled_pi )
- {
- glVertex2f( radius * sin( angle ), radius * cos( angle ) );
- angle += step_size;
- }
-
- // draw to end
- angle = doubled_pi;
- glVertex2f( radius * sin( angle ), radius * cos( angle ) );
-
- glEnd();
-
- // clear line width
- if( line_width != 1 )
- {
- glLineWidth( 1 );
- }
-
- // clear color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( 255, 255, 255, 255 );
- }
-
- End_Color_Combine();
- End_Render();
- }
-
- /* *** *** *** *** *** *** cSurfaceRequest *** *** *** *** *** *** *** *** *** *** *** */
-
- cSurfaceRequest :: cSurfaceRequest( void )
- : cRenderRequest()
- {
- type = REND_SURFACE;
- texture_id = 0;
-
- pos_x = 0;
- pos_y = 0;
-
- w = 0;
- h = 0;
-
- rotx = 0;
- roty = 0;
- rotz = 0;
-
- scale_x = 1;
- scale_y = 1;
- scale_z = 1;
-
- color = static_cast<Uint8>(255);
-
- delete_texture = 0;
- }
-
- cSurfaceRequest :: ~cSurfaceRequest( void )
- {
- if( delete_texture && glIsTexture( texture_id ) )
- {
- glDeleteTextures( 1, &texture_id );
- }
- }
-
- void cSurfaceRequest :: Draw( void )
- {
- // draw shadow
- if( shadow_pos )
- {
- // shadow position
- pos_x += shadow_pos;
- pos_y += shadow_pos;
- pos_z -= 0.000001f;
-
- // save data
- Color temp_color = color;
- float temp_shadow_pos = shadow_pos;
- GLint temp_combine_type = combine_type;
- float temp_combine_col[3];
- temp_combine_col[0] = combine_col[0];
- temp_combine_col[1] = combine_col[1];
- temp_combine_col[2] = combine_col[2];
-
- // temporarily unset to prevent endless loop
- shadow_pos = 0;
- // shadow as a white texture
- color = black;
- // keep shadow_color alpha
- color.alpha = shadow_color.alpha;
- // combine color
- combine_type = GL_REPLACE;
- combine_col[0] = static_cast<float>(shadow_color.red) / 260;
- combine_col[1] = static_cast<float>(shadow_color.green) / 260;
- combine_col[2] = static_cast<float>(shadow_color.blue) / 260;
-
- // draw shadow
- Draw();
-
- // set back data
- shadow_pos = temp_shadow_pos;
- color = temp_color;
- combine_type = temp_combine_type;
- combine_col[0] = temp_combine_col[0];
- combine_col[1] = temp_combine_col[1];
- combine_col[2] = temp_combine_col[2];
- pos_z += 0.000001f;
-
- // move back to original position
- pos_x -= shadow_pos;
- pos_y -= shadow_pos;
- }
-
- Begin_Render();
-
- // position
- float final_pos_x = pos_x + ( ( w / 2 ) * scale_x );
- float final_pos_y = pos_y + ( ( h / 2 ) * scale_y );
-
- // set camera position
- if( !no_camera )
- {
- final_pos_x -= pActive_Camera->x;
- final_pos_y -= pActive_Camera->y;
- }
-
- glTranslatef( final_pos_x, final_pos_y, pos_z );
-
- // scale
- if( scale_x != 1 || scale_y != 1 || scale_z != 1 )
- {
- glScalef( scale_x, scale_y, scale_z );
- }
-
- // rotation
- if( rotx != 0 )
- {
- glRotatef( rotx, 1, 0, 0 );
- }
- if( roty != 0 )
- {
- glRotatef( roty, 0, 1, 0 );
- }
- if( rotz != 0 )
- {
- glRotatef( rotz, 0, 0, 1 );
- }
-
- Begin_Color_Combine();
-
- // color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( color.red, color.green, color.blue, color.alpha );
- }
-
- if( !glIsEnabled( GL_TEXTURE_2D ) )
- {
- glEnable( GL_TEXTURE_2D );
- }
-
- // bind texture id
- GLint last_bind_texture = 0;
- glGetIntegerv( GL_TEXTURE_BINDING_2D, &last_bind_texture );
- // only bind if not the same texture
- if( static_cast<GLuint>(last_bind_texture) != texture_id )
- {
- glBindTexture( GL_TEXTURE_2D, texture_id );
- }
-
- // rectangle
- glBegin( GL_QUADS );
- // top left
- glTexCoord2f( 0, 0 );
- glVertex2f( -w / 2, -h / 2 );
- // top right
- glTexCoord2f( 1, 0 );
- glVertex2f( w / 2, -h / 2 );
- // bottom right
- glTexCoord2f( 1, 1 );
- glVertex2f( w / 2, h / 2 );
- // bottom left
- glTexCoord2f( 0, 1 );
- glVertex2f( -w / 2, h / 2 );
- glEnd();
-
-
- // clear color
- if( color.red != 255 || color.green != 255 || color.blue != 255 || color.alpha != 255 )
- {
- glColor4ub( 255, 255, 255, 255 );
- }
-
- End_Color_Combine();
- End_Render();
- }
-
- /* *** *** *** *** *** *** cRenderQueue *** *** *** *** *** *** *** *** *** *** *** */
-
- cRenderQueue :: cRenderQueue( unsigned int reserve_items )
- {
- renderdata.reserve( reserve_items );
- }
-
- cRenderQueue :: ~cRenderQueue( void )
- {
- Clear();
- }
-
- void cRenderQueue :: Add( cRenderRequest *obj )
- {
- if( !obj )
- {
- return;
- }
-
- // if no type
- if( obj->type == REND_NOTHING )
- {
- delete obj;
- return;
- }
-
- renderdata.push_back( obj );
- }
-
- void cRenderQueue :: Render( bool clear /* = 1 */ )
- {
- // z position sort
- sort( renderdata.begin(), renderdata.end(), zpos_sort() );
-
- // draw
- for( RenderList::iterator itr = renderdata.begin(), itr_end = renderdata.end(); itr != itr_end; ++itr )
- {
- // get object pointer
- cRenderRequest *obj = (*itr);
-
- obj->Draw();
- obj->render_count--;
- }
-
- // clear
- if( clear )
- {
- Clear( 0 );
- }
- }
-
- void cRenderQueue :: Clear( bool force /* = 1 */ )
- {
- for( RenderList::iterator itr = renderdata.begin(); itr != renderdata.end(); )
- {
- // get object pointer
- cRenderRequest *obj = (*itr);
-
- // if forced or finished rendering
- if( force || obj->render_count <= 0 )
- {
- itr = renderdata.erase( itr );
- delete obj;
- }
- // increment
- else
- {
- ++itr;
- }
- }
- }
-
- /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
-
- cRenderQueue *pRenderer = NULL;
- cRenderQueue *pRenderer_GUI = NULL;
-