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>
2011-06-13 19:05:04 +02:00
# include "OBJModel.h"
2010-04-05 23:38:59 +02:00
# 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 ) ;
2011-06-13 17:05:07 +02:00
// Initialize GLEW and check for anything we need
GLenum err = glewInit ( ) ;
if ( GLEW_OK ! = err ) {
LogError ( " Could not init GLEW properly: %s " , glewGetErrorString ( err ) ) ;
}
LogDebug ( " Using GLEW version %s " , glewGetString ( GLEW_VERSION ) ) ;
if ( glewIsExtensionSupported ( " GL_ARB_vertex_buffer_object " ) ) {
} else {
LogError ( " VBOs are not supported! " ) ;
}
// read OpenGL version
std : : string gl_version ( reinterpret_cast < const char * > ( glGetString ( GL_VERSION ) ) ) ;
if ( gl_version . size ( ) = = 0 )
LogError ( " Could not retrieve GL version! " ) ;
std : : string major_number_str = gl_version . substr ( 0 , gl_version . find ( ' . ' ) ) ;
std : : string minor_number_str = gl_version . substr ( major_number_str . size ( ) + 1 , gl_version . find_first_of ( " . " , major_number_str . size ( ) ) ) ;
mGLVersionInfo . GLMajor = atoi ( major_number_str . c_str ( ) ) ;
mGLVersionInfo . GLMinor = atoi ( minor_number_str . c_str ( ) ) ;
// read GLSL version
std : : string glsl_version ( reinterpret_cast < const char * > ( glGetString ( GL_SHADING_LANGUAGE_VERSION ) ) ) ;
if ( glsl_version . size ( ) = = 0 )
LogError ( " Could not retrieve GLSL version! " ) ;
major_number_str = glsl_version . substr ( 0 , glsl_version . find ( ' . ' ) ) ;
minor_number_str = glsl_version . substr ( major_number_str . size ( ) + 1 , glsl_version . find_first_of ( " . " , major_number_str . size ( ) ) ) ;
mGLVersionInfo . GLSLMajor = atoi ( major_number_str . c_str ( ) ) ;
mGLVersionInfo . GLSLMinor = atoi ( minor_number_str . c_str ( ) ) ;
LogMessage ( " GL Version = %s, gl_major = %d, gl_minor = %d " , gl_version . c_str ( ) , mGLVersionInfo . GLMajor , mGLVersionInfo . GLMinor ) ;
LogMessage ( " GLSL Version = %s, gl_major = %d, gl_minor = %d " , gl_version . c_str ( ) , mGLVersionInfo . GLSLMajor , mGLVersionInfo . GLSLMinor ) ;
if ( mGLVersionInfo . GLMajor > = 2 & & mGLVersionInfo . GLMinor > = 0 )
mUseShaders = true ;
else
mUseShaders = false ;
// load the shaders if possible
if ( mUseShaders ) {
2011-06-13 19:05:04 +02:00
mBlinnPhongShader = LoadShaderProgram ( GetResourceFullPath ( " /data/shaders/blinn_phong.glsl " ) ) ;
mNormalMappingShader = LoadShaderProgram ( GetResourceFullPath ( " /data/shaders/normal_mapping.glsl " ) ) ;
2011-06-13 17:05:07 +02:00
} else {
mBlinnPhongShader = 0 ;
mNormalMappingShader = 0 ;
}
// Create a null texture that can be used for objects without textures
// taken from http://www.dhpoware.com/demos/glslNormalMapping.html
int pitch = ( ( 2 * 32 + 31 ) & ~ 31 ) > > 3 ; // align to 4-byte boundaries
std : : vector < GLubyte > pixels ( pitch * 2 , 255 ) ;
mNullTexture = 0 ;
glGenTextures ( 1 , & mNullTexture ) ;
glBindTexture ( GL_TEXTURE_2D , mNullTexture ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA8 , 2 , 2 , 0 , GL_BGRA ,
GL_UNSIGNED_BYTE , & pixels [ 0 ] ) ;
// Load fonts etc.
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 ( ) ) {
2011-05-04 18:33:44 +02:00
LogError ( " Could not load font %s! (ptr=%x " , font_path . c_str ( ) , ( void * ) font ) ;
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 ) ) ;
2011-05-04 18:33:44 +02:00
LogDebug ( " Loading font %s successful! " , font_name . c_str ( ) ) ;
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 ) ;
2011-05-04 18:33:44 +02:00
2010-05-02 22:39:49 +02:00
if ( LoadFont ( font ) ) {
2011-05-04 18:33:44 +02: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 ) ;
}
2011-04-19 10:38:59 +02:00
float ViewBase : : GetCurrentFontSize ( ) {
if ( mCurrentFont = = NULL ) {
LogError ( " Could not get current font size: no font selected! " ) ;
return 0. ;
}
return mCurrentFont - > pointSize ( ) ;
}
2010-05-02 22:39:49 +02:00
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
}
2011-06-13 17:05:07 +02:00
GLuint ViewBase : : LoadTextureFromPNG ( const std : : string & filename ) {
std : : map < std : : string , GLuint > : : iterator texture_iterator = mGLTextures . find ( filename ) ;
if ( texture_iterator ! = mGLTextures . end ( ) ) {
return texture_iterator - > second ;
}
Sprite temp_sprite ;
temp_sprite . LoadFromPNG ( filename . c_str ( ) ) ;
// register the texture in the View
mGLTextures [ filename ] = temp_sprite . GetGLTextureName ( ) ;
return temp_sprite . GetGLTextureName ( ) ;
}
2011-06-13 19:05:04 +02:00
/*
* OBJModel loading and drawing
*/
OBJModelPtr ViewBase : : LoadOBJModel ( const std : : string & model_filename ) {
LogDebug ( " Loading OBJ model %s " , model_filename . c_str ( ) ) ;
OBJModelPtr result_model ( new OBJModel ) ;
if ( ! result_model - > import ( model_filename . c_str ( ) , true ) ) {
LogError ( " Could not load model %s " , model_filename . c_str ( ) ) ;
return result_model ;
}
result_model - > normalize ( ) ;
result_model - > reverseWinding ( ) ;
// Load any associated textures.
// Note the path where the textures are assumed to be located.
const OBJModel : : Material * pMaterial = 0 ;
GLuint textureId = 0 ;
std : : string : : size_type offset = 0 ;
std : : string filename ;
for ( int i = 0 ; i < result_model - > getNumberOfMaterials ( ) ; + + i )
{
pMaterial = & result_model - > getMaterial ( i ) ;
// Look for and load any diffuse color map textures.
if ( ! pMaterial - > colorMapFilename . empty ( ) ) {
// Try load the texture using the path in the .MTL file.
textureId = LoadTextureFromPNG ( pMaterial - > colorMapFilename . c_str ( ) ) ;
if ( ! textureId )
{
offset = pMaterial - > colorMapFilename . find_last_of ( ' \\ ' ) ;
if ( offset ! = std : : string : : npos )
filename = pMaterial - > colorMapFilename . substr ( + + offset ) ;
else
filename = pMaterial - > colorMapFilename ;
// Try loading the texture from the same directory as the OBJ file.
textureId = LoadTextureFromPNG ( ( filename ) . c_str ( ) ) ;
}
} else {
LogMessage ( " No diffuse color map found! " ) ;
}
// Look for and load any normal map textures.
if ( ! pMaterial - > bumpMapFilename . empty ( ) ) {
// Try load the texture using the path in the .MTL file.
textureId = LoadTextureFromPNG ( ( pMaterial - > bumpMapFilename ) . c_str ( ) ) ;
if ( ! textureId )
{
offset = pMaterial - > bumpMapFilename . find_last_of ( ' \\ ' ) ;
if ( offset ! = std : : string : : npos )
filename = pMaterial - > bumpMapFilename . substr ( + + offset ) ;
else
filename = pMaterial - > bumpMapFilename ;
// Try loading the texture from the same directory as the OBJ file.
textureId = LoadTextureFromPNG ( ( result_model - > getPath ( ) + filename ) . c_str ( ) ) ;
}
} else {
LogMessage ( " Material has no bumpmap! " ) ;
continue ;
}
}
// Update the window caption.
LogMessage ( " Loaded model %s successful, dimensions (whl): %f, %f, %f meshes %d vertices %d triangles: %d " ,
model_filename . c_str ( ) ,
result_model - > getWidth ( ) ,
result_model - > getHeight ( ) ,
result_model - > getLength ( ) ,
result_model - > getNumberOfMeshes ( ) ,
result_model - > getNumberOfVertices ( ) ,
result_model - > getNumberOfTriangles ( )
) ;
return result_model ;
}
void ViewBase : : DrawOBJModel ( OBJModelPtr obj_model ) {
if ( mUseShaders ) {
DrawOBJModelShaded ( obj_model ) ;
} else {
DrawOBJModelSolid ( obj_model ) ;
}
}
void ViewBase : : DrawOBJModelSolid ( OBJModelPtr obj_model ) {
const OBJModel : : Mesh * pMesh = 0 ;
const OBJModel : : Material * pMaterial = 0 ;
const OBJModel : : Vertex * pVertices = 0 ;
std : : map < std : : string , GLuint > : : const_iterator iter ;
for ( int i = 0 ; i < obj_model - > getNumberOfMeshes ( ) ; + + i )
{
pMesh = & obj_model - > getMesh ( i ) ;
pMaterial = pMesh - > pMaterial ;
pVertices = obj_model - > getVertexBuffer ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_AMBIENT , pMaterial - > ambient ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_DIFFUSE , pMaterial - > diffuse ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_SPECULAR , pMaterial - > specular ) ;
glMaterialf ( GL_FRONT_AND_BACK , GL_SHININESS , pMaterial - > shininess * 128.0f ) ;
if ( pMaterial - > colorMapFilename . size ( ) > 0 )
{
iter = mGLTextures . find ( pMaterial - > colorMapFilename ) ;
if ( iter = = mGLTextures . end ( ) )
{
LogError ( " Could not find required colormap '%s' " , pMaterial - > colorMapFilename . c_str ( ) ) ;
glDisable ( GL_TEXTURE_2D ) ;
}
else
{
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , iter - > second ) ;
}
}
else
{
glDisable ( GL_TEXTURE_2D ) ;
}
if ( obj_model - > hasPositions ( ) )
{
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 3 , GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > position ) ;
}
if ( obj_model - > hasTextureCoords ( ) )
{
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glTexCoordPointer ( 2 , GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > texCoord ) ;
}
if ( obj_model - > hasNormals ( ) )
{
glEnableClientState ( GL_NORMAL_ARRAY ) ;
glNormalPointer ( GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > normal ) ;
}
glDrawElements ( GL_TRIANGLES , pMesh - > triangleCount * 3 , GL_UNSIGNED_INT ,
obj_model - > getIndexBuffer ( ) + pMesh - > startIndex ) ;
if ( obj_model - > hasNormals ( ) )
glDisableClientState ( GL_NORMAL_ARRAY ) ;
if ( obj_model - > hasTextureCoords ( ) )
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
if ( obj_model - > hasPositions ( ) )
glDisableClientState ( GL_VERTEX_ARRAY ) ;
// disable texture drawing if active
if ( pMaterial - > colorMapFilename . size ( ) > 0 )
glDisable ( GL_TEXTURE_2D ) ;
}
}
void ViewBase : : DrawOBJModelShaded ( OBJModelPtr obj_model ) {
const OBJModel : : Mesh * pMesh = 0 ;
const OBJModel : : Material * pMaterial = 0 ;
const OBJModel : : Vertex * pVertices = 0 ;
std : : map < std : : string , GLuint > : : const_iterator iter ;
GLuint texture = 0 ;
for ( int i = 0 ; i < obj_model - > getNumberOfMeshes ( ) ; + + i )
{
pMesh = & obj_model - > getMesh ( i ) ;
pMaterial = pMesh - > pMaterial ;
pVertices = obj_model - > getVertexBuffer ( ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_AMBIENT , pMaterial - > ambient ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_DIFFUSE , pMaterial - > diffuse ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_SPECULAR , pMaterial - > specular ) ;
glMaterialf ( GL_FRONT_AND_BACK , GL_SHININESS , pMaterial - > shininess * 128.0f ) ;
// if there is no bumpmap we will simply use a blinn phong shader and draw
// the color map onto our model
if ( pMaterial - > bumpMapFilename . empty ( ) )
{
// LogMessage ("using Blinn Phong shader");
// Per fragment Blinn-Phong code path.
glUseProgram ( mBlinnPhongShader ) ;
// Bind the color map texture.
texture = mNullTexture ;
if ( pMaterial - > colorMapFilename . size ( ) > 0 ) {
iter = mGLTextures . find ( pMaterial - > colorMapFilename ) ;
if ( iter ! = mGLTextures . end ( ) )
texture = iter - > second ;
} else {
LogMessage ( " Disabling textures " ) ;
}
glActiveTexture ( GL_TEXTURE0 ) ;
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , texture ) ;
// Update shader parameters.
assert ( glIsProgram ( mBlinnPhongShader ) = = GL_TRUE ) ;
assert ( glGetUniformLocation ( mBlinnPhongShader , " materialAlpha " ) ! = - 1 ) ;
assert ( glGetUniformLocation ( mBlinnPhongShader , " colorMap " ) ! = - 1 ) ;
glUniform1i ( glGetUniformLocation (
mBlinnPhongShader , " colorMap " ) , 0 ) ;
glUniform1f ( glGetUniformLocation (
mBlinnPhongShader , " materialAlpha " ) , pMaterial - > alpha ) ;
}
else
{
// if there is a bumpmap we use both the bump map and the color map and
// apply it on our model
// LogMessage ("using Normal Mapping Shader");
// Normal mapping code path.
glUseProgram ( mNormalMappingShader ) ;
// Bind the normal map texture.
iter = mGLTextures . find ( pMaterial - > bumpMapFilename ) ;
if ( iter ! = mGLTextures . end ( ) ) {
texture = iter - > second ;
glActiveTexture ( GL_TEXTURE1 ) ;
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , texture ) ;
} else {
2011-06-13 19:21:39 +02:00
LogError ( " bumpmap %s not found " , pMaterial - > bumpMapFilename . c_str ( ) ) ;
2011-06-13 19:05:04 +02:00
}
// Bind the color map texture.
texture = mNullTexture ;
if ( pMaterial - > colorMapFilename . size ( ) > 0 )
{
iter = mGLTextures . find ( pMaterial - > colorMapFilename ) ;
if ( iter ! = mGLTextures . end ( ) ) {
texture = iter - > second ;
} else {
2011-06-13 19:21:39 +02:00
LogError ( " color map %s not found " , pMaterial - > colorMapFilename . c_str ( ) ) ;
2011-06-13 19:05:04 +02:00
}
}
glActiveTexture ( GL_TEXTURE0 ) ;
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , texture ) ;
// Update shader parameters.
assert ( glGetUniformLocation ( mNormalMappingShader , " colorMap " ) ! = - 1 ) ;
assert ( glGetUniformLocation ( mNormalMappingShader , " normalMap " ) ! = - 1 ) ;
assert ( glGetUniformLocation ( mNormalMappingShader , " materialAlpha " ) ! = - 1 ) ;
glUniform1i ( glGetUniformLocation (
mNormalMappingShader , " colorMap " ) , 0 ) ;
glUniform1i ( glGetUniformLocation (
mNormalMappingShader , " normalMap " ) , 1 ) ;
glUniform1f ( glGetUniformLocation (
mNormalMappingShader , " materialAlpha " ) , pMaterial - > alpha ) ;
}
// Render mesh.
if ( obj_model - > hasPositions ( ) )
{
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 3 , GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > position ) ;
}
if ( obj_model - > hasTextureCoords ( ) )
{
glClientActiveTexture ( GL_TEXTURE0 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glTexCoordPointer ( 2 , GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > texCoord ) ;
}
if ( obj_model - > hasNormals ( ) )
{
glEnableClientState ( GL_NORMAL_ARRAY ) ;
glNormalPointer ( GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > normal ) ;
}
if ( obj_model - > hasTangents ( ) )
{
glClientActiveTexture ( GL_TEXTURE1 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glTexCoordPointer ( 4 , GL_FLOAT , obj_model - > getVertexSize ( ) ,
obj_model - > getVertexBuffer ( ) - > tangent ) ;
}
glDrawElements ( GL_TRIANGLES , pMesh - > triangleCount * 3 , GL_UNSIGNED_INT ,
obj_model - > getIndexBuffer ( ) + pMesh - > startIndex ) ;
if ( obj_model - > hasTangents ( ) )
{
glClientActiveTexture ( GL_TEXTURE1 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
}
if ( obj_model - > hasNormals ( ) )
glDisableClientState ( GL_NORMAL_ARRAY ) ;
if ( obj_model - > hasTextureCoords ( ) )
{
glClientActiveTexture ( GL_TEXTURE0 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
}
if ( obj_model - > hasPositions ( ) )
glDisableClientState ( GL_VERTEX_ARRAY ) ;
}
// as we might be using multiple textures (at least for the normal mapping
// case) we have to disable both textures
glActiveTexture ( GL_TEXTURE1 ) ;
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2011-06-13 19:21:39 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2011-06-13 19:05:04 +02:00
glUseProgram ( 0 ) ;
}
/*
* Shader loading , compiling , linking
*/
/** Compiles a shader program
*
* This function contains code mainly taken from dhpowares excellent
* objviewer example ( see http : //www.dhpoware.com/demos/gl3NormalMapping.html ).
*/
GLuint ViewBase : : CompileShader ( GLenum type , const GLchar * source , GLint length ) {
GLuint shader = glCreateShader ( type ) ;
if ( shader ) {
GLint compiled = 0 ;
glShaderSource ( shader , 1 , & source , & length ) ;
glCompileShader ( shader ) ;
glGetShaderiv ( shader , GL_COMPILE_STATUS , & compiled ) ;
if ( ! compiled ) {
GLsizei info_log_size = 0 ;
std : : string info_log ;
glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , & info_log_size ) ;
info_log . resize ( info_log_size ) ;
glGetShaderInfoLog ( shader , info_log_size , & info_log_size , & info_log [ 0 ] ) ;
LogError ( " Error compiling shader: %s " , info_log . c_str ( ) ) ;
}
}
return shader ;
}
/** Links the given shader programs
*
* This function contains code mainly taken from dhpowares excellent
* objviewer example ( see http : //www.dhpoware.com/demos/gl3NormalMapping.html ).
*/
GLuint ViewBase : : LinkShaders ( GLuint vertex_shader , GLuint fragment_shader ) {
GLuint program = glCreateProgram ( ) ;
if ( program ) {
GLint linked = 0 ;
if ( vertex_shader )
glAttachShader ( program , vertex_shader ) ;
if ( fragment_shader )
glAttachShader ( program , fragment_shader ) ;
glLinkProgram ( program ) ;
glGetProgramiv ( program , GL_LINK_STATUS , & linked ) ;
if ( ! linked ) {
GLsizei info_log_size = 0 ;
std : : string info_log ;
glGetProgramiv ( program , GL_INFO_LOG_LENGTH , & info_log_size ) ;
info_log . resize ( info_log_size ) ;
glGetProgramInfoLog ( program , info_log_size , & info_log_size , & info_log [ 0 ] ) ;
LogError ( " Error linking shaders vert: %d, frag: %d " , vertex_shader , fragment_shader ) ;
}
if ( vertex_shader )
glDeleteShader ( vertex_shader ) ;
if ( fragment_shader )
glDeleteShader ( fragment_shader ) ;
}
return program ;
}
/** Loads a vertex or fragment shader program
*
* This function contains code mainly taken from dhpowares excellent
* objviewer example ( see http : //www.dhpoware.com/demos/gl3NormalMapping.html ).
*/
GLuint ViewBase : : LoadShaderProgram ( const std : : string & filename ) {
LogDebug ( " Loading shader program %s " , filename . c_str ( ) ) ;
std : : ifstream program_file ( filename . c_str ( ) ) ;
if ( ! program_file ) {
LogError ( " Could not open file '%s' while loading shader program " , filename . c_str ( ) ) ;
}
// read the whole file into a string
std : : string shader_program ( ( std : : istreambuf_iterator < char > ( program_file ) ) , std : : istreambuf_iterator < char > ( ) ) ;
program_file . close ( ) ;
GLuint program = 0 ;
if ( shader_program . size ( ) > 0 ) {
const GLchar * source ;
GLint length = 0 ;
GLuint vertex_shader = 0 ;
GLuint fragment_shader = 0 ;
std : : string : : size_type vertex_shader_offset = shader_program . find ( " [vert] " ) ;
std : : string : : size_type fragment_shader_offset = shader_program . find ( " [frag] " ) ;
if ( vertex_shader_offset ! = std : : string : : npos ) {
// skip over the [vert] tag
vertex_shader_offset + = 6 ;
source = reinterpret_cast < const GLchar * > ( & shader_program [ vertex_shader_offset ] ) ;
length = static_cast < GLint > ( fragment_shader_offset - vertex_shader_offset ) ;
vertex_shader = CompileShader ( GL_VERTEX_SHADER , source , length ) ;
LogMessage ( " Compiled vertex shader with id %d " , vertex_shader ) ;
}
if ( fragment_shader_offset ! = std : : string : : npos ) {
// skip over the [vert] tag
fragment_shader_offset + = 6 ;
source = reinterpret_cast < const GLchar * > ( & shader_program [ fragment_shader_offset ] ) ;
length = static_cast < GLint > ( shader_program . length ( ) - fragment_shader_offset - 1 ) ;
fragment_shader = CompileShader ( GL_FRAGMENT_SHADER , source , length ) ;
LogMessage ( " Compiled fragment shader with id %d " , fragment_shader ) ;
}
program = LinkShaders ( vertex_shader , fragment_shader ) ;
LogMessage ( " Successfully linked shaders vert: %d frag: %d from file %s into program %d " , vertex_shader , fragment_shader , filename . c_str ( ) , program ) ;
}
mShaderPrograms [ filename ] = program ;
return program ;
}
/*
* Camera and other auxillary functions
*/
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 ) ;
}
2011-04-19 10:38:59 +02:00
float GetCurrentFontSize ( ) {
if ( ! ViewInstance ) {
LogError ( " Cannot get font size: View not yet initialized! " ) ;
return 0. ;
}
return ViewInstance - > GetCurrentFontSize ( ) ;
}
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 ( ) ;
}
}