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

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