* Add "less" target to view make output through less.
[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         ilInit();
377         iluInit();
378         ilutRenderer(ILUT_OPENGL);
379
380   /*
381    * Now, we want to setup our requested
382    * window attributes for our OpenGL window.
383    * We want *at least* 5 bits of red, green
384    * and blue. We also want at least a 16-bit
385    * depth buffer.
386    *
387    * The last thing we do is request a double
388    * buffered window. '1' turns on double
389    * buffering, '0' turns it off.
390    *
391    * Note that we do not use SDL_DOUBLEBUF in
392    * the flags to SDL_SetVideoMode. That does
393    * not affect the GL attribute state, only
394    * the standard 2D blitting setup.
395    */
396   SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
397   SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
398   SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
399   SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bpp );
400   SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
401
402   flags = SDL_OPENGL | ( fullScreen ? SDL_FULLSCREEN : 0 );
403
404   /*
405    * Set the video mode
406    */
407   if ( ( imp->screen = SDL_SetVideoMode( width, height, bpp, flags ) ) == 0 )
408   {
409     /*
410      * This could happen for a variety of reasons,
411      * including DISPLAY not being set, the specified
412      * resolution not being available, etc.
413      */
414     std::cerr << "Video mode set failed: " << SDL_GetError() << std::endl;
415     return 2;
416   }
417
418   SDL_SetGamma(1.8, 1.8, 1.8);
419   
420   float ratio = ( float ) width / ( float ) height;
421   /* Our shading model--Gouraud (smooth). */
422   glShadeModel( GL_SMOOTH );
423   glClearDepth( 1.0f );
424
425   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
426
427   //   glDepthFunc( GL_LEQUAL );
428   /* Set the clear color. */
429   glClearColor( bgcolour[ 0 ], bgcolour[ 1 ], bgcolour[ 2 ], bgcolour[ 3 ] );
430   glMatrixMode( GL_PROJECTION );
431   glLoadIdentity();
432
433   glViewport( 0, 0, width, height );
434   gluPerspective( 45.0, ratio, 1.0, 10000.0 );
435
436   /* Culling. Boh8aei sto Blending*/
437   glCullFace( GL_BACK );
438 /* Polygons whose vertices are in counterclockwise order are called frontfacing but dx thinks different ?*/
439   glFrontFace( GL_CW );
440         if( culling)
441                 glEnable( GL_CULL_FACE );
442
443         if(zBuffer)
444                 glEnable( GL_DEPTH_TEST );
445         
446         glEnable( GL_TEXTURE_2D );
447   if ( alpha )
448     glEnable( GL_BLEND );
449   if ( lighting )
450     glEnable( GL_LIGHTING );
451
452   //TODO: 8a prepei na oristei synarthsh setMaterial...
453   float diffuse[] = {1.0, 1.0, 1.0, 1.0};
454   float specular[] = {0.0, 0.0, 0.0, 0.0};
455   float ambient[] = {   0.0, 0.0, 0.0, 0.0};
456   float  emissive[] = {0.0, 0.0, 0.0, 0.0};
457         glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse );
458         glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, specular );
459         glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, emissive );
460         glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, ambient );
461
462   
463         if ( !queryExtension( "GL_EXT_texture_filter_anisotropic" ) )
464                 std::cout << "Extension GL_EXT_texture_filter_anisotropic not found...\n";
465         else
466         {
467                 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropySupported);
468                 std::cout << "max Anisotropy supported = " << maxAnisotropySupported << '\n';
469                 supportsAnisotropic = true;
470         }
471         
472         /*glGenBuffers(1, &gpuBuf); // mono gia OpenGL 1.5 
473   glBindBuffer(GL_ARRAY_BUFFER, gpuBuf);            // mono gia OpenGL 1.5
474   glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &parameter); // mono gia OpenGL 1.5
475   printf("Buffer size is %d \n", parameter); */
476   if ( !queryExtension( "GL_ARB_point_sprite" ) )
477     std::cout << "Extension GL_ARB_point_sprite not found...\n";
478   else
479   {
480     // This is how will our point sprite's size will be modified by
481     // distance from the viewer
482     float quadratic[] =  { 1.0f, 0.0f, 0.01f };
483     glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
484     // Query for the max point size supported by the hardware
485     maxSize = 0.0f;
486     glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
487     // Clamp size to 100.0f or the sprites could get a little too big on some
488     // of the newer graphic cards. My ATI card at home supports a max point
489     // size of 1024.0f!
490
491     // The alpha of a point is calculated to allow the fading of points
492     // instead of shrinking them past a defined threshold size. The threshold
493     // is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
494     // the minimum and maximum point sizes.
495     glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
496     glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 10.0f );
497     glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
498
499     // Specify point sprite texture coordinate replacement mode for each
500     // texture unit
501     glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
502     glEnable( GL_POINT_SPRITE_ARB );
503     glEnable( GL_ARB_point_sprite );
504   }
505
506   std::cout << "OpenGL Version =" << glGetString( GL_VERSION ) << std::endl;
507   int _red,_green,_blue, _alpha, _depth, _stencil;
508   glGetIntegerv(GL_RED_BITS, &_red);
509   glGetIntegerv(GL_GREEN_BITS, &_green);
510   glGetIntegerv(GL_BLUE_BITS, &_blue);
511   glGetIntegerv(GL_ALPHA_BITS, &_alpha);
512   std::cout << "Color Buffers RGBA bits = " << _red <<  _green <<  _blue << _alpha << std::endl;
513   glGetIntegerv(GL_DEPTH_BITS, &_depth);
514   std::cout << "Depth Buffer bits = " << _depth << "\n";
515   glGetIntegerv(GL_STENCIL_BITS, &_stencil);
516   std::cout << "Stencil Buffer bits = " << _stencil << "\n";
517   int _aux;
518   glGetIntegerv(GL_AUX_BUFFERS, &_aux);
519   std::cout << "Aux buffers = " << _aux << "\n";
520   //    putenv("__GL_SYNC_TO_VBLANK=1");
521
522   //    XF86VidModeModeLine mode;
523   //    int unused;
524
525   //    Display *d = XOpenDisplay(NULL);
526   /*Bool XF86VidModeGetModeLine(
527                 Display *display ,
528   int screen ,
529   int *dotclock_return ,
530   XF86VidModeModeLine *modeline );
531   */
532   //    printf("d=%p\n",d);
533   //    if(XF86VidModeGetModeLine(d, 0, &unused, &mode))
534   //    {
535
536   //            printf("OK  %d mexri %d\n", mode.hsyncstart, mode.hsyncend);
537   //    }
538   //    else
539   //            printf("not ok\n");
540   //    glXWaitVideoSyncSGI();
541   //    GLX_SGI_video_sync
542   //    unsigned int k;
543   //    glXGetVideoSyncSGI(&k);
544   //    printf("k=%d\n", k);
545   glMatrixMode( GL_MODELVIEW );
546
547   return 0;
548 }
549
550
551
552 void Graphics::beginScene( void )
553 {
554   /* Clear the color and depth buffers. */
555   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
556   glMatrixMode( GL_MODELVIEW );
557   glLoadIdentity();
558   //gia symbatothta me to DirectX
559   glScalef( -1.0, 1.0, 1.0 );
560   sceneBegin = true;
561
562   return ;
563 }
564
565
566 void Graphics::endScene()
567 {
568   glColorMask(GL_TRUE, GL_TRUE,  GL_TRUE,  GL_TRUE);
569   //if(vSync)
570     //glXSwapIntervalSGI(1);
571   SDL_GL_SwapBuffers();
572
573   sceneBegin = false;
574   z_order = 1.0;
575   return ;
576 }
577
578
579 GLdouble mm[4][4];
580 void _gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
581                  GLdouble centerx, GLdouble centery, GLdouble centerz,
582                  GLdouble upx, GLdouble upy, GLdouble upz )
583 {
584   GLdouble m[ 16 ];
585   GLdouble x[ 3 ], y[ 3 ], z[ 3 ];
586   GLdouble mag;
587
588   /* Make rotation matrix */
589
590   /* Z vector */
591   z[ 0 ] = ( eyex - centerx );
592   z[ 1 ] = ( eyey - centery );
593   z[ 2 ] = ( eyez - centerz );
594   mag = sqrt( z[ 0 ] * z[ 0 ] + z[ 1 ] * z[ 1 ] + z[ 2 ] * z[ 2 ] );
595   if ( mag )
596   {                     /* mpichler, 19950515 */
597     z[ 0 ] /= mag;
598     z[ 1 ] /= mag;
599     z[ 2 ] /= mag;
600   }
601
602   /* Y vector */
603   y[ 0 ] = upx;
604   y[ 1 ] = upy;
605   y[ 2 ] = upz;
606
607   /* X vector = Y cross Z */
608   x[ 0 ] = y[ 1 ] * z[ 2 ] - y[ 2 ] * z[ 1 ];
609   x[ 1 ] = y[ 2 ] * z[ 0 ] - y[ 0 ] * z[ 2 ] ;
610   x[ 2 ] = y[ 0 ] * z[ 1 ] - y[ 1 ] * z[ 0 ];
611
612   /* Recompute Y = Z cross X */
613   y[ 0 ] = z[ 1 ] * x[ 2 ] - z[ 2 ] * x[ 1 ];
614   y[ 1 ] = -z[ 0 ] * x[ 2 ] + z[ 2 ] * x[ 0 ];
615   y[ 2 ] = z[ 0 ] * x[ 1 ] - z[ 1 ] * x[ 0 ];
616
617   /* mpichler, 19950515 */
618   /* cross product gives area of parallelogram, which is < 1.0 for
619   * non-perpendicular unit-length vectors; so normalize x, y here
620   */
621
622   mag = sqrt( x[ 0 ] * x[ 0 ] + x[ 1 ] * x[ 1 ] + x[ 2 ] * x[ 2 ] );
623   if ( mag )
624   {
625     x[ 0 ] /= mag;
626     x[ 1 ] /= mag;
627     x[ 2 ] /= mag;
628   }
629
630   mag = sqrt( y[ 0 ] * y[ 0 ] + y[ 1 ] * y[ 1 ] + y[ 2 ] * y[ 2 ] );
631   if ( mag )
632   {
633     y[ 0 ] /= mag;
634     y[ 1 ] /= mag;
635     y[ 2 ] /= mag;
636   }
637
638 #define M(row,col)  m[col*4+row]
639   M( 0, 0 ) = x[ 0 ];
640   M( 0, 1 ) = x[ 1 ];
641   M( 0, 2 ) = x[ 2 ];
642   M( 0, 3 ) = -( x[ 0 ] * eyex + x[ 1 ] * eyey + x[ 2 ] * eyez );
643
644   M( 1, 0 ) = y[ 0 ];
645   M( 1, 1 ) = y[ 1 ];
646   M( 1, 2 ) = y[ 2 ];
647   M( 1, 3 ) = -( y[ 0 ] * eyex + y[ 1 ] * eyey + y[ 2 ] * eyez );
648
649   M( 2, 0 ) = z[ 0 ];
650   M( 2, 1 ) = z[ 1 ];
651   M( 2, 2 ) = z[ 2 ];
652   M( 2, 3 ) = -( z[ 0 ] * eyex + z[ 1 ] * eyey + z[ 2 ] * eyez );
653
654   M( 3, 0 ) = 0.0;
655   M( 3, 1 ) = 0.0;
656   M( 3, 2 ) = 0.0;
657   M( 3, 3 ) = 1.0;
658   /*   M(0, 0) = x[0];
659         M(1, 0) = y[0];
660         M(2, 0) = z[0];
661         M(3, 0) = 0.0;
662      
663         M(0, 1) = x[1];
664         M(1, 1) = y[1];
665         M(2, 1) = z[1];
666         M(3, 1) = 0.0;
667      
668         M(0, 2) = x[2];
669         M(1, 2) = y[2];
670         M(2, 2) = z[2];
671         M(3, 2) = 0.0;
672      
673         M(0, 3) = 0.0;
674         M(1, 3) = 0.0;
675         M(2, 3) = 0.0;
676         M(3, 3) = 1.0;
677   */
678 #undef M
679   glScalef( -1.0, 1.0, 1.0 );
680   glMultMatrixd( m );
681   glScalef( -1.0, 1.0, 1.0 );
682
683 }
684
685
686
687 int Graphics::setCamera(  float camx,  float camy,  float camz,
688                           float lookx, float looky, float lookz,
689                           float upx,  float upy, float upz )
690 {
691
692   _gluLookAt( camx, camy, camz, lookx, looky, lookz, upx, upy, upz );
693
694   cam.camx = camx;
695   cam.camy = camy;
696   cam.camz = camz;
697
698   cam.lookx = lookx;
699   cam.looky = looky;
700   cam.lookz = lookz;
701
702   cam.upx = upx;
703   cam.upy = upy;
704   cam.upz = upz;
705
706   return 0;
707 }
708
709
710 struct camera Graphics::getCamera()
711 {
712   return cam;
713 }
714
715
716
717
718 int Graphics::renderTriangle(vertex v1, vertex v2, vertex v3 )
719 {
720 //   GLfloat colour[ 4 ];
721   if ( !sceneBegin )
722   {
723     std::cout << "DEBUG: oust...!\n";
724     exit( 1 );
725     return 1;
726   }
727
728
729 //      glPushAttrib(GL_ALL_ATTRIB_BITS); //kyriws gia na epanaferoume to xrwma
730   glBegin( GL_TRIANGLES );
731
732 //   transform_colourv( colour, v1.col );
733   glColor4f( v1.col.r, v1.col.g, v1.col.b, v1.col.a);
734   glNormal3f( v1.nx, v1.ny, v1.nz );
735   glTexCoord2f( v1.u, 1.0 - v1.v );
736   glVertex3f( v1.x, v1.y, v1.z );
737
738 //   transform_colourv( colour, v2.col );
739 //   glColor4f( colour[ 0 ], colour[ 1 ], colour[ 2 ], colour[ 3 ] );
740         glColor4f( v2.col.r, v2.col.g, v2.col.b, v2.col.a);
741   glNormal3f( v2.nx, v2.ny, v2.nz );
742   glTexCoord2f( v2.u, 1.0 - v2.v );
743   glVertex3f( v2.x, v2.y, v2.z );
744
745         glColor4f( v3.col.r, v3.col.g, v3.col.b, v3.col.a);
746   glNormal3f( v3.nx, v3.ny, v3.nz );
747   glTexCoord2f( v3.u, 1.0 - v3.v );
748   glVertex3f( v3.x, v3.y, v3.z );
749
750   glEnd();
751 //      glPopAttrib();
752   //isos na prepei na epanafero pisw to arxiko xrwma...
753
754   return 0;
755 }
756
757
758
759 int Graphics::setWorld( float transx, float transy, float transz,
760                         float rotx, float roty, float rotz, float scalex, float scaley, float scalez,
761                                                          int rotationOrder)
762 {
763   glMatrixMode( GL_MODELVIEW );
764   glLoadIdentity();
765
766   struct camera c = getCamera();
767   setCamera( c.camx, c.camy, c.camz, c.lookx, c.looky, c.lookz, c.upx, c.upy, c.upz );
768   
769   glScalef( -1.0, 1.0, 1.0 ); //gia symbatothta me to DirectX
770   glTranslatef( transx, transy, transz );
771
772   if(rotationOrder == AM_XYZ)
773   {
774                 glRotatef( rotz, 0, 0, 1 );
775                 glRotatef( roty, 0, 1, 0 );
776                 glRotatef( rotx, 1, 0, 0 );
777   }
778   else if(rotationOrder == AM_XZY)
779   {
780           glRotatef( roty, 0, 1, 0 );     
781           glRotatef( rotz, 0, 0, 1 );
782           glRotatef( rotx, 1, 0, 0 );
783
784   }
785   else if(rotationOrder == AM_YZX)
786   {
787           glRotatef( rotx, 1, 0, 0 );
788           glRotatef( rotz, 0, 0, 1 );
789           glRotatef( roty, 0, 1, 0 );
790   }
791   else if(rotationOrder == AM_YXZ)
792   {
793           glRotatef( rotz, 0, 0, 1 );
794           glRotatef( rotx, 1, 0, 0 );
795           glRotatef( roty, 0, 1, 0 );
796
797   }
798   else if(rotationOrder == AM_ZXY)
799   {
800           glRotatef( roty, 0, 1, 0 );
801           glRotatef( rotx, 1, 0, 0 );
802           glRotatef( rotz, 0, 0, 1 );
803   }
804   else
805   {
806           glRotatef( rotx, 1, 0, 0 );
807           glRotatef( roty, 0, 1, 0 );
808           glRotatef( rotz, 0, 0, 1 );
809   }
810   
811   glScalef( scalex, scaley, scalez );
812   
813   return 0;
814 }
815
816
817
818 /*
819
820 int Graphics::setWorld2( float transx, float transy, float transz,
821                                                                 float rotx, float roty, float rotz, float scalex, float scaley, float scalez )
822 {
823         glMatrixMode( GL_MODELVIEW );
824         glLoadIdentity();
825
826
827         struct camera c = getCamera();
828         setCamera( c.camx, c.camy, c.camz, c.lookx, c.looky, c.lookz, c.upx, c.upy, c.upz );
829   
830         glScalef( -1.0, 1.0, 1.0 ); //gia symbatothta me to DirectX
831         glTranslatef( transx, transy, transz );
832         glRotatef( roty, 0, 1, 0 );
833         glRotatef( rotz, 0, 0, 1 );
834         glRotatef( rotx, 1, 0, 0 );
835         glScalef( scalex, scaley, scalez );
836   
837
838         return 0;
839 }
840
841   */
842
843
844
845
846
847 void Graphics::setBackground( colour colour )
848 {
849 //   transform_colourv( bgcolour, colour );
850   //    printf( "(%f, %f, %f ,%f)\n", bgcolour[ 0 ], bgcolour[ 1 ], bgcolour[ 2 ], bgcolour[ 3 ] );
851         bgcolour[0] = colour.r;
852         bgcolour[1] = colour.g;
853         bgcolour[2] = colour.b;
854         bgcolour[3] = colour.a;
855         glClearColor( ( float ) bgcolour[ 0 ], ( float ) bgcolour[ 1 ], ( float ) bgcolour[ 2 ], ( float ) bgcolour[ 3 ] );
856         
857 return ;
858 }
859
860
861 colour Graphics::getBackground( void )
862 {
863         colour c;
864         c.r = bgcolour[0];
865         c.g = bgcolour[1];
866         c.b = bgcolour[2];
867         c.a = bgcolour[3];
868         return c;
869 }
870         
871         
872
873
874 void Graphics::project( float objx, float objy, float objz,
875                         //const double modelMatrix[16], const double projMatrix[16], const int viewport[4],
876                                                                 float *winx, float *winy, float *winz )
877 {
878   double _winx = 0;
879   double _winy = 0;
880   double _winz = 0;
881   GLint viewport[ 4 ];
882   GLdouble mvmatrix[ 16 ], projmatrix[ 16 ];
883
884   glGetIntegerv ( GL_VIEWPORT, viewport );
885   glGetDoublev ( GL_MODELVIEW_MATRIX, mvmatrix );
886   glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix );
887
888   gluProject( objx, objy, objz, mvmatrix, projmatrix, viewport,
889               &_winx, &_winy, &_winz );
890
891   *winx = _winx;
892   *winy = viewport[ 3 ] - ( int ) _winy - 1;
893   *winz = _winz;
894
895   return ;
896 }
897
898
899 void Graphics::unproject( float winx, float winy, float winz,
900                           //const double modelMatrix[16], const double projMatrix[16], const int viewport[4],
901                                                                   float *objx, float *objy, float *objz )
902 {
903   int realy;
904   double _objx = 0;
905   double _objy = 0;
906   double _objz = 0;
907         GLint viewport[ 4 ];
908   GLdouble mvmatrix[ 16 ], projmatrix[ 16 ];
909
910   glGetIntegerv ( GL_VIEWPORT, viewport );
911   glGetDoublev ( GL_MODELVIEW_MATRIX, mvmatrix );
912   glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix );
913    
914   realy = viewport[ 3 ] - ( int ) winy - 1;
915   //    std::cout << "realy=" <<realy << "\n";
916
917   gluUnProject( winx, realy, winz,
918                 mvmatrix, projmatrix, viewport,
919                 &_objx, &_objy, &_objz );
920
921   *objx = _objx;
922   *objy = _objy;
923   *objz = _objz;
924
925   return ;
926 }
927
928
929
930 void Graphics::enableCursor( bool state )
931 {
932         cursorState = state;
933         if ( state )
934                 SDL_ShowCursor( SDL_ENABLE );
935         else
936                 SDL_ShowCursor( SDL_DISABLE );
937   return;
938 }
939
940 bool Graphics::isCursor()
941 {
942         return cursorState;
943 }
944
945
946
947 void Graphics::planeIntersect( float a, float b, float c, float d,
948                                float p1x, float p1y, float p1z, float p2x, float p2y, float p2z,
949                                                                                  float *poutx, float *pouty, float *poutz )
950 {
951   float numerator = -( a * p1x + b * p1y + c * p1z + d );
952   if ( numerator == 0 )
953   {
954     ( *poutx ) = p1x;
955     ( *pouty ) = p1y;
956     ( *poutz ) = p1z;
957     return ;
958   }
959   else
960   {
961     float denominator = a * ( p2x - p1x ) + b * ( p2y - p1y ) + c * ( p2z - p1z );
962     if ( denominator == 0 )
963     {
964       ( *poutx ) = 0.0;
965       ( *pouty ) = 0.0;
966       ( *poutz ) = 0.0;
967                 printf("denominator==0!!!\n");
968                 exit(1);
969       return ;
970     }
971     else
972     {
973       float t = numerator / denominator;
974       ( *poutx ) = p1x + t * ( p2x - p1x );
975       ( *pouty ) = p1y + t * ( p2y - p1y );
976       ( *poutz ) = p1z + t * ( p2z - p1z );
977       return ;
978     }
979   }
980
981   return ;
982 }
983
984
985
986 void Graphics::setLight( int numLight, const light& l )
987 {
988         GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
989         GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0};
990         GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0};
991         GLfloat position[] = {0.0, 0.0, 1.0, 0.0};
992         GLenum enm = GL_LIGHT0;
993
994         if(numLight == 0)  enm = GL_LIGHT0;
995         else if(numLight == 1) enm = GL_LIGHT1;
996         else if(numLight == 2) enm = GL_LIGHT2;
997         else if(numLight == 3) enm = GL_LIGHT3;
998         else if(numLight == 4) enm = GL_LIGHT4;
999         else if(numLight == 5) enm = GL_LIGHT5;
1000         else if(numLight == 6) enm = GL_LIGHT6;
1001         else if(numLight == 7 ) enm = GL_LIGHT7;
1002
1003 //   transform_colourv( ambient, l.ambient );
1004 //   transform_colourv( diffuse, l.diffuse );
1005 //   transform_colourv( specular, l.specular );
1006         ambient[0] = l.ambient.r;               ambient[1] = l.ambient.g;               ambient[2] = l.ambient.b;               ambient[3] = l.ambient.a;
1007         diffuse[0] = l.diffuse.r;               diffuse[1] = l.diffuse.g;               diffuse[2] = l.diffuse.b;               diffuse[3] = l.diffuse.a;
1008         specular[0] = l.specular.r;             specular[1] = l.specular.g;             specular[2] = l.specular.b;             specular[3] = l.specular.a;
1009         
1010         if ( l.type == AM_POINT_LIGHT )
1011   {
1012     position[ 3 ] = 1.0;
1013     position[ 0 ] = l.posx;
1014     position[ 1 ] = l.posy;
1015     position[ 2 ] = l.posz;
1016   }
1017   else
1018     if ( l.type == AM_DIRECTIONAL_LIGHT )
1019     {
1020                  //float val = sqrt(l.dirx*l.dirx + l.diry*l.diry + l.dirz*l.dirz);
1021                  position[ 3 ] = 0.0;
1022                  position[ 0 ] = -l.dirx;
1023                  position[ 1 ] = -l.diry;
1024                  position[ 2 ] = l.dirz;
1025     }
1026
1027
1028   /*glPushMatrix();
1029   glBegin(GL_POINTS);
1030   glPointSize(1000.);
1031   glVertex3f(position[0], position[1], position[2]);
1032   glVertex3f(360, 10, 360);
1033   glEnd();
1034   */
1035   glLightfv( enm, GL_AMBIENT, ambient );
1036   glLightfv( enm, GL_DIFFUSE, diffuse );
1037   glLightfv( enm, GL_SPECULAR, specular );
1038   glLightfv( enm, GL_POSITION, position );
1039   //    glPopMatrix();
1040
1041   return ;
1042 }
1043
1044
1045 void Graphics::showLight( int numLight, bool state )
1046 {
1047   GLenum enm = GL_LIGHT0;
1048   if ( numLight == 0 )
1049     enm = GL_LIGHT0;
1050   else
1051     if ( numLight == 1 )
1052       enm = GL_LIGHT1;
1053     else
1054       if ( numLight == 2 )
1055         enm = GL_LIGHT2;
1056
1057   if ( state )
1058     glEnable( enm );
1059   else
1060     glDisable( enm );
1061
1062   return ;
1063 }
1064
1065
1066
1067
1068
1069 void inverseMatrix( double A[16], double B[16])
1070 {
1071
1072         double detA;
1073         
1074         double a11 = A[0];
1075         double a12 = A[1];
1076         double a13 = A[2];
1077         double a14 = A[3];
1078         double a21 = A[4];
1079         double a22 = A[5];
1080         double a23 = A[6];
1081         double a24 = A[7];
1082         double a31 = A[8];
1083         double a32 = A[9];
1084         double a33 = A[10];
1085         double a34 = A[11];
1086         double a41 = A[12];
1087         double a42 = A[13];
1088         double a43 = A[14];
1089         double a44 = A[15];
1090         
1091         detA =  a11*a22*a33*a44 + a11*a23*a34*a42 + a11*a24*a32*a43 \
1092                         +a12*a21*a34*a43 + a12*a23*a31*a44 + a12*a24*a33*a41 \
1093                         +a13*a21*a32*a44 + a13*a22*a34*a41 + a13*a24*a31*a42 \
1094                         +a14*a21*a33*a42 + a14*a22*a31*a43 + a14*a23*a32*a41 \
1095                         -a11*a22*a34*a43 - a11*a23*a32*a44 - a11*a24*a33*a42 \
1096                         -a12*a21*a33*a44 - a12*a23*a34*a41 - a12*a24*a31*a43 \
1097                         -a13*a21*a34*a42 - a13*a22*a31*a44 - a13*a24*a32*a41 \
1098                         -a14*a21*a32*a43 - a14*a22*a33*a41 - a14*a23*a31*a42;
1099
1100 //      printf("detA=%f\n",detA); 
1101         
1102         B[0] = (a22*a33*a44 + a23*a34*a42 + a24*a32*a43 - a22*a34*a43 - a23*a32*a44 - a24*a33*a42)/detA;
1103         B[1] = (a12*a34*a43 + a13*a32*a44 + a14*a33*a42 - a12*a33*a44 - a13*a34*a42 - a14*a32*a43)/detA;
1104         B[2] = (a12*a23*a44 + a13*a24*a42 + a14*a22*a43 - a12*a24*a43 - a13*a22*a44 - a14*a23*a42)/detA; 
1105         B[3] = (a12*a24*a33 + a13*a22*a34 + a14*a23*a32 - a12*a23*a34 - a13*a24*a32 - a14*a22*a33)/detA;
1106         B[4] = (a21*a34*a43 + a23*a31*a44 + a24*a33*a41 - a21*a33*a44 - a23*a34*a41 - a24*a31*a43)/detA;
1107         B[5] = (a11*a33*a44 + a13*a34*a41 + a14*a31*a43 - a11*a34*a43 - a13*a31*a44 - a14*a33*a41)/detA;
1108         B[6] = (a11*a24*a43 + a13*a21*a44 + a14*a23*a41 - a11*a23*a44 - a13*a24*a41 - a14*a21*a43)/detA;
1109         B[7] = (a11*a23*a34 + a13*a24*a31 + a14*a21*a33 - a11*a24*a33 - a13*a21*a34 - a14*a23*a31)/detA;
1110         B[8] = (a21*a32*a44 + a22*a34*a41 + a24*a31*a42 - a21*a34*a42 - a22*a31*a44 - a24*a32*a41)/detA;
1111         B[9] = (a11*a34*a42 + a12*a31*a44 + a14*a32*a41 - a11*a32*a44 - a12*a34*a41 - a14*a31*a42)/detA;
1112         B[10] = (a11*a22*a44 + a12*a24*a41 + a14*a21*a42 - a11*a24*a42 - a12*a21*a44 - a14*a22*a41)/detA;
1113         B[11] = (a11*a24*a32 + a12*a21*a34 + a14*a22*a31 - a11*a22*a34 - a12*a24*a31 - a14*a21*a32)/detA;
1114         B[12] = (a21*a33*a42 + a22*a31*a43 + a23*a32*a41 - a21*a32*a43 - a22*a33*a41 - a23*a31*a42)/detA;
1115         B[13] = (a11*a32*a43 + a12*a33*a41 + a13*a31*a42 - a11*a33*a42 - a12*a31*a43 - a13*a32*a41)/detA;
1116         B[14] = (a11*a23*a42 + a12*a21*a43 + a13*a22*a41 - a11*a22*a43 - a12*a23*a41 - a13*a21*a42)/detA;
1117         B[15] = (a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a11*a23*a32 - a12*a21*a33 - a13*a22*a31)/detA;
1118
1119         return;
1120 }
1121
1122
1123
1124 void Graphics::drawBillboardParticle(float x, float y, float z, float size, colour col)
1125 {
1126 //   float v[4];
1127   
1128   glPushAttrib(GL_ALL_ATTRIB_BITS);
1129   glDisable(GL_DEPTH_TEST);
1130   glDepthMask( GL_FALSE );
1131   enableAlpha(true);
1132   glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1133   glDisable(GL_CULL_FACE);
1134   glEnable( GL_TEXTURE_2D );
1135   /*********************************/
1136   GLdouble modelview[16], B[16];
1137   // save the current modelview matrix
1138   glPushMatrix();
1139   // get the current modelview matrix
1140   glGetDoublev(GL_MODELVIEW_MATRIX , modelview);
1141   inverseMatrix(modelview, B);
1142   // set the modelview with no rotations and scaling
1143          glMultMatrixd(B);
1144          glLoadMatrixd(modelview);
1145         glTranslatef(x,y,z);
1146         
1147    float s2 = size / 2.0;
1148 //   transform_colourv(v, col);
1149   glBegin(GL_QUADS);
1150         glColor4f(col.r, col.g, col.b, col.a);
1151         glTexCoord2f( 0.0, 0.0 );       glVertex3f(-s2,s2,0);
1152         glTexCoord2f( 1.0, 0.0 );       glVertex3f(s2,s2,0);
1153         glTexCoord2f( 1.0, 1.0 );       glVertex3f(s2,-s2,0);
1154         glTexCoord2f( 0.0, 1.0 );       glVertex3f(-s2,-s2,0);
1155   glEnd();
1156
1157   // restores the modelview matrix
1158   glPopMatrix();
1159   /*********************************/
1160   glPopAttrib();
1161
1162   return;
1163 }
1164
1165
1166 void Graphics::renderParticleArray(particle *array, unsigned int sizeOfArray, int type)
1167 {
1168         unsigned int i;
1169         
1170         if(type == AM_HARDWARE_PARTICLE)
1171         {       
1172                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1173                         glEnable(GL_DEPTH_TEST);
1174                         glDepthMask( GL_FALSE );
1175                         enableAlpha(true);
1176                         glBlendFunc( GL_DST_ALPHA, GL_ONE );
1177                         
1178                         for(i=0; i < sizeOfArray; i++)
1179                         {
1180                                 glPointSize( (array[i].size > maxSize ? maxSize : array[i].size) );
1181                                 glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, (array[i].size > maxSize ? maxSize : array[i].size)  );
1182                                 glBegin(GL_POINTS);
1183                                         glColor4f(array[i].col.r, array[i].col.g, array[i].col.b, array[i].col.a);
1184                                         glVertex3f(array[i].x, array[i].y, array[i].z);
1185                                 glEnd();
1186                         }
1187                 glPopAttrib();
1188         }
1189         else
1190         if(type == AM_SOFTWARE_PARTICLE)
1191         {
1192                 float mat[16];
1193                 struct point
1194                 {
1195                         float x,y,z;
1196                 }quad_lower_left, quad_lower_right;
1197   
1198                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1199                         glEnable(GL_DEPTH_TEST);
1200                         enableAlpha(true);
1201                         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1202                         glDisable(GL_CULL_FACE);
1203                         glEnable( GL_TEXTURE_2D );
1204                         glGetFloatv( GL_MODELVIEW_MATRIX, mat );
1205                         
1206                         for(i=0; i < sizeOfArray; i++)
1207                         {
1208                                 float s2 = array[i].size / 2.0;
1209                                 quad_lower_left.x = (-s2) * (mat[0] + mat[1]);
1210                                 quad_lower_left.y = (-s2) * (mat[4] + mat[5]);
1211                                 quad_lower_left.z = (-s2) * (mat[8] + mat[9]);
1212                                 quad_lower_right.x = (s2) * (mat[0] - mat[1]);
1213                                 quad_lower_right.y = (s2) * (mat[4] - mat[5]);
1214                                 quad_lower_right.z = (s2) * (mat[8] - mat[9]);
1215
1216                                 glBegin(GL_QUADS);
1217                                         glColor4f(array[i].col.r, array[i].col.g, array[i].col.b, array[i].col.a);
1218                                         glTexCoord2f(0.0, 0.0);
1219                                         glVertex3f(array[i].x + quad_lower_left.x, array[i].y + quad_lower_left.y, array[i].z + quad_lower_left.z);
1220                                         glTexCoord2f(1.0, 0.0);
1221                                         glVertex3f(array[i].x + quad_lower_right.x, array[i].y + quad_lower_right.y, array[i].z + quad_lower_right.z);
1222                                         glTexCoord2f(1.0, 1.0);
1223                                         glVertex3f(array[i].x - quad_lower_left.x, array[i].y - quad_lower_left.y, array[i].z - quad_lower_left.z);
1224                                         glTexCoord2f(0.0, 1.0);
1225                                         glVertex3f(array[i].x - quad_lower_right.x, array[i].y - quad_lower_right.y, array[i].z - quad_lower_right.z);
1226                                 glEnd();
1227                         }
1228                 glPopAttrib();
1229         }
1230         
1231         return; 
1232 }
1233
1234
1235
1236
1237 void Graphics::renderParticle(float x, float y, float z, float size, colour col, int type)
1238 {
1239         if(type == AM_HARDWARE_PARTICLE)
1240         {       
1241                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1242                 glPointSize( (size > maxSize ? maxSize : size) );
1243                 glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, (size > maxSize ? maxSize : size)  );
1244                 glEnable(GL_DEPTH_TEST);
1245                 glDepthMask( GL_FALSE );
1246                 enableAlpha(true);
1247 //              glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1248                 glBlendFunc( GL_DST_ALPHA, GL_ONE );
1249                 glBegin(GL_POINTS);
1250 //              float v[4];
1251 //              transform_colourv(v, col);
1252                 glColor4f(col.r , col.g, col.b, col.a);
1253                 glVertex3f(x,y,z);
1254                 glEnd();
1255                 glPopAttrib();
1256         }
1257         else
1258                 if(type == AM_SOFTWARE_PARTICLE)
1259                 {
1260 //                      float v[4];
1261                         float mat[16];
1262                         struct point
1263                         {
1264                                 float x,y,z;
1265                 
1266                         }quad_lower_left,quad_lower_right;
1267   
1268                         glPushAttrib(GL_ALL_ATTRIB_BITS);
1269                         glEnable(GL_DEPTH_TEST);
1270 //      glDepthMask( GL_FALSE );
1271                         enableAlpha(true);
1272                         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
1273                         glDisable(GL_CULL_FACE);
1274                         glEnable( GL_TEXTURE_2D );
1275
1276 //      glPushMatrix();
1277         // Get modelview matrix. We will only use the upper left 3x3 part of
1278     // the matrix, which represents the rotation.
1279                         glGetFloatv( GL_MODELVIEW_MATRIX, mat );
1280
1281     // 1) & 2) We do it in one swift step:
1282                         // Although not obvious, the following six lines represent two matrix/
1283     // vector multiplications. The matrix is the inverse 3x3 rotation
1284     // matrix (i.e. the transpose of the same matrix), and the two vectors
1285     // represent the lower left corner of the quad, PARTICLE_SIZE/2 *
1286     // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0).
1287     // The upper left/right corners of the quad is always the negative of
1288     // the opposite corners (regardless of rotation).
1289                         float s2 = size / 2.0;
1290                         quad_lower_left.x = (-s2) * (mat[0] + mat[1]);
1291                         quad_lower_left.y = (-s2) * (mat[4] + mat[5]);
1292                         quad_lower_left.z = (-s2) * (mat[8] + mat[9]);
1293                         quad_lower_right.x = (s2) * (mat[0] - mat[1]);
1294                         quad_lower_right.y = (s2) * (mat[4] - mat[5]);
1295                         quad_lower_right.z = (s2) * (mat[8] - mat[9]);
1296
1297             // 3) Translate the quad to the correct position in modelview
1298             // space and store its parameters in vertex arrays (we also
1299             // store texture coord and color information for each vertex).
1300 //                      transform_colourv(v, col);
1301                         glBegin(GL_QUADS);
1302                         glColor4f(col.r, col.g, col.b, col.a);
1303                 // Lower left corner
1304                         glTexCoord2f(0.0, 0.0);
1305                         glVertex3f(x + quad_lower_left.x, y + quad_lower_left.y, z + quad_lower_left.z);
1306 //              printf("1. %f %f %f\n",x + quad_lower_left.x, y + quad_lower_left.y, z + quad_lower_left.z);
1307             // Lower right corner
1308                         glTexCoord2f(1.0, 0.0);
1309                         glVertex3f(x + quad_lower_right.x, y + quad_lower_right.y, z + quad_lower_right.z);
1310 //              printf("2. %f %f %f\n",x + quad_lower_right.x, y + quad_lower_right.y, z + quad_lower_right.z); 
1311             // Upper right corner
1312                         glTexCoord2f(1.0, 1.0);
1313                         glVertex3f(x - quad_lower_left.x, y - quad_lower_left.y, z - quad_lower_left.z);
1314 //              printf("3. %f %f %f\n", x - quad_lower_left.x, y - quad_lower_left.y, z - quad_lower_left.z);
1315             // Upper left corner
1316                         glTexCoord2f(0.0, 1.0);
1317                         glVertex3f(x - quad_lower_right.x, y - quad_lower_right.y, z - quad_lower_right.z);
1318 //              printf("4. %f %f %f\n", x - quad_lower_right.x, y - quad_lower_right.y, z - quad_lower_right.z);
1319                         glEnd();
1320  // restores the modelview matrix
1321 //      glPopMatrix();
1322                         /*********************************/
1323                         glPopAttrib();
1324                 }
1325                         
1326         return;
1327 }
1328
1329
1330 /* - fov
1331                         Specifies the field of view angle, in degrees, in the y direction.
1332         -       ratio
1333                         Specifies the aspect ratio that determines the field of view in the x direction. 
1334                         The aspect ratio is the ratio of x (width) to y (height).
1335   -     zNear
1336                         Specifies the distance from the viewer to the near clipping plane (always positive).
1337   -     zFar
1338                         Specifies the distance from the viewer to the far clipping plane (always positive).
1339 */
1340 void Graphics::setPerspective(float fov, float ratio, float zNear, float zFar)
1341 {
1342         int matrixMode;
1343         
1344         glGetIntegerv( GL_MATRIX_MODE, &matrixMode);
1345         glMatrixMode( GL_PROJECTION );
1346         glLoadIdentity();
1347         gluPerspective( fov, ratio, zNear, zFar );
1348         glMatrixMode( matrixMode );
1349         return;
1350 }
1351
1352
1353 void Graphics::renderVertexArray(vertex *array, unsigned int numOfPrimitives, int type)
1354 {
1355         int t = type;
1356         if(type == AM_TRIANGLE_STRIP)
1357                 t = GL_TRIANGLE_STRIP;
1358         else if (type == AM_TRIANGLE_FAN)
1359                 t = GL_TRIANGLE_FAN;
1360         else if (type == AM_TRIANGLES)
1361                 t = GL_TRIANGLES;
1362         else if (type == AM_POINT_LIST)
1363                 t = GL_POINTS;
1364         else if (type ==  AM_LINE_LIST)
1365                 t = GL_LINES;
1366         else if (type == AM_LINE_STRIP)
1367                 t = GL_LINE_STRIP;
1368         
1369          // UGLY hack to reverse texture coordinate...implement an operator in struct vertex..?!?
1370         vertex *tmp = new vertex[numOfPrimitives];
1371         memcpy(tmp, array, numOfPrimitives*sizeof(vertex));
1372         int i;
1373         for(i=0; i < numOfPrimitives; i++)
1374                 tmp[i].v = 1 - tmp[i].v;
1375
1376         glInterleavedArrays( GL_T2F_C4F_N3F_V3F, 0, (void *) tmp);
1377         glDrawArrays( t, 0, numOfPrimitives);
1378
1379         delete tmp;
1380         return;
1381 }
1382
1383
1384 void Graphics::setCullingMode(int mode)
1385 {
1386         cmode = mode;
1387         if(mode == AM_CULL_NONE)
1388    {
1389       culling = false;
1390       glDisable(GL_CULL_FACE );
1391       return;
1392    }
1393    else
1394    {
1395                 if(!culling)
1396                 {
1397                         culling = true;
1398                         glEnable( GL_CULL_FACE );
1399                 }
1400                 if(mode == AM_CULL_FRONT)
1401                         glCullFace(GL_FRONT);
1402                 else if (mode == AM_CULL_BACK) 
1403                         glCullFace(GL_BACK);
1404    }
1405    return;
1406
1407
1408 int Graphics::getCullingMode()
1409 {
1410         return cmode;
1411 }
1412
1413
1414
1415 void Graphics::enter2dMode(void)
1416 {
1417         glPushAttrib( GL_ALL_ATTRIB_BITS );
1418  
1419         glDisable( GL_LIGHTING );
1420         glDisable( GL_DEPTH_TEST );
1421         glDisable( GL_CULL_FACE );
1422         glEnable( GL_TEXTURE_2D );
1423  
1424         glViewport( 0, 0, getWidth(), getHeight() );
1425  
1426         glMatrixMode( GL_PROJECTION );
1427         glPushMatrix();
1428         glLoadIdentity();
1429  
1430         glOrtho( 0.0, ( GLdouble ) getWidth(), ( GLdouble ) getHeight(), 0.0, 0.0, 1.0 );
1431  
1432         glMatrixMode( GL_MODELVIEW );
1433         glPushMatrix();
1434         glLoadIdentity();
1435         //      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1436         return ;
1437 }
1438  
1439  
1440 void Graphics::leave2dMode(void)
1441 {
1442         glMatrixMode( GL_MODELVIEW );
1443         glPopMatrix();
1444  
1445         glMatrixMode( GL_PROJECTION );
1446         glPopMatrix();
1447  
1448         glPopAttrib();
1449         return ;
1450 }
1451
1452
1453 void Graphics::enableDepthBuffer( bool b )
1454 {
1455         zBuffer = b;
1456         if(b)
1457                 glEnable( GL_DEPTH_TEST );
1458         else
1459                 glDisable( GL_DEPTH_TEST );
1460                 
1461         return;
1462 }
1463
1464
1465 bool Graphics::isDepthBuffer()
1466 {
1467         return zBuffer;
1468 }
1469
1470
1471
1472 /*--------------------------------------------------
1473 *                                                                                Texture
1474 *-----------------------------------------------------*/
1475
1476
1477
1478 Texture::Texture(  char *file, colour key, Graphics *g )
1479 {
1480         gl_Tex = 0;
1481         filteringDefinition = filtering = AM_LINEAR;
1482         this->g = g;
1483         glEnable( GL_TEXTURE_2D );
1484         colourKey = key;
1485         colourKeyEnabled = true;
1486
1487         // CreateTexture(&gl_Tex, file, 0);
1488         LoadGLTextures( &gl_Tex, file );
1489         std::cout << "file=" << file << ", gl_Tex=" << gl_Tex << "\n";
1490
1491   return ;
1492 }
1493
1494
1495 Texture::Texture( char *file, Graphics *g)
1496 {
1497         gl_Tex = 0;
1498   this->g = g;
1499   filteringDefinition = filtering = AM_LINEAR;
1500   glEnable( GL_TEXTURE_2D );
1501   assert(g);
1502   colourKeyEnabled = false;
1503   // CreateTexture(&gl_Tex, file, 0);
1504   LoadGLTextures( &gl_Tex, file );
1505   std::cout << "file=" << file << ", gl_Tex=" << gl_Tex << "\n";
1506
1507   return ;
1508 }
1509
1510 Texture::Texture(void *data, unsigned int w, unsigned int h, int format, int type, Graphics *g)
1511 {
1512         gl_Tex = 0;
1513         filteringDefinition = filtering = AM_LINEAR;
1514         this->g = g;
1515         assert(g);
1516         colourKeyEnabled = false;
1517         
1518         glEnable( GL_TEXTURE_2D );
1519         glGenTextures(1, &gl_Tex);
1520         glBindTexture( GL_TEXTURE_2D, gl_Tex );
1521         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1522         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1523         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1524         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1525         
1526         GLenum f = GL_RGBA, t = GL_UNSIGNED_BYTE;
1527         int c = 4;
1528         
1529         if(format == AM_ALPHA)
1530         {
1531                 f = GL_ALPHA;
1532                 c = GL_ALPHA; /* Warning!!! Dont change this value cause font rendering depends on it!*/
1533         }       
1534         else if (format == AM_RGBA)
1535         {
1536                         f = GL_RGBA;
1537                         c = 4;
1538         }
1539         
1540         if(type == AM_UBYTE)
1541                 t = GL_UNSIGNED_BYTE;
1542         
1543         //glTexImage2D( GL_TEXTURE_2D, 0, c, w, h, 0,   f, t, data);
1544         gluBuild2DMipmaps( GL_TEXTURE_2D, c, w, h,      f, t, data);
1545                 
1546         this->width = w;
1547         this->height = h;
1548
1549         std::cout << "gl_Tex=" << gl_Tex << "\n";
1550
1551         return ;
1552 }
1553
1554
1555
1556 Texture::~Texture()
1557 {
1558   return ;
1559 }
1560
1561
1562 /*
1563 unsigned int Texture::gl_getGLTex()
1564 {
1565   return gl_Tex;
1566 }
1567 */
1568
1569 void Texture::texSubImage2D(int xoff, int yoff, unsigned int w, unsigned int h, int format, int type, const void *pixels)
1570 {
1571         GLenum f = GL_RGBA, t = GL_UNSIGNED_BYTE;
1572         
1573         if(format == AM_ALPHA)
1574                 f = GL_ALPHA;
1575         else if (format == AM_RGBA)
1576                 f = GL_RGBA;
1577         
1578         if(type == AM_UBYTE)
1579                 t = GL_UNSIGNED_BYTE;
1580
1581         glBindTexture(GL_TEXTURE_2D, this->gl_Tex);
1582         glTexSubImage2D(GL_TEXTURE_2D, 0, xoff, yoff, w, h, f, t, pixels);
1583         
1584         //TODO kane popAttributes etsi wste na einai current texture auto pou htan prin...
1585          
1586         return;
1587 }
1588
1589 unsigned long Texture::getWidth()
1590 {
1591   return width;
1592 }
1593
1594 unsigned long Texture::getHeight()
1595 {
1596   return height;
1597 }
1598
1599
1600 int Texture::getFiltering()
1601 {
1602         return filteringDefinition;
1603 }
1604
1605
1606 /* this function needs some fixes and some rewrite */
1607 void Texture::setFiltering(int f, float anisotropyLevel)
1608 {
1609         int _f  = f;
1610         if(f == AM_LINEAR)
1611                 _f = GL_LINEAR;
1612         else if (f == AM_PLAIN)
1613                 _f = GL_NEAREST;
1614         
1615         filteringDefinition = filtering = f;
1616         if(_f == AM_ANISOTROPIC)
1617         {
1618                 if(supportsAnisotropic)
1619                 {
1620                         float a = anisotropyLevel;
1621                         if( a > maxAnisotropySupported) //fix this for round-off errors
1622                                 a = maxAnisotropySupported;
1623                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, a);
1624                 }
1625                 filtering = GL_LINEAR;
1626         }
1627         // 'filtering' cannot have here a value of AM_ANISOTROPIC
1628         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1629         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering );
1630         
1631         return;
1632 }
1633
1634
1635 void Texture::LoadGLTextures( GLuint *gl_Tex, const char * filename )
1636 {
1637         /*gl_Tex = ilutGLLoadImage( (char *) filename);
1638         glBindTexture( GL_TEXTURE_2D, *gl_Tex ); 
1639         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1640         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1641 */
1642         
1643         // Generate the main image name to use.
1644         ilGenImages (1, gl_Tex);
1645         ilBindImage (*gl_Tex);
1646         ilEnable(IL_ORIGIN_SET);
1647         ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
1648         if (!ilLoadImage ((char *)filename)) 
1649                 printf("cannot load image %s \n", filename);
1650         
1651         ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
1652
1653         ILinfo imageInfo;
1654         iluGetImageInfo(&imageInfo); 
1655         ILubyte *data = ilGetData();
1656         printf("image info. %d x %d depth=%d Bp=%d data=%d\n", imageInfo.Width, imageInfo.Height, imageInfo.Depth, imageInfo.Bpp,
1657                                                         imageInfo.SizeOfData);
1658         bool a = false;
1659         if ( colourKeyEnabled )
1660         {
1661                 //ksepaketaroume to colourkey
1662                 unsigned char ckR = 0, ckG = 0, ckB = 0, ckA = 255;
1663                 unsigned long mR, mG, mB, mA;
1664                 mB = 0x000000FF;
1665                 mG = 0x0000FF00;
1666                 mR = 0x00FF0000;
1667                 mA = 0xFF000000;
1668         ckR = (unsigned char) (colourKey.r * 255.0) ;
1669         ckG = (unsigned char) (colourKey.g * 255.0) ;
1670         ckB = (unsigned char) (colourKey.b * 255.0) ;
1671         ckA = (unsigned char) (colourKey.a * 255.0) ;
1672                 unsigned char _r, _g, _b; 
1673                 assert(g);
1674                 a = g->isAlpha();
1675                 g->enableAlpha(true);
1676                 int step = imageInfo.Bpp;
1677                 for(unsigned long i=0; i <  imageInfo.SizeOfData; i+=step)
1678                 {
1679                         _r = data[i];
1680                         _g = data[i + 1];
1681                         _b= data[i + 2];
1682                 
1683         if ( _r == ckR && _g == ckG && _b == ckB )
1684                                 data[i + 3] = 0;
1685                 }
1686         }
1687
1688         glBindTexture( GL_TEXTURE_2D, *gl_Tex ); 
1689
1690         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1691         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering );
1692         
1693 //      glTexImage2D( GL_TEXTURE_2D, 0, 4, imageInfo.Width, imageInfo.Height, 0,        GL_RGBA, GL_UNSIGNED_BYTE, data );
1694         
1695         gluBuild2DMipmaps( GL_TEXTURE_2D, 4, imageInfo.Width, imageInfo.Height,
1696                                                          GL_RGBA, GL_UNSIGNED_BYTE, data);
1697         
1698         
1699         width = imageInfo.Width;
1700         height = imageInfo.Height;
1701         if ( colourKeyEnabled ) 
1702                 g->enableAlpha(a);
1703
1704         return ;
1705 }