/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx 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 2, or (at your option) any later version. ### File Specific: main-programmer: Simon Hofmann co-programmer: */ #include "hud.h" using namespace std; Hud::Hud () { } Hud::~Hud () { } bool Hud::LoadTGA(TextureImage *texture, char *filename) { GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};//Uncompressed TGA Header GLubyte TGAcompare[12]; GLubyte header[6];//First 6 bytes of header GLuint bytesPerPixel; GLuint imageSize; GLuint temp; GLuint type=GL_RGBA;//GL Mode is RBGA (32 BPP) FILE *file = fopen(filename, "rb"); if( file==NULL || fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) || memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 || fread(header,1,sizeof(header),file)!=sizeof(header)) { if (file == NULL) return false; else { fclose(file); return false; } } texture->width = header[1] * 256 + header[0];//width (highbyte*256+lowbyte) texture->height = header[3] * 256 + header[2];//height (highbyte*256+lowbyte) if(texture->width <= 0 || texture->height <=0 || (header[4]!=24 && header[4]!=32)) { fclose(file); return false; } texture->bpp = header[4];//TGA's bits per pixel bytesPerPixel = texture->bpp/8; imageSize = texture->width*texture->height*bytesPerPixel;//memory required texture->imageData=(GLubyte *)malloc(imageSize);//Reserve Memory if(texture->imageData==NULL || fread(texture->imageData, 1, imageSize, file)!=imageSize) { if(texture->imageData!=NULL) free(texture->imageData); fclose(file); return false; } for(GLuint i=0; iimageData[i];//Swaps the 1st and 3rd byte (red & blue) texture->imageData[i] = texture->imageData[i + 2]; texture->imageData[i + 2] = temp; } fclose (file); glGenTextures(1, &texture[0].texID); // Generate OpenGL texture IDs glBindTexture(GL_TEXTURE_2D, texture[0].texID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (texture[0].bpp==24) { type=GL_RGB; } glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData); return true; } GLvoid Hud::BuildFont(GLvoid) { base=glGenLists(256); glBindTexture(GL_TEXTURE_2D, textures[0].texID); for (int loop1=0; loop1<256; loop1++) { float cx=float(loop1%16)/16.0f;//X of current character float cy=float(loop1/16)/16.0f;//Y of current character glNewList(base+loop1,GL_COMPILE); glBegin(GL_QUADS);//Use a quad for each character glTexCoord2f(cx,1.0f-cy-0.0625f); glVertex2d(0,16); glTexCoord2f(cx+0.0625f,1.0f-cy-0.0625f); glVertex2i(16,16); glTexCoord2f(cx+0.0625f,1.0f-cy-0.001f); glVertex2i(16,0); glTexCoord2f(cx,1.0f-cy-0.001f); glVertex2i(0,0); glEnd(); glTranslated(14,0,0);//Move to the right of the character glEndList(); } } GLvoid Hud::KillFont(GLvoid) { glDeleteLists(base,256); } GLvoid Hud::glPrint(GLint x, GLint y, int set, const char *fmt, ...) { char text[1024]; va_list ap; if (fmt == NULL) return; va_start(ap, fmt);//parses string for variables, converts to numbers vsprintf(text, fmt, ap); va_end(ap); if (set>1) { set=1; } glEnable(GL_TEXTURE_2D);//Enable texture mapping glLoadIdentity(); glTranslated(x,y,0); glListBase(base-32+(128*set)); glScalef(1.0f,2.0f,1.0f);//Enlarge by factor 2 glCallLists(strlen(text),GL_UNSIGNED_BYTE, text); glDisable(GL_TEXTURE_2D); } void Hud::Resize(int width, int height) { swidth=width; // Set Scissor Width To Window Width sheight=height; // Set Scissor Height To Window Height if (height==0) { height=1; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f,640,480,0.0f,-1.0f,1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int Hud::InitGL() { if (!LoadTGA(&textures[0],"Data/Font.tga")) {//Load font texture return false; } BuildFont(); glShadeModel(GL_SMOOTH);//enable smooth shading glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glBindTexture(GL_TEXTURE_2D, textures[0].texID); return true; } void Hud::handleKeyPress(SDL_keysym *keysym) { switch(keysym->sym) { case SDLK_ESCAPE: SDL_Quit(); break; case SDLK_UP: scroller = -1; break; case SDLK_DOWN: scroller = 1; break; default: break; } return; } void Hud::DrawGLScene() { char *token; int cnt=0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer glColor3f(1.0f,0.5f,0.5f);//Set color to bright red glPrint(50,16,1,"Renderer"); glPrint(80,48,1,"Hersteller"); glPrint(66,80,1,"Version"); glColor3f(1.0f,0.7f,0.4f);//Set color to orange glPrint(200,16,1,(char *)glGetString(GL_RENDERER)); glPrint(200,48,1,(char *)glGetString(GL_VENDOR)); glPrint(200,80,1,(char *)glGetString(GL_VERSION)); glColor3f(0.5f,0.5f,1.0f);//Set color to bright blue glPrint(192,432,1,"orxonox HUD"); glLoadIdentity(); glColor3f(1.0f,1.0f,1.0f);//Set the color to white glBegin(GL_LINE_STRIP); glVertex2d(639,417); glVertex2d( 0,417); glVertex2d( 0,480); glVertex2d(639,480); glVertex2d(639,128); glEnd(); glBegin(GL_LINE_STRIP); glVertex2d( 0,128); glVertex2d(639,128); glVertex2d(639, 1); glVertex2d( 0, 1); glVertex2d( 0,417); glEnd(); glScissor(1 ,int(0.135416f*sheight),swidth-2,int(0.597916f*sheight));//Scissor region glEnable(GL_SCISSOR_TEST); char* text=(char *)malloc(strlen((char *)glGetString(GL_EXTENSIONS))+1); strcpy (text,(char *)glGetString(GL_EXTENSIONS));//Store extension list token=strtok(text," "); while(token!=NULL) { cnt++; if (cnt>maxtokens) { maxtokens=cnt; } glColor3f(0.5f,1.0f,0.5f);//Set color to bright green glPrint(0,96+(cnt*32)-scroll,0,"%i",cnt); glColor3f(1.0f,1.0f,0.5f); // Set Color To Yellow glPrint(50,96+(cnt*32)-scroll,0,token); token=strtok(NULL," "); } glDisable(GL_SCISSOR_TEST); free(text); SDL_GL_SwapBuffers(); return; } int Hud::main(int argc, char **argv) { int videoFlags; int done = false; SDL_Event event; const SDL_VideoInfo *videoInfo; int isActive = true; if(SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError()); SDL_Quit(); exit(0); } videoInfo = SDL_GetVideoInfo(); if(!videoInfo) { fprintf(stderr, "Video query failed: %s\n", SDL_GetError()); SDL_Quit(); exit(0); } videoFlags = SDL_OPENGL; // Enable OpenGL in SDL videoFlags |= SDL_GL_DOUBLEBUFFER; // Enable double buffering videoFlags |= SDL_HWPALETTE; // Store the palette in hardware videoFlags |= SDL_RESIZABLE; // Enable window resizing if(videoInfo->hw_available) videoFlags |= SDL_HWSURFACE; else videoFlags |= SDL_SWSURFACE; if (videoInfo->blit_hw) videoFlags |= SDL_HWACCEL; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); surface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags); if (!surface) { fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } InitGL(); Resize(SCREEN_WIDTH, SCREEN_HEIGHT); DrawGLScene(); while (!done) { SDL_Delay(10); while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_ACTIVEEVENT: if(event.active.gain == 0) isActive = false; else isActive = true; break; case SDL_VIDEORESIZE: surface = SDL_SetVideoMode(event.resize.w, event.resize.h, 16, videoFlags); if(!surface) { fprintf(stderr, "Could not get a surface after resize: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } Resize(event.resize.w, event.resize.h); break; case SDL_KEYDOWN: handleKeyPress(&event.key.keysym); break; case SDL_KEYUP: scroller = 0; break; case SDL_QUIT: done = true; break; default: break; } } if(scroller == -1) if(scroll > 0) scroll -= 2; if(scroller == 1) if(scroll < 32*(maxtokens-9)) scroll += 2; if(isActive) DrawGLScene(); } SDL_Quit(); exit(0); }