#include "MiniMap.h" #include "UIGlobals.h" #include "TextureManager.h" #include "Terrain.h" #include "Renderer.h" #include "ogl.h" extern CTerrain g_Terrain; struct TGAHeader { // header stuff unsigned char iif_size; unsigned char cmap_type; unsigned char image_type; unsigned char pad[5]; // origin : unused unsigned short d_x_origin; unsigned short d_y_origin; // dimensions unsigned short width; unsigned short height; // bits per pixel : 16, 24 or 32 unsigned char bpp; // image descriptor : Bits 3-0: size of alpha channel // Bit 4: must be 0 (reserved) // Bit 5: should be 0 (origin) // Bits 6-7: should be 0 (interleaving) unsigned char image_descriptor; }; static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data) { FILE* fp=fopen(filename,"wb"); if (!fp) return false; // fill file header TGAHeader header; header.iif_size=0; header.cmap_type=0; header.image_type=2; memset(header.pad,0,sizeof(header.pad)); header.d_x_origin=0; header.d_y_origin=0; header.width=width; header.height=height; header.bpp=bpp; header.image_descriptor=(bpp==32) ? 8 : 0; if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) { fclose(fp); return false; } // write data if (fwrite(data,width*height*bpp/8,1,fp)!=1) { fclose(fp); return false; } // return success .. fclose(fp); return true; } static unsigned int ScaleColor(unsigned int color,float x) { unsigned int r=unsigned int(float(color & 0xff)*x); unsigned int g=unsigned int(float((color>>8) & 0xff)*x); unsigned int b=unsigned int(float((color>>16) & 0xff)*x); return (0xff000000 | r | g<<8 | b<<16); } static int RoundUpToPowerOf2(int x) { if ((x & (x-1))==0) return x; int d=x; while (d & (d-1)) { d&=(d-1); } return d<<1; } CMiniMap::CMiniMap() : m_Handle(0), m_Data(0), m_Size(0) { } void CMiniMap::Initialise() { // get rid of existing texture, if we've got one if (m_Handle) { glDeleteTextures(1,(GLuint*) &m_Handle); delete[] m_Data; } // allocate a handle, bind to it glGenTextures(1,(GLuint*) &m_Handle); g_Renderer.BindTexture(0,m_Handle); // allocate an image big enough to fit the entire map into m_Size=RoundUpToPowerOf2(g_Terrain.GetVerticesPerSide()); u32 mapSize=g_Terrain.GetVerticesPerSide(); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_Size,m_Size,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,0); // allocate local copy m_Data=new u32[(mapSize-1)*(mapSize-1)]; // set texture parameters glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); // force a rebuild to get correct initial view Rebuild(); } void CMiniMap::Render() { // setup renderstate glDisable(GL_DEPTH_TEST); glDepthMask(0); // load identity modelview glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); // setup ortho view glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); int w=g_Renderer.GetWidth(); int h=g_Renderer.GetHeight(); glOrtho(0,w,0,h,-1,1); // bind to the minimap g_Renderer.BindTexture(0,m_Handle); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); float tclimit=float(g_Terrain.GetVerticesPerSide()-1)/float(m_Size); // render minimap as quad glBegin(GL_QUADS); glTexCoord2f(0,tclimit); glVertex2i(w-200,200); glTexCoord2f(0,0); glVertex2i(w-200,2); glTexCoord2f(tclimit,0); glVertex2i(w-3,2); glTexCoord2f(tclimit,tclimit); glVertex2i(w-3,200); glEnd(); // switch off textures glDisable(GL_TEXTURE_2D); // render border glLineWidth(2); glColor3f(0.4f,0.35f,0.8f); glBegin(GL_LINE_LOOP); glVertex2i(w-202,202); glVertex2i(w-1,202); glVertex2i(w-1,1); glVertex2i(w-202,1); glEnd(); // render view rect glScissor(w-200,2,w,198); glEnable(GL_SCISSOR_TEST); glLineWidth(2); glColor3f(1.0f,0.3f,0.3f); glBegin(GL_LINE_LOOP); glVertex2f(w-200+m_ViewRect[0][0],m_ViewRect[0][1]); glVertex2f(w-200+m_ViewRect[1][0],m_ViewRect[1][1]); glVertex2f(w-200+m_ViewRect[2][0],m_ViewRect[2][1]); glVertex2f(w-200+m_ViewRect[3][0],m_ViewRect[3][1]); glEnd(); glDisable(GL_SCISSOR_TEST); // restore matrices glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); // restore renderstate glEnable(GL_DEPTH_TEST); glDepthMask(1); } void CMiniMap::Update(int x,int y,unsigned int color) { // get height at this pixel int hmap=(int) g_Terrain.GetHeightMap()[y*g_Terrain.GetVerticesPerSide() + x]>>8; // shift from 0-255 to 170-255 int val=(hmap/3)+170; // get modulated color u32 mapSize=g_Terrain.GetVerticesPerSide(); *(m_Data+(y*(mapSize-1)+x))=ScaleColor(color,float(val)/255.0f); UpdateTexture(); } void CMiniMap::Update(int x,int y,int w,int h,unsigned int color) { u32 mapSize=g_Terrain.GetVerticesPerSide(); for (int j=0;j>8; // shift from 0-255 to 170-255 int val=(hmap/3)+170; // load scaled color into data pointer *dataptr++=ScaleColor(color,float(val)/255.0f); } } UpdateTexture(); } void CMiniMap::Rebuild() { u32 mapSize=g_Terrain.GetVerticesPerSide(); Rebuild(0,0,mapSize-1,mapSize-1); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // UpdateTexture: send data to GL; update stored texture data void CMiniMap::UpdateTexture() { // bind to the minimap g_Renderer.BindTexture(0,m_Handle); // subimage to update pixels u32 mapSize=g_Terrain.GetVerticesPerSide(); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,mapSize-1,mapSize-1,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_Data); } void CMiniMap::Rebuild(int x,int y,int w,int h) { u32 mapSize=g_Terrain.GetVerticesPerSide(); for (int j=0;j>8; // shift from 0-255 to 170-255 int val=(hmap/3)+170; CMiniPatch* mp=g_Terrain.GetTile(x+i,y+j); unsigned int color; if (mp) { // get texture on this time CTextureEntry* tex=mp->Tex1 ? g_TexMan.FindTexture(mp->Tex1) : 0; color=tex ? tex->GetBaseColor() : 0xffffffff; } else { color=0xffffffff; } // load scaled color into data pointer *dataptr++=ScaleColor(color,float(val)/255.0f); } } UpdateTexture(); }