* Move ILUT initialization down to below OpenGL initilization, to prevent segfaults.
[matthijs/ABM2.git] / ABM2 / Amaltheia / Graphics.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos   *
3  *   <psybases@gmail.com>                                                             *
4  *                                                                                                       *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Library General Public License as       *
7  *   published by the Free Software Foundation; either version 2 of the    *
8  *   License, or (at your option) any later version.                                    *
9  *                                                                                                           *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU Library General Public     *
16  *   License along with this program; if not, write to the                 *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include "Graphics.h"
22 // #include <X11/Xlib.h>
23 // #include <X11/extensions/xf86vmode.h>
24 #include <FTGL/FTGLTextureFont.h>
25 #include <GL/glext.h>
26 #include <IL/il.h>
27 #include <IL/ilu.h>
28 #include <IL/ilut.h>
29 #include <SDL/SDL.h>
30 // #include <SDL/SDL_thread.h>
31 #include <GL/gl.h>
32 #include <GL/glu.h>
33 #include <iostream>
34 #include <cmath>
35 #include <cassert>
36
37 // using namespace Amaltheia;
38 extern float z_order; //for Sprite
39 static bool supportsAnisotropic = false;
40 static GLfloat maxAnisotropySupported = 0.0;
41 typedef unsigned long COLOUR;
42
43 colour COLOUR_RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a )
44 {
45         colour c;
46         c.a = a/255.0f;
47         c.r = r/255.0f;
48         c.g = g/255.0f;
49         c.b = b/255.0f;
50
51         return c;
52 }
53
54
55  inline COLOUR CLR_RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a )
56 {
57         return ( ( COLOUR ) ( ( ( ( a ) & 0xff ) << 24 ) | ( ( ( r ) & 0xff ) << 16 ) | ( ( ( g ) & 0xff ) << 8 ) | ( ( b ) & 0xff ) ) );
58 }
59
60
61
62 inline void transform_colourv( float *v, COLOUR col )
63 {
64         int a, r, g, b;
65         int mask = 0x000000ff;
66
67         b = col & mask;
68         col >>= 8;
69         g = col & mask;
70         col >>= 8;
71         r = col & mask;
72         col >>= 8;
73         a = col & mask;
74
75
76         v[ 3 ] = ( float ) a / 255.0f;
77         v[ 2 ] = ( float ) b / 255.0f;
78         v[ 1 ] = ( float ) g / 255.0f;
79         v[ 0 ] = ( float ) r / 255.0f;
80         
81         return;
82 }
83
84  
85 float rad( float deg )
86 {
87   return ( deg * M_PI ) / 180.f;
88 }
89
90 float deg( float rad )
91 {
92   return ( rad * 180.0f ) / M_PI;
93 }
94
95
96 inline GLboolean queryExtension(char *extName)
97 {
98         char *p = (char *) glGetString(GL_EXTENSIONS);
99         if(p == NULL)
100                 return GL_FALSE;
101         char *end = p + strlen(p);
102         unsigned int n = 0;
103         while(p < end)
104         {
105                 n = strcspn(p, " ");
106                 if((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
107                         return GL_TRUE;
108                 p += (n + 1);
109         }
110
111         return GL_FALSE;
112 }
113
114
115
116
117
118 class FontImp
119 {
120         public:
121                 FTGLTextureFont *font;
122                 int fontSize;
123                 Graphics *g;
124         
125 };
126
127
128 Font::Font()  :  imp( new FontImp() )
129 {
130 }
131
132 Font::~Font()
133 {
134         delete imp;
135         //      delete font;
136         return ;
137 }
138
139
140 Font::Font(const char *name, int size, Graphics *g) :  imp( new FontImp() )
141 {
142         assert(g);
143         imp->g = g;
144         imp->fontSize = size;
145         imp->font =  new FTGLTextureFont(name);
146         imp->font->FaceSize(size);
147         imp->font->CharMap(ft_encoding_unicode);
148         imp->fontSize = size;
149         /*this->g = g;
150         this->fontSize = size;
151         font =  new FTGLTextureFont(name);
152         font->FaceSize(size);
153         font->CharMap(ft_encoding_unicode);
154         fontSize = size; */
155 }
156  
157
158 void Font::print( const wchar_t *str, int x1, int y1, int x2, int y2, colour c )
159 {
160         imp->g->enter2dMode();
161         glColor4f( c.r, c.g, c.b, c.a);
162         float h= imp->font->LineHeight()*0.64f;         /* factor 0.64*/
163         glTranslatef(x1, y1 + h, 0);
164         glScalef(1.0, -1.0, 1.0);
165         imp->font->Render(str);
166 //      ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
167         imp->g->leave2dMode();
168 }
169
170         void Font::print( char *str, int x1, int y1, int x2, int y2, colour c )
171         {
172                 imp->g->enter2dMode();
173                 glColor4f( c.r, c.g, c.b, c.a);
174                 float h= imp->font->LineHeight()*0.64f;         /* factor 0.64*/
175                 glTranslatef(x1, y1 + h, 0);
176                 glScalef(1.0, -1.0, 1.0);
177                 imp->font->Render(str);
178         //      ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
179                 imp->g->leave2dMode();
180         }
181
182         
183 bool Graphics::oneGraphics = false;
184
185 class GraphicsImp
186 {
187 public:
188         SDL_Surface *screen;
189 };
190         
191         
192 Graphics::Graphics( int w, int h, int bpp, bool fullScreen, bool a, bool l ) : imp(new GraphicsImp())
193 {
194   if ( oneGraphics )
195   {
196     std::cerr << "Only one graphics object allowed!\n";
197     exit( 1 );
198   }
199
200   oneGraphics = true;
201   width = w;
202   height = h;
203   this->fullScreen = fullScreen;
204   this->bpp = bpp;
205   alpha = a;
206   lighting = l;
207   sceneBegin = false;
208   culling = true;
209   cmode = AM_CULL_BACK;
210   zBuffer = true;
211   cursorState = true;
212   bgcolour[ 0 ] = 0;
213   bgcolour[ 1 ] = 0;
214   bgcolour[ 2 ] = 0;
215   bgcolour[ 3 ] = 1;
216
217   cam.camx = 0.0;
218   cam.camy = 0.0;
219   cam.camz = 0.0;
220
221   cam.lookx = 0.0;
222   cam.looky = 0.0;
223   cam.lookz = 1.0;
224
225   cam.upx = 0.0;
226   cam.upy = 1.0;
227   cam.upz = 0.0;
228
229   this->currentTexture = 0;
230 }
231
232
233
234 Graphics::~Graphics( void )
235 {
236   //glDeleteBuffers(1, &gpuBuf); // mono gia OpenGL 1.5
237         delete imp;
238         SDL_Quit();
239         return ;
240 }
241
242
243
244 void Graphics::setHeight( int h)
245 {
246   height = h;
247   return ;
248 }
249
250 int Graphics::getHeight()
251 {
252   return height;
253 }
254
255 void Graphics::setWidth(int w)
256 {
257   width = w;
258   return ;
259 }
260 int Graphics::getWidth()
261 {
262   return width;
263 }
264
265 void Graphics::setBpp( int b )
266 {
267   bpp = b;
268   return ;
269 }
270 int Graphics::getBpp()
271 {
272   return bpp;
273 }
274
275 void Graphics::enableVsync( bool v )
276 {
277   vSync = v;
278   return ;
279 }
280 bool Graphics::isVsync()
281 {
282   return vSync;
283 }
284
285
286 void Graphics::enableFullScreen( bool f )
287 {
288   fullScreen = f;
289   return ;
290 }
291 bool Graphics::isFullScreen( void )
292 {
293   return fullScreen;
294 }
295
296                                                                                                                                         
297 void Graphics::enableLighting( bool l )
298 {
299   lighting = l;
300
301   if ( lighting )
302     glEnable( GL_LIGHTING );
303   else
304     glDisable( GL_LIGHTING );
305
306   return ;
307 }
308
309
310 bool Graphics::isLighting()
311 {
312   return lighting;
313 }
314
315 void Graphics::enableAlpha( bool a )
316 {
317   alpha = a;
318   if ( alpha )
319     glEnable( GL_BLEND );
320   else
321     glDisable( GL_BLEND );
322
323   return ;
324 }
325
326
327 bool Graphics::isAlpha( void )
328 {
329   return alpha;
330 }
331
332 void Graphics::setTexture( Texture *t )
333 {
334   if ( t == 0 )
335     return ;
336
337   currentTexture = t;
338   glBindTexture( GL_TEXTURE_2D, t->gl_Tex );
339
340   return ;
341 }
342
343 Texture* Graphics::getTexture(void)
344 {
345         return currentTexture;
346 }
347
348
349 int Graphics::createDisplay()
350 {
351
352
353   /* Information about the current video settings. */
354   const SDL_VideoInfo * info = 0;
355   /* Flags we will pass into SDL_SetVideoMode. */
356   int flags = 0;
357
358   //    putenv("__GL_SYNC_TO_VBLANK=1");
359
360   /* First, initialize SDL's video subsystem. */
361   if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
362   {
363     /* Failed, exit. */
364     fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError() );
365     return 2;
366   }
367
368   /* Let's get some video information. */
369   info = SDL_GetVideoInfo( );
370
371   if ( !info )
372   {
373     std::cerr << "Video query failed: " << SDL_GetError() << std::endl;
374     return 2;
375   }
376
377   /*
378    * Now, we want to setup our requested
379    * window attributes for our OpenGL window.
380    * We want *at least* 5 bits of red, green
381    * and blue. We also want at least a 16-bit
382    * depth buffer.
383    *
384    * The last thing we do is request a double
385    * buffered window. '1' turns on double
386    * buffering, '0' turns it off.
387    *
388    * Note that we do not use SDL_DOUBLEBUF in
389    * the flags to SDL_SetVideoMode. That does
390    * not affect the GL attribute state, only
391    * the standard 2D blitting setup.
392    */
393   SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
394   SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
395   SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
396   SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bpp );
397   SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
398
399   flags = SDL_OPENGL | ( fullScreen ? SDL_FULLSCREEN : 0 );
400
401   /*
402    * Set the video mode
403    */
404   if ( ( imp->screen = SDL_SetVideoMode( width, height, bpp, flags ) ) == 0 )
405   {
406     /*
407      * This could happen for a variety of reasons,
408      * including DISPLAY not being set, the specified
409      * resolution not being available, etc.
410      */
411     std::cerr << "Video mode set failed: " << SDL_GetError() << std::endl;
412     return 2;
413   }
414
415   ilInit();
416   iluInit();
417   ilutRenderer(ILUT_OPENGL);
418
419   SDL_SetGamma(1.8, 1.8, 1.8);
420   
421   float ratio = ( float ) width / ( float ) height;
422   /* Our shading model--Gouraud (smooth). */
423   glShadeModel( GL_SMOOTH );
424   glClearDepth( 1.0f );
425
426   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
427
428   //   glDepthFunc( GL_LEQUAL );
429   /* Set the clear color. */
430   glClearColor( bgcolour[ 0 ], bgcolour[ 1 ], bgcolour[ 2 ], bgcolour[ 3 ] );
431   glMatrixMode( GL_PROJECTION );
432   glLoadIdentity();
433
434   glViewport( 0, 0, width, height );
435   gluPerspective( 45.0, ratio, 1.0, 10000.0 );
436
437   /* Culling. Boh8aei sto Blending*/
438   glCullFace( GL_BACK );
439 /* Polygons whose vertices are in counterclockwise order are called frontfacing but dx thinks different ?*/
440   glFrontFace( GL_CW );
441         if( culling)
442                 glEnable( GL_CULL_FACE );
443
444         if(zBuffer)
445                 glEnable( GL_DEPTH_TEST );
446         
447         glEnable( GL_TEXTURE_2D );
448   if ( alpha )
449     glEnable( GL_BLEND );
450   if ( lighting )
451     glEnable( GL_LIGHTING );
452
453   //TODO: 8a prepei na oristei synarthsh setMaterial...
454   float diffuse[] = {1.0, 1.0, 1.0, 1.0};
455   float specular[] = {0.0, 0.0, 0.0, 0.0};
456   float ambient[] = {   0.0, 0.0, 0.0, 0.0};
457   float  emissive[] = {0.0, 0.0, 0.0, 0.0};
458         glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse );
459         glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, specular );
460         glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, emissive );
461         glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, ambient );
462
463   
464         if ( !queryExtension( "GL_EXT_texture_filter_anisotropic" ) )
465                 std::cout << "Extension GL_EXT_texture_filter_anisotropic not found...\n";
466         else
467         {
468                 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropySupported);
469                 std::cout << "max Anisotropy supported = " << maxAnisotropySupported << '\n';
470                 supportsAnisotropic = true;
471         }
472         
473         /*glGenBuffers(1, &gpuBuf); // mono gia OpenGL 1.5 
474   glBindBuffer(GL_ARRAY_BUFFER, gpuBuf);            // mono gia OpenGL 1.5
475   glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &parameter); // mono gia OpenGL 1.5
476   printf("Buffer size is %d \n", parameter); */
477   if ( !queryExtension( "GL_ARB_point_sprite" ) )
478     std::cout << "Extension GL_ARB_point_sprite not found...\n";
479   else
480   {
481     // This is how will our point sprite's size will be modified by
482     // distance from the viewer
483     float quadratic[] =  { 1.0f, 0.0f, 0.01f };
484     glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
485     // Query for the max point size supported by the hardware
486     maxSize = 0.0f;
487     glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
488     // Clamp size to 100.0f or the sprites could get a little too big on some
489     // of the newer graphic cards. My ATI card at home supports a max point
490     // size of 1024.0f!
491
492     // The alpha of a point is calculated to allow the fading of points
493     // instead of shrinking them past a defined threshold size. The threshold
494     // is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
495     // the minimum and maximum point sizes.
496     glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
497     glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 10.0f );
498     glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
499
500     // Specify point sprite texture coordinate replacement mode for each
501     // texture unit
502     glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
503     glEnable( GL_POINT_SPRITE_ARB );
504     glEnable( GL_ARB_point_sprite );
505   }
506
507   std::cout << "OpenGL Version =" << glGetString( GL_VERSION ) << std::endl;
508   int _red,_green,_blue, _alpha, _depth, _stencil;
509   glGetIntegerv(GL_RED_BITS, &_red);
510   glGetIntegerv(GL_GREEN_BITS, &_green);
511   glGetIntegerv(GL_BLUE_BITS, &_blue);
512   glGetIntegerv(GL_ALPHA_BITS, &_alpha);
513   std::cout << "Color Buffers RGBA bits = " << _red <<  _green <<  _blue << _alpha << std::endl;
514   glGetIntegerv(GL_DEPTH_BITS, &_depth);
515   std::cout << "Depth Buffer bits = " << _depth << "\n";
516   glGetIntegerv(GL_STENCIL_BITS, &_stencil);
517   std::cout << "Stencil Buffer bits = " << _stencil << "\n";
518   int _aux;
519   glGetIntegerv(GL_AUX_BUFFERS, &_aux);
520   std::cout << "Aux buffers = " << _aux << "\n";
521   //    putenv("__GL_SYNC_TO_VBLANK=1");
522
523   //    XF86VidModeModeLine mode;
524   //    int unused;
525
526   //    Display *d = XOpenDisplay(NULL);
527   /*Bool XF86VidModeGetModeLine(
528                 Display *display ,
529   int screen ,
530   int *dotclock_return ,
531   XF86VidModeModeLine *modeline );
532   */
533   //    printf("d=%p\n",d);
534   //    if(XF86VidModeGetModeLine(d, 0, &unused, &mode))
535   //    {
536
537   //            printf("OK  %d mexri %d\n", mode.hsyncstart, mode.hsyncend);
538   //    }
539   //    else
540   //            printf("not ok\n");
541   //    glXWaitVideoSyncSGI();
542   //    GLX_SGI_video_sync
543   //    unsigned int k;
544   //    glXGetVideoSyncSGI(&k);
545   //    printf("k=%d\n", k);
546   glMatrixMode( GL_MODELVIEW );
547
548   return 0;
549 }
550
551
552
553 void Graphics::beginScene( void )
554 {
555   /* Clear the color and depth buffers. */
556   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
557   glMatrixMode( GL_MODELVIEW );
558   glLoadIdentity();
559   //gia symbatothta me to DirectX
560   glScalef( -1.0, 1.0, 1.0 );
561   sceneBegin = true;
562
563   return ;
564 }
565
566
567 void Graphics::endScene()
568 {
569   glColorMask(GL_TRUE, GL_TRUE,  GL_TRUE,  GL_TRUE);
570   //if(vSync)
571     //glXSwapIntervalSGI(1);
572   SDL_GL_SwapBuffers();
573
574   sceneBegin = false;
575   z_order = 1.0;
576   return ;
577 }
578
579
580 GLdouble mm[4][4];
581 void _gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
582                  GLdouble centerx, GLdouble centery, GLdouble centerz,
583                  GLdouble upx, GLdouble upy, GLdouble upz )
584 {
585   GLdouble m[ 16 ];
586   GLdouble x[ 3 ], y[ 3 ], z[ 3 ];
587   GLdouble mag;
588
589   /* Make rotation matrix */
590
591   /* Z vector */
592   z[ 0 ] = ( eyex - centerx );
593   z[ 1 ] = ( eyey - centery );
594   z[ 2 ] = ( eyez - centerz );
595   mag = sqrt( z[ 0 ] * z[ 0 ] + z[ 1 ] * z[ 1 ] + z[ 2 ] * z[ 2 ] );
596   if ( mag )
597   {                     /* mpichler, 19950515 */
598     z[ 0 ] /= mag;
599     z[ 1 ] /= mag;
600     z[ 2 ] /= mag;
601   }
602
603   /* Y vector */
604   y[ 0 ] = upx;
605   y[ 1 ] = upy;
606   y[ 2 ] = upz;
607
608   /* X vector = Y cross Z */
609   x[ 0 ] = y[ 1 ] * z[ 2 ] - y[ 2 ] * z[ 1 ];
610   x[ 1 ] = y[ 2 ] * z[ 0 ] - y[ 0 ] * z[ 2 ] ;
611   x[ 2 ] = y[ 0 ] * z[ 1 ] - y[ 1 ] * z[ 0 ];
612
613   /* Recompute Y = Z cross X */
614   y[ 0 ] = z[ 1 ] * x[ 2 ] - z[ 2 ] * x[ 1 ];
615   y[ 1 ] = -z[ 0 ] * x[ 2 ] + z[ 2 ] * x[ 0 ];
616   y[ 2 ] = z[ 0 ] * x[ 1 ] - z[ 1 ] * x[ 0 ];
617
618   /* mpichler, 19950515 */
619   /* cross product gives area of parallelogram, which is < 1.0 for
620   * non-perpendicular unit-length vectors; so normalize x, y here
621   */
622
623   mag = sqrt( x[ 0 ] * x[ 0 ] + x[ 1 ] * x[ 1 ] + x[ 2 ] * x[ 2 ] );
624   if ( mag )
625   {
626     x[ 0 ] /= mag;
627     x[ 1 ] /= mag;
628     x[ 2 ] /= mag;
629   }
630
631   mag = sqrt( y[ 0 ] * y[ 0 ] + y[ 1 ] * y[ 1 ] + y[ 2 ] * y[ 2 ] );
632   if ( mag )
633   {
634     y[ 0 ] /= mag;
635     y[ 1 ] /= mag;
636     y[ 2 ] /= mag;
637   }
638
639 #define M(row,col)  m[col*4+row]
640   M( 0, 0 ) = x[ 0 ];
641   M( 0, 1 ) = x[ 1 ];
642   M( 0, 2 ) = x[ 2 ];
643   M( 0, 3 ) = -( x[ 0 ] * eyex + x[ 1 ] * eyey + x[ 2 ] * eyez );
644
645   M( 1, 0 ) = y[ 0 ];
646   M( 1, 1 ) = y[ 1 ];
647   M( 1, 2 ) = y[ 2 ];
648   M( 1, 3 ) = -( y[ 0 ] * eyex + y[ 1 ] * eyey + y[ 2 ] * eyez );
649
650   M( 2, 0 ) = z[ 0 ];
651   M( 2, 1 ) = z[ 1 ];
652   M( 2, 2 ) = z[ 2 ];
653   M( 2, 3 ) = -( z[ 0 ] * eyex + z[ 1 ] * eyey + z[ 2 ] * eyez );
654
655   M( 3, 0 ) = 0.0;
656   M( 3, 1 ) = 0.0;
657   M( 3, 2 ) = 0.0;
658   M( 3, 3 ) = 1.0;
659   /*   M(0, 0) = x[0];
660         M(1, 0) = y[0];
661         M(2, 0) = z[0];
662         M(3, 0) = 0.0;
663      
664         M(0, 1) = x[1];
665         M(1, 1) = y[1];
666         M(2, 1) = z[1];
667         M(3, 1) = 0.0;
668      
669         M(0, 2) = x[2];
670         M(1, 2) = y[2];
671         M(2, 2) = z[2];
672         M(3, 2) = 0.0;
673      
674         M(0, 3) = 0.0;
675         M(1, 3) = 0.0;
676         M(2, 3) = 0.0;
677         M(3, 3) = 1.0;
678   */
679 #undef M
680   glScalef( -1.0, 1.0, 1.0 );
681   glMultMatrixd( m );
682   glScalef( -1.0, 1.0, 1.0 );
683
684 }
685
686
687
688 int Graphics::setCamera(  float camx,  float camy,  float camz,
689                           float lookx, float looky, float lookz,
690                           float upx,  float upy, float upz )
691 {
692
693   _gluLookAt( camx, camy, camz, lookx, looky, lookz, upx, upy, upz );
694
695   cam.camx = camx;
696   cam.camy = camy;
697   cam.camz = camz;
698
699   cam.lookx = lookx;
700   cam.looky = looky;
701   cam.lookz = lookz;
702
703   cam.upx = upx;
704   cam.upy = upy;
705   cam.upz = upz;
706
707   return 0;
708 }
709
710
711 struct camera Graphics::getCamera()
712 {
713   return cam;
714 }
715
716
717
718
719 int Graphics::renderTriangle(vertex v1, vertex v2, vertex v3 )
720 {
721 //   GLfloat colour[ 4 ];
722   if ( !sceneBegin )
723   {
724     std::cout << "DEBUG: oust...!\n";
725     exit( 1 );
726     return 1;
727   }
728
729
730 //      glPushAttrib(GL_ALL_ATTRIB_BITS); //kyriws gia na epanaferoume to xrwma
731   glBegin( GL_TRIANGLES );
732
733 //   transform_colourv( colour, v1.col );
734   glColor4f( v1.col.r, v1.col.g, v1.col.b, v1.col.a);
735   glNormal3f( v1.nx, v1.ny, v1.nz );
736   glTexCoord2f( v1.u, 1.0 - v1.v );
737   glVertex3f( v1.x, v1.y, v1.z );
738
739 //   transform_colourv( colour, v2.col );
740 //   glColor4f( colour[ 0 ], colour[ 1 ], colour[ 2 ], colour[ 3 ] );
741         glColor4f( v2.col.r, v2.col.g, v2.col.b, v2.col.a);
742   glNormal3f( v2.nx, v2.ny, v2.nz );
743   glTexCoord2f( v2.u, 1.0 - v2.v );
744   glVertex3f( v2.x, v2.y, v2.z );
745
746         glColor4f( v3.col.r, v3.col.g, v3.col.b, v3.col.a);
747   glNormal3f( v3.nx, v3.ny, v3.nz );
748   glTexCoord2f( v3.u, 1.0 - v3.v );
749   glVertex3f( v3.x, v3.y, v3.z );
750
751   glEnd();
752 //      glPopAttrib();
753   //isos na prepei na epanafero pisw to arxiko xrwma...
754
755   return 0;
756 }
757
758
759
760 int Graphics::setWorld( float transx, float transy, float transz,
761                         float rotx, float roty, float rotz, float scalex, float scaley, float scalez,
762                                                          int rotationOrder)
763 {
764   glMatrixMode( GL_MODELVIEW );
765   glLoadIdentity();
766
767   struct camera c = getCamera();
768   setCamera( c.camx, c.camy, c.camz, c.lookx, c.looky, c.lookz, c.upx, c.upy, c.upz );
769   
770   glScalef( -1.0, 1.0, 1.0 ); //gia symbatothta me to DirectX
771   glTranslatef( transx, transy, transz );
772
773   if(rotationOrder == AM_XYZ)
774   {
775                 glRotatef( rotz, 0, 0, 1 );
776                 glRotatef( roty, 0, 1, 0 );
777                 glRotatef( rotx, 1, 0, 0 );
778   }
779   else if(rotationOrder == AM_XZY)
780   {
781           glRotatef( roty, 0, 1, 0 );     
782           glRotatef( rotz, 0, 0, 1 );
783           glRotatef( rotx, 1, 0, 0 );
784
785   }
786   else if(rotationOrder == AM_YZX)
787   {
788           glRotatef( rotx, 1, 0, 0 );
789           glRotatef( rotz, 0, 0, 1 );
790           glRotatef( roty, 0, 1, 0 );
791   }
792   else if(rotationOrder == AM_YXZ)
793   {
794           glRotatef( rotz, 0, 0, 1 );
795           glRotatef( rotx, 1, 0, 0 );
796           glRotatef( roty, 0, 1, 0 );
797
798   }
799   else if(rotationOrder == AM_ZXY)
800   {
801           glRotatef( roty, 0, 1, 0 );
802           glRotatef( rotx, 1, 0, 0 );
803           glRotatef( rotz, 0, 0, 1 );
804   }
805   else
806   {
807           glRotatef( rotx, 1, 0, 0 );
808           glRotatef( roty, 0, 1, 0 );
809           glRotatef( rotz, 0, 0, 1 );
810   }
811   
812   glScalef( scalex, scaley, scalez );
813   
814   return 0;
815 }
816
817
818
819 /*
820
821 int Graphics::setWorld2( float transx, float transy, float transz,
822                                                                 float rotx, float roty, float rotz, float scalex, float scaley, float scalez )
823 {
824         glMatrixMode( GL_MODELVIEW );
825         glLoadIdentity();
826
827
828         struct camera c = getCamera();
829         setCamera( c.camx, c.camy, c.camz, c.lookx, c.looky, c.lookz, c.upx, c.upy, c.upz );
830   
831         glScalef( -1.0, 1.0, 1.0 ); //gia symbatothta me to DirectX
832         glTranslatef( transx, transy, transz );
833         glRotatef( roty, 0, 1, 0 );
834         glRotatef( rotz, 0, 0, 1 );
835         glRotatef( rotx, 1, 0, 0 );
836         glScalef( scalex, scaley, scalez );
837   
838
839         return 0;
840 }
841
842   */
843
844
845
846
847
848 void Graphics::setBackground( colour colour )
849 {
850 //   transform_colourv( bgcolour, colour );
851   //    printf( "(%f, %f, %f ,%f)\n", bgcolour[ 0 ], bgcolour[ 1 ], bgcolour[ 2 ], bgcolour[ 3 ] );
852         bgcolour[0] = colour.r;
853         bgcolour[1] = colour.g;
854         bgcolour[2] = colour.b;
855         bgcolour[3] = colour.a;
856         glClearColor( ( float ) bgcolour[ 0 ], ( float ) bgcolour[ 1 ], ( float ) bgcolour[ 2 ], ( float ) bgcolour[ 3 ] );
857         
858 return ;
859 }
860
861
862 colour Graphics::getBackground( void )
863 {
864         colour c;
865         c.r = bgcolour[0];
866         c.g = bgcolour[1];
867         c.b = bgcolour[2];
868         c.a = bgcolour[3];
869         return c;
870 }
871         
872         
873
874
875 void Graphics::project( float objx, float objy, float objz,
876                         //const double modelMatrix[16], const double projMatrix[16], const int viewport[4],
877                                                                 float *winx, float *winy, float *winz )
878 {
879   double _winx = 0;
880   double _winy = 0;
881   double _winz = 0;
882   GLint viewport[ 4 ];
883   GLdouble mvmatrix[ 16 ], projmatrix[ 16 ];
884
885   glGetIntegerv ( GL_VIEWPORT, viewport );
886   glGetDoublev ( GL_MODELVIEW_MATRIX, mvmatrix );
887   glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix );
888
889   gluProject( objx, objy, objz, mvmatrix, projmatrix, viewport,
890               &_winx, &_winy, &_winz );
891
892   *winx = _winx;
893   *winy = viewport[ 3 ] - ( int ) _winy - 1;
894   *winz = _winz;
895
896   return ;
897 }
898
899
900 void Graphics::unproject( float winx, float winy, float winz,
901                           //const double modelMatrix[16], const double projMatrix[16], const int viewport[4],
902                                                                   float *objx, float *objy, float *objz )
903 {
904   int realy;
905   double _objx = 0;
906   double _objy = 0;
907   double _objz = 0;
908         GLint viewport[ 4 ];
909   GLdouble mvmatrix[ 16 ], projmatrix[ 16 ];
910
911   glGetIntegerv ( GL_VIEWPORT, viewport );
912   glGetDoublev ( GL_MODELVIEW_MATRIX, mvmatrix );
913   glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix );
914    
915   realy = viewport[ 3 ] - ( int ) winy - 1;
916   //    std::cout << "realy=" <<realy << "\n";
917
918   gluUnProject( winx, realy, winz,
919                 mvmatrix, projmatrix, viewport,
920                 &_objx, &_objy, &_objz );
921
922   *objx = _objx;
923   *objy = _objy;
924   *objz = _objz;
925
926   return ;
927 }
928
929
930
931 void Graphics::enableCursor( bool state )
932 {
933         cursorState = state;
934         if ( state )
935                 SDL_ShowCursor( SDL_ENABLE );
936         else
937                 SDL_ShowCursor( SDL_DISABLE );
938   return;
939 }
940
941 bool Graphics::isCursor()
942 {
943         return cursorState;
944 }
945
946
947
948 void Graphics::planeIntersect( float a, float b, float c, float d,
949                                float p1x, float p1y, float p1z, float p2x, float p2y, float p2z,
950                                                                                  float *poutx, float *pouty, float *poutz )
951 {
952   float numerator = -( a * p1x + b * p1y + c * p1z + d );
953   if ( numerator == 0 )
954   {
955     ( *poutx ) = p1x;
956     ( *pouty ) = p1y;
957     ( *poutz ) = p1z;
958     return ;
959   }
960   else
961   {
962     float denominator = a * ( p2x - p1x ) + b * ( p2y - p1y ) + c * ( p2z - p1z );
963     if ( denominator == 0 )
964     {
965       ( *poutx ) = 0.0;
966       ( *pouty ) = 0.0;
967       ( *poutz ) = 0.0;
968                 printf("denominator==0!!!\n");
969                 exit(1);
970       return ;
971     }
972     else
973     {
974       float t = numerator / denominator;
975       ( *poutx ) = p1x + t * ( p2x - p1x );
976       ( *pouty ) = p1y + t * ( p2y - p1y );
977       ( *poutz ) = p1z + t * ( p2z - p1z );
978       return ;
979     }
980   }
981
982   return ;
983 }
984
985
986
987 void Graphics::setLight( int numLight, const light& l )
988 {
989         GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
990         GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0};
991         GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0};
992         GLfloat position[] = {0.0, 0.0, 1.0, 0.0};
993         GLenum enm = GL_LIGHT0;
994
995         if(numLight == 0)  enm = GL_LIGHT0;
996         else if(numLight == 1) enm = GL_LIGHT1;
997         else if(numLight == 2) enm = GL_LIGHT2;
998         else if(numLight == 3) enm = GL_LIGHT3;
999         else if(numLight == 4) enm = GL_LIGHT4;
1000         else if(numLight == 5) enm = GL_LIGHT5;
1001         else if(numLight == 6) enm = GL_LIGHT6;
1002         else if(numLight == 7 ) enm = GL_LIGHT7;
1003
1004 //   transform_colourv( ambient, l.ambient );
1005 //   transform_colourv( diffuse, l.diffuse );
1006 //   transform_colourv( specular, l.specular );
1007         ambient[0] = l.ambient.r;               ambient[1] = l.ambient.g;               ambient[2] = l.ambient.b;               ambient[3] = l.ambient.a;
1008         diffuse[0] = l.diffuse.r;               diffuse[1] = l.diffuse.g;               diffuse[2] = l.diffuse.b;               diffuse[3] = l.diffuse.a;
1009         specular[0] = l.specular.r;             specular[1] = l.specular.g;             specular[2] = l.specular.b;             specular[3] = l.specular.a;
1010         
1011         if ( l.type == AM_POINT_LIGHT )
1012   {
1013     position[ 3 ] = 1.0;
1014     position[ 0 ] = l.posx;
1015     position[ 1 ] = l.posy;
1016     position[ 2 ] = l.posz;
1017   }
1018   else
1019     if ( l.type == AM_DIRECTIONAL_LIGHT )
1020     {
1021                  //float val = sqrt(l.dirx*l.dirx + l.diry*l.diry + l.dirz*l.dirz);
1022                  position[ 3 ] = 0.0;
1023                  position[ 0 ] = -l.dirx;
1024                  position[ 1 ] = -l.diry;
1025                  position[ 2 ] = l.dirz;
1026     }
1027
1028
1029   /*glPushMatrix();
1030   glBegin(GL_POINTS);
1031   glPointSize(1000.);
1032   glVertex3f(position[0], position[1], position[2]);
1033   glVertex3f(360, 10, 360);
1034   glEnd();
1035   */
1036   glLightfv( enm, GL_AMBIENT, ambient );
1037   glLightfv( enm, GL_DIFFUSE, diffuse );
1038   glLightfv( enm, GL_SPECULAR, specular );
1039   glLightfv( enm, GL_POSITION, position );
1040   //    glPopMatrix();
1041
1042   return ;
1043 }
1044
1045
1046 void Graphics::showLight( int numLight, bool state )
1047 {
1048   GLenum enm = GL_LIGHT0;
1049   if ( numLight == 0 )
1050     enm = GL_LIGHT0;
1051   else
1052     if ( numLight == 1 )
1053       enm = GL_LIGHT1;
1054     else
1055       if ( numLight == 2 )
1056         enm = GL_LIGHT2;
1057
1058   if ( state )
1059     glEnable( enm );
1060   else
1061     glDisable( enm );
1062
1063   return ;
1064 }
1065
1066
1067
1068
1069
1070 void inverseMatrix( double A[16], double B[16])
1071 {
1072
1073         double detA;
1074         
1075         double a11 = A[0];
1076         double a12 = A[1];
1077         double a13 = A[2];
1078         double a14 = A[3];
1079         double a21 = A[4];
1080         double a22 = A[5];
1081         double a23 = A[6];
1082         double a24 = A[7];
1083         double a31 = A[8];
1084         double a32 = A[9];
1085         double a33 = A[10];
1086         double a34 = A[11];
1087         double a41 = A[12];
1088         double a42 = A[13];
1089         double a43 = A[14];
1090         double a44 = A[15];
1091         
1092         detA =  a11*a22*a33*a44 + a11*a23*a34*a42 + a11*a24*a32*a43 \
1093                         +a12*a21*a34*a43 + a12*a23*a31*a44 + a12*a24*a33*a41 \
1094                         +a13*a21*a32*a44 + a13*a22*a34*a41 + a13*a24*a31*a42 \
1095                         +a14*a21*a33*a42 + a14*a22*a31*a43 + a14*a23*a32*a41 \
1096                         -a11*a22*a34*a43 - a11*a23*a32*a44 - a11*a24*a33*a42 \
1097                         -a12*a21*a33*a44 - a12*a23*a34*a41 - a12*a24*a31*a43 \
1098                         -a13*a21*a34*a42 - a13*a22*a31*a44 - a13*a24*a32*a41 \
1099                         -a14*a21*a32*a43 - a14*a22*a33*a41 - a14*a23*a31*a42;
1100
1101 //      printf("detA=%f\n",detA); 
1102         
1103         B[0] = (a22*a33*a44 + a23*a34*a42 + a24*a32*a43 - a22*a34*a43 - a23*a32*a44 - a24*a33*a42)/detA;
1104         B[1] = (a12*a34*a43 + a13*a32*a44 + a14*a33*a42 - a12*a33*a44 - a13*a34*a42 - a14*a32*a43)/detA;
1105         B[2] = (a12*a23*a44 + a13*a24*a42 + a14*a22*a43 - a12*a24*a43 - a13*a22*a44 - a14*a23*a42)/detA; 
1106         B[3] = (a12*a24*a33 + a13*a22*a34 + a14*a23*a32 - a12*a23*a34 - a13*a24*a32 - a14*a22*a33)/detA;
1107         B[4] = (a21*a34*a43 + a23*a31*a44 + a24*a33*a41 - a21*a33*a44 - a23*a34*a41 - a24*a31*a43)/detA;
1108         B[5] = (a11*a33*a44 + a13*a34*a41 + a14*a31*a43 - a11*a34*a43 - a13*a31*a44 - a14*a33*a41)/detA;
1109         B[6] = (a11*a24*a43 + a13*a21*a44 + a14*a23*a41 - a11*a23*a44 - a13*a24*a41 - a14*a21*a43)/detA;
1110         B[7] = (a11*a23*a34 + a13*a24*a31 + a14*a21*a33 - a11*a24*a33 - a13*a21*a34 - a14*a23*a31)/detA;
1111         B[8] = (a21*a32*a44 + a22*a34*a41 + a24*a31*a42 - a21*a34*a42 - a22*a31*a44 - a24*a32*a41)/detA;
1112         B[9] = (a11*a34*a42 + a12*a31*a44 + a14*a32*a41 - a11*a32*a44 - a12*a34*a41 - a14*a31*a42)/detA;
1113         B[10] = (a11*a22*a44 + a12*a24*a41 + a14*a21*a42 - a11*a24*a42 - a12*a21*a44 - a14*a22*a41)/detA;
1114         B[11] = (a11*a24*a32 + a12*a21*a34 + a14*a22*a31 - a11*a22*a34 - a12*a24*a31 - a14*a21*a32)/detA;
1115         B[12] = (a21*a33*a42 + a22*a31*a43 + a23*a32*a41 - a21*a32*a43 - a22*a33*a41 - a23*a31*a42)/detA;
1116         B[13] = (a11*a32*a43 + a12*a33*a41 + a13*a31*a42 - a11*a33*a42 - a12*a31*a43 - a13*a32*a41)/detA;
1117         B[14] = (a11*a23*a42 + a12*a21*a43 + a13*a22*a41 - a11*a22*a43 - a12*a23*a41 - a13*a21*a42)/detA;
1118         B[15] = (a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a11*a23*a32 - a12*a21*a33 - a13*a22*a31)/detA;
1119
1120         return;
1121 }
1122
1123
1124
1125 void Graphics::drawBillboardParticle(float x, float y, float z, float size, colour col)
1126 {
1127 //   float v[4];
1128   
1129   glPushAttrib(GL_ALL_ATTRIB_BITS);
1130   glDisable(GL_DEPTH_TEST);
1131   glDepthMask( GL_FALSE );
1132   enableAlpha(true);
1133   glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1134   glDisable(GL_CULL_FACE);
1135   glEnable( GL_TEXTURE_2D );
1136   /*********************************/
1137   GLdouble modelview[16], B[16];
1138   // save the current modelview matrix
1139   glPushMatrix();
1140   // get the current modelview matrix
1141   glGetDoublev(GL_MODELVIEW_MATRIX , modelview);
1142   inverseMatrix(modelview, B);
1143   // set the modelview with no rotations and scaling
1144          glMultMatrixd(B);
1145          glLoadMatrixd(modelview);
1146         glTranslatef(x,y,z);
1147         
1148    float s2 = size / 2.0;
1149 //   transform_colourv(v, col);
1150   glBegin(GL_QUADS);
1151         glColor4f(col.r, col.g, col.b, col.a);
1152         glTexCoord2f( 0.0, 0.0 );       glVertex3f(-s2,s2,0);
1153         glTexCoord2f( 1.0, 0.0 );       glVertex3f(s2,s2,0);
1154         glTexCoord2f( 1.0, 1.0 );       glVertex3f(s2,-s2,0);
1155         glTexCoord2f( 0.0, 1.0 );       glVertex3f(-s2,-s2,0);
1156   glEnd();
1157
1158   // restores the modelview matrix
1159   glPopMatrix();
1160   /*********************************/
1161   glPopAttrib();
1162
1163   return;
1164 }
1165
1166
1167 void Graphics::renderParticleArray(particle *array, unsigned int sizeOfArray, int type)
1168 {
1169         unsigned int i;
1170         
1171         if(type == AM_HARDWARE_PARTICLE)
1172         {       
1173                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1174                         glEnable(GL_DEPTH_TEST);
1175                         glDepthMask( GL_FALSE );
1176                         enableAlpha(true);
1177                         glBlendFunc( GL_DST_ALPHA, GL_ONE );
1178                         
1179                         for(i=0; i < sizeOfArray; i++)
1180                         {
1181                                 glPointSize( (array[i].size > maxSize ? maxSize : array[i].size) );
1182                                 glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, (array[i].size > maxSize ? maxSize : array[i].size)  );
1183                                 glBegin(GL_POINTS);
1184                                         glColor4f(array[i].col.r, array[i].col.g, array[i].col.b, array[i].col.a);
1185                                         glVertex3f(array[i].x, array[i].y, array[i].z);
1186                                 glEnd();
1187                         }
1188                 glPopAttrib();
1189         }
1190         else
1191         if(type == AM_SOFTWARE_PARTICLE)
1192         {
1193                 float mat[16];
1194                 struct point
1195                 {
1196                         float x,y,z;
1197                 }quad_lower_left, quad_lower_right;
1198   
1199                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1200                         glEnable(GL_DEPTH_TEST);
1201                         enableAlpha(true);
1202                         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1203                         glDisable(GL_CULL_FACE);
1204                         glEnable( GL_TEXTURE_2D );
1205                         glGetFloatv( GL_MODELVIEW_MATRIX, mat );
1206                         
1207                         for(i=0; i < sizeOfArray; i++)
1208                         {
1209                                 float s2 = array[i].size / 2.0;
1210                                 quad_lower_left.x = (-s2) * (mat[0] + mat[1]);
1211                                 quad_lower_left.y = (-s2) * (mat[4] + mat[5]);
1212                                 quad_lower_left.z = (-s2) * (mat[8] + mat[9]);
1213                                 quad_lower_right.x = (s2) * (mat[0] - mat[1]);
1214                                 quad_lower_right.y = (s2) * (mat[4] - mat[5]);
1215                                 quad_lower_right.z = (s2) * (mat[8] - mat[9]);
1216
1217                                 glBegin(GL_QUADS);
1218                                         glColor4f(array[i].col.r, array[i].col.g, array[i].col.b, array[i].col.a);
1219                                         glTexCoord2f(0.0, 0.0);
1220                                         glVertex3f(array[i].x + quad_lower_left.x, array[i].y + quad_lower_left.y, array[i].z + quad_lower_left.z);
1221                                         glTexCoord2f(1.0, 0.0);
1222                                         glVertex3f(array[i].x + quad_lower_right.x, array[i].y + quad_lower_right.y, array[i].z + quad_lower_right.z);
1223                                         glTexCoord2f(1.0, 1.0);
1224                                         glVertex3f(array[i].x - quad_lower_left.x, array[i].y - quad_lower_left.y, array[i].z - quad_lower_left.z);
1225                                         glTexCoord2f(0.0, 1.0);
1226                                         glVertex3f(array[i].x - quad_lower_right.x, array[i].y - quad_lower_right.y, array[i].z - quad_lower_right.z);
1227                                 glEnd();
1228                         }
1229                 glPopAttrib();
1230         }
1231         
1232         return; 
1233 }
1234
1235
1236
1237
1238 void Graphics::renderParticle(float x, float y, float z, float size, colour col, int type)
1239 {
1240         if(type == AM_HARDWARE_PARTICLE)
1241         {       
1242                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1243                 glPointSize( (size > maxSize ? maxSize : size) );
1244                 glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, (size > maxSize ? maxSize : size)  );
1245                 glEnable(GL_DEPTH_TEST);
1246                 glDepthMask( GL_FALSE );
1247                 enableAlpha(true);
1248 //              glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1249                 glBlendFunc( GL_DST_ALPHA, GL_ONE );
1250                 glBegin(GL_POINTS);
1251 //              float v[4];
1252 //              transform_colourv(v, col);
1253                 glColor4f(col.r , col.g, col.b, col.a);
1254                 glVertex3f(x,y,z);
1255                 glEnd();
1256                 glPopAttrib();
1257         }
1258         else
1259                 if(type == AM_SOFTWARE_PARTICLE)
1260                 {
1261 //                      float v[4];
1262                         float mat[16];
1263                         struct point
1264                         {
1265                                 float x,y,z;
1266                 
1267                         }quad_lower_left,quad_lower_right;
1268   
1269                         glPushAttrib(GL_ALL_ATTRIB_BITS);
1270                         glEnable(GL_DEPTH_TEST);
1271 //      glDepthMask( GL_FALSE );
1272                         enableAlpha(true);
1273                         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1274                         glDisable(GL_CULL_FACE);
1275                         glEnable( GL_TEXTURE_2D );
1276
1277 //      glPushMatrix();
1278         // Get modelview matrix. We will only use the upper left 3x3 part of
1279     // the matrix, which represents the rotation.
1280                         glGetFloatv( GL_MODELVIEW_MATRIX, mat );
1281
1282     // 1) & 2) We do it in one swift step:
1283                         // Although not obvious, the following six lines represent two matrix/
1284     // vector multiplications. The matrix is the inverse 3x3 rotation
1285     // matrix (i.e. the transpose of the same matrix), and the two vectors
1286     // represent the lower left corner of the quad, PARTICLE_SIZE/2 *
1287     // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0).
1288     // The upper left/right corners of the quad is always the negative of
1289     // the opposite corners (regardless of rotation).
1290                         float s2 = size / 2.0;
1291                         quad_lower_left.x = (-s2) * (mat[0] + mat[1]);
1292                         quad_lower_left.y = (-s2) * (mat[4] + mat[5]);
1293                         quad_lower_left.z = (-s2) * (mat[8] + mat[9]);
1294                         quad_lower_right.x = (s2) * (mat[0] - mat[1]);
1295                         quad_lower_right.y = (s2) * (mat[4] - mat[5]);
1296                         quad_lower_right.z = (s2) * (mat[8] - mat[9]);
1297
1298             // 3) Translate the quad to the correct position in modelview
1299             // space and store its parameters in vertex arrays (we also
1300             // store texture coord and color information for each vertex).
1301 //                      transform_colourv(v, col);
1302                         glBegin(GL_QUADS);
1303                         glColor4f(col.r, col.g, col.b, col.a);
1304                 // Lower left corner
1305                         glTexCoord2f(0.0, 0.0);
1306                         glVertex3f(x + quad_lower_left.x, y + quad_lower_left.y, z + quad_lower_left.z);
1307 //              printf("1. %f %f %f\n",x + quad_lower_left.x, y + quad_lower_left.y, z + quad_lower_left.z);
1308             // Lower right corner
1309                         glTexCoord2f(1.0, 0.0);
1310                         glVertex3f(x + quad_lower_right.x, y + quad_lower_right.y, z + quad_lower_right.z);
1311 //              printf("2. %f %f %f\n",x + quad_lower_right.x, y + quad_lower_right.y, z + quad_lower_right.z); 
1312             // Upper right corner
1313                         glTexCoord2f(1.0, 1.0);
1314                         glVertex3f(x - quad_lower_left.x, y - quad_lower_left.y, z - quad_lower_left.z);
1315 //              printf("3. %f %f %f\n", x - quad_lower_left.x, y - quad_lower_left.y, z - quad_lower_left.z);
1316             // Upper left corner
1317                         glTexCoord2f(0.0, 1.0);
1318                         glVertex3f(x - quad_lower_right.x, y - quad_lower_right.y, z - quad_lower_right.z);
1319 //              printf("4. %f %f %f\n", x - quad_lower_right.x, y - quad_lower_right.y, z - quad_lower_right.z);
1320                         glEnd();
1321  // restores the modelview matrix
1322 //      glPopMatrix();
1323                         /*********************************/
1324                         glPopAttrib();
1325                 }
1326                         
1327         return;
1328 }
1329
1330
1331 /* - fov
1332                         Specifies the field of view angle, in degrees, in the y direction.
1333         -       ratio
1334                         Specifies the aspect ratio that determines the field of view in the x direction. 
1335                         The aspect ratio is the ratio of x (width) to y (height).
1336   -     zNear
1337                         Specifies the distance from the viewer to the near clipping plane (always positive).
1338   -     zFar
1339                         Specifies the distance from the viewer to the far clipping plane (always positive).
1340 */
1341 void Graphics::setPerspective(float fov, float ratio, float zNear, float zFar)
1342 {
1343         int matrixMode;
1344         
1345         glGetIntegerv( GL_MATRIX_MODE, &matrixMode);
1346         glMatrixMode( GL_PROJECTION );
1347         glLoadIdentity();
1348         gluPerspective( fov, ratio, zNear, zFar );
1349         glMatrixMode( matrixMode );
1350         return;
1351 }
1352
1353
1354 void Graphics::renderVertexArray(vertex *array, unsigned int numOfPrimitives, int type)
1355 {
1356         int t = type;
1357         if(type == AM_TRIANGLE_STRIP)
1358                 t = GL_TRIANGLE_STRIP;
1359         else if (type == AM_TRIANGLE_FAN)
1360                 t = GL_TRIANGLE_FAN;
1361         else if (type == AM_TRIANGLES)
1362                 t = GL_TRIANGLES;
1363         else if (type == AM_POINT_LIST)
1364                 t = GL_POINTS;
1365         else if (type ==  AM_LINE_LIST)
1366                 t = GL_LINES;
1367         else if (type == AM_LINE_STRIP)
1368                 t = GL_LINE_STRIP;
1369         
1370          // UGLY hack to reverse texture coordinate...implement an operator in struct vertex..?!?
1371         vertex *tmp = new vertex[numOfPrimitives];
1372         memcpy(tmp, array, numOfPrimitives*sizeof(vertex));
1373         int i;
1374         for(i=0; i < numOfPrimitives; i++)
1375                 tmp[i].v = 1 - tmp[i].v;
1376
1377         glInterleavedArrays( GL_T2F_C4F_N3F_V3F, 0, (void *) tmp);
1378         glDrawArrays( t, 0, numOfPrimitives);
1379
1380         delete tmp;
1381         return;
1382 }
1383
1384
1385 void Graphics::setCullingMode(int mode)
1386 {
1387         cmode = mode;
1388         if(mode == AM_CULL_NONE)
1389    {
1390       culling = false;
1391       glDisable(GL_CULL_FACE );
1392       return;
1393    }
1394    else
1395    {
1396                 if(!culling)
1397                 {
1398                         culling = true;
1399                         glEnable( GL_CULL_FACE );
1400                 }
1401                 if(mode == AM_CULL_FRONT)
1402                         glCullFace(GL_FRONT);
1403                 else if (mode == AM_CULL_BACK) 
1404                         glCullFace(GL_BACK);
1405    }
1406    return;
1407
1408
1409 int Graphics::getCullingMode()
1410 {
1411         return cmode;
1412 }
1413
1414
1415
1416 void Graphics::enter2dMode(void)
1417 {
1418         glPushAttrib( GL_ALL_ATTRIB_BITS );
1419  
1420         glDisable( GL_LIGHTING );
1421         glDisable( GL_DEPTH_TEST );
1422         glDisable( GL_CULL_FACE );
1423         glEnable( GL_TEXTURE_2D );
1424  
1425         glViewport( 0, 0, getWidth(), getHeight() );
1426  
1427         glMatrixMode( GL_PROJECTION );
1428         glPushMatrix();
1429         glLoadIdentity();
1430  
1431         glOrtho( 0.0, ( GLdouble ) getWidth(), ( GLdouble ) getHeight(), 0.0, 0.0, 1.0 );
1432  
1433         glMatrixMode( GL_MODELVIEW );
1434         glPushMatrix();
1435         glLoadIdentity();
1436         //      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1437         return ;
1438 }
1439  
1440  
1441 void Graphics::leave2dMode(void)
1442 {
1443         glMatrixMode( GL_MODELVIEW );
1444         glPopMatrix();
1445  
1446         glMatrixMode( GL_PROJECTION );
1447         glPopMatrix();
1448  
1449         glPopAttrib();
1450         return ;
1451 }
1452
1453
1454 void Graphics::enableDepthBuffer( bool b )
1455 {
1456         zBuffer = b;
1457         if(b)
1458                 glEnable( GL_DEPTH_TEST );
1459         else
1460                 glDisable( GL_DEPTH_TEST );
1461                 
1462         return;
1463 }
1464
1465
1466 bool Graphics::isDepthBuffer()
1467 {
1468         return zBuffer;
1469 }
1470
1471
1472
1473 /*--------------------------------------------------
1474 *                                                                                Texture
1475 *-----------------------------------------------------*/
1476
1477
1478
1479 Texture::Texture(  char *file, colour key, Graphics *g )
1480 {
1481         gl_Tex = 0;
1482         filteringDefinition = filtering = AM_LINEAR;
1483         this->g = g;
1484         glEnable( GL_TEXTURE_2D );
1485         colourKey = key;
1486         colourKeyEnabled = true;
1487
1488         // CreateTexture(&gl_Tex, file, 0);
1489         LoadGLTextures( &gl_Tex, file );
1490         std::cout << "file=" << file << ", gl_Tex=" << gl_Tex << "\n";
1491
1492   return ;
1493 }
1494
1495
1496 Texture::Texture( char *file, Graphics *g)
1497 {
1498         gl_Tex = 0;
1499   this->g = g;
1500   filteringDefinition = filtering = AM_LINEAR;
1501   glEnable( GL_TEXTURE_2D );
1502   assert(g);
1503   colourKeyEnabled = false;
1504   // CreateTexture(&gl_Tex, file, 0);
1505   LoadGLTextures( &gl_Tex, file );
1506   std::cout << "file=" << file << ", gl_Tex=" << gl_Tex << "\n";
1507
1508   return ;
1509 }
1510
1511 Texture::Texture(void *data, unsigned int w, unsigned int h, int format, int type, Graphics *g)
1512 {
1513         gl_Tex = 0;
1514         filteringDefinition = filtering = AM_LINEAR;
1515         this->g = g;
1516         assert(g);
1517         colourKeyEnabled = false;
1518         
1519         glEnable( GL_TEXTURE_2D );
1520         glGenTextures(1, &gl_Tex);
1521         glBindTexture( GL_TEXTURE_2D, gl_Tex );
1522         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1523         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1524         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1525         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1526         
1527         GLenum f = GL_RGBA, t = GL_UNSIGNED_BYTE;
1528         int c = 4;
1529         
1530         if(format == AM_ALPHA)
1531         {
1532                 f = GL_ALPHA;
1533                 c = GL_ALPHA; /* Warning!!! Dont change this value cause font rendering depends on it!*/
1534         }       
1535         else if (format == AM_RGBA)
1536         {
1537                         f = GL_RGBA;
1538                         c = 4;
1539         }
1540         
1541         if(type == AM_UBYTE)
1542                 t = GL_UNSIGNED_BYTE;
1543         
1544         //glTexImage2D( GL_TEXTURE_2D, 0, c, w, h, 0,   f, t, data);
1545         gluBuild2DMipmaps( GL_TEXTURE_2D, c, w, h,      f, t, data);
1546                 
1547         this->width = w;
1548         this->height = h;
1549
1550         std::cout << "gl_Tex=" << gl_Tex << "\n";
1551
1552         return ;
1553 }
1554
1555
1556
1557 Texture::~Texture()
1558 {
1559   return ;
1560 }
1561
1562
1563 /*
1564 unsigned int Texture::gl_getGLTex()
1565 {
1566   return gl_Tex;
1567 }
1568 */
1569
1570 void Texture::texSubImage2D(int xoff, int yoff, unsigned int w, unsigned int h, int format, int type, const void *pixels)
1571 {
1572         GLenum f = GL_RGBA, t = GL_UNSIGNED_BYTE;
1573         
1574         if(format == AM_ALPHA)
1575                 f = GL_ALPHA;
1576         else if (format == AM_RGBA)
1577                 f = GL_RGBA;
1578         
1579         if(type == AM_UBYTE)
1580                 t = GL_UNSIGNED_BYTE;
1581
1582         glBindTexture(GL_TEXTURE_2D, this->gl_Tex);
1583         glTexSubImage2D(GL_TEXTURE_2D, 0, xoff, yoff, w, h, f, t, pixels);
1584         
1585         //TODO kane popAttributes etsi wste na einai current texture auto pou htan prin...
1586          
1587         return;
1588 }
1589
1590 unsigned long Texture::getWidth()
1591 {
1592   return width;
1593 }
1594
1595 unsigned long Texture::getHeight()
1596 {
1597   return height;
1598 }
1599
1600
1601 int Texture::getFiltering()
1602 {
1603         return filteringDefinition;
1604 }
1605
1606
1607 /* this function needs some fixes and some rewrite */
1608 void Texture::setFiltering(int f, float anisotropyLevel)
1609 {
1610         int _f  = f;
1611         if(f == AM_LINEAR)
1612                 _f = GL_LINEAR;
1613         else if (f == AM_PLAIN)
1614                 _f = GL_NEAREST;
1615         
1616         filteringDefinition = filtering = f;
1617         if(_f == AM_ANISOTROPIC)
1618         {
1619                 if(supportsAnisotropic)
1620                 {
1621                         float a = anisotropyLevel;
1622                         if( a > maxAnisotropySupported) //fix this for round-off errors
1623                                 a = maxAnisotropySupported;
1624                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, a);
1625                 }
1626                 filtering = GL_LINEAR;
1627         }
1628         // 'filtering' cannot have here a value of AM_ANISOTROPIC
1629         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1630         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering );
1631         
1632         return;
1633 }
1634
1635
1636 void Texture::LoadGLTextures( GLuint *gl_Tex, const char * filename )
1637 {
1638         /*gl_Tex = ilutGLLoadImage( (char *) filename);
1639         glBindTexture( GL_TEXTURE_2D, *gl_Tex ); 
1640         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1641         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1642 */
1643         
1644         // Generate the main image name to use.
1645         ilGenImages (1, gl_Tex);
1646         ilBindImage (*gl_Tex);
1647         ilEnable(IL_ORIGIN_SET);
1648         ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
1649         if (!ilLoadImage ((char *)filename)) 
1650                 printf("cannot load image %s \n", filename);
1651         
1652         ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
1653
1654         ILinfo imageInfo;
1655         iluGetImageInfo(&imageInfo); 
1656         ILubyte *data = ilGetData();
1657         printf("image info. %d x %d depth=%d Bp=%d data=%d\n", imageInfo.Width, imageInfo.Height, imageInfo.Depth, imageInfo.Bpp,
1658                                                         imageInfo.SizeOfData);
1659         bool a = false;
1660         if ( colourKeyEnabled )
1661         {
1662                 //ksepaketaroume to colourkey
1663                 unsigned char ckR = 0, ckG = 0, ckB = 0, ckA = 255;
1664                 unsigned long mR, mG, mB, mA;
1665                 mB = 0x000000FF;
1666                 mG = 0x0000FF00;
1667                 mR = 0x00FF0000;
1668                 mA = 0xFF000000;
1669         ckR = (unsigned char) (colourKey.r * 255.0) ;
1670         ckG = (unsigned char) (colourKey.g * 255.0) ;
1671         ckB = (unsigned char) (colourKey.b * 255.0) ;
1672         ckA = (unsigned char) (colourKey.a * 255.0) ;
1673                 unsigned char _r, _g, _b; 
1674                 assert(g);
1675                 a = g->isAlpha();
1676                 g->enableAlpha(true);
1677                 int step = imageInfo.Bpp;
1678                 for(unsigned long i=0; i <  imageInfo.SizeOfData; i+=step)
1679                 {
1680                         _r = data[i];
1681                         _g = data[i + 1];
1682                         _b= data[i + 2];
1683                 
1684         if ( _r == ckR && _g == ckG && _b == ckB )
1685                                 data[i + 3] = 0;
1686                 }
1687         }
1688
1689         glBindTexture( GL_TEXTURE_2D, *gl_Tex ); 
1690
1691         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1692         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering );
1693         
1694 //      glTexImage2D( GL_TEXTURE_2D, 0, 4, imageInfo.Width, imageInfo.Height, 0,        GL_RGBA, GL_UNSIGNED_BYTE, data );
1695         
1696         gluBuild2DMipmaps( GL_TEXTURE_2D, 4, imageInfo.Width, imageInfo.Height,
1697                                                          GL_RGBA, GL_UNSIGNED_BYTE, data);
1698         
1699         
1700         width = imageInfo.Width;
1701         height = imageInfo.Height;
1702         if ( colourKeyEnabled ) 
1703                 g->enableAlpha(a);
1704
1705         return ;
1706 }