2010-04-05 23:38:59 +02:00
# include "ViewBase.h"
# include "ModelBase.h"
# include "ControllerBase.h"
# include "CameraBase.h"
# include "OverlayBase.h"
# include "SimpleConsoleOverlay.h"
# include "OGLFT.h"
# include <GL/gl.h>
# include <GL/glu.h>
# include "DrawingsGL.h"
using namespace std ;
namespace Engine {
static ViewBase * ViewInstance = NULL ;
void InitGL ( ) {
glClearColor ( 0.3f , 0.3f , 0.3f , 1.0f ) ;
glClearDepth ( 1.0 ) ;
2010-08-29 23:59:24 +02:00
glDepthFunc ( GL_LEQUAL ) ;
2010-04-05 23:38:59 +02:00
glEnable ( GL_DEPTH_TEST ) ;
glShadeModel ( GL_SMOOTH ) ;
glEnable ( GL_CULL_FACE ) ;
glDisable ( GL_FOG ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
}
/*
* Inherited Module functions
*/
int ViewBase : : OnInit ( int argc , char * argv [ ] ) {
LogMessage ( " View Init " ) ;
mWindowHeight = VIEW_DEFAULT_HEIGHT ;
mWindowWidth = VIEW_DEFAULT_WIDTH ;
2011-02-12 15:43:06 +01:00
// get and save the screen resolution
mScreenHeight = SDL_GetVideoInfo ( ) - > current_h ;
mScreenWidth = SDL_GetVideoInfo ( ) - > current_w ;
mDrawFullscreen = false ;
2010-04-05 23:38:59 +02:00
SDL_GL_SetAttribute ( SDL_GL_DOUBLEBUFFER , 1 ) ;
2011-02-12 15:43:06 +01:00
if ( SDL_SetVideoMode ( mWindowWidth , mWindowHeight , 16 , SDL_OPENGL ) = = 0 ) {
2010-04-05 23:38:59 +02:00
LogError ( " Video mode set failed: %s " , SDL_GetError ( ) ) ;
exit ( - 1 ) ;
}
2011-02-12 15:43:06 +01:00
LogMessage ( " Resolution is %dx%d " , SDL_GetVideoInfo ( ) - > current_w , SDL_GetVideoInfo ( ) - > current_h ) ;
2010-04-05 23:38:59 +02:00
InitGL ( ) ;
Resize ( mWindowWidth , mWindowHeight ) ;
2010-05-02 22:39:49 +02:00
LoadFont ( " console.ttf " ) ;
mCurrentFont = mFonts [ " console.ttf " ] ;
2010-04-05 23:38:59 +02:00
2010-06-06 00:58:11 +02:00
// Overlays
2010-04-14 22:01:45 +02:00
OverlayBasePtr console_overlay ( new SimpleConsoleOverlay ) ;
2010-06-06 00:58:11 +02:00
mOverlayManager . Register ( console_overlay , 0 ) ;
//AddOverlay (console_overlay);
2010-04-05 23:38:59 +02:00
mDrawGrid = false ;
mGridSizeX = 8 ;
mGridSizeZ = 8 ;
ViewInstance = this ;
return 0 ;
}
void ViewBase : : OnDestroy ( ) {
2010-05-02 22:39:49 +02:00
std : : map < std : : string , OGLFT : : Monochrome * > : : iterator iter ;
for ( iter = mFonts . begin ( ) ; iter ! = mFonts . end ( ) ; + + iter ) {
delete iter - > second ;
}
mFonts . clear ( ) ;
2010-04-05 23:38:59 +02:00
ViewInstance = NULL ;
LogDebug ( " View Destroy " ) ;
}
void ViewBase : : CalcWorldCoordinates ( int screen_x , int screen_y , float world_y , float * pos_out ) {
GLdouble modelMatrix [ 16 ] , projMatrix [ 16 ] ;
GLint viewport [ 4 ] ;
GLdouble wx , wy , wz ;
glGetIntegerv ( GL_VIEWPORT , viewport ) ;
glGetDoublev ( GL_MODELVIEW_MATRIX , modelMatrix ) ;
glGetDoublev ( GL_PROJECTION_MATRIX , projMatrix ) ;
int realy = viewport [ 3 ] - screen_y - 1 ;
gluUnProject ( ( GLdouble ) screen_x , ( GLdouble ) realy , 1. ,
modelMatrix , projMatrix , viewport , & wx , & wy , & wz ) ;
GLdouble t ;
GLdouble d [ 3 ] ;
float eye [ 3 ] ;
mCamera - > GetEye ( & eye [ 0 ] ) ;
d [ 0 ] = wx - eye [ 0 ] ;
d [ 1 ] = wy - eye [ 1 ] ;
d [ 2 ] = wz - eye [ 2 ] ;
assert ( fabs ( d [ 1 ] ) > = 1.0e-3 ) ;
t = - eye [ 1 ] / d [ 1 ] + world_y ;
pos_out [ 0 ] = eye [ 0 ] + t * d [ 0 ] ;
pos_out [ 1 ] = eye [ 1 ] + t * d [ 1 ] ;
pos_out [ 2 ] = eye [ 2 ] + t * d [ 2 ] ;
}
/*
* Module specific functions
*/
void ViewBase : : UpdateCamera ( ) {
EntityPhysicState * player_ent = GetEntityPhysicState ( GetPlayerEntityId ( ) ) ;
if ( ! player_ent ) {
LogError ( " Could not call Model::PositionCamera(): player entity not found! " ) ;
exit ( - 1 ) ;
}
vector3d entity_camera_distance ( - 2 , 3 , 0 ) ;
vector3d entity_position = player_ent - > GetPosition ( ) ;
player_ent - > Globalize ( entity_camera_distance ) ;
mCamera - > SetEye (
entity_camera_distance [ 0 ] ,
entity_camera_distance [ 1 ] ,
entity_camera_distance [ 2 ]
) ;
mCamera - > SetPointOfIntrest (
entity_position [ 0 ] ,
entity_position [ 1 ] ,
entity_position [ 2 ]
) ;
mCamera - > Update ( ) ;
}
2010-09-11 02:28:50 +02:00
void ViewBase : : PreDraw ( ) {
2010-04-05 23:38:59 +02:00
// Clear the screen
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
// update the frame rate counter
static Uint32 this_frame_ticks ;
static Uint32 last_frame_ticks = 0 ;
static Uint32 last_fps_update = 0 ;
static int frame_counter = 0 ;
this_frame_ticks = SDL_GetTicks ( ) ;
last_fps_update + = this_frame_ticks - last_frame_ticks ;
last_frame_ticks = this_frame_ticks ;
frame_counter + + ;
if ( last_fps_update > 1000 ) {
mFrameRate = frame_counter ;
last_fps_update = 0 ;
frame_counter = 0 ;
}
2010-09-11 02:28:50 +02:00
}
void ViewBase : : Draw ( ) {
// Perform pre-Draw actions
PreDraw ( ) ;
// Actual Drawing
2010-04-05 23:38:59 +02:00
UpdateCamera ( ) ;
if ( mDrawGrid )
DrawGrid ( ) ;
DrawWorld ( ) ;
2010-06-06 00:58:11 +02:00
mOverlayManager . Draw ( ) ;
2010-04-05 23:38:59 +02:00
2010-09-11 02:28:50 +02:00
// Perform post-Draw actions
PostDraw ( ) ;
}
void ViewBase : : PostDraw ( ) {
2010-04-05 23:38:59 +02:00
SDL_GL_SwapBuffers ( ) ;
}
2011-02-12 15:43:06 +01:00
void ViewBase : : SetFullscreen ( bool fullscreen ) {
if ( fullscreen & & mDrawFullscreen )
return ;
if ( ! fullscreen & & ! mDrawFullscreen )
return ;
if ( mDrawFullscreen ) {
mWindowHeight = VIEW_DEFAULT_HEIGHT ;
mWindowWidth = VIEW_DEFAULT_WIDTH ;
mDrawFullscreen = false ;
} else {
mWindowWidth = mScreenWidth ;
mWindowHeight = mScreenHeight ;
mDrawFullscreen = true ;
}
Resize ( mWindowWidth , mWindowHeight ) ;
}
2010-05-02 22:39:49 +02:00
/* Fonts */
2010-11-01 22:33:14 +01:00
/** \brief Parses font specifications strings into its values
*
* Fonts can be specified by strings such as
* name = default . ttf color = # ff0000 size = 12
* color = # ff00ff size = 12 otherfont . ttf
* myfont . ttf
* for which the appropriate values will be parsed . Default size is 12 and
* default color is white ( # ffffff )
*/
void parse_font_spec_string ( const std : : string & spec_string ,
std : : string & font_name ,
float font_color [ 3 ] ,
float * font_size ) {
// set default values
font_name = " default.ttf " ;
font_color [ 0 ] = 1.f ;
font_color [ 1 ] = 1.f ;
font_color [ 2 ] = 1.f ;
* font_size = 12.f ;
// perform the actual parsing
std : : string : : size_type pos = 0 ;
while ( pos < spec_string . size ( ) ) {
std : : string : : size_type next_start = spec_string . find_first_not_of ( " \t " , pos ) ;
// if we don't find anything we break out of this loop
if ( next_start = = std : : string : : npos )
break ;
// find the next token
std : : string : : size_type next_end = spec_string . find_first_of ( " \t " , next_start ) ;
std : : string token ( spec_string . substr ( next_start , next_end - next_start ) ) ;
// If no id was given it is automatically set to name
std : : string id ( " name " ) ;
std : : string value ( token ) ;
// Split the token into id and value if there is an '=' sign.
if ( token . find ( ' = ' , 0 ) ! = std : : string : : npos ) {
id = token . substr ( 0 , token . find ( ' = ' , 0 ) ) ;
value = token . substr ( id . size ( ) + 1 , token . size ( ) ) ;
}
// std::cout << "id = " << id << " value = " << value << std::endl;
if ( id = = " name " )
font_name = value ;
else if ( id = = " size " ) {
std : : istringstream istr ( value ) ;
istr > > * font_size ;
} else if ( id = = " color " ) {
// we assume #RRGGBB specification
if ( value [ 0 ] ! = ' # ' | | value . size ( ) ! = 7 )
LogError ( " Invalid font color specification '%s'. Please specify as #rrggbb! " , value . c_str ( ) ) ;
// convert the color string to float values
int num ;
std : : istringstream istr ( value . substr ( 1 , 2 ) ) ;
istr > > std : : hex > > num ;
font_color [ 0 ] = static_cast < float > ( num ) / 255. ;
istr . clear ( ) ;
istr . str ( value . substr ( 3 , 2 ) ) ;
istr > > std : : hex > > num ;
font_color [ 1 ] = static_cast < float > ( num ) / 255. ;
istr . clear ( ) ;
istr . str ( value . substr ( 5 , 2 ) ) ;
istr > > std : : hex > > num ;
font_color [ 2 ] = static_cast < float > ( num ) / 255. ;
}
pos = next_end ;
}
}
bool ViewBase : : LoadFont ( const std : : string & font_spec_string ) {
// font_spec_string can be of the form
// (name=)<name> (color=<color>) (size=<size>)
std : : string font_name ;
float font_size = 12. ;
float font_color [ 3 ] = { 1. , 1. , 1. } ;
parse_font_spec_string ( font_spec_string , font_name , font_color , & font_size ) ;
2010-12-03 00:15:26 +01:00
std : : string font_path ( GetResourceFullPath ( " /data/fonts/ " ) ) ;
2010-05-02 22:39:49 +02:00
font_path + = font_name ;
2010-11-01 22:33:14 +01:00
LogDebug ( " Loading font %s color (%1.2f, %1.2f, %1.2f) size %f from %s " , font_name . c_str ( ) , font_color [ 0 ] , font_color [ 1 ] , font_color [ 2 ] , font_size , font_path . c_str ( ) ) ;
OGLFT : : Monochrome * font = new OGLFT : : Monochrome ( font_path . c_str ( ) , font_size ) ;
2010-05-02 22:39:49 +02:00
if ( font = = 0 | | ! font - > isValid ( ) ) {
LogError ( " Could not load font %s! " , font_path . c_str ( ) ) ;
2010-06-06 00:58:11 +02:00
return false ;
2010-05-02 22:39:49 +02:00
}
2011-03-15 10:21:26 +01:00
font - > setForegroundColor ( font_color [ 0 ] , font_color [ 1 ] , font_color [ 2 ] , 1. ) ;
font - > setBackgroundColor ( 0. , 0. , 0. , 0. ) ;
2010-11-01 22:33:14 +01:00
mFonts . insert ( std : : make_pair < std : : string , OGLFT : : Monochrome * > ( font_spec_string , font ) ) ;
2010-06-06 00:58:11 +02:00
return true ;
2010-05-02 22:39:49 +02:00
}
void ViewBase : : SelectFont ( const char * font ) {
std : : map < std : : string , OGLFT : : Monochrome * > : : iterator font_iter ;
font_iter = mFonts . find ( font ) ;
if ( font_iter ! = mFonts . end ( ) ) {
mCurrentFont = font_iter - > second ;
return ;
}
2010-11-01 22:33:14 +01:00
LogDebug ( " Selecting font %s failed, trying to load it " , font ) ;
LogDebug ( " font count = %d " , mFonts . size ( ) ) ;
2010-05-02 22:39:49 +02:00
if ( LoadFont ( font ) ) {
2010-11-01 22:33:14 +01:00
LogDebug ( " font count = %d " , mFonts . size ( ) ) ;
2010-05-02 22:39:49 +02:00
font_iter = mFonts . find ( font ) ;
assert ( mFonts . find ( font ) ! = mFonts . end ( ) ) ;
mCurrentFont = font_iter - > second ;
return ;
}
LogError ( " Error trying to load font %s " , font ) ;
}
void ViewBase : : SetFontJustification ( FontJustification justification ) {
2010-11-01 22:33:14 +01:00
assert ( mCurrentFont ! = NULL ) ;
2010-05-02 22:39:49 +02:00
if ( justification = = FontJustificationRight )
mCurrentFont - > setHorizontalJustification ( OGLFT : : Face : : RIGHT ) ;
else if ( justification = = FontJustificationCenter )
mCurrentFont - > setHorizontalJustification ( OGLFT : : Face : : CENTER ) ;
else mCurrentFont - > setHorizontalJustification ( OGLFT : : Face : : LEFT ) ;
}
2010-04-05 23:38:59 +02:00
void ViewBase : : DrawGLString ( float x , float y , const char * str ) {
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
2010-05-02 22:39:49 +02:00
mCurrentFont - > draw ( x , y , str ) ;
2010-04-05 23:38:59 +02:00
}
2010-08-29 23:59:24 +02:00
void ViewBase : : DrawGLStringMeasure ( const char * str , float * width , float * height ) {
OGLFT : : BBox bbox = mCurrentFont - > measure ( str ) ;
* width = bbox . x_max_ - bbox . x_min_ ;
* height = bbox . y_max_ - bbox . y_min_ ;
2010-11-13 18:45:15 +01:00
// LogDebug ("measure bbox '%s' = %f,%f %f,%f",str, bbox.x_min_, bbox.y_min_, bbox.x_max_, bbox.y_max_);
2010-08-29 23:59:24 +02:00
}
2010-04-05 23:38:59 +02:00
void ViewBase : : GetCamereEye ( float * eye_out ) {
assert ( mCamera ) ;
mCamera - > GetEye ( eye_out ) ;
}
void ViewBase : : DrawGrid ( ) {
float xmin , xmax , xstep , zmin , zmax , zstep ;
int i , count_x , count_z ;
xmin = - mGridSizeX ;
xmax = mGridSizeX ;
zmin = - mGridSizeZ ;
zmax = mGridSizeZ ;
count_x = mGridSizeX * 2 ;
count_z = mGridSizeZ * 2 ;
xstep = 1. ;
zstep = 1. ;
2011-01-02 18:25:20 +01:00
glColor3f ( 0.8 , 0.8 , 0.8 ) ;
glLineWidth ( 1. ) ;
2010-04-05 23:38:59 +02:00
glBegin ( GL_LINES ) ;
for ( i = 0 ; i < = count_x ; i + + ) {
glVertex3f ( i * xstep + xmin , 0. , zmin ) ;
glVertex3f ( i * xstep + xmin , 0. , zmax ) ;
}
for ( i = 0 ; i < = count_z ; i + + ) {
glVertex3f ( xmin , 0 , i * zstep + zmin ) ;
glVertex3f ( xmax , 0 , i * zstep + zmin ) ;
}
glEnd ( ) ;
}
void ViewBase : : DrawWorld ( ) {
}
void ViewBase : : Resize ( int width , int height ) {
if ( height = = 0 )
height = 1 ;
mWindowWidth = static_cast < unsigned int > ( width ) ;
mWindowHeight = static_cast < unsigned int > ( height ) ;
glViewport ( 0 , 0 , width , height ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
gluPerspective ( mCamera - > GetFOVY ( ) , float ( width ) / float ( height ) , 0.1 , 100 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
LogDebug ( " Resize to: %d x %d " , mWindowWidth , mWindowHeight ) ;
/** \warning
* This call has to be made for SDL 1.2 for 1.3 there seems to be a
* workaround , however since I do not yet run SDL 1.3 I hold on to this .
* See http : //lists.libsdl.org/pipermail/sdl-libsdl.org/2008-November/067306.html
*/
2011-02-12 15:43:06 +01:00
Uint32 video_flags = SDL_OPENGL ;
if ( mDrawFullscreen )
video_flags = video_flags | SDL_FULLSCREEN ;
if ( SDL_SetVideoMode ( mWindowWidth , mWindowHeight , 16 , video_flags ) = = 0 ) {
2010-04-05 23:38:59 +02:00
LogError ( " Video mode set failed: %s " , SDL_GetError ( ) ) ;
exit ( - 1 ) ;
}
}
2010-06-06 00:58:11 +02:00
/*
2010-04-05 23:38:59 +02:00
bool ViewBase : : SendKeyDown ( const SDL_keysym & keysym ) {
2010-04-14 22:01:45 +02:00
std : : vector < OverlayBasePtr > : : iterator overlay_iter ;
2010-04-05 23:38:59 +02:00
for ( overlay_iter = mOverlays . begin ( ) ; overlay_iter ! = mOverlays . end ( ) ; overlay_iter + + ) {
if ( ( * overlay_iter ) - > OnKeyDown ( keysym ) )
return true ;
}
return false ;
}
bool ViewBase : : SendKeyUp ( const SDL_keysym & keysym ) {
2010-04-14 22:01:45 +02:00
std : : vector < OverlayBasePtr > : : iterator overlay_iter ;
2010-04-05 23:38:59 +02:00
for ( overlay_iter = mOverlays . begin ( ) ; overlay_iter ! = mOverlays . end ( ) ; overlay_iter + + ) {
if ( ( * overlay_iter ) - > OnKeyUp ( keysym ) )
return true ;
}
return false ;
}
bool ViewBase : : SendMouseButtonUp ( Uint8 button , Uint16 xpos , Uint16 ypos ) {
2010-04-14 22:01:45 +02:00
std : : vector < OverlayBasePtr > : : iterator overlay_iter ;
2010-04-05 23:38:59 +02:00
for ( overlay_iter = mOverlays . begin ( ) ; overlay_iter ! = mOverlays . end ( ) ; overlay_iter + + ) {
if ( ( * overlay_iter ) - > OnMouseButtonUp ( button , xpos , ypos ) )
return true ;
}
return false ;
}
bool ViewBase : : SendMouseButtonDown ( Uint8 button , Uint16 xpos , Uint16 ypos ) {
2010-04-14 22:01:45 +02:00
std : : vector < OverlayBasePtr > : : iterator overlay_iter ;
2010-04-05 23:38:59 +02:00
for ( overlay_iter = mOverlays . begin ( ) ; overlay_iter ! = mOverlays . end ( ) ; overlay_iter + + ) {
if ( ( * overlay_iter ) - > OnMouseButtonDown ( button , xpos , ypos ) )
return true ;
}
return false ;
}
2010-06-06 00:58:11 +02:00
*/
2010-04-05 23:38:59 +02:00
/*
* Global functions
*/
void DrawGLString ( float x , float y , const char * str ) {
if ( ! ViewInstance ) {
LogError ( " Cannot Draw GL String: View not yet initialized! " ) ;
return ;
}
ViewInstance - > DrawGLString ( x , y , str ) ;
}
2010-05-02 22:39:49 +02:00
void SelectFont ( const char * font ) {
if ( ! ViewInstance ) {
LogError ( " Cannot select font: View not yet initialized! " ) ;
return ;
}
ViewInstance - > SelectFont ( font ) ;
}
2010-06-06 01:22:01 +02:00
void SetFontJustification ( FontJustification justification ) {
if ( ! ViewInstance ) {
LogError ( " Cannot select font: View not yet initialized! " ) ;
return ;
}
ViewInstance - > SetFontJustification ( justification ) ;
}
2010-04-05 23:38:59 +02:00
unsigned int GetWindowWidth ( ) {
return ViewInstance - > GetWindowWidth ( ) ;
}
unsigned int GetWindowHeight ( ) {
return ViewInstance - > GetWindowHeight ( ) ;
}
int GetFrameRate ( ) {
return ViewInstance - > GetFrameRate ( ) ;
}
}