5b708df75ab0b5edf833db1b455e6388737e8d33
[progcomp2012.git] / judge / manager / graphics.cpp
1 #include "graphics.h"
2 #include <cmath>
3 #include <cassert>
4 #include <iostream>
5
6
7 #undef DEBUG
8 //#define DEBUG
9
10 std::list<SDL_Surface*> Graphics::allTextures = std::list<SDL_Surface*>();
11 Screen * Graphics::screen = NULL;
12
13 int Graphics::screenWidth = 0;
14 int Graphics::screenHeight = 0;
15 bool Graphics::initialised = false;
16
17 using namespace std;
18
19 Texture::Texture(const char * filename, bool newDrawCentred) : surface(NULL), texture(0), drawCentred(newDrawCentred)
20 {
21         #ifdef DEBUG
22                 printf("Texture::Texture - loading \"%s\".\n", filename);
23         #endif //DEBUG
24
25         surface = Graphics::LoadTextureBMP(filename);
26         if (surface == NULL)
27         {
28                 fprintf(stderr, "Texture::Texture - Could not open texture from file \"%s\"! ABORT\n", filename);
29                 exit(EXIT_FAILURE);
30         }
31
32         GLenum texture_format; 
33         GLint nOfColours = surface->format->BytesPerPixel;
34         switch (nOfColours)
35         {
36                 case 4: //contains alpha
37                         texture_format = (surface->format->Rmask == 0x000000FF) ? GL_RGBA : GL_BGRA;
38                         break;
39                 case 3: //does not contain alpha
40                         texture_format = (surface->format->Rmask == 0x000000FF) ? GL_RGB : GL_BGR;      
41                         break;
42                 default:
43                         fprintf(stderr,"Texture::Texture - Could not understand SDL_Surface format (%d colours)! ABORT\n", nOfColours);
44                         exit(EXIT_FAILURE);
45                         break;  
46         }
47
48         glGenTextures(1, &texture);
49         glBindTexture(GL_TEXTURE_2D, texture);
50         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
51         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
52         glTexImage2D(GL_TEXTURE_2D, 0, nOfColours, surface->w, surface->h,0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
53
54 }
55
56 Texture::~Texture()
57 {
58         #ifdef DEBUG
59                 printf("Texture::~Texture - %p has been deleted. glDeleteTexture and SDL_FreeSurface here.\n", (void*)(this));
60         #endif //DEBUG
61         glDeleteTextures(1, &texture); 
62         //SDL_FreeSurface(surface);
63 }
64
65 void Texture::DrawColour(int x, int y, double angle, double scale, Colour colour)
66 {
67         if (scale > surface->w || scale > surface->h)
68         {
69                 Graphics::DrawPixel(x/scale,y/scale,colour);
70         }
71         else
72         {
73                 glColor3f(colour.r,colour.g,colour.b);  
74                 Draw(x,y,angle,scale);
75                 glColor3f(1,1,1);
76         }
77 }
78
79 void Texture::Draw(int x, int y, double angle , double scale )
80 {
81         //Draws the CENTRE of the texture at x, y, rotated by angle
82         
83         #ifdef DEBUG
84                 printf("        Texture::Draw - Drawing %p at (%d, %d) ; angle %2f ; scale % 2f\n", (void*)(this), x, y, angle, scale);
85         #endif //DEBUG
86
87         //if (x/scale < 0 || x/scale > Graphics::ScreenWidth() || y/scale < 0 || y/scale > Graphics::ScreenHeight() )
88         //      return;
89
90         glPushMatrix(); //NOT deprecated
91         
92         
93         glTranslatef(x/scale, y/scale,0);
94
95         if (scale > surface->w || scale > surface->h)
96         {
97                 Graphics::DrawPixel(0,0, Colour(255,255,255));
98         }
99         else
100         {
101                 glRotated(angle, 0, 0, 1);
102                 glEnable(GL_TEXTURE_2D);
103                 glBindTexture(GL_TEXTURE_2D, texture);
104                 glBegin(GL_QUADS);
105
106                 //scale /= 2;
107                 if (drawCentred)
108                 {
109                         glTexCoord2i(0,0); glVertex3f(-0.5f/scale*surface->w ,-0.5f/scale*surface->h,0); //bottom left
110                         glTexCoord2i(1,0); glVertex3f(0.5f/scale*surface->w,-0.5f/scale*surface->h,0); //bottom right
111                         glTexCoord2i(1,1); glVertex3f(0.5f/scale*surface->w,0.5f/scale*surface->h,0); //top right
112                         glTexCoord2i(0,1); glVertex3f(-0.5f/scale*surface->w,0.5f/scale*surface->h,0); //top left
113                 }
114                 else
115                 {
116                         glTexCoord2i(0,0); glVertex3f(0 ,0,0); //bottom left
117                         glTexCoord2i(1,0); glVertex3f(1.0f/scale*surface->w,0,0); //bottom right
118                         glTexCoord2i(1,1); glVertex3f(1.0f/scale*surface->w,1.0f/scale*surface->h,0); //top right
119                         glTexCoord2i(0,1); glVertex3f(0,1.0f/scale*surface->h,0); //top left
120                 }
121         
122                 glEnd();
123                 glDisable(GL_TEXTURE_2D);
124         }
125                 glPopMatrix();
126
127 }
128
129
130 Font::Font(const char * filename, int newWidth, int newHeight) : Texture(filename), width(newWidth), height(newHeight)
131 {
132
133 }
134
135 Font::~Font()
136 {
137
138 }
139
140 void Font::DrawText(const char * string, int x, int y, double angle, double scale)
141 {
142         #ifdef DEBUG
143                 printf("Font::DrawText - drawing \"%s\"\n", string);
144         #endif //DEBUG
145         glPushMatrix(); //NOT deprecated
146         glTranslatef(x, y,0);
147         glRotated(angle, 0, 0, 1);
148
149         glEnable(GL_TEXTURE_2D);
150         glBindTexture(GL_TEXTURE_2D, texture);
151
152
153         for (int ii=0; string[ii] != '\0'; ++ii)
154         {
155                 if (string[ii] != ' ')
156                 {
157                         glPushMatrix();
158                         glTranslatef(ii*(float)(width)/(float)(scale),0,0);
159
160                         int index = (int)(string[ii]) - (int)('!');
161                         if (index < 0 || index > (int)('~') - (int)('!'))
162                                 index = (int)('~') - (int)('!') + 1;
163
164                         float start = (float)(((((float)(index))*((float)(width)))-3.0f)/((float)surface->w));
165                         float end = (float)(((((float)(index+1))*((float)(width)))-4.0f)/((float)surface->w));
166                         if (start < 0) {start = 0;} if (end > 1) {end = 1;}
167                         glBegin(GL_QUADS);
168                         glTexCoord2f(start,0); glVertex3f(-0.5f/scale*width ,-0.5f/scale*height,0); //bottom left
169                         glTexCoord2f(end,0); glVertex3f(0.5f/scale*width,-0.5f/scale*height,0); //bottom right
170                         glTexCoord2f(end,1); glVertex3f(0.5f/scale*width,0.5f/scale*height,0); //top right
171                         glTexCoord2f(start,1); glVertex3f(-0.5f/scale*width,0.5f/scale*height,0); //top left
172                         //printf("Index %d - Drawing %c - maps to %f->%f\n", index,string[ii],start,end);
173                         
174                         glEnd();
175                         glPopMatrix();
176                 }
177         }
178
179         
180         glDisable(GL_TEXTURE_2D);
181         glPopMatrix();
182
183 }
184
185
186 void Graphics::Initialise(const char * caption, int newWidth, int newHeight)
187 {
188         if (Initialised())
189         {
190                 std::cerr << "Graphics have already been initialised! Fatal Error\n";
191                 exit(EXIT_FAILURE);
192         }
193         screenWidth = newWidth; screenHeight = newHeight;
194
195         if (SDL_Init(SDL_INIT_VIDEO) != 0)
196         {
197                 std::cerr << "Couldn't init SDL!\n";
198                 exit(EXIT_FAILURE);
199         }
200       //        atexit(Graphics::Destroy); BREAKS THINGS
201
202         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); //According to sulix does not matter. (much)
203
204
205         
206
207         screen = SDL_SetVideoMode(screenWidth,screenHeight, 32, SDL_OPENGL);
208         if ( screen == NULL )
209         {
210                 std::cerr << "Couldn't set " << screenWidth << "x" << screenHeight << "x32 video mode: " << SDL_GetError() << "\n";
211                 exit(EXIT_FAILURE);
212         } 
213
214         //COMES AFTER SETVIDEO MODE
215         glEnable(GL_TEXTURE_2D);
216         glClearColor(1,1,1,0); //Set clear colour (white) here
217         glViewport(0,0,screenWidth,screenHeight);       //DOES matter
218         glClear(GL_COLOR_BUFFER_BIT);
219         glMatrixMode(GL_PROJECTION);
220         glLoadIdentity();
221         glOrtho(0,screenWidth,screenHeight,0,-1,1);
222         glMatrixMode(GL_MODELVIEW);
223         glLoadIdentity();
224         glDisable(GL_DEPTH_TEST);
225         SDL_WM_SetCaption( caption, NULL);
226
227         Graphics::initialised = true;
228         
229 }
230
231 void Graphics::Destroy()
232 {
233         list<SDL_Surface*>::iterator i(allTextures.begin());
234         while (i != allTextures.end())
235         {
236                 SDL_FreeSurface((*i));
237                 ++i;
238         }
239         SDL_Quit();
240 }
241
242 SDL_Surface * Graphics::LoadTextureBMP(const char * file)
243 {
244                 SDL_Surface * tmp = SDL_LoadBMP(file);
245                 if (tmp == NULL)
246                         return NULL;
247                 //assert(tmp != NULL);
248         
249
250                 if (Graphics::screen != NULL)
251                 {
252                         SDL_Surface * tex = SDL_DisplayFormat(tmp);
253                         SDL_FreeSurface(tmp);
254                 
255                         allTextures.push_back(tex);
256                         return tex;
257                 }
258                 return tmp;
259 }
260
261 void Graphics::SaveTextureBMP(SDL_Surface * tex, const char * file)
262 {
263         SDL_SaveBMP(tex, file);
264 }
265
266
267 void Graphics::DrawTexture(SDL_Surface * tex, int destX, int destY, int srcX, int srcY, int w, int h)
268 {
269         if (w < 0) {w = tex->w - srcX;}
270         if (h < 0) {h = tex->h - srcY;}
271         Graphics::DrawTexture(screen, tex, destX, destY, srcX, srcY, w, h);
272 }
273
274 void Graphics::DrawTexture(SDL_Surface * dest, SDL_Surface * tex, int destX, int destY, int srcX, int srcY, int width, int height)
275 {
276         if ((destX < 0)||(destX >= dest->w)||(destY < 0)||(destY >= dest->h)
277                 ||(srcX < 0)||(srcX >= tex->w)||(srcY < 0)||(srcY >= tex->h))
278                 return;
279
280         assert(dest->format->BitsPerPixel == 32);
281         assert(tex->format->BitsPerPixel == 32);
282         
283         if (SDL_MUSTLOCK(tex))   
284                 SDL_LockSurface(tex);
285
286         if (SDL_MUSTLOCK(dest))   
287                 SDL_LockSurface(dest);
288
289         
290         
291         Colour transparent = Graphics::GetPixel(tex, srcX, srcY);
292         //printf("transparent from %d %d\n", srcX, srcY);
293
294         for (int xOff = 0; xOff < width; xOff++)
295         
296         {
297                 for (int yOff = 0; yOff < height; yOff++)
298                 {
299                         Colour nextColour = Graphics::GetPixel(tex, srcX+xOff, srcY+yOff);
300                         if (nextColour != transparent)
301                         {
302                                 Graphics::DrawPixel(dest, destX + xOff, destY + yOff, nextColour);
303                         }
304                 }
305         }       
306
307         if (SDL_MUSTLOCK(tex))
308                 SDL_UnlockSurface(tex);
309
310         if (SDL_MUSTLOCK(dest))
311                 SDL_UnlockSurface(dest);
312         
313 }
314
315 void Graphics::ClearScreen()
316 {
317         //SDL_FillRect(screen, NULL ,Graphics::MakeColour(0,0,0));
318         glClear(GL_COLOR_BUFFER_BIT);
319
320 }
321
322 void Graphics::UpdateScreen()
323 {
324         SDL_GL_SwapBuffers();
325         //SDL_Flip(screen);
326 }
327
328 void Graphics::DrawPixel(int x, int y, Colour colour)
329 {
330         DrawPixel(screen, x, y, colour);
331 }
332
333 void Graphics::DrawPixel(SDL_Surface * dest, int x, int y, Colour colour)
334 {
335         glBegin(GL_POINTS);
336         glColor4f(colour.r/255, colour.g/255, colour.b/255, colour.a);
337         glVertex2f(x, y);       
338         glColor3f(1,1,1);
339         glEnd();
340 }
341
342 void Graphics::DrawGrid(int gridWidth, int gridHeight, Colour colour)
343 {
344         for (int x = 0; x < screen->w; x+=gridWidth)
345         {
346                 Graphics::DrawLine(x,0, x,screen->h - 1, colour);
347         }
348         for (int y = 0; y < screen->h; y+=gridHeight)
349         {
350                 Graphics::DrawLine(0,y, screen->w - 1,y, colour);       
351         }
352 }
353
354 Uint8 Graphics::MakeColour(int R, int G, int B, int Alpha)
355 {
356         return SDL_MapRGB(screen->format,R,G,B);
357 }
358
359 Colour Graphics::GetPixel(int x, int y)
360 {
361         return Graphics::GetPixel(screen, x, y);
362 }
363
364 Colour Graphics::GetPixel(SDL_Surface * src, int x, int y)
365
366         //Convert the pixels to 32 bit 
367         Uint8 * pixels = (Uint8*)src->pixels; 
368         //Get the requested pixel 
369
370         if (((y > 0)&&(y < src->h)) && ((x > 0)&&(x < src->w)))
371                 return ConvertColour(pixels[ ( y * src->w ) + x ]); 
372         return Colour(0,0,0,0);
373
374
375
376
377
378 void Graphics::DrawLine(int x1, int y1, int x2, int y2, Colour colour,double scale)
379 {               
380         //printf("DRAW LINE\n");
381         glColor4f(colour.r/255,colour.g/255,colour.b/255,colour.a);
382         glBegin(GL_LINES);
383         glVertex2f(x1/scale, y1/scale); // origin of the line
384         glVertex2f(x2/scale, y2/scale); // ending point of the line
385         glColor3f(1,1,1);
386         glEnd();
387
388         
389 }
390
391 void Graphics::DrawLineDashed(int x1, int y1, int x2, int y2, Colour colour, double scale)
392 {
393         glLineStipple(8, 0xAAAA);
394         glEnable(GL_LINE_STIPPLE);
395         DrawLine(x1,y1,x2,y2,colour,scale);
396         glDisable(GL_LINE_STIPPLE);
397         glEnd();
398 }
399
400 void Graphics::DrawRectangle(int topX, int topY, int botX, int botY, Colour colour, double scale)
401 {
402         glColor4f(colour.r/255,colour.g/255,colour.b/255,colour.a);
403         glBegin(GL_LINES);
404         glVertex2f(topX/scale, topY/scale); // origin of the rectangle
405         glVertex2f(botX/scale, topY/scale); // point1
406         glVertex2f(botX/scale, botY/scale); // point2
407         glVertex2f(topX/scale, botY/scale); // point3
408         glVertex2f(topX/scale, topY/scale); // point4
409         glEnd();
410 }
411
412 Colour Graphics::ConvertColour(Uint8 from)
413 {
414         SDL_PixelFormat * fmt=screen->format;
415         Colour result;
416
417         Uint8 temp;
418         
419         //Get red
420         temp=from&fmt->Rmask; /* Isolate red component */
421         temp=temp>>fmt->Rshift;/* Shift it down to 8-bit */
422         temp=temp<<fmt->Rloss; /* Expand to a full 8-bit number */
423         result.r = (float)(temp);
424
425         //Get green
426         temp=from&fmt->Gmask; /* Isolate red component */
427         temp=temp>>fmt->Gshift;/* Shift it down to 8-bit */
428         temp=temp<<fmt->Gloss; /* Expand to a full 8-bit number */
429         result.g = (float)(temp);
430
431         //Get blue
432         temp=from&fmt->Bmask; /* Isolate red component */
433         temp=temp>>fmt->Bshift;/* Shift it down to 8-bit */
434         temp=temp<<fmt->Bloss; /* Expand to a full 8-bit number */
435         result.b = (float)(temp);
436
437         //Get alpha
438         temp=from&fmt->Amask; /* Isolate red component */
439         temp=temp>>fmt->Ashift;/* Shift it down to 8-bit */
440         temp=temp<<fmt->Aloss; /* Expand to a full 8-bit number */
441         result.a = (float)(temp);
442         return result;
443 }
444
445
446
447
448
449

UCC git Repository :: git.ucc.asn.au