* Add Amaltheia library.
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "Graphics.h"
+// #include <X11/Xlib.h>
+// #include <X11/extensions/xf86vmode.h>
+#include <FTGL/FTGLTextureFont.h>
+#include <GL/glext.h>
+#include <IL/il.h>
+#include <IL/ilu.h>
+#include <IL/ilut.h>
+#include <SDL/SDL.h>
+// #include <SDL/SDL_thread.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <iostream>
+#include <cmath>
+#include <cassert>
+
+// using namespace Amaltheia;
+extern float z_order; //for Sprite
+static bool supportsAnisotropic = false;
+static GLfloat maxAnisotropySupported = 0.0;
+typedef unsigned long COLOUR;
+
+colour COLOUR_RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a )
+{
+ colour c;
+ c.a = a/255.0f;
+ c.r = r/255.0f;
+ c.g = g/255.0f;
+ c.b = b/255.0f;
+
+ return c;
+}
+
+
+ inline COLOUR CLR_RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a )
+{
+ return ( ( COLOUR ) ( ( ( ( a ) & 0xff ) << 24 ) | ( ( ( r ) & 0xff ) << 16 ) | ( ( ( g ) & 0xff ) << 8 ) | ( ( b ) & 0xff ) ) );
+}
+
+
+
+inline void transform_colourv( float *v, COLOUR col )
+{
+ int a, r, g, b;
+ int mask = 0x000000ff;
+
+ b = col & mask;
+ col >>= 8;
+ g = col & mask;
+ col >>= 8;
+ r = col & mask;
+ col >>= 8;
+ a = col & mask;
+
+
+ v[ 3 ] = ( float ) a / 255.0f;
+ v[ 2 ] = ( float ) b / 255.0f;
+ v[ 1 ] = ( float ) g / 255.0f;
+ v[ 0 ] = ( float ) r / 255.0f;
+
+ return;
+}
+
+
+float rad( float deg )
+{
+ return ( deg * M_PI ) / 180.f;
+}
+
+float deg( float rad )
+{
+ return ( rad * 180.0f ) / M_PI;
+}
+
+
+inline GLboolean queryExtension(char *extName)
+{
+ char *p = (char *) glGetString(GL_EXTENSIONS);
+ if(p == NULL)
+ return GL_FALSE;
+ char *end = p + strlen(p);
+ unsigned int n = 0;
+ while(p < end)
+ {
+ n = strcspn(p, " ");
+ if((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
+ return GL_TRUE;
+ p += (n + 1);
+ }
+
+ return GL_FALSE;
+}
+
+
+
+
+
+class FontImp
+{
+ public:
+ FTGLTextureFont *font;
+ int fontSize;
+ Graphics *g;
+
+};
+
+
+Font::Font() : imp( new FontImp() )
+{
+}
+
+Font::~Font()
+{
+ delete imp;
+ // delete font;
+ return ;
+}
+
+
+Font::Font(const char *name, int size, Graphics *g) : imp( new FontImp() )
+{
+ assert(g);
+ imp->g = g;
+ imp->fontSize = size;
+ imp->font = new FTGLTextureFont(name);
+ imp->font->FaceSize(size);
+ imp->font->CharMap(ft_encoding_unicode);
+ imp->fontSize = size;
+ /*this->g = g;
+ this->fontSize = size;
+ font = new FTGLTextureFont(name);
+ font->FaceSize(size);
+ font->CharMap(ft_encoding_unicode);
+ fontSize = size; */
+}
+
+
+void Font::print( const wchar_t *str, int x1, int y1, int x2, int y2, colour c )
+{
+ imp->g->enter2dMode();
+ glColor4f( c.r, c.g, c.b, c.a);
+ float h= imp->font->LineHeight()*0.64f; /* factor 0.64*/
+ glTranslatef(x1, y1 + h, 0);
+ glScalef(1.0, -1.0, 1.0);
+ imp->font->Render(str);
+// ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
+ imp->g->leave2dMode();
+}
+
+ void Font::print( char *str, int x1, int y1, int x2, int y2, colour c )
+ {
+ imp->g->enter2dMode();
+ glColor4f( c.r, c.g, c.b, c.a);
+ float h= imp->font->LineHeight()*0.64f; /* factor 0.64*/
+ glTranslatef(x1, y1 + h, 0);
+ glScalef(1.0, -1.0, 1.0);
+ imp->font->Render(str);
+ // ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
+ imp->g->leave2dMode();
+ }
+
+
+bool Graphics::oneGraphics = false;
+
+class GraphicsImp
+{
+public:
+ SDL_Surface *screen;
+};
+
+
+Graphics::Graphics( int w, int h, int bpp, bool fullScreen, bool a, bool l ) : imp(new GraphicsImp())
+{
+ if ( oneGraphics )
+ {
+ std::cerr << "Only one graphics object allowed!\n";
+ exit( 1 );
+ }
+
+ oneGraphics = true;
+ width = w;
+ height = h;
+ this->fullScreen = fullScreen;
+ this->bpp = bpp;
+ alpha = a;
+ lighting = l;
+ sceneBegin = false;
+ culling = true;
+ cmode = AM_CULL_BACK;
+ zBuffer = true;
+ cursorState = true;
+ bgcolour[ 0 ] = 0;
+ bgcolour[ 1 ] = 0;
+ bgcolour[ 2 ] = 0;
+ bgcolour[ 3 ] = 1;
+
+ cam.camx = 0.0;
+ cam.camy = 0.0;
+ cam.camz = 0.0;
+
+ cam.lookx = 0.0;
+ cam.looky = 0.0;
+ cam.lookz = 1.0;
+
+ cam.upx = 0.0;
+ cam.upy = 1.0;
+ cam.upz = 0.0;
+
+ this->currentTexture = 0;
+}
+
+
+
+Graphics::~Graphics( void )
+{
+ //glDeleteBuffers(1, &gpuBuf); // mono gia OpenGL 1.5
+ delete imp;
+ SDL_Quit();
+ return ;
+}
+
+
+
+void Graphics::setHeight( int h)
+{
+ height = h;
+ return ;
+}
+
+int Graphics::getHeight()
+{
+ return height;
+}
+
+void Graphics::setWidth(int w)
+{
+ width = w;
+ return ;
+}
+int Graphics::getWidth()
+{
+ return width;
+}
+
+void Graphics::setBpp( int b )
+{
+ bpp = b;
+ return ;
+}
+int Graphics::getBpp()
+{
+ return bpp;
+}
+
+void Graphics::enableVsync( bool v )
+{
+ vSync = v;
+ return ;
+}
+bool Graphics::isVsync()
+{
+ return vSync;
+}
+
+
+void Graphics::enableFullScreen( bool f )
+{
+ fullScreen = f;
+ return ;
+}
+bool Graphics::isFullScreen( void )
+{
+ return fullScreen;
+}
+
+
+void Graphics::enableLighting( bool l )
+{
+ lighting = l;
+
+ if ( lighting )
+ glEnable( GL_LIGHTING );
+ else
+ glDisable( GL_LIGHTING );
+
+ return ;
+}
+
+
+bool Graphics::isLighting()
+{
+ return lighting;
+}
+
+void Graphics::enableAlpha( bool a )
+{
+ alpha = a;
+ if ( alpha )
+ glEnable( GL_BLEND );
+ else
+ glDisable( GL_BLEND );
+
+ return ;
+}
+
+
+bool Graphics::isAlpha( void )
+{
+ return alpha;
+}
+
+void Graphics::setTexture( Texture *t )
+{
+ if ( t == 0 )
+ return ;
+
+ currentTexture = t;
+ glBindTexture( GL_TEXTURE_2D, t->gl_Tex );
+
+ return ;
+}
+
+Texture* Graphics::getTexture(void)
+{
+ return currentTexture;
+}
+
+
+int Graphics::createDisplay()
+{
+
+
+ /* Information about the current video settings. */
+ const SDL_VideoInfo * info = 0;
+ /* Flags we will pass into SDL_SetVideoMode. */
+ int flags = 0;
+
+ // putenv("__GL_SYNC_TO_VBLANK=1");
+
+ /* First, initialize SDL's video subsystem. */
+ if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
+ {
+ /* Failed, exit. */
+ fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError() );
+ return 2;
+ }
+
+ /* Let's get some video information. */
+ info = SDL_GetVideoInfo( );
+
+ if ( !info )
+ {
+ std::cerr << "Video query failed: " << SDL_GetError() << std::endl;
+ return 2;
+ }
+ ilInit();
+ iluInit();
+ ilutRenderer(ILUT_OPENGL);
+
+ /*
+ * Now, we want to setup our requested
+ * window attributes for our OpenGL window.
+ * We want *at least* 5 bits of red, green
+ * and blue. We also want at least a 16-bit
+ * depth buffer.
+ *
+ * The last thing we do is request a double
+ * buffered window. '1' turns on double
+ * buffering, '0' turns it off.
+ *
+ * Note that we do not use SDL_DOUBLEBUF in
+ * the flags to SDL_SetVideoMode. That does
+ * not affect the GL attribute state, only
+ * the standard 2D blitting setup.
+ */
+ SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
+ SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
+ SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
+ SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bpp );
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+
+ flags = SDL_OPENGL | ( fullScreen ? SDL_FULLSCREEN : 0 );
+
+ /*
+ * Set the video mode
+ */
+ if ( ( imp->screen = SDL_SetVideoMode( width, height, bpp, flags ) ) == 0 )
+ {
+ /*
+ * This could happen for a variety of reasons,
+ * including DISPLAY not being set, the specified
+ * resolution not being available, etc.
+ */
+ std::cerr << "Video mode set failed: " << SDL_GetError() << std::endl;
+ return 2;
+ }
+
+ SDL_SetGamma(1.8, 1.8, 1.8);
+
+ float ratio = ( float ) width / ( float ) height;
+ /* Our shading model--Gouraud (smooth). */
+ glShadeModel( GL_SMOOTH );
+ glClearDepth( 1.0f );
+
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ // glDepthFunc( GL_LEQUAL );
+ /* Set the clear color. */
+ glClearColor( bgcolour[ 0 ], bgcolour[ 1 ], bgcolour[ 2 ], bgcolour[ 3 ] );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+
+ glViewport( 0, 0, width, height );
+ gluPerspective( 45.0, ratio, 1.0, 10000.0 );
+
+ /* Culling. Boh8aei sto Blending*/
+ glCullFace( GL_BACK );
+/* Polygons whose vertices are in counterclockwise order are called frontfacing but dx thinks different ?*/
+ glFrontFace( GL_CW );
+ if( culling)
+ glEnable( GL_CULL_FACE );
+
+ if(zBuffer)
+ glEnable( GL_DEPTH_TEST );
+
+ glEnable( GL_TEXTURE_2D );
+ if ( alpha )
+ glEnable( GL_BLEND );
+ if ( lighting )
+ glEnable( GL_LIGHTING );
+
+ //TODO: 8a prepei na oristei synarthsh setMaterial...
+ float diffuse[] = {1.0, 1.0, 1.0, 1.0};
+ float specular[] = {0.0, 0.0, 0.0, 0.0};
+ float ambient[] = { 0.0, 0.0, 0.0, 0.0};
+ float emissive[] = {0.0, 0.0, 0.0, 0.0};
+ glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse );
+ glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, specular );
+ glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, emissive );
+ glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, ambient );
+
+
+ if ( !queryExtension( "GL_EXT_texture_filter_anisotropic" ) )
+ std::cout << "Extension GL_EXT_texture_filter_anisotropic not found...\n";
+ else
+ {
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropySupported);
+ std::cout << "max Anisotropy supported = " << maxAnisotropySupported << '\n';
+ supportsAnisotropic = true;
+ }
+
+ /*glGenBuffers(1, &gpuBuf); // mono gia OpenGL 1.5
+ glBindBuffer(GL_ARRAY_BUFFER, gpuBuf); // mono gia OpenGL 1.5
+ glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, ¶meter); // mono gia OpenGL 1.5
+ printf("Buffer size is %d \n", parameter); */
+ if ( !queryExtension( "GL_ARB_point_sprite" ) )
+ std::cout << "Extension GL_ARB_point_sprite not found...\n";
+ else
+ {
+ // This is how will our point sprite's size will be modified by
+ // distance from the viewer
+ float quadratic[] = { 1.0f, 0.0f, 0.01f };
+ glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
+ // Query for the max point size supported by the hardware
+ maxSize = 0.0f;
+ glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
+ // Clamp size to 100.0f or the sprites could get a little too big on some
+ // of the newer graphic cards. My ATI card at home supports a max point
+ // size of 1024.0f!
+
+ // The alpha of a point is calculated to allow the fading of points
+ // instead of shrinking them past a defined threshold size. The threshold
+ // is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
+ // the minimum and maximum point sizes.
+ glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
+ glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 10.0f );
+ glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
+
+ // Specify point sprite texture coordinate replacement mode for each
+ // texture unit
+ glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
+ glEnable( GL_POINT_SPRITE_ARB );
+ glEnable( GL_ARB_point_sprite );
+ }
+
+ std::cout << "OpenGL Version =" << glGetString( GL_VERSION ) << std::endl;
+ int _red,_green,_blue, _alpha, _depth, _stencil;
+ glGetIntegerv(GL_RED_BITS, &_red);
+ glGetIntegerv(GL_GREEN_BITS, &_green);
+ glGetIntegerv(GL_BLUE_BITS, &_blue);
+ glGetIntegerv(GL_ALPHA_BITS, &_alpha);
+ std::cout << "Color Buffers RGBA bits = " << _red << _green << _blue << _alpha << std::endl;
+ glGetIntegerv(GL_DEPTH_BITS, &_depth);
+ std::cout << "Depth Buffer bits = " << _depth << "\n";
+ glGetIntegerv(GL_STENCIL_BITS, &_stencil);
+ std::cout << "Stencil Buffer bits = " << _stencil << "\n";
+ int _aux;
+ glGetIntegerv(GL_AUX_BUFFERS, &_aux);
+ std::cout << "Aux buffers = " << _aux << "\n";
+ // putenv("__GL_SYNC_TO_VBLANK=1");
+
+ // XF86VidModeModeLine mode;
+ // int unused;
+
+ // Display *d = XOpenDisplay(NULL);
+ /*Bool XF86VidModeGetModeLine(
+ Display *display ,
+ int screen ,
+ int *dotclock_return ,
+ XF86VidModeModeLine *modeline );
+ */
+ // printf("d=%p\n",d);
+ // if(XF86VidModeGetModeLine(d, 0, &unused, &mode))
+ // {
+
+ // printf("OK %d mexri %d\n", mode.hsyncstart, mode.hsyncend);
+ // }
+ // else
+ // printf("not ok\n");
+ // glXWaitVideoSyncSGI();
+ // GLX_SGI_video_sync
+ // unsigned int k;
+ // glXGetVideoSyncSGI(&k);
+ // printf("k=%d\n", k);
+ glMatrixMode( GL_MODELVIEW );
+
+ return 0;
+}
+
+
+
+void Graphics::beginScene( void )
+{
+ /* Clear the color and depth buffers. */
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ //gia symbatothta me to DirectX
+ glScalef( -1.0, 1.0, 1.0 );
+ sceneBegin = true;
+
+ return ;
+}
+
+
+void Graphics::endScene()
+{
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ //if(vSync)
+ //glXSwapIntervalSGI(1);
+ SDL_GL_SwapBuffers();
+
+ sceneBegin = false;
+ z_order = 1.0;
+ return ;
+}
+
+
+GLdouble mm[4][4];
+void _gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
+ GLdouble centerx, GLdouble centery, GLdouble centerz,
+ GLdouble upx, GLdouble upy, GLdouble upz )
+{
+ GLdouble m[ 16 ];
+ GLdouble x[ 3 ], y[ 3 ], z[ 3 ];
+ GLdouble mag;
+
+ /* Make rotation matrix */
+
+ /* Z vector */
+ z[ 0 ] = ( eyex - centerx );
+ z[ 1 ] = ( eyey - centery );
+ z[ 2 ] = ( eyez - centerz );
+ mag = sqrt( z[ 0 ] * z[ 0 ] + z[ 1 ] * z[ 1 ] + z[ 2 ] * z[ 2 ] );
+ if ( mag )
+ { /* mpichler, 19950515 */
+ z[ 0 ] /= mag;
+ z[ 1 ] /= mag;
+ z[ 2 ] /= mag;
+ }
+
+ /* Y vector */
+ y[ 0 ] = upx;
+ y[ 1 ] = upy;
+ y[ 2 ] = upz;
+
+ /* X vector = Y cross Z */
+ x[ 0 ] = y[ 1 ] * z[ 2 ] - y[ 2 ] * z[ 1 ];
+ x[ 1 ] = y[ 2 ] * z[ 0 ] - y[ 0 ] * z[ 2 ] ;
+ x[ 2 ] = y[ 0 ] * z[ 1 ] - y[ 1 ] * z[ 0 ];
+
+ /* Recompute Y = Z cross X */
+ y[ 0 ] = z[ 1 ] * x[ 2 ] - z[ 2 ] * x[ 1 ];
+ y[ 1 ] = -z[ 0 ] * x[ 2 ] + z[ 2 ] * x[ 0 ];
+ y[ 2 ] = z[ 0 ] * x[ 1 ] - z[ 1 ] * x[ 0 ];
+
+ /* mpichler, 19950515 */
+ /* cross product gives area of parallelogram, which is < 1.0 for
+ * non-perpendicular unit-length vectors; so normalize x, y here
+ */
+
+ mag = sqrt( x[ 0 ] * x[ 0 ] + x[ 1 ] * x[ 1 ] + x[ 2 ] * x[ 2 ] );
+ if ( mag )
+ {
+ x[ 0 ] /= mag;
+ x[ 1 ] /= mag;
+ x[ 2 ] /= mag;
+ }
+
+ mag = sqrt( y[ 0 ] * y[ 0 ] + y[ 1 ] * y[ 1 ] + y[ 2 ] * y[ 2 ] );
+ if ( mag )
+ {
+ y[ 0 ] /= mag;
+ y[ 1 ] /= mag;
+ y[ 2 ] /= mag;
+ }
+
+#define M(row,col) m[col*4+row]
+ M( 0, 0 ) = x[ 0 ];
+ M( 0, 1 ) = x[ 1 ];
+ M( 0, 2 ) = x[ 2 ];
+ M( 0, 3 ) = -( x[ 0 ] * eyex + x[ 1 ] * eyey + x[ 2 ] * eyez );
+
+ M( 1, 0 ) = y[ 0 ];
+ M( 1, 1 ) = y[ 1 ];
+ M( 1, 2 ) = y[ 2 ];
+ M( 1, 3 ) = -( y[ 0 ] * eyex + y[ 1 ] * eyey + y[ 2 ] * eyez );
+
+ M( 2, 0 ) = z[ 0 ];
+ M( 2, 1 ) = z[ 1 ];
+ M( 2, 2 ) = z[ 2 ];
+ M( 2, 3 ) = -( z[ 0 ] * eyex + z[ 1 ] * eyey + z[ 2 ] * eyez );
+
+ M( 3, 0 ) = 0.0;
+ M( 3, 1 ) = 0.0;
+ M( 3, 2 ) = 0.0;
+ M( 3, 3 ) = 1.0;
+ /* M(0, 0) = x[0];
+ M(1, 0) = y[0];
+ M(2, 0) = z[0];
+ M(3, 0) = 0.0;
+
+ M(0, 1) = x[1];
+ M(1, 1) = y[1];
+ M(2, 1) = z[1];
+ M(3, 1) = 0.0;
+
+ M(0, 2) = x[2];
+ M(1, 2) = y[2];
+ M(2, 2) = z[2];
+ M(3, 2) = 0.0;
+
+ M(0, 3) = 0.0;
+ M(1, 3) = 0.0;
+ M(2, 3) = 0.0;
+ M(3, 3) = 1.0;
+ */
+#undef M
+ glScalef( -1.0, 1.0, 1.0 );
+ glMultMatrixd( m );
+ glScalef( -1.0, 1.0, 1.0 );
+
+}
+
+
+
+int Graphics::setCamera( float camx, float camy, float camz,
+ float lookx, float looky, float lookz,
+ float upx, float upy, float upz )
+{
+
+ _gluLookAt( camx, camy, camz, lookx, looky, lookz, upx, upy, upz );
+
+ cam.camx = camx;
+ cam.camy = camy;
+ cam.camz = camz;
+
+ cam.lookx = lookx;
+ cam.looky = looky;
+ cam.lookz = lookz;
+
+ cam.upx = upx;
+ cam.upy = upy;
+ cam.upz = upz;
+
+ return 0;
+}
+
+
+struct camera Graphics::getCamera()
+{
+ return cam;
+}
+
+
+
+
+int Graphics::renderTriangle(vertex v1, vertex v2, vertex v3 )
+{
+// GLfloat colour[ 4 ];
+ if ( !sceneBegin )
+ {
+ std::cout << "DEBUG: oust...!\n";
+ exit( 1 );
+ return 1;
+ }
+
+
+// glPushAttrib(GL_ALL_ATTRIB_BITS); //kyriws gia na epanaferoume to xrwma
+ glBegin( GL_TRIANGLES );
+
+// transform_colourv( colour, v1.col );
+ glColor4f( v1.col.r, v1.col.g, v1.col.b, v1.col.a);
+ glNormal3f( v1.nx, v1.ny, v1.nz );
+ glTexCoord2f( v1.u, 1.0 - v1.v );
+ glVertex3f( v1.x, v1.y, v1.z );
+
+// transform_colourv( colour, v2.col );
+// glColor4f( colour[ 0 ], colour[ 1 ], colour[ 2 ], colour[ 3 ] );
+ glColor4f( v2.col.r, v2.col.g, v2.col.b, v2.col.a);
+ glNormal3f( v2.nx, v2.ny, v2.nz );
+ glTexCoord2f( v2.u, 1.0 - v2.v );
+ glVertex3f( v2.x, v2.y, v2.z );
+
+ glColor4f( v3.col.r, v3.col.g, v3.col.b, v3.col.a);
+ glNormal3f( v3.nx, v3.ny, v3.nz );
+ glTexCoord2f( v3.u, 1.0 - v3.v );
+ glVertex3f( v3.x, v3.y, v3.z );
+
+ glEnd();
+// glPopAttrib();
+ //isos na prepei na epanafero pisw to arxiko xrwma...
+
+ return 0;
+}
+
+
+
+int Graphics::setWorld( float transx, float transy, float transz,
+ float rotx, float roty, float rotz, float scalex, float scaley, float scalez,
+ int rotationOrder)
+{
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ struct camera c = getCamera();
+ setCamera( c.camx, c.camy, c.camz, c.lookx, c.looky, c.lookz, c.upx, c.upy, c.upz );
+
+ glScalef( -1.0, 1.0, 1.0 ); //gia symbatothta me to DirectX
+ glTranslatef( transx, transy, transz );
+
+ if(rotationOrder == AM_XYZ)
+ {
+ glRotatef( rotz, 0, 0, 1 );
+ glRotatef( roty, 0, 1, 0 );
+ glRotatef( rotx, 1, 0, 0 );
+ }
+ else if(rotationOrder == AM_XZY)
+ {
+ glRotatef( roty, 0, 1, 0 );
+ glRotatef( rotz, 0, 0, 1 );
+ glRotatef( rotx, 1, 0, 0 );
+
+ }
+ else if(rotationOrder == AM_YZX)
+ {
+ glRotatef( rotx, 1, 0, 0 );
+ glRotatef( rotz, 0, 0, 1 );
+ glRotatef( roty, 0, 1, 0 );
+ }
+ else if(rotationOrder == AM_YXZ)
+ {
+ glRotatef( rotz, 0, 0, 1 );
+ glRotatef( rotx, 1, 0, 0 );
+ glRotatef( roty, 0, 1, 0 );
+
+ }
+ else if(rotationOrder == AM_ZXY)
+ {
+ glRotatef( roty, 0, 1, 0 );
+ glRotatef( rotx, 1, 0, 0 );
+ glRotatef( rotz, 0, 0, 1 );
+ }
+ else
+ {
+ glRotatef( rotx, 1, 0, 0 );
+ glRotatef( roty, 0, 1, 0 );
+ glRotatef( rotz, 0, 0, 1 );
+ }
+
+ glScalef( scalex, scaley, scalez );
+
+ return 0;
+}
+
+
+
+/*
+
+int Graphics::setWorld2( float transx, float transy, float transz,
+ float rotx, float roty, float rotz, float scalex, float scaley, float scalez )
+{
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+
+ struct camera c = getCamera();
+ setCamera( c.camx, c.camy, c.camz, c.lookx, c.looky, c.lookz, c.upx, c.upy, c.upz );
+
+ glScalef( -1.0, 1.0, 1.0 ); //gia symbatothta me to DirectX
+ glTranslatef( transx, transy, transz );
+ glRotatef( roty, 0, 1, 0 );
+ glRotatef( rotz, 0, 0, 1 );
+ glRotatef( rotx, 1, 0, 0 );
+ glScalef( scalex, scaley, scalez );
+
+
+ return 0;
+}
+
+ */
+
+
+
+
+
+void Graphics::setBackground( colour colour )
+{
+// transform_colourv( bgcolour, colour );
+ // printf( "(%f, %f, %f ,%f)\n", bgcolour[ 0 ], bgcolour[ 1 ], bgcolour[ 2 ], bgcolour[ 3 ] );
+ bgcolour[0] = colour.r;
+ bgcolour[1] = colour.g;
+ bgcolour[2] = colour.b;
+ bgcolour[3] = colour.a;
+ glClearColor( ( float ) bgcolour[ 0 ], ( float ) bgcolour[ 1 ], ( float ) bgcolour[ 2 ], ( float ) bgcolour[ 3 ] );
+
+return ;
+}
+
+
+colour Graphics::getBackground( void )
+{
+ colour c;
+ c.r = bgcolour[0];
+ c.g = bgcolour[1];
+ c.b = bgcolour[2];
+ c.a = bgcolour[3];
+ return c;
+}
+
+
+
+
+void Graphics::project( float objx, float objy, float objz,
+ //const double modelMatrix[16], const double projMatrix[16], const int viewport[4],
+ float *winx, float *winy, float *winz )
+{
+ double _winx = 0;
+ double _winy = 0;
+ double _winz = 0;
+ GLint viewport[ 4 ];
+ GLdouble mvmatrix[ 16 ], projmatrix[ 16 ];
+
+ glGetIntegerv ( GL_VIEWPORT, viewport );
+ glGetDoublev ( GL_MODELVIEW_MATRIX, mvmatrix );
+ glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix );
+
+ gluProject( objx, objy, objz, mvmatrix, projmatrix, viewport,
+ &_winx, &_winy, &_winz );
+
+ *winx = _winx;
+ *winy = viewport[ 3 ] - ( int ) _winy - 1;
+ *winz = _winz;
+
+ return ;
+}
+
+
+void Graphics::unproject( float winx, float winy, float winz,
+ //const double modelMatrix[16], const double projMatrix[16], const int viewport[4],
+ float *objx, float *objy, float *objz )
+{
+ int realy;
+ double _objx = 0;
+ double _objy = 0;
+ double _objz = 0;
+ GLint viewport[ 4 ];
+ GLdouble mvmatrix[ 16 ], projmatrix[ 16 ];
+
+ glGetIntegerv ( GL_VIEWPORT, viewport );
+ glGetDoublev ( GL_MODELVIEW_MATRIX, mvmatrix );
+ glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix );
+
+ realy = viewport[ 3 ] - ( int ) winy - 1;
+ // std::cout << "realy=" <<realy << "\n";
+
+ gluUnProject( winx, realy, winz,
+ mvmatrix, projmatrix, viewport,
+ &_objx, &_objy, &_objz );
+
+ *objx = _objx;
+ *objy = _objy;
+ *objz = _objz;
+
+ return ;
+}
+
+
+
+void Graphics::enableCursor( bool state )
+{
+ cursorState = state;
+ if ( state )
+ SDL_ShowCursor( SDL_ENABLE );
+ else
+ SDL_ShowCursor( SDL_DISABLE );
+ return;
+}
+
+bool Graphics::isCursor()
+{
+ return cursorState;
+}
+
+
+
+void Graphics::planeIntersect( float a, float b, float c, float d,
+ float p1x, float p1y, float p1z, float p2x, float p2y, float p2z,
+ float *poutx, float *pouty, float *poutz )
+{
+ float numerator = -( a * p1x + b * p1y + c * p1z + d );
+ if ( numerator == 0 )
+ {
+ ( *poutx ) = p1x;
+ ( *pouty ) = p1y;
+ ( *poutz ) = p1z;
+ return ;
+ }
+ else
+ {
+ float denominator = a * ( p2x - p1x ) + b * ( p2y - p1y ) + c * ( p2z - p1z );
+ if ( denominator == 0 )
+ {
+ ( *poutx ) = 0.0;
+ ( *pouty ) = 0.0;
+ ( *poutz ) = 0.0;
+ printf("denominator==0!!!\n");
+ exit(1);
+ return ;
+ }
+ else
+ {
+ float t = numerator / denominator;
+ ( *poutx ) = p1x + t * ( p2x - p1x );
+ ( *pouty ) = p1y + t * ( p2y - p1y );
+ ( *poutz ) = p1z + t * ( p2z - p1z );
+ return ;
+ }
+ }
+
+ return ;
+}
+
+
+
+void Graphics::setLight( int numLight, const light& l )
+{
+ GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0};
+ GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0};
+ GLfloat position[] = {0.0, 0.0, 1.0, 0.0};
+ GLenum enm = GL_LIGHT0;
+
+ if(numLight == 0) enm = GL_LIGHT0;
+ else if(numLight == 1) enm = GL_LIGHT1;
+ else if(numLight == 2) enm = GL_LIGHT2;
+ else if(numLight == 3) enm = GL_LIGHT3;
+ else if(numLight == 4) enm = GL_LIGHT4;
+ else if(numLight == 5) enm = GL_LIGHT5;
+ else if(numLight == 6) enm = GL_LIGHT6;
+ else if(numLight == 7 ) enm = GL_LIGHT7;
+
+// transform_colourv( ambient, l.ambient );
+// transform_colourv( diffuse, l.diffuse );
+// transform_colourv( specular, l.specular );
+ ambient[0] = l.ambient.r; ambient[1] = l.ambient.g; ambient[2] = l.ambient.b; ambient[3] = l.ambient.a;
+ diffuse[0] = l.diffuse.r; diffuse[1] = l.diffuse.g; diffuse[2] = l.diffuse.b; diffuse[3] = l.diffuse.a;
+ specular[0] = l.specular.r; specular[1] = l.specular.g; specular[2] = l.specular.b; specular[3] = l.specular.a;
+
+ if ( l.type == AM_POINT_LIGHT )
+ {
+ position[ 3 ] = 1.0;
+ position[ 0 ] = l.posx;
+ position[ 1 ] = l.posy;
+ position[ 2 ] = l.posz;
+ }
+ else
+ if ( l.type == AM_DIRECTIONAL_LIGHT )
+ {
+ //float val = sqrt(l.dirx*l.dirx + l.diry*l.diry + l.dirz*l.dirz);
+ position[ 3 ] = 0.0;
+ position[ 0 ] = -l.dirx;
+ position[ 1 ] = -l.diry;
+ position[ 2 ] = l.dirz;
+ }
+
+
+ /*glPushMatrix();
+ glBegin(GL_POINTS);
+ glPointSize(1000.);
+ glVertex3f(position[0], position[1], position[2]);
+ glVertex3f(360, 10, 360);
+ glEnd();
+ */
+ glLightfv( enm, GL_AMBIENT, ambient );
+ glLightfv( enm, GL_DIFFUSE, diffuse );
+ glLightfv( enm, GL_SPECULAR, specular );
+ glLightfv( enm, GL_POSITION, position );
+ // glPopMatrix();
+
+ return ;
+}
+
+
+void Graphics::showLight( int numLight, bool state )
+{
+ GLenum enm = GL_LIGHT0;
+ if ( numLight == 0 )
+ enm = GL_LIGHT0;
+ else
+ if ( numLight == 1 )
+ enm = GL_LIGHT1;
+ else
+ if ( numLight == 2 )
+ enm = GL_LIGHT2;
+
+ if ( state )
+ glEnable( enm );
+ else
+ glDisable( enm );
+
+ return ;
+}
+
+
+
+
+
+void inverseMatrix( double A[16], double B[16])
+{
+
+ double detA;
+
+ double a11 = A[0];
+ double a12 = A[1];
+ double a13 = A[2];
+ double a14 = A[3];
+ double a21 = A[4];
+ double a22 = A[5];
+ double a23 = A[6];
+ double a24 = A[7];
+ double a31 = A[8];
+ double a32 = A[9];
+ double a33 = A[10];
+ double a34 = A[11];
+ double a41 = A[12];
+ double a42 = A[13];
+ double a43 = A[14];
+ double a44 = A[15];
+
+ detA = a11*a22*a33*a44 + a11*a23*a34*a42 + a11*a24*a32*a43 \
+ +a12*a21*a34*a43 + a12*a23*a31*a44 + a12*a24*a33*a41 \
+ +a13*a21*a32*a44 + a13*a22*a34*a41 + a13*a24*a31*a42 \
+ +a14*a21*a33*a42 + a14*a22*a31*a43 + a14*a23*a32*a41 \
+ -a11*a22*a34*a43 - a11*a23*a32*a44 - a11*a24*a33*a42 \
+ -a12*a21*a33*a44 - a12*a23*a34*a41 - a12*a24*a31*a43 \
+ -a13*a21*a34*a42 - a13*a22*a31*a44 - a13*a24*a32*a41 \
+ -a14*a21*a32*a43 - a14*a22*a33*a41 - a14*a23*a31*a42;
+
+// printf("detA=%f\n",detA);
+
+ B[0] = (a22*a33*a44 + a23*a34*a42 + a24*a32*a43 - a22*a34*a43 - a23*a32*a44 - a24*a33*a42)/detA;
+ B[1] = (a12*a34*a43 + a13*a32*a44 + a14*a33*a42 - a12*a33*a44 - a13*a34*a42 - a14*a32*a43)/detA;
+ B[2] = (a12*a23*a44 + a13*a24*a42 + a14*a22*a43 - a12*a24*a43 - a13*a22*a44 - a14*a23*a42)/detA;
+ B[3] = (a12*a24*a33 + a13*a22*a34 + a14*a23*a32 - a12*a23*a34 - a13*a24*a32 - a14*a22*a33)/detA;
+ B[4] = (a21*a34*a43 + a23*a31*a44 + a24*a33*a41 - a21*a33*a44 - a23*a34*a41 - a24*a31*a43)/detA;
+ B[5] = (a11*a33*a44 + a13*a34*a41 + a14*a31*a43 - a11*a34*a43 - a13*a31*a44 - a14*a33*a41)/detA;
+ B[6] = (a11*a24*a43 + a13*a21*a44 + a14*a23*a41 - a11*a23*a44 - a13*a24*a41 - a14*a21*a43)/detA;
+ B[7] = (a11*a23*a34 + a13*a24*a31 + a14*a21*a33 - a11*a24*a33 - a13*a21*a34 - a14*a23*a31)/detA;
+ B[8] = (a21*a32*a44 + a22*a34*a41 + a24*a31*a42 - a21*a34*a42 - a22*a31*a44 - a24*a32*a41)/detA;
+ B[9] = (a11*a34*a42 + a12*a31*a44 + a14*a32*a41 - a11*a32*a44 - a12*a34*a41 - a14*a31*a42)/detA;
+ B[10] = (a11*a22*a44 + a12*a24*a41 + a14*a21*a42 - a11*a24*a42 - a12*a21*a44 - a14*a22*a41)/detA;
+ B[11] = (a11*a24*a32 + a12*a21*a34 + a14*a22*a31 - a11*a22*a34 - a12*a24*a31 - a14*a21*a32)/detA;
+ B[12] = (a21*a33*a42 + a22*a31*a43 + a23*a32*a41 - a21*a32*a43 - a22*a33*a41 - a23*a31*a42)/detA;
+ B[13] = (a11*a32*a43 + a12*a33*a41 + a13*a31*a42 - a11*a33*a42 - a12*a31*a43 - a13*a32*a41)/detA;
+ B[14] = (a11*a23*a42 + a12*a21*a43 + a13*a22*a41 - a11*a22*a43 - a12*a23*a41 - a13*a21*a42)/detA;
+ B[15] = (a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a11*a23*a32 - a12*a21*a33 - a13*a22*a31)/detA;
+
+ return;
+}
+
+
+
+void Graphics::drawBillboardParticle(float x, float y, float z, float size, colour col)
+{
+// float v[4];
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask( GL_FALSE );
+ enableAlpha(true);
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+ glDisable(GL_CULL_FACE);
+ glEnable( GL_TEXTURE_2D );
+ /*********************************/
+ GLdouble modelview[16], B[16];
+ // save the current modelview matrix
+ glPushMatrix();
+ // get the current modelview matrix
+ glGetDoublev(GL_MODELVIEW_MATRIX , modelview);
+ inverseMatrix(modelview, B);
+ // set the modelview with no rotations and scaling
+ glMultMatrixd(B);
+ glLoadMatrixd(modelview);
+ glTranslatef(x,y,z);
+
+ float s2 = size / 2.0;
+// transform_colourv(v, col);
+ glBegin(GL_QUADS);
+ glColor4f(col.r, col.g, col.b, col.a);
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f(-s2,s2,0);
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f(s2,s2,0);
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f(s2,-s2,0);
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f(-s2,-s2,0);
+ glEnd();
+
+ // restores the modelview matrix
+ glPopMatrix();
+ /*********************************/
+ glPopAttrib();
+
+ return;
+}
+
+
+void Graphics::renderParticleArray(particle *array, unsigned int sizeOfArray, int type)
+{
+ unsigned int i;
+
+ if(type == AM_HARDWARE_PARTICLE)
+ {
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask( GL_FALSE );
+ enableAlpha(true);
+ glBlendFunc( GL_DST_ALPHA, GL_ONE );
+
+ for(i=0; i < sizeOfArray; i++)
+ {
+ glPointSize( (array[i].size > maxSize ? maxSize : array[i].size) );
+ glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, (array[i].size > maxSize ? maxSize : array[i].size) );
+ glBegin(GL_POINTS);
+ glColor4f(array[i].col.r, array[i].col.g, array[i].col.b, array[i].col.a);
+ glVertex3f(array[i].x, array[i].y, array[i].z);
+ glEnd();
+ }
+ glPopAttrib();
+ }
+ else
+ if(type == AM_SOFTWARE_PARTICLE)
+ {
+ float mat[16];
+ struct point
+ {
+ float x,y,z;
+ }quad_lower_left, quad_lower_right;
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glEnable(GL_DEPTH_TEST);
+ enableAlpha(true);
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+ glDisable(GL_CULL_FACE);
+ glEnable( GL_TEXTURE_2D );
+ glGetFloatv( GL_MODELVIEW_MATRIX, mat );
+
+ for(i=0; i < sizeOfArray; i++)
+ {
+ float s2 = array[i].size / 2.0;
+ quad_lower_left.x = (-s2) * (mat[0] + mat[1]);
+ quad_lower_left.y = (-s2) * (mat[4] + mat[5]);
+ quad_lower_left.z = (-s2) * (mat[8] + mat[9]);
+ quad_lower_right.x = (s2) * (mat[0] - mat[1]);
+ quad_lower_right.y = (s2) * (mat[4] - mat[5]);
+ quad_lower_right.z = (s2) * (mat[8] - mat[9]);
+
+ glBegin(GL_QUADS);
+ glColor4f(array[i].col.r, array[i].col.g, array[i].col.b, array[i].col.a);
+ glTexCoord2f(0.0, 0.0);
+ glVertex3f(array[i].x + quad_lower_left.x, array[i].y + quad_lower_left.y, array[i].z + quad_lower_left.z);
+ glTexCoord2f(1.0, 0.0);
+ glVertex3f(array[i].x + quad_lower_right.x, array[i].y + quad_lower_right.y, array[i].z + quad_lower_right.z);
+ glTexCoord2f(1.0, 1.0);
+ glVertex3f(array[i].x - quad_lower_left.x, array[i].y - quad_lower_left.y, array[i].z - quad_lower_left.z);
+ glTexCoord2f(0.0, 1.0);
+ glVertex3f(array[i].x - quad_lower_right.x, array[i].y - quad_lower_right.y, array[i].z - quad_lower_right.z);
+ glEnd();
+ }
+ glPopAttrib();
+ }
+
+ return;
+}
+
+
+
+
+void Graphics::renderParticle(float x, float y, float z, float size, colour col, int type)
+{
+ if(type == AM_HARDWARE_PARTICLE)
+ {
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glPointSize( (size > maxSize ? maxSize : size) );
+ glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, (size > maxSize ? maxSize : size) );
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask( GL_FALSE );
+ enableAlpha(true);
+// glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+ glBlendFunc( GL_DST_ALPHA, GL_ONE );
+ glBegin(GL_POINTS);
+// float v[4];
+// transform_colourv(v, col);
+ glColor4f(col.r , col.g, col.b, col.a);
+ glVertex3f(x,y,z);
+ glEnd();
+ glPopAttrib();
+ }
+ else
+ if(type == AM_SOFTWARE_PARTICLE)
+ {
+// float v[4];
+ float mat[16];
+ struct point
+ {
+ float x,y,z;
+
+ }quad_lower_left,quad_lower_right;
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glEnable(GL_DEPTH_TEST);
+// glDepthMask( GL_FALSE );
+ enableAlpha(true);
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+ glDisable(GL_CULL_FACE);
+ glEnable( GL_TEXTURE_2D );
+
+// glPushMatrix();
+ // Get modelview matrix. We will only use the upper left 3x3 part of
+ // the matrix, which represents the rotation.
+ glGetFloatv( GL_MODELVIEW_MATRIX, mat );
+
+ // 1) & 2) We do it in one swift step:
+ // Although not obvious, the following six lines represent two matrix/
+ // vector multiplications. The matrix is the inverse 3x3 rotation
+ // matrix (i.e. the transpose of the same matrix), and the two vectors
+ // represent the lower left corner of the quad, PARTICLE_SIZE/2 *
+ // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0).
+ // The upper left/right corners of the quad is always the negative of
+ // the opposite corners (regardless of rotation).
+ float s2 = size / 2.0;
+ quad_lower_left.x = (-s2) * (mat[0] + mat[1]);
+ quad_lower_left.y = (-s2) * (mat[4] + mat[5]);
+ quad_lower_left.z = (-s2) * (mat[8] + mat[9]);
+ quad_lower_right.x = (s2) * (mat[0] - mat[1]);
+ quad_lower_right.y = (s2) * (mat[4] - mat[5]);
+ quad_lower_right.z = (s2) * (mat[8] - mat[9]);
+
+ // 3) Translate the quad to the correct position in modelview
+ // space and store its parameters in vertex arrays (we also
+ // store texture coord and color information for each vertex).
+// transform_colourv(v, col);
+ glBegin(GL_QUADS);
+ glColor4f(col.r, col.g, col.b, col.a);
+ // Lower left corner
+ glTexCoord2f(0.0, 0.0);
+ glVertex3f(x + quad_lower_left.x, y + quad_lower_left.y, z + quad_lower_left.z);
+// printf("1. %f %f %f\n",x + quad_lower_left.x, y + quad_lower_left.y, z + quad_lower_left.z);
+ // Lower right corner
+ glTexCoord2f(1.0, 0.0);
+ glVertex3f(x + quad_lower_right.x, y + quad_lower_right.y, z + quad_lower_right.z);
+// printf("2. %f %f %f\n",x + quad_lower_right.x, y + quad_lower_right.y, z + quad_lower_right.z);
+ // Upper right corner
+ glTexCoord2f(1.0, 1.0);
+ glVertex3f(x - quad_lower_left.x, y - quad_lower_left.y, z - quad_lower_left.z);
+// printf("3. %f %f %f\n", x - quad_lower_left.x, y - quad_lower_left.y, z - quad_lower_left.z);
+ // Upper left corner
+ glTexCoord2f(0.0, 1.0);
+ glVertex3f(x - quad_lower_right.x, y - quad_lower_right.y, z - quad_lower_right.z);
+// printf("4. %f %f %f\n", x - quad_lower_right.x, y - quad_lower_right.y, z - quad_lower_right.z);
+ glEnd();
+ // restores the modelview matrix
+// glPopMatrix();
+ /*********************************/
+ glPopAttrib();
+ }
+
+ return;
+}
+
+
+/* - fov
+ Specifies the field of view angle, in degrees, in the y direction.
+ - ratio
+ Specifies the aspect ratio that determines the field of view in the x direction.
+ The aspect ratio is the ratio of x (width) to y (height).
+ - zNear
+ Specifies the distance from the viewer to the near clipping plane (always positive).
+ - zFar
+ Specifies the distance from the viewer to the far clipping plane (always positive).
+*/
+void Graphics::setPerspective(float fov, float ratio, float zNear, float zFar)
+{
+ int matrixMode;
+
+ glGetIntegerv( GL_MATRIX_MODE, &matrixMode);
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluPerspective( fov, ratio, zNear, zFar );
+ glMatrixMode( matrixMode );
+ return;
+}
+
+
+void Graphics::renderVertexArray(vertex *array, unsigned int numOfPrimitives, int type)
+{
+ int t = type;
+ if(type == AM_TRIANGLE_STRIP)
+ t = GL_TRIANGLE_STRIP;
+ else if (type == AM_TRIANGLE_FAN)
+ t = GL_TRIANGLE_FAN;
+ else if (type == AM_TRIANGLES)
+ t = GL_TRIANGLES;
+ else if (type == AM_POINT_LIST)
+ t = GL_POINTS;
+ else if (type == AM_LINE_LIST)
+ t = GL_LINES;
+ else if (type == AM_LINE_STRIP)
+ t = GL_LINE_STRIP;
+
+ // UGLY hack to reverse texture coordinate...implement an operator in struct vertex..?!?
+ vertex *tmp = new vertex[numOfPrimitives];
+ memcpy(tmp, array, numOfPrimitives*sizeof(vertex));
+ int i;
+ for(i=0; i < numOfPrimitives; i++)
+ tmp[i].v = 1 - tmp[i].v;
+
+ glInterleavedArrays( GL_T2F_C4F_N3F_V3F, 0, (void *) tmp);
+ glDrawArrays( t, 0, numOfPrimitives);
+
+ delete tmp;
+ return;
+}
+
+
+void Graphics::setCullingMode(int mode)
+{
+ cmode = mode;
+ if(mode == AM_CULL_NONE)
+ {
+ culling = false;
+ glDisable(GL_CULL_FACE );
+ return;
+ }
+ else
+ {
+ if(!culling)
+ {
+ culling = true;
+ glEnable( GL_CULL_FACE );
+ }
+ if(mode == AM_CULL_FRONT)
+ glCullFace(GL_FRONT);
+ else if (mode == AM_CULL_BACK)
+ glCullFace(GL_BACK);
+ }
+ return;
+}
+
+int Graphics::getCullingMode()
+{
+ return cmode;
+}
+
+
+
+void Graphics::enter2dMode(void)
+{
+ glPushAttrib( GL_ALL_ATTRIB_BITS );
+
+ glDisable( GL_LIGHTING );
+ glDisable( GL_DEPTH_TEST );
+ glDisable( GL_CULL_FACE );
+ glEnable( GL_TEXTURE_2D );
+
+ glViewport( 0, 0, getWidth(), getHeight() );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix();
+ glLoadIdentity();
+
+ glOrtho( 0.0, ( GLdouble ) getWidth(), ( GLdouble ) getHeight(), 0.0, 0.0, 1.0 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glLoadIdentity();
+ // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+ return ;
+}
+
+
+void Graphics::leave2dMode(void)
+{
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
+
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix();
+
+ glPopAttrib();
+ return ;
+}
+
+
+void Graphics::enableDepthBuffer( bool b )
+{
+ zBuffer = b;
+ if(b)
+ glEnable( GL_DEPTH_TEST );
+ else
+ glDisable( GL_DEPTH_TEST );
+
+ return;
+}
+
+
+bool Graphics::isDepthBuffer()
+{
+ return zBuffer;
+}
+
+
+
+/*--------------------------------------------------
+* Texture
+*-----------------------------------------------------*/
+
+
+
+Texture::Texture( char *file, colour key, Graphics *g )
+{
+ gl_Tex = 0;
+ filteringDefinition = filtering = AM_LINEAR;
+ this->g = g;
+ glEnable( GL_TEXTURE_2D );
+ colourKey = key;
+ colourKeyEnabled = true;
+
+ // CreateTexture(&gl_Tex, file, 0);
+ LoadGLTextures( &gl_Tex, file );
+ std::cout << "file=" << file << ", gl_Tex=" << gl_Tex << "\n";
+
+ return ;
+}
+
+
+Texture::Texture( char *file, Graphics *g)
+{
+ gl_Tex = 0;
+ this->g = g;
+ filteringDefinition = filtering = AM_LINEAR;
+ glEnable( GL_TEXTURE_2D );
+ assert(g);
+ colourKeyEnabled = false;
+ // CreateTexture(&gl_Tex, file, 0);
+ LoadGLTextures( &gl_Tex, file );
+ std::cout << "file=" << file << ", gl_Tex=" << gl_Tex << "\n";
+
+ return ;
+}
+
+Texture::Texture(void *data, unsigned int w, unsigned int h, int format, int type, Graphics *g)
+{
+ gl_Tex = 0;
+ filteringDefinition = filtering = AM_LINEAR;
+ this->g = g;
+ assert(g);
+ colourKeyEnabled = false;
+
+ glEnable( GL_TEXTURE_2D );
+ glGenTextures(1, &gl_Tex);
+ glBindTexture( GL_TEXTURE_2D, gl_Tex );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ GLenum f = GL_RGBA, t = GL_UNSIGNED_BYTE;
+ int c = 4;
+
+ if(format == AM_ALPHA)
+ {
+ f = GL_ALPHA;
+ c = GL_ALPHA; /* Warning!!! Dont change this value cause font rendering depends on it!*/
+ }
+ else if (format == AM_RGBA)
+ {
+ f = GL_RGBA;
+ c = 4;
+ }
+
+ if(type == AM_UBYTE)
+ t = GL_UNSIGNED_BYTE;
+
+ //glTexImage2D( GL_TEXTURE_2D, 0, c, w, h, 0, f, t, data);
+ gluBuild2DMipmaps( GL_TEXTURE_2D, c, w, h, f, t, data);
+
+ this->width = w;
+ this->height = h;
+
+ std::cout << "gl_Tex=" << gl_Tex << "\n";
+
+ return ;
+}
+
+
+
+Texture::~Texture()
+{
+ return ;
+}
+
+
+/*
+unsigned int Texture::gl_getGLTex()
+{
+ return gl_Tex;
+}
+*/
+
+void Texture::texSubImage2D(int xoff, int yoff, unsigned int w, unsigned int h, int format, int type, const void *pixels)
+{
+ GLenum f = GL_RGBA, t = GL_UNSIGNED_BYTE;
+
+ if(format == AM_ALPHA)
+ f = GL_ALPHA;
+ else if (format == AM_RGBA)
+ f = GL_RGBA;
+
+ if(type == AM_UBYTE)
+ t = GL_UNSIGNED_BYTE;
+
+ glBindTexture(GL_TEXTURE_2D, this->gl_Tex);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, xoff, yoff, w, h, f, t, pixels);
+
+ //TODO kane popAttributes etsi wste na einai current texture auto pou htan prin...
+
+ return;
+}
+
+unsigned long Texture::getWidth()
+{
+ return width;
+}
+
+unsigned long Texture::getHeight()
+{
+ return height;
+}
+
+
+int Texture::getFiltering()
+{
+ return filteringDefinition;
+}
+
+
+/* this function needs some fixes and some rewrite */
+void Texture::setFiltering(int f, float anisotropyLevel)
+{
+ int _f = f;
+ if(f == AM_LINEAR)
+ _f = GL_LINEAR;
+ else if (f == AM_PLAIN)
+ _f = GL_NEAREST;
+
+ filteringDefinition = filtering = f;
+ if(_f == AM_ANISOTROPIC)
+ {
+ if(supportsAnisotropic)
+ {
+ float a = anisotropyLevel;
+ if( a > maxAnisotropySupported) //fix this for round-off errors
+ a = maxAnisotropySupported;
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, a);
+ }
+ filtering = GL_LINEAR;
+ }
+ // 'filtering' cannot have here a value of AM_ANISOTROPIC
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering );
+
+ return;
+}
+
+
+void Texture::LoadGLTextures( GLuint *gl_Tex, const char * filename )
+{
+ /*gl_Tex = ilutGLLoadImage( (char *) filename);
+ glBindTexture( GL_TEXTURE_2D, *gl_Tex );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+*/
+
+ // Generate the main image name to use.
+ ilGenImages (1, gl_Tex);
+ ilBindImage (*gl_Tex);
+ ilEnable(IL_ORIGIN_SET);
+ ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
+ if (!ilLoadImage ((char *)filename))
+ printf("cannot load image %s \n", filename);
+
+ ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
+
+ ILinfo imageInfo;
+ iluGetImageInfo(&imageInfo);
+ ILubyte *data = ilGetData();
+ printf("image info. %d x %d depth=%d Bp=%d data=%d\n", imageInfo.Width, imageInfo.Height, imageInfo.Depth, imageInfo.Bpp,
+ imageInfo.SizeOfData);
+ bool a = false;
+ if ( colourKeyEnabled )
+ {
+ //ksepaketaroume to colourkey
+ unsigned char ckR = 0, ckG = 0, ckB = 0, ckA = 255;
+ unsigned long mR, mG, mB, mA;
+ mB = 0x000000FF;
+ mG = 0x0000FF00;
+ mR = 0x00FF0000;
+ mA = 0xFF000000;
+ ckR = (unsigned char) (colourKey.r * 255.0) ;
+ ckG = (unsigned char) (colourKey.g * 255.0) ;
+ ckB = (unsigned char) (colourKey.b * 255.0) ;
+ ckA = (unsigned char) (colourKey.a * 255.0) ;
+ unsigned char _r, _g, _b;
+ assert(g);
+ a = g->isAlpha();
+ g->enableAlpha(true);
+ int step = imageInfo.Bpp;
+ for(unsigned long i=0; i < imageInfo.SizeOfData; i+=step)
+ {
+ _r = data[i];
+ _g = data[i + 1];
+ _b= data[i + 2];
+
+ if ( _r == ckR && _g == ckG && _b == ckB )
+ data[i + 3] = 0;
+ }
+ }
+
+ glBindTexture( GL_TEXTURE_2D, *gl_Tex );
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering );
+
+// glTexImage2D( GL_TEXTURE_2D, 0, 4, imageInfo.Width, imageInfo.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, 4, imageInfo.Width, imageInfo.Height,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+
+ width = imageInfo.Width;
+ height = imageInfo.Height;
+ if ( colourKeyEnabled )
+ g->enableAlpha(a);
+
+ return ;
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _Graphics
+#define _Graphics
+
+
+#define GL_GLEXT_PROTOTYPES 1
+
+#ifdef _WIN32 // an eimaste se Windows
+ #include <windows.h>
+ #define _USE_MATH_DEFINES
+#endif
+
+/* #define GLX_GLXEXT_PROTOTYPES
+ #include <GL/glx.h>
+ #include <GL/glxext.h> */
+
+
+extern char **argv;
+extern int argc;
+
+/********
+group: Types
+*/
+
+
+
+
+struct colour
+{
+ float r;
+ float g;
+ float b;
+ float a;
+};
+
+/*struct: particle */
+struct particle
+{
+ float x;
+ float y;
+ float z;
+ float size;
+ colour col;
+};
+
+
+
+
+/*struct: vertex
+This struct represents a 3D vertex
+
+see also:
+<COLOUR_RGBA>, <Graphics::renderVertexArray>, <Graphics::renderTriangle>*/
+struct vertex
+{
+/* field: u,v
+ texture coordinates*/
+ float u,v;
+/* field: col
+ the vertex colour*/
+ colour col;
+/* field: nx,ny,nz
+ direction of the normal vector for the vertex */
+ float nx,ny,nz;
+/*fields: x,y,z
+ 3D coordinates for the vertex*/
+ float x,y,z;
+
+};
+
+
+struct camera
+{
+ float camx, camy, camz;
+ float lookx, looky, lookz;
+ float upx, upy, upz;
+};
+
+
+/*struct: light
+3D light type
+
+see also:
+<Graphics::setLight>, <Graphics::showLight>, <COLOUR_RGBA>*/
+struct light
+{
+ /*field: type
+ the type of light. _type_ can be one of
+
+ + *AM_POINT_LIGHT* specifies a point light. This type of light has a position within the scene but no single direction.
+ They emit their light in all directions. Think of a light-bulb in your house ;)
+ + *AM_DIRECTIONAL_LIGHT* specifies a directional light. This type of light has a direction but not position.
+ Think the sun here.
+ + *AM_SPOT_LIGHT* specifies a spot light. *NOTE* currently, spot light is partially implemented. */
+ int type;
+/*field: diffuse
+ the diffuse RGBA intensity of the light */
+ colour diffuse;
+/*field: specular
+ the specular RGBA intensity of the light*/
+ colour specular;
+/*field:ambient
+ the ambient RGBA intensity of the light*/
+ colour ambient;
+/*fields: posx,posy,posz
+ the position of the point light. *Only* for point lights*/
+ float posx,posy,posz;
+
+/*fields: dirx,diry,dirz
+ the direction of the directional light. *Only* for directional lights */
+ float dirx,diry,dirz;
+/*field: range
+ only for spot lights*/
+ float range;
+/*fields: falloff,theta,phi
+ only for spot lights*/
+ float falloff,theta,phi;
+};
+
+
+#define AM_POINT_LIGHT 1
+#define AM_DIRECTIONAL_LIGHT 2
+#define AM_SPOT_LIGHT 3
+
+#define AM_SOFTWARE_PARTICLE 4
+#define AM_HARDWARE_PARTICLE 5
+
+#define AM_CULL_FRONT 6
+#define AM_CULL_BACK 7
+#define AM_CULL_NONE 8
+
+#define AM_PLAIN 9
+#define AM_LINEAR 10
+#define AM_ANISOTROPIC 11
+
+#define AM_TRIANGLE_STRIP 12
+#define AM_TRIANGLE_FAN 13
+#define AM_TRIANGLES 14
+#define AM_POINT_LIST 15
+#define AM_LINE_LIST 16
+#define AM_LINE_STRIP 17
+
+#define AM_ALPHA 18
+#define AM_RGBA 19
+
+#define AM_UBYTE 20
+
+#define AM_XYZ 21
+#define AM_XZY 22
+#define AM_ZXY 23
+#define AM_ZYX 24
+#define AM_YZX 25
+#define AM_YXZ 26
+
+
+
+/*
+group: Macros
+*/
+
+/*function: COLOUR_RGBA
+
+parameters:
+ r,g,b,a - the Red, Green, Blue and Alpha colour components */
+extern colour COLOUR_RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a );
+
+
+
+
+/*
+group: Classes
+*/
+
+class Graphics;
+class FontImp;
+
+class Font
+{
+public:
+ Font();
+ ~Font();
+
+ Font(const char *name, int size, Graphics *g);
+
+ void print( const wchar_t *str, int x1, int y1, int x2, int y2, colour c );
+ void print( char *str, int x1, int y1, int x2, int y2, colour c );
+
+private:
+ FontImp *imp;
+ /* FTGLTextureFont *font;
+ int fontSize;
+ Graphics *g;*/
+};
+
+
+class Texture;
+class GraphicsImp;
+
+
+/* class: Graphics
+ This class is the core class of the Amaltheia library. It handles the display and
+ via its methods you can render 2D and 3D primitives.
+*/
+class Graphics
+{
+
+public:
+
+/* group: Constructors*/
+ /* constructor: Graphics
+
+parameters:
+ width - the desired width of the display's resolution
+ height - the desired height of the display's resolution
+ fullScreen - if *true* run in full screen, otherwise in a window
+ bpp - the desired Bits Per Pixel for the display
+ alpha - enables/disables alpha blending
+ lighting - enables/disables lighting
+
+see also:
+ <createDisplay> */
+ Graphics( int width = 1024, int height = 768, int bpp = 16, bool fullScreen = false,
+ bool alpha = false, bool lighting = false );
+ ~Graphics();
+
+
+/* group: Methods */
+
+ /* Method: setWidth
+ Sets the width of the display
+
+ parameters:
+ w - the desired width
+
+ see also:
+ <getWidth>*/
+ void setWidth( int w = 1024 );
+
+/* Method: getWidth
+ Returns the width of the display
+
+ returns:
+ the current display's width in pixels
+
+ see also:
+ <setWidth>*/
+ int getWidth();
+
+/* Method: setHeight
+ Sets the height of the display
+
+parameters:
+ h - the desired height
+
+see also:
+ <getHeight>*/
+ void setHeight( int h = 768 );
+
+/* Method: getHeight
+ Returns the height of the display
+
+returns:
+ the height of the display in pixels
+
+see also:
+ <setHeight>*/
+ int getHeight();
+
+ /*method: setBpp
+ Sets the Bits per Pixel for the display
+
+ parameters:
+ bpp - bits per pixel
+
+ see also:
+ <getBpp> */
+ void setBpp( int bpp = 16);
+
+ /*method: getBpp
+ Returns the current BPP of the display
+
+ returns:
+ bits per pixel
+
+ see also:
+ <setBpp>*/
+ int getBpp();
+
+ void enableVsync( bool b);
+ bool isVsync();
+
+
+ void enableFullScreen( bool b);
+ bool isFullScreen();
+
+ /*method: enableLighting
+ Enables/disables lighting in the scene
+
+ parameters:
+ *true* to enable lighting or *false* to disable it
+
+ see also:
+ <isLighting> */
+ void enableLighting( bool );
+
+ /*method: isLighting
+ Is lighting enabled?
+
+ returns:
+ *true* if lighting is enabled, *false* otherwise
+
+see also:
+ <enableLighting>*/
+ bool isLighting();
+
+ /*method: enableDepthBuffer
+ Enables/disables the depth (Z) buffer
+
+ parameters:
+ *true* to enable the Z-buffer, *false* to disable it
+
+ see also:
+ <isDepthBuffer> */
+ void enableDepthBuffer( bool );
+
+ /*method: isDepthBuffer
+ Is the depth buffer enabled?
+
+ returns:
+ *true* if the depth buffer is enabled, *false* otherwise
+
+ see also:
+ <enableDepthBuffer> */
+ bool isDepthBuffer();
+
+ /*method: enableAlpha
+ Enables/disables alpha blending
+
+ parameters:
+ *true* to enable alpha blending, *false* to disable it
+
+ see also:
+ <isAlpha> */
+ void enableAlpha( bool );
+
+ /*method: isAlpha
+ Is alpha blending enabled?
+
+ returns:
+ *true* is alpha blending is enabled, *false* otherwise
+
+ see also:
+ <enableAlpha> */
+ bool isAlpha();
+
+
+ void enableCursor( bool );
+ bool isCursor();
+
+
+ /* method: createDisplay
+ Creates the display. You should call this method *once*.
+
+ see also:
+ <Graphics>*/
+ int createDisplay();
+
+ /*method: beginScene
+ You must call this method before starting drawing/rendering primitives to the display.
+ This method does some initializations e.g clears the color and depth buffers, etc...
+
+ see also:
+ <endScene>*/
+ void beginScene();
+
+ /*method: endScene
+ You must call this method after you have finished rendering the current frame and you want
+ to be visible on the screen. <beginScene> and <endScene> methods must be pair, so you must
+ call <beginScene> once, before calling <endScene>.
+
+ see also:
+ <beginScene>*/
+ void endScene();
+
+
+
+ /*method: setWorld
+ Sets the world tranformations matrices (translation, rotation, scale)
+
+ parameters:
+ transx - number of units to translate in the X axis
+ transy - number of units to translate in the Y axis
+ transz - number of units to translate in the Z axis
+ rotx - degrees to rotate in the X axis
+ roty - degrees to rotate in the Y axis
+ rotz - degrees to rotate in the Z axis
+ scalex - scale factor in the X axis (a factor of 1.0 performs no scale)
+ scaley - scale factor in the Y axis
+ scalez - scale factor in the Z axis */
+ int setWorld( float transx, float transy, float transz,
+ float rotx, float roty, float rotz,
+ float scalex, float scaley, float scalez, int rotationOrder = AM_XYZ);
+
+
+ /*
+ int setWorld2( float transx, float transy, float transz,
+ float rotx, float roty, float rotz,
+ float scalex, float scaley, float scalez );
+
+ */
+
+
+ /*method: setCamera
+ Specifies the position and the direction of the camera.
+
+ parameters:
+ camx - the x coordinate of the camera position
+ camy - the y coordinate of the camera position
+ camz - the z coordinate of the camera position
+ lookx - the x coordinate of the reference point
+ looky - the y coordinate of the reference point
+ lookz - the z coordinate of the reference point
+ upx - the x coordinate of the up vector
+ upy - the y coordinate of the up vector
+ upz - the z coordinate of the up vector
+
+ see also:
+ <getCamera> */
+ int setCamera( float camx, float camy, float camz,
+ float lookx, float looky, float lookz,
+ float upx, float upy, float upz );
+
+/*method: getCamera
+ Returns a <camera> struct containing the position and the direction of the camera
+
+ returns:
+ a <camera> struct
+
+ see also:
+ <setCamera>*/
+ struct camera getCamera();
+
+
+ /*method: setBackground
+ Sets the background colour of the display.
+
+ parameters:
+ c - the colour to set. Use the COLOUR_RGBA() macro to specify it
+
+ see also:
+ <getBackground>*/
+ void setBackground( colour c );
+
+ /* method: getBackground
+
+ returns:
+ the colour of the display background
+
+ see also:
+ <setBackground> */
+ colour getBackground();
+
+ /* method: setTexture
+ Sets which will be the current texture to use.
+
+ parameters:
+ tex - a pointer to a <Texture> object
+
+ see also:
+ <getTexture>, <Texture> class*/
+ void setTexture( Texture *tex );
+
+ /*method: getTexture
+
+ returns:
+ a pointer to the current <Texture> object
+
+ see also:
+ <setTexture>, <Texture> class */
+ Texture* getTexture();
+
+ /*method: setCullingMode
+ Specifies the culling mode to use, whether front or back facets will be culled.
+ The orientation of front-facing polygons is clock-wise.
+
+ parameters:
+ mode - the desired culling mode
+
+ valid values for _mode_ are
+
+ + *AM_CULL_BACK* for culling back facets
+ + *AM_CULL_FRONT* for culling front facets
+ + *AM_CULL_NONE* for culling none of the facets
+
+ see also:
+ <getCullingMode> */
+ void setCullingMode(int mode);
+
+ /*method: getCullingMode
+
+ returns:
+ The current culling mode
+
+ see also:
+ <setCullingMode> */
+ int getCullingMode();
+
+
+ /*method: renderTriangle
+ Renders a triangle in the display
+
+ parameters:
+ v1, v2, v3 - the 3 vertices that specify the triangle
+
+ see also:
+ <vertex> struct, <renderVertexArray> */
+ int renderTriangle(vertex v1, vertex v2, vertex v3 );
+
+ /*method: renderVertexArray
+ Renders a mesh of vertices
+
+ parameters:
+ array - an array containing the vertices
+ numOfVertices - the number of vertices in the array
+ type - how to connect the vertices
+
+
+ valid values for _type_ are
+
+ + *AM_TRIANGLE_STRIP* renders a connected group of triangles. One triangle is defined for each vertex
+ presented after the first two vertices. For odd i, vertices i, i+1, and i+2 define triangle i.
+ For even i, vertices i+1, i, and i+2 define triangle i. 'numOfVertices-2' triangles are rendered
+ + *AM_TRIANGLE_FAN* renders a connected group of triangles. One triangle is defined for each vertex
+ presented after the first two vertices. Vertices 1, i+1, and i+2 define triangle i. 'numOfVertices/-2' triangles are rendered
+ + *AM_TRIANGLES* renders each triplet of vertices as an independent triangle.
+ Vertices 3i-2, 3i-1, and 3i define triangle i. 'numOfVertices/3' triangles are rendered
+ + *AM_POINT_LIST* renders each vertex as a single point. Vertex i defines point i. 'numOfVertices' points are rendered
+ + *AM_LINE_LIST* renders each pair of vertices as an independent line segment.
+ Vertices 2i-1 and 2i define line i. 'numOfVertices/2' lines are rendered
+ + *AM_LINE_STRIP* renders a connected group of line segments from the first vertex to the last. Vertices i and i+1 define line i. 'numOfVertices - 1' lines are rendered
+
+see also:
+ <renderTriangle>, <vertex> struct */
+ void renderVertexArray(vertex *array, unsigned int numOfVertices, int type);
+
+
+
+
+ /*method: setLight
+ Creates a new light numbered 'numLight' with the properties defined in 'lt'
+
+ parameters:
+ numLight - Specifies a light number. The number of lights depends on the underlying implementation,
+ but at least eight lights are supported. They are identified by integers 0 .. maximum lights
+
+ lt - a struct <light> variable which defines the properties of the 'numLight' light
+
+see also:
+ struct <light>, <showLight>*/
+ void setLight( int numLight, const light& lt );
+
+ /*method: showLight
+ Enables/disables light 'numLight'. Light 'numLight' must first have been created with the <setLight> method.
+
+ parameters:
+ numLight - the number of the light to enable/disable
+
+ state - *true* to enable the light, *false* otherwise
+
+ see also:
+ struct <light>, <setLight>*/
+ void showLight( int numLight, bool state );
+
+ /*method: renderParticle
+ Renders a particle in the display
+
+ parameters:
+ x - the x coordinate of the particle position
+
+ y - the y coordinate of the particle position
+
+ z - the z coordinate of the particle position
+
+ size - size of the particle
+
+ col - colour of the particle
+
+ type - can be *AM_SOFTWARE_PARTICLE* or *AM_HARDWARE_PARTICLE*
+
+ see also:
+ <renderParticleArray>*/
+ void renderParticle(float x, float y, float z, float size, colour col, int type);
+
+ /*method: renderParticleArray
+ Useful for rendering lots of particles
+
+ parameters:
+ array - the array of particles
+
+ sizeOfArray - guess what...
+
+ type - can be *AM_SOFTWARE_PARTICLE* or *AM_HARDWARE_PARTICLE*
+
+ see also:
+ <renderParticle>*/
+ void renderParticleArray(particle *array, unsigned int sizeOfArray, int type);
+ void setPerspective(float fov, float ratio, float zNear, float zFar);
+
+ /*method: project*/
+ void project( float objx, float objy, float objz,
+ float *winx, float *winy, float *winz );
+
+ /*method: unproject*/
+ void unproject( float winx, float winy, float winz,
+ float *objx, float *objy, float *objz );
+
+ /*method: planeIntersect*/
+ void planeIntersect( float a, float b, float c, float d,
+ float p1x, float p1y, float p1z, float p2x, float p2y, float p2z,
+ float *poutx, float *pouty, float *poutz );
+
+ /*method: enter2dMode*/
+ void enter2dMode();
+ /*method: leave2dMode*/
+ void leave2dMode();
+
+private:
+ static bool oneGraphics; //gia na dhmiourgeitai mono ena antikeimeno Graphics
+ int width;
+ int height;
+ int bpp;
+ bool fullScreen;
+ bool vSync;
+ bool lighting;
+ bool alpha;
+ bool culling;
+ int cmode;
+ bool zBuffer;
+ bool cursorState;
+ Texture *currentTexture;
+ struct camera cam;
+ bool sceneBegin; //flag gia to an egine sceneBegin
+ float bgcolour[ 4 ];
+ unsigned int gpuBuf;
+ int parameter;
+ float maxSize; //point size gia particles me point pixel
+ void drawBillboardParticle(float x, float y, float z, float size, colour col);
+ GraphicsImp *imp;
+ //SDL_Surface *screen;
+
+};
+
+
+
+class Sprite;
+
+/*class: Texture
+A class for representing 2d textures
+
+see also:
+<Graphics>*/
+
+class Texture
+{
+ friend class Sprite;
+private:
+ colour colourKey;
+ int filtering, filteringDefinition;
+ bool colourKeyEnabled;
+ unsigned long width;
+ unsigned long height;
+ // GLuint gl_Tex;
+ Graphics *g;
+ //void swap( unsigned char &a, unsigned char &b );
+// void CreateTexture( unsigned int textureArray[], char *strFileName, int textureID );
+// int ImageLoad( const char *filename, Image *image );
+ void LoadGLTextures( unsigned int *gl_Tex, const char * filename );
+
+ friend void Graphics::setTexture( Texture *tex );
+
+public:
+
+ unsigned int gl_Tex;
+
+/* group: Constructors*/
+
+
+ /* constructor: Texture
+ Creates a texture from an image file
+
+ parameters:
+ file - the filename of the image to use as a texture. Accepted formats are PNG, TGA, BMP, JPG, DDS.
+ g - a pointer to a Graphics object*/
+ Texture( char *file, Graphics *g);
+ /* constructor: Texture
+ Creates a texture from an image file
+
+ parameters:
+ file - the filename of the image to use as a texture. Accepted formats are PNG, TGA, BMP, JPG.
+ key - the colour key to use
+ g - a pointer to a Graphics object*/
+ Texture( char *file, colour key, Graphics *g);
+ /* constructor: Texture
+ Creates a texture from memory
+
+ parameters:
+ data - a pointer to the textures data
+ w - the width of the texture
+ h - the height of the texture
+ format - the format of the pixels in _data_. Accepted values are AM_RGBA, AM_ALPHA
+ type - currently the one supported type is AM_BYTE
+ g - a pointer to a Graphics object*/
+ Texture(void *data, unsigned int w, unsigned int h, int format, int type, Graphics *g);
+ ~Texture();
+
+/*group: Methods */
+ void texSubImage2D(int xoff, int yoff, unsigned int w, unsigned int h, int format, int type, const void *pixels);
+ void setFiltering(int f, float anisotropyLevel = 1.0);
+ int getFiltering();
+ /*method: getWidth
+ returns:
+ the texture width */
+ unsigned long getWidth();
+ /*method: getHeight
+ returns:
+ the texture height*/
+ unsigned long getHeight();
+ //unsigned int gl_getGLTex();
+};
+
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "Input.h"
+#include <SDL/SDL.h>
+#include <ctype.h>
+
+
+const int LEFT_BUTTON = SDL_BUTTON_LEFT;
+const int MIDDLE_BUTTON = SDL_BUTTON_MIDDLE;
+const int RIGHT_BUTTON = SDL_BUTTON_RIGHT;
+
+const int KEY_ESC = SDLK_ESCAPE;
+const int KEY_ESCAPE = SDLK_ESCAPE;
+
+const int KEY_MINUS = SDLK_MINUS;
+const int KEY_EQUALS = SDLK_EQUALS;
+
+const int KEY_BACKSPACE = SDLK_BACKSPACE;
+
+const int KEY_TAB = SDLK_TAB;
+
+const int KEY_LBRACKET = SDLK_LEFTBRACKET;
+const int KEY_RBRACKET = SDLK_RIGHTBRACKET;
+
+const int KEY_ENTER = SDLK_RETURN;
+const int KEY_RETURN = SDLK_RETURN;
+
+const int KEY_CTRL = SDLK_LCTRL;
+const int KEY_LCTRL = SDLK_LCTRL;
+const int KEY_RCTRL = SDLK_RCTRL;
+
+const int KEY_SHIFT = SDLK_LSHIFT;
+const int KEY_LSHIFT = SDLK_LSHIFT;
+const int KEY_RSHIFT = SDLK_RSHIFT;
+
+const int KEY_ALT = SDLK_LSUPER;
+const int KEY_LALT = SDLK_LSUPER;
+const int KEY_RALT = SDLK_RSUPER;
+
+const int KEY_0 = SDLK_0;
+const int KEY_1 = SDLK_1;
+const int KEY_2 = SDLK_2;
+const int KEY_3 = SDLK_3;
+const int KEY_4 = SDLK_4;
+const int KEY_5 = SDLK_5;
+const int KEY_6 = SDLK_6;
+const int KEY_7 = SDLK_7;
+const int KEY_8 = SDLK_8;
+const int KEY_9 = SDLK_9;
+
+const int KEY_A = SDLK_a;
+const int KEY_B = SDLK_b;
+const int KEY_C = SDLK_c;
+const int KEY_D = SDLK_d;
+const int KEY_E = SDLK_e;
+const int KEY_F = SDLK_f;
+const int KEY_G = SDLK_g;
+const int KEY_H = SDLK_h;
+const int KEY_I = SDLK_i;
+const int KEY_J = SDLK_j;
+const int KEY_K = SDLK_k;
+const int KEY_L = SDLK_l;
+const int KEY_M = SDLK_m;
+const int KEY_N = SDLK_n;
+const int KEY_O = SDLK_o;
+const int KEY_P = SDLK_p;
+const int KEY_Q = SDLK_q;
+const int KEY_R = SDLK_r;
+const int KEY_S = SDLK_s;
+const int KEY_T = SDLK_t;
+const int KEY_U = SDLK_u;
+const int KEY_V = SDLK_v;
+const int KEY_W = SDLK_w;
+const int KEY_X = SDLK_x;
+const int KEY_Y = SDLK_y;
+const int KEY_Z = SDLK_z;
+
+const int KEY_SEMICOLON = SDLK_SEMICOLON;
+const int KEY_APOSTROPHE = SDLK_QUOTE;
+
+const int KEY_TILDE = SDLK_UNKNOWN;
+const int KEY_GRAVE = SDLK_BACKQUOTE;
+
+const int KEY_BACKSLASH = SDLK_BACKSLASH;
+
+const int KEY_COMMA = SDLK_COMMA;
+const int KEY_PERIOD = SDLK_PERIOD;
+const int KEY_FORWARDSLASH = SDLK_SLASH;
+const int KEY_SLASH = SDLK_SLASH;
+
+const int KEY_SPACE = SDLK_SPACE;
+
+const int KEY_CAPSLOCK = SDLK_CAPSLOCK;
+const int KEY_CAPITAL = SDLK_CAPSLOCK;
+
+const int KEY_F1 = SDLK_F1;
+const int KEY_F2 = SDLK_F2;
+const int KEY_F3 = SDLK_F3;
+const int KEY_F4 = SDLK_F4;
+const int KEY_F5 = SDLK_F5;
+const int KEY_F6 = SDLK_F6;
+const int KEY_F7 = SDLK_F7;
+const int KEY_F8 = SDLK_F8;
+const int KEY_F9 = SDLK_F9;
+const int KEY_F10 = SDLK_F10;
+const int KEY_F11 = SDLK_F11;
+const int KEY_F12 = SDLK_F12;
+
+const int KEY_SYSRQ = SDLK_SYSREQ;
+const int KEY_SCROLLLOCK = SDLK_SCROLLOCK;
+const int KEY_PAUSE = SDLK_PAUSE;
+
+const int KEY_NUMLOCK = SDLK_NUMLOCK;
+const int KEY_NUMPAD0 = SDLK_KP0;
+const int KEY_NUMPAD1 = SDLK_KP1;
+const int KEY_NUMPAD2 = SDLK_KP2;
+const int KEY_NUMPAD3 = SDLK_KP3;
+const int KEY_NUMPAD4 = SDLK_KP4;
+const int KEY_NUMPAD5 = SDLK_KP5;
+const int KEY_NUMPAD6 = SDLK_KP6;
+const int KEY_NUMPAD7 = SDLK_KP7;
+const int KEY_NUMPAD8 = SDLK_KP8;
+const int KEY_NUMPAD9 = SDLK_KP9;
+const int KEY_ADD = SDLK_PLUS;
+const int KEY_SUBTRACT = SDLK_MINUS;
+const int KEY_DIVIDE = SDLK_SLASH;
+const int KEY_MULTIPLY = SDLK_ASTERISK;
+const int KEY_DECIMAL = SDLK_PERIOD;
+const int KEY_NUMPADENTER = SDLK_UNKNOWN;
+
+const int KEY_INSERT = SDLK_INSERT;
+const int KEY_DELETE = SDLK_DELETE;
+const int KEY_HOME = SDLK_HOME;
+const int KEY_END = SDLK_END;
+const int KEY_PAGEUP = SDLK_PAGEUP;
+const int KEY_PAGEDOWN = SDLK_PAGEDOWN;
+
+const int KEY_UP = SDLK_UP;
+const int KEY_DOWN = SDLK_DOWN;
+const int KEY_LEFT = SDLK_LEFT;
+const int KEY_RIGHT = SDLK_RIGHT;
+
+const int KEY_LWIN = SDLK_LSUPER;
+const int KEY_RWIN = SDLK_RSUPER;
+const int KEY_APPS = SDLK_MENU;
+
+
+
+
+
+Input::Input(bool keyb,bool mous)
+{
+ int i;
+ lockBuffer = 0;
+
+ for (i=0;i<4;i++)
+ mouseLockBuffer[i]=-1;
+
+ symbol[0] = ')';
+ symbol[1] = '!';
+ symbol[2] = '@';
+ symbol[3] = '#';
+ symbol[4] = '$';
+ symbol[5] = '%';
+ symbol[6] = '^';
+ symbol[7] = '&';
+ symbol[8] = '*';
+ symbol[9] = '(';
+
+ keyLockDuration = D;
+ return ;
+}
+
+Input::~Input()
+{
+ return ;
+}
+
+
+
+bool Input::keyboardGetKeyState(int key)
+{
+
+ static long tm = getTime();
+ bool retValue = false;
+
+ tm = getTime();
+ SDL_PumpEvents();
+ SDLMod mod = SDL_GetModState();
+
+ if(key == KEY_CTRL && (mod & KMOD_CTRL))
+ retValue = true;
+ else
+ if(key == KEY_LCTRL && (mod & KMOD_LCTRL))
+ retValue = true;
+ else
+ if(key == KEY_RCTRL && (mod & KMOD_RCTRL))
+ retValue = true;
+ else
+ if(key == KEY_SHIFT && (mod & KMOD_SHIFT))
+ retValue = true;
+ else
+ if(key == KEY_LSHIFT && (mod & KMOD_LSHIFT))
+ retValue = true;
+ else
+ if(key == KEY_RSHIFT && (mod & KMOD_RSHIFT))
+ retValue = true;
+ else
+ if(key == KEY_ALT && (mod & KMOD_ALT))
+ retValue = true;
+ else
+ if(key == KEY_LALT && (mod & KMOD_LALT))
+ retValue = true;
+ else
+ if(key == KEY_RALT && (mod & KMOD_RALT))
+ retValue = true;
+ else
+ if((key == KEY_CAPSLOCK || key == KEY_CAPITAL ) && (mod & KMOD_CAPS))
+ retValue = true;
+ else
+ if(key == KEY_NUMLOCK && (mod & KMOD_NUM))
+ retValue = true;
+ else
+ {
+ Uint8 *keystate = SDL_GetKeyState(NULL);
+ if( keystate[key])
+ {
+ retValue = true;
+ key_val = 0;
+ }
+ }
+
+
+ return retValue;
+}
+
+
+/*
+bool Input::keyboardGetKeyState(int key)
+{
+ bool retValue = false;
+
+ if (getTime() - lockBuffer[key] > keyLockDuration)
+ lockBuffer[key]=-1;
+
+// printf("key = %d\n", key);
+ if(lockBuffer[key]==-1)
+{
+ if(key_press && key_val == key)
+ retValue = true;
+}
+
+ return retValue;
+}
+*/
+
+
+void Input::mousePrepare()
+{
+ SDL_PumpEvents();
+ SDL_GetRelativeMouseState(&mx, &my);
+ return;
+}
+
+long Input::mouseGetYDelta(void)
+{
+ return my;
+}
+
+
+long Input::mouseGetXDelta(void)
+{
+ return mx;
+}
+
+
+bool Input::mouseGetButtonState(int button)
+{
+ bool retValue = false;
+
+ if (getTime()-mouseLockBuffer[button]>buttonLockDuration)
+ mouseLockBuffer[button]=-1;
+
+ /*
+ while(SDL_PollEvent(&event))
+ {
+ if(event.type == SDL_MOUSEBUTTONDOWN)
+ {
+ if((&event.button)->button == button)
+ retValue = true;
+ else
+ {
+ if(SDL_PushEvent(&event) == -1)
+ std::cerr << "push event failed\n";
+ retValue = false;
+ }
+ break;
+ }
+ else
+ if(event.type == SDL_MOUSEBUTTONUP)
+ continue;
+ else
+ if(event.type == SDL_KEYDOWN || event.type == SDL_MOUSEMOTION)
+ {
+ if(SDL_PushEvent(&event) == -1)
+ std::cerr << "push event failed\n";
+ break;
+ }
+ else
+ break;
+
+ } // while
+ */
+ if (mouseLockBuffer[button]==-1)
+ {
+ SDL_PumpEvents();
+ if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(button))
+ retValue = true;
+ }
+
+ return retValue;
+}
+
+
+void Input::lockKey(int key, int duration)
+{
+ if (key<0 || key>255)
+ return ;
+ keyLockDuration=duration;
+ return ;
+}
+
+void Input::lockButton(int button, int duration)
+{
+ if (button<0 || button>3)
+ return ;
+
+ //if (mouseLockBuffer[button]!=-1) return ;
+
+ mouseLockBuffer[button]=(int)(getTime());
+
+ buttonLockDuration=duration;
+
+ return ;
+}
+
+
+char Input::getChar(void)
+{
+
+ static int oldKey = 0;
+ static long delay = getTime();
+ static long repeat = getTime();
+
+
+ if(key_val == oldKey)
+ {
+ repeat = getTime();
+ if(getTime() - delay < D)
+ return 0;
+ else
+ delay = getTime();
+ }
+ else
+ {
+ delay = getTime();
+ if(getTime() - repeat < R)
+ return 0;
+ else
+ repeat = getTime();
+ }
+
+ oldKey = key_val;
+
+ if(key_press)
+ {
+ if(key_val == 13)
+ return '\n';
+ else
+ {
+ SDL_PumpEvents();
+ SDLMod mod = SDL_GetModState();
+
+ if((mod & KMOD_CAPS) && !(mod & KMOD_SHIFT))
+ key_val = toupper(key_val);
+
+ if((mod & KMOD_SHIFT))
+ {
+ if(isdigit(key_val))
+ return symbol[key_val - 48];
+ if(key_val == '\'')
+ return '\"';
+ if(key_val == ';')
+ return ':';
+ if(key_val == ',')
+ return '<';
+ if(key_val == '.')
+ return '>';
+ if(key_val == '[')
+ return '{';
+ if(key_val == ']')
+ return '}';
+ if(key_val == '-')
+ return '_';
+ if(key_val == '=')
+ return '+';
+ if(key_val == '\\')
+ return '|';
+ if(key_val == '/')
+ return '?';
+
+ if(!(mod & KMOD_CAPS))
+ return toupper(key_val);
+ }
+ return key_val;
+ }
+ }
+
+ return 0;
+ /*
+ for (i=0;i<256;i++)
+ if(keyboardGetKeyState(i))
+ {
+ lockKey(i, 300);
+
+ if(i ==13)
+ return '\n';
+
+ return i;
+ }
+ */
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place* Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _INPUT
+#define _INPUT
+
+#include "System.h"
+/*group: KEY codes
+
++ *LEFT_BUTTON* the left mouse button
++ *MIDDLE_BUTTON* the middle mouse button
++ *RIGHT_BUTTON* the right mouse button
+
++ *KEY_ESC* the escape key
++ *KEY_ESCAPE*
+
++ *KEY_MINUS*
++ *KEY_EQUALS*
++ *KEY_BACKSPACE*
++ *KEY_TAB*
+
++ *KEY_LBRACKET*
++ *KEY_RBRACKET*
+
++ *KEY_ENTER*
++ *KEY_RETURN*
+
++ *KEY_CTRL*
++ *KEY_LCTRL*
++ *KEY_RCTRL*
+
++ *KEY_SHIFT*
++ *KEY_LSHIFT*
++ *KEY_RSHIFT*
+
++ *KEY_ALT*
++ *KEY_LALT*
++ *KEY_RALT*
+
++ *KEY_0*
++ *KEY_1*
++ *KEY_2*
++ *KEY_3*
++ *KEY_4*
++ *KEY_5*
++ *KEY_6*
++ *KEY_7*
++ *KEY_8*
++ *KEY_9*
+
++ *KEY_A*
++ *KEY_B*
++ *KEY_C*
++ *KEY_D*
++ *KEY_E*
++ *KEY_F*
++ *KEY_G*
++ *KEY_H*
++ *KEY_I*
++ *KEY_J*
++ *KEY_K*
++ *KEY_L*
++ *KEY_M*
++ *KEY_N*
++ *KEY_O*
++ *KEY_P*
++ *KEY_Q*
++ *KEY_R*
++ *KEY_S*
++ *KEY_T*
++ *KEY_U*
++ *KEY_V*
++ *KEY_W*
++ *KEY_X*
++ *KEY_Y*
++ *KEY_Z*
+
++ *KEY_SEMICOLON*
++ *KEY_APOSTROPHE*
+
++ *KEY_TILDE*
++ *KEY_GRAVE*
+
++ *KEY_BACKSLASH*
+
++ *KEY_COMMA*
++ *KEY_PERIOD*
++ *KEY_FORWARDSLASH*
++ *KEY_SLASH*
+
++ *KEY_SPACE*
+
++ *KEY_CAPSLOCK*
++ *KEY_CAPITAL*
+
++ *KEY_F1*
++ *KEY_F2*
++ *KEY_F3*
++ *KEY_F4*
++ *KEY_F5*
++ *KEY_F6*
++ *KEY_F7*
++ *KEY_F8*
++ *KEY_F9*
++ *KEY_F10*
++ *KEY_F11*
++ *KEY_F12*
+
++ *KEY_SYSRQ*
++ *KEY_SCROLLLOCK*
++ *KEY_PAUSE*
+
++ *KEY_NUMLOCK*
++ *KEY_NUMPAD0*
++ *KEY_NUMPAD1*
++ *KEY_NUMPAD2*
++ *KEY_NUMPAD3*
++ *KEY_NUMPAD4*
++ *KEY_NUMPAD5*
++ *KEY_NUMPAD6*
++ *KEY_NUMPAD7*
++ *KEY_NUMPAD8*
++ *KEY_NUMPAD9*
++ *KEY_ADD*
++ *KEY_SUBTRACT*
++ *KEY_DIVIDE*
++ *KEY_MULTIPLY*
++ *KEY_DECIMAL*
++ *KEY_NUMPADENTER*
+
++ *KEY_INSERT*
++ *KEY_DELETE*
++ *KEY_HOME*
++ *KEY_END*
++ *KEY_PAGEUP*
++ *KEY_PAGEDOWN*
+
++ *KEY_UP*
++ *KEY_DOWN*
++ *KEY_LEFT*
++ *KEY_RIGHT*
+
++ *KEY_LWIN*
++ *KEY_RWIN*
++ *KEY_APPS*
+
+ */
+
+extern const int LEFT_BUTTON;
+extern const int MIDDLE_BUTTON;
+extern const int RIGHT_BUTTON;
+
+extern const int KEY_ESC;
+extern const int KEY_ESCAPE;
+
+extern const int KEY_MINUS;
+extern const int KEY_EQUALS;
+extern const int KEY_BACKSPACE;
+extern const int KEY_TAB;
+
+extern const int KEY_LBRACKET;
+extern const int KEY_RBRACKET;
+
+extern const int KEY_ENTER;
+extern const int KEY_RETURN;
+
+extern const int KEY_CTRL;
+extern const int KEY_LCTRL;
+extern const int KEY_RCTRL;
+
+extern const int KEY_SHIFT;
+extern const int KEY_LSHIFT;
+extern const int KEY_RSHIFT;
+
+extern const int KEY_ALT;
+extern const int KEY_LALT;
+extern const int KEY_RALT;
+
+extern const int KEY_0;
+extern const int KEY_1;
+extern const int KEY_2;
+extern const int KEY_3;
+extern const int KEY_4;
+extern const int KEY_5;
+extern const int KEY_6;
+extern const int KEY_7;
+extern const int KEY_8;
+extern const int KEY_9;
+
+extern const int KEY_A;
+extern const int KEY_B;
+extern const int KEY_C;
+extern const int KEY_D;
+extern const int KEY_E;
+extern const int KEY_F;
+extern const int KEY_G;
+extern const int KEY_H;
+extern const int KEY_I;
+extern const int KEY_J;
+extern const int KEY_K;
+extern const int KEY_L;
+extern const int KEY_M;
+extern const int KEY_N;
+extern const int KEY_O;
+extern const int KEY_P;
+extern const int KEY_Q;
+extern const int KEY_R;
+extern const int KEY_S;
+extern const int KEY_T;
+extern const int KEY_U;
+extern const int KEY_V;
+extern const int KEY_W;
+extern const int KEY_X;
+extern const int KEY_Y;
+extern const int KEY_Z;
+
+extern const int KEY_SEMICOLON;
+extern const int KEY_APOSTROPHE;
+
+extern const int KEY_TILDE;
+extern const int KEY_GRAVE;
+
+extern const int KEY_BACKSLASH;
+
+extern const int KEY_COMMA;
+extern const int KEY_PERIOD;
+extern const int KEY_FORWARDSLASH;
+extern const int KEY_SLASH;
+
+extern const int KEY_SPACE;
+
+extern const int KEY_CAPSLOCK;
+extern const int KEY_CAPITAL;
+
+extern const int KEY_F1;
+extern const int KEY_F2;
+extern const int KEY_F3;
+extern const int KEY_F4;
+extern const int KEY_F5;
+extern const int KEY_F6;
+extern const int KEY_F7;
+extern const int KEY_F8;
+extern const int KEY_F9;
+extern const int KEY_F10;
+extern const int KEY_F11;
+extern const int KEY_F12;
+
+extern const int KEY_SYSRQ;
+extern const int KEY_SCROLLLOCK;
+extern const int KEY_PAUSE;
+
+extern const int KEY_NUMLOCK;
+extern const int KEY_NUMPAD0;
+extern const int KEY_NUMPAD1;
+extern const int KEY_NUMPAD2;
+extern const int KEY_NUMPAD3;
+extern const int KEY_NUMPAD4;
+extern const int KEY_NUMPAD5;
+extern const int KEY_NUMPAD6;
+extern const int KEY_NUMPAD7;
+extern const int KEY_NUMPAD8;
+extern const int KEY_NUMPAD9;
+extern const int KEY_ADD;
+extern const int KEY_SUBTRACT;
+extern const int KEY_DIVIDE;
+extern const int KEY_MULTIPLY;
+extern const int KEY_DECIMAL;
+extern const int KEY_NUMPADENTER;
+
+extern const int KEY_INSERT;
+extern const int KEY_DELETE;
+extern const int KEY_HOME;
+extern const int KEY_END;
+extern const int KEY_PAGEUP;
+extern const int KEY_PAGEDOWN;
+
+extern const int KEY_UP;
+extern const int KEY_DOWN;
+extern const int KEY_LEFT;
+extern const int KEY_RIGHT;
+
+extern const int KEY_LWIN;
+extern const int KEY_RWIN;
+extern const int KEY_APPS;
+
+#define D 200
+#define R 1
+
+
+
+extern int key_val;
+extern bool key_press;
+
+//group: Classes
+
+/*class: Input
+Handles keyboard and mouse input*/
+class Input
+{
+protected:
+ int lockBuffer;
+ int mouseLockBuffer[4];
+ char map[512];
+ int keyLockDuration;
+ int buttonLockDuration;
+ char symbol[10];
+ //SDL_Event event;
+ int mx,my;
+
+
+public:
+
+//group: Constructors
+ /*constructor: Input
+ parameters:
+ keyb - *true* to enable the keyboard subsystem, *false* otherwise
+ mous - *true* to enable the mouse subsystem, *false* otherwise
+ */
+ Input(bool keyb, bool mous);
+ ~Input(void);
+
+/*group: Methods */
+
+/*method: mousePrepare
+ This method is the actual method that makes the reading from the hardware.
+ It should be called at regular intervals. If called too often or too sparsely it will result in missing some information
+ from the input. In general terms it is safe just to call it in every frame. But if the frame rate if very high it might
+ result in strange behavior from the mouse. We suggest assigning a timer of X ms to the calling of the function
+ and fine-tune it for better results.
+
+see also:
+ <mouseGetButtonState>, <mouseGetXDelta> and <mouseGetYDelta>*/
+ void mousePrepare();
+
+/*method: mouseGetButtonState
+ Checks whether a speficic mouse button is pressed
+
+ parameters:
+ button - the mouse button to check. Valid values are
+
+ + *LEFT_BUTTON*
+ + *MIDDLE_BUTTON*
+ + *RIGHT_BUTTON*
+
+ retuns:
+ *true* if _button_ is pressed, *false* otherwise
+
+see also:
+ <mousePrepare>*/
+ bool mouseGetButtonState(int button);
+
+/*method: mouseGetXDelta
+ Reports deltas for mouse movement in X axis
+
+ returns:
+ the units of the mouse movement in the X axis. A negative integer will be returned when the mouse is moved in the
+ left direction, and a positive when moved in the right. Zero will be returned when there is no movement
+
+ see also:
+ <mouseGetYDelta>*/
+ long mouseGetXDelta(void);
+
+/*method: mouseGetYDelta
+ Reports deltas for mouse movement in Y axis
+
+ returns:
+ the units of the mouse movement in the Y axis
+
+ see also:
+ <mouseGetXDelta>*/
+ long mouseGetYDelta(void);
+
+/*method: lockButton
+ Locks a mouse button for _duration_ milliseconds. When you lock a button it will not report its state for _duration_ millis
+
+ button - the desired button to lock
+ duration - duration of the locking in milliseconds
+
+ see also:
+ <mouseGetButtonState>*/
+ void lockButton(int button, int duration=100);
+
+/*method: keyboardGetKeyState
+ Checks whether a speficic key on the keyboard is pressed
+
+ parameters:
+ key - the key to check. See the <KEY codes>
+
+ retuns:
+ *true* if _key_ is pressed, *false* otherwise*/
+ bool keyboardGetKeyState(int key);
+
+/*method: getChar
+Returns the character that has been pressed on the keyboard*/
+ char getChar(void);
+
+/*method: lockKey */
+ void lockKey(int key, int duration=100);
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "Network.h"
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <ctype.h>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+
+
+Socket::Socket(int sd)
+{
+ int x = 1;
+ s=sd;
+ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) == -1)
+ perror("sockopt");
+ this->type=AM_TCP;
+
+ return ;
+}
+
+Socket::Socket(int type, int protocol)
+{
+ int x = 1;
+ int t = SOCK_STREAM;
+
+ if(type == AM_UDP)
+ t = SOCK_DGRAM;
+
+ s=socket(AF_INET, t, protocol);
+ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) == -1)
+ perror("sockopt");
+
+ this->type=type;
+
+ return ;
+}
+
+Socket::~Socket()
+{
+ shutdown(s, SHUT_RDWR);
+
+ return ;
+}
+
+int Socket::Bind(int port)
+{
+ struct sockaddr_in myaddr;
+
+ myaddr.sin_family=AF_INET;
+ myaddr.sin_port=htons(port);
+ myaddr.sin_addr.s_addr=htonl(INADDR_ANY);
+
+ int res=bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr));
+ if (res ==-1)
+ perror("bind returned -1"), exit(1);
+
+ return res;
+}
+
+int Socket::Listen(int log)
+{
+ int res=listen(s, log);
+ if (res ==-1)
+ perror("listen returned -1"), exit(1);
+
+ return res;
+}
+
+Socket* Socket::Accept(void)
+{
+ socklen_t l = sizeof(struct sockaddr);
+
+ int res = accept(s, (struct sockaddr *)&peer, &l);
+ if(res == -1)
+ perror("accept returned -1"), exit(1);
+
+ Socket *tmp = new Socket((int)res);
+
+ return tmp;
+}
+
+
+int Socket::Connect()
+{
+ struct in_addr tmp;
+ tmp.s_addr = peer.sin_addr.s_addr;
+
+ printf(" con to %s %d\n", inet_ntoa(tmp), ntohs(peer.sin_port));
+ int res;
+ res = connect(s, (struct sockaddr *)&peer, sizeof(peer));
+
+ if (res ==-1)
+ perror("connect returned -1");
+
+ return res;
+}
+
+
+
+
+int Socket::Send(void *buffer, unsigned long size)
+{
+// printf("send buf=%s\n", (const char *)buffer);
+ int res=send(s, (const char *)buffer, size, 0);
+
+ if (res ==-1)
+ {
+ perror("send returned -1");
+ if(errno == ENOTSOCK)
+ printf("ENOTSOCK\n");
+ else
+ printf("ERROR\n");
+ }
+
+ return res;
+}
+
+int Socket::Receive(void *buffer, unsigned long size)
+{
+ int res=recv(s, (char *)buffer, size, 0);
+ if (res ==-1)
+ perror("recv returned -1"), exit(1);
+
+ return res;
+}
+
+int Socket::SendTo(void *buffer, unsigned long size)
+{
+ int res=sendto(s, (const char *)buffer, size, 0, (const struct sockaddr *)&peer, sizeof(peer));
+ if (res ==-1)
+ perror("sendto returned -1"), exit(1);
+
+ return res;
+}
+
+int Socket::RecvFrom(void *buffer, unsigned long size)
+{
+ unsigned int l;
+ int res=recvfrom(s, (char *)buffer, size, 0, (struct sockaddr *)&peer, &l);
+ if (res ==-1)
+ perror("recvfrom returned -1"), exit(1);
+
+ return res;
+}
+
+void Socket::SetPeer(struct sockaddr_in data)
+{
+ memcpy(&peer, &data, sizeof(data));
+
+ return ;
+}
+
+
+struct sockaddr_in Socket::GetPeer(void)
+{
+ return peer;
+}
+
+struct sockaddr_in Socket::CreatePeer(const char *address, int port)
+{
+ struct sockaddr_in youraddr;
+
+ printf("Hostname address specified: %s\n", address);
+
+ youraddr.sin_port=htons(port);
+ youraddr.sin_family=AF_INET;
+ youraddr.sin_addr.s_addr=0;
+
+ if (isdigit(address[0]))
+ {
+ unsigned long addr;
+
+ addr=inet_addr(address);
+
+ memcpy((void *)&(youraddr.sin_addr), (const void *)&addr, sizeof(addr));
+ }
+ else
+ {
+ struct hostent *otherhost;
+
+ otherhost = gethostbyname(address);
+
+ if(otherhost == NULL)
+ herror("otherhost");
+
+ if (otherhost != NULL)
+ memcpy((void *)&(youraddr.sin_addr), (const void *)otherhost->h_addr_list[0], otherhost->h_length);
+ }
+
+ return youraddr;
+}
+
+
+int Socket::Select(unsigned long seconds, unsigned long microsecs)
+{
+ struct timeval tv;
+
+ tv.tv_sec = seconds;
+ tv.tv_usec = microsecs;
+
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+
+ int ret = select(s+1, &rfds, NULL, NULL, &tv);
+ return ret;
+}
+
+
+int Socket::Select(unsigned long microsecs)
+{
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = microsecs;
+
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+
+ int ret = select(s+1, &rfds, NULL, NULL, &tv);
+ return ret;
+}
+
+
+Network::Network()
+{
+ ;
+}
+
+Network::~Network()
+{
+ ;
+}
+
+Socket * Network::getSocket(int type, int protocol)
+{
+ Socket *tmp=new Socket(type, protocol);
+
+ return tmp;
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _NETWORK_H
+#define _NETWORK_H
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define AM_TCP 1
+#define AM_UDP 2
+
+extern char **argv;
+extern int argc;
+
+//group: Classes
+
+/*class: Socket
+A TCP/IP socket*/
+class Socket
+{
+public:
+ int s;
+
+//group: Fields
+ /*field: peer*/
+ struct sockaddr_in peer;
+ int type;
+
+public:
+ //group: Constructors
+ /*constructor: Socket
+parameters:
+ sd - a socket descriptor */
+ Socket(int sd);
+ /*constructor: Socket
+ parameters:
+ type - can be *AM_TCP* or *AM_UDP*
+ protocol - 0
+ */
+ Socket(int type, int protocol);
+ ~Socket();
+
+//group: Methods
+ /*method: Bind */
+ int Bind(int port);
+ /*method: Listen */
+ int Listen(int log);
+ /*method: Accept */
+ Socket * Accept(void);
+ /*method: Connect */
+ int Connect(void);
+ /*method: Send */
+ int Send(void *buffer, unsigned long size);
+ /*method: Receive */
+ int Receive(void *buffer, unsigned long size);
+ /*method: SendTo */
+ int SendTo(void *buffer, unsigned long size);
+ /*method: RecvFrom */
+ int RecvFrom(void *buffer, unsigned long size);
+ /*method: Select */
+ int Select(unsigned long seconds, unsigned long microsecs);
+ /*method: Select */
+ int Select(unsigned long microsecs);
+ /*method: SetPeer */
+ void SetPeer(struct sockaddr_in data);
+ /*method: GetPeer */
+ struct sockaddr_in GetPeer(void);
+ /*method: CreatePeer */
+ struct sockaddr_in CreatePeer(const char *address, int port);
+
+};
+
+
+/*class: Network*/
+class Network
+{
+ public:
+ bool ok;
+//group: Constructors
+ /*constructor: Network */
+ Network();
+ ~Network();
+//group: Methods
+ /*method: getSocket*/
+ Socket * getSocket(int type, int protocol);
+};
+
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "Sprite.h"
+#include <GL/gl.h>
+
+
+Graphics *gr;
+float z_order = 1.0;
+
+
+void Sprite::glEnter2DMode()
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glEnable(GL_TEXTURE_2D);
+
+
+ /* This allows alpha blending of 2D textures with the scene */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+ glViewport(0, 0, gr->getWidth(), gr->getHeight());
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glOrtho(0.0, (GLdouble)gr->getWidth(), (GLdouble)gr->getHeight(), 0.0, 0.0, -2.0);
+// gluOrtho2D(0.0, (GLdouble)gr->getWidth(), (GLdouble)gr->getHeight(), 0.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+ return;
+}
+
+
+void Sprite::glLeave2DMode()
+{
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glPopAttrib();
+ return;
+}
+
+Sprite::Sprite( char * filename, colour key, int tw, int th, Graphics *g)
+{
+ this->g = g;
+ tileWidth=tw;
+ tileHeight=th;
+
+ glAlphaFunc(GL_NOTEQUAL, 0);
+ glEnable(GL_ALPHA_TEST);
+ tex = new Texture(filename, key, g);
+
+ texW = tex->getWidth();
+ texH = tex->getHeight();
+ texWFactor = (tileWidth / (float) texW);
+ texHFactor = (tileHeight / (float) texH);
+
+ return ;
+}
+
+
+Sprite::~Sprite(void)
+{
+ delete tex;
+ return ;
+}
+
+
+void Sprite::blit(int x, int y, float scalex, float scaley, int dx, int dy, colour col)
+{
+ z_order-=0.000001;
+ glEnter2DMode();
+// glColor4ub((colour & 0x00FF0000) >> 16, (colour & 0x0000FF00) >> 8,
+// (colour & 0x000000FF), (colour & 0xFF000000) >> 24);
+ glColor4f(col.r, col.g, col.b, col.a);
+
+ glBindTexture(GL_TEXTURE_2D, tex->gl_Tex);
+ glPushMatrix();
+ glTranslatef(x,y, 0);
+
+ glScalef(scalex, scaley, 1);
+ glBegin(GL_QUADS);
+ glTexCoord2f(dx*texWFactor, 1 - dy*texHFactor);
+ glVertex3f(0,0, z_order);
+
+ glTexCoord2f(dx*texWFactor, 1 - (dy + 1)*texHFactor);
+ glVertex3f(0, tileHeight, z_order);
+
+ glTexCoord2f((dx + 1)*texWFactor, 1 - (dy + 1)*texHFactor);
+ glVertex3f( tileWidth, tileHeight, z_order);
+
+ glTexCoord2f((dx + 1)*texWFactor, 1 - dy*texHFactor);
+ glVertex3f( tileWidth, 0, z_order);
+ glEnd();
+ glPopMatrix();
+
+ glLeave2DMode();
+
+
+ return ;
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _SPRITE
+#define _SPRITE
+
+#include "Graphics.h"
+
+
+/*
+Class: Sprite
+Represents a sprite
+*/
+
+class Sprite
+{
+private:
+ Texture *tex;
+ int tileWidth;
+ int tileHeight;
+ Graphics *g;
+ //SDL_Rect sRect;
+ unsigned long texW;
+ unsigned long texH;
+ float texWFactor;
+ float texHFactor;
+ void glEnter2DMode();
+ void glLeave2DMode();
+
+public:
+//group: Constructors
+
+ /*constructor: Sprite
+
+ parameters:
+
+ filename - the filename of the image which will be our sprite
+ key - the colour key to use for this sprite
+ tw - the tile width
+ th - the tile height. _tw_ and _th are useful when you have the sprite's animation in fixed tiles in an image.
+ In many cases we haven't, so we specify the full size of the image
+ g- a pointer to the Graphics object*/
+ Sprite( char *filename, colour key, int tw, int th, Graphics *g);
+ ~Sprite(void);
+
+//group: Methods
+
+/*method: blit
+ Blits a sprite on the display at point (x,y). This is the top-left point of the sprite.
+
+parameters:
+ x - x coordinate in screen coordinates
+ y - y coordinate in screen coordinates
+ scalex - the factor to scale in the X axis
+ scalex - the factor to scale in the Y axis
+ dx - tile index in X
+ dy - tile index in Y
+ colour - the colour mask to use*/
+ void blit(int x, int y, float scalex, float scaley, int dx, int dy, colour c);
+
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "System.h"
+#include <SDL/SDL.h>
+
+
+Mutex::Mutex()
+{
+ if(pthread_mutex_init(&mutex, NULL) != 0)
+ printf("mutex init failed\n");
+
+}
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void Mutex::lock()
+{
+ pthread_mutex_lock(&mutex);
+}
+
+void Mutex::unlock()
+{
+ pthread_mutex_unlock(&mutex);
+}
+
+
+unsigned long getTime(void)
+{
+ return SDL_GetTicks();
+}
+
+
+bool createThread(void *(func)(void *), void *param)
+{
+ pthread_t id;
+ int ret = pthread_create(&id, NULL, func, param);
+
+ if(ret == 0)
+ return false;
+
+ return true;
+}
+
+
+
+void setWindowCaption(char *name)
+{
+ SDL_WM_SetCaption(name, NULL);
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _SYSTEM
+#define _SYSTEM
+
+
+#include <pthread.h>
+#include <stdio.h>
+
+extern char **argv;
+extern int argc;
+
+extern unsigned long getTime(void);
+extern bool createThread(void *(func)(void *), void *param);
+extern void setWindowCaption(char *name);
+
+class Mutex
+{
+ private:
+ pthread_mutex_t mutex;
+
+ public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+};
+
+#endif
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+//Include files
+
+#include "Graphics.h"
+#include "Input.h"
+#include "md2model.h"
+#include "Sprite.h"
+#include "System.h"
+#include <SDL/SDL.h>
+
+extern bool init();
+extern bool cleanup();
+extern bool renderFrame();
+
+#define _DEBUG
+
+int key_val = 0;
+bool key_press = false;
+int argc = 0;
+char **argv = 0;
+
+int main( int _argc, char **_argv )
+{
+ argc = _argc;
+ argv = _argv;
+
+
+#ifndef _DEBUG
+ init();
+ while ( renderFrame() )
+ { ; }
+
+ cleanup();
+ return 0;
+#else
+ SDL_Event event;
+ init();
+ while(renderFrame())
+ {
+ SDL_PollEvent(&event);
+ switch( event.type )
+ {
+ case SDL_KEYDOWN:
+ if(1 /*(&event.key.keysym)->sym == key*/)
+ {
+
+ key_val = (&event.key.keysym)->sym;/* - (((&event.key.keysym)->mod & KMOD_RSHIFT) ? 32: 0);*/
+ //printf("Pressed = %d\n", key_val);
+ if(key_val > 256)
+ {
+ key_val = 0;
+ break;
+ }
+ key_press = true;
+
+ }
+ break;
+ case SDL_KEYUP:
+ key_press = false;
+ break;
+ default:
+ key_press = false;
+ break;
+ }
+ }
+ cleanup();
+ return 0;
+#endif
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _MD2MODEL
+#define _MD2MODEL
+
+
+// #include "Texture.h"
+#include "Graphics.h"
+
+// using namespace Amaltheia;
+
+class model;
+class c_model;
+
+typedef unsigned char BYTE;
+
+struct tex
+{
+ short u, v;
+};
+
+struct texturecoord
+{
+ float u;
+ float v;
+};
+
+struct face
+{
+ short vindex[ 3 ];
+ short tindex[ 3 ];
+};
+
+struct triangle
+{
+ BYTE vertex[ 3 ];
+ BYTE lightNormalIndex;
+};
+
+struct frame
+{
+ float scale[ 3 ];
+ float translate[ 3 ];
+ char name[ 16 ];
+ struct triangle **tr;
+};
+
+struct MD2header
+{
+ int magic; // This is used to identify the file
+ int version; // The version number of the file (Must be 8)
+ int skinWidth; // The skin width in pixels
+ int skinHeight; // The skin height in pixels
+ int frameSize; // The size in bytes the frames are
+ int numSkins; // The number of skins associated with the model
+ int numVertices; // The number of vertices (constant for each frame)
+ int numTexCoords; // The number of texture coordinates
+ int numTriangles; // The number of faces (polygons)
+ int numGlCommands; // The number of gl commands
+ int numFrames; // The number of animation frames
+ int offsetSkins; // The offset in the file for the skin data
+ int offsetTexCoords; // The offset in the file for the texture data
+ int offsetTriangles; // The offset in the file for the face data
+ int offsetFrames; // The offset in the file for the frames data
+ int offsetGlCommands; // The offset in the file for the gl commands data
+ int offsetEnd; // The end of the file offset
+};
+
+struct fnode
+{
+ int fnumber;
+ struct fnode *next;
+};
+typedef struct fnode flist;
+
+
+
+
+class model
+{
+private:
+ // void delframelist(void);
+ int framecounter;
+ char *bitmap_filename;
+ Texture *modelTexture;
+ bool change;
+ Graphics *graph;
+// GLfloat *v;
+ float *v;
+ // bool minMax; //ginetai true otan kaleitai h setframeseq. To elegxei h getMin...
+
+public:
+ bool *mark;
+ float xmin, xmax, ymin, ymax, zmin, zmax;
+ struct MD2header md2h;
+ struct tex *tex1;
+ struct texturecoord *tc;
+ struct face *fc;
+ struct frame **fr;
+ bool ok;
+ float FPS;
+ flist *cpointer;
+
+ model( char *, char *, Graphics *g );
+ ~model();
+
+ void render( float t );
+ int getframecounter( void );
+
+};
+
+
+
+
+class c_model
+{
+private:
+ model *mod;
+ flist *fhead, *ftail;
+ int nframes;
+ void delFrameSequence( void );
+ int current_offset;
+ float oldt;
+ float gettime( void );
+
+public:
+ float FPS;
+ float xmin, xmax, ymin, ymax, zmin, zmax;
+ flist *cpointer;
+ char *current_frame_sequence;
+
+ c_model( model *m );
+ ~c_model();
+ void setFrameSequence( char *name );
+ void render( void );
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *
+ * <psybases@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "md2model.h"
+
+#include <GL/gl.h>
+#include <cstring>
+#include <iostream>
+#include <cstdlib>
+#include <SDL/SDL.h>
+// extern FILE *errorfp;
+
+struct vec3
+{
+ float nx, ny, nz;
+};
+
+struct vec3 normalVectorArray[] =
+ {
+ { -0.525731f, 0.000000f, 0.850651f },
+ { -0.442863f, 0.238856f, 0.864188f },
+ { -0.295242f, 0.000000f, 0.955423f },
+ { -0.309017f, 0.500000f, 0.809017f },
+ { -0.162460f, 0.262866f, 0.951056f },
+ { 0.000000f, 0.000000f, 1.000000f },
+ { 0.000000f, 0.850651f, 0.525731f },
+ { -0.147621f, 0.716567f, 0.681718f },
+ { 0.147621f, 0.716567f, 0.681718f },
+ { 0.000000f, 0.525731f, 0.850651f },
+ { 0.309017f, 0.500000f, 0.809017f },
+ { 0.525731f, 0.000000f, 0.850651f },
+ { 0.295242f, 0.000000f, 0.955423f },
+ { 0.442863f, 0.238856f, 0.864188f },
+ { 0.162460f, 0.262866f, 0.951056f },
+ { -0.681718f, 0.147621f, 0.716567f },
+ { -0.809017f, 0.309017f, 0.500000f },
+ { -0.587785f, 0.425325f, 0.688191f },
+ { -0.850651f, 0.525731f, 0.000000f },
+ { -0.864188f, 0.442863f, 0.238856f },
+ { -0.716567f, 0.681718f, 0.147621f },
+ { -0.688191f, 0.587785f, 0.425325f },
+ { -0.500000f, 0.809017f, 0.309017f },
+ { -0.238856f, 0.864188f, 0.442863f },
+ { -0.425325f, 0.688191f, 0.587785f },
+ { -0.716567f, 0.681718f, -0.147621f },
+ { -0.500000f, 0.809017f, -0.309017f },
+ { -0.525731f, 0.850651f, 0.000000f },
+ { 0.000000f, 0.850651f, -0.525731f },
+ { -0.238856f, 0.864188f, -0.442863f },
+ { 0.000000f, 0.955423f, -0.295242f },
+ { -0.262866f, 0.951056f, -0.162460f },
+ { 0.000000f, 1.000000f, 0.000000f },
+ { 0.000000f, 0.955423f, 0.295242f },
+ { -0.262866f, 0.951056f, 0.162460f },
+ { 0.238856f, 0.864188f, 0.442863f },
+ { 0.262866f, 0.951056f, 0.162460f },
+ { 0.500000f, 0.809017f, 0.309017f },
+ { 0.238856f, 0.864188f, -0.442863f },
+ { 0.262866f, 0.951056f, -0.162460f },
+ { 0.500000f, 0.809017f, -0.309017f },
+ { 0.850651f, 0.525731f, 0.000000f },
+ { 0.716567f, 0.681718f, 0.147621f },
+ { 0.716567f, 0.681718f, -0.147621f },
+ { 0.525731f, 0.850651f, 0.000000f },
+ { 0.425325f, 0.688191f, 0.587785f },
+ { 0.864188f, 0.442863f, 0.238856f },
+ { 0.688191f, 0.587785f, 0.425325f },
+ { 0.809017f, 0.309017f, 0.500000f },
+ { 0.681718f, 0.147621f, 0.716567f },
+ { 0.587785f, 0.425325f, 0.688191f },
+ { 0.955423f, 0.295242f, 0.000000f },
+ { 1.000000f, 0.000000f, 0.000000f },
+ { 0.951056f, 0.162460f, 0.262866f },
+ { 0.850651f, -0.525731f, 0.000000f },
+ { 0.955423f, -0.295242f, 0.000000f },
+ { 0.864188f, -0.442863f, 0.238856f },
+ { 0.951056f, -0.162460f, 0.262866f },
+ { 0.809017f, -0.309017f, 0.500000f },
+ { 0.681718f, -0.147621f, 0.716567f },
+ { 0.850651f, 0.000000f, 0.525731f },
+ { 0.864188f, 0.442863f, -0.238856f },
+ { 0.809017f, 0.309017f, -0.500000f },
+ { 0.951056f, 0.162460f, -0.262866f },
+ { 0.525731f, 0.000000f, -0.850651f },
+ { 0.681718f, 0.147621f, -0.716567f },
+ { 0.681718f, -0.147621f, -0.716567f },
+ { 0.850651f, 0.000000f, -0.525731f },
+ { 0.809017f, -0.309017f, -0.500000f },
+ { 0.864188f, -0.442863f, -0.238856f },
+ { 0.951056f, -0.162460f, -0.262866f },
+ { 0.147621f, 0.716567f, -0.681718f },
+ { 0.309017f, 0.500000f, -0.809017f },
+ { 0.425325f, 0.688191f, -0.587785f },
+ { 0.442863f, 0.238856f, -0.864188f },
+ { 0.587785f, 0.425325f, -0.688191f },
+ { 0.688191f, 0.587785f, -0.425325f },
+ { -0.147621f, 0.716567f, -0.681718f },
+ { -0.309017f, 0.500000f, -0.809017f },
+ { 0.000000f, 0.525731f, -0.850651f },
+ { -0.525731f, 0.000000f, -0.850651f },
+ { -0.442863f, 0.238856f, -0.864188f },
+ { -0.295242f, 0.000000f, -0.955423f },
+ { -0.162460f, 0.262866f, -0.951056f },
+ { 0.000000f, 0.000000f, -1.000000f },
+ { 0.295242f, 0.000000f, -0.955423f },
+ { 0.162460f, 0.262866f, -0.951056f },
+ { -0.442863f, -0.238856f, -0.864188f },
+ { -0.309017f, -0.500000f, -0.809017f },
+ { -0.162460f, -0.262866f, -0.951056f },
+ { 0.000000f, -0.850651f, -0.525731f },
+ { -0.147621f, -0.716567f, -0.681718f },
+ { 0.147621f, -0.716567f, -0.681718f },
+ { 0.000000f, -0.525731f, -0.850651f },
+ { 0.309017f, -0.500000f, -0.809017f },
+ { 0.442863f, -0.238856f, -0.864188f },
+ { 0.162460f, -0.262866f, -0.951056f },
+ { 0.238856f, -0.864188f, -0.442863f },
+ { 0.500000f, -0.809017f, -0.309017f },
+ { 0.425325f, -0.688191f, -0.587785f },
+ { 0.716567f, -0.681718f, -0.147621f },
+ { 0.688191f, -0.587785f, -0.425325f },
+ { 0.587785f, -0.425325f, -0.688191f },
+ { 0.000000f, -0.955423f, -0.295242f },
+ { 0.000000f, -1.000000f, 0.000000f },
+ { 0.262866f, -0.951056f, -0.162460f },
+ { 0.000000f, -0.850651f, 0.525731f },
+ { 0.000000f, -0.955423f, 0.295242f },
+ { 0.238856f, -0.864188f, 0.442863f },
+ { 0.262866f, -0.951056f, 0.162460f },
+ { 0.500000f, -0.809017f, 0.309017f },
+ { 0.716567f, -0.681718f, 0.147621f },
+ { 0.525731f, -0.850651f, 0.000000f },
+ { -0.238856f, -0.864188f, -0.442863f },
+ { -0.500000f, -0.809017f, -0.309017f },
+ { -0.262866f, -0.951056f, -0.162460f },
+ { -0.850651f, -0.525731f, 0.000000f },
+ { -0.716567f, -0.681718f, -0.147621f },
+ { -0.716567f, -0.681718f, 0.147621f },
+ { -0.525731f, -0.850651f, 0.000000f },
+ { -0.500000f, -0.809017f, 0.309017f },
+ { -0.238856f, -0.864188f, 0.442863f },
+ { -0.262866f, -0.951056f, 0.162460f },
+ { -0.864188f, -0.442863f, 0.238856f },
+ { -0.809017f, -0.309017f, 0.500000f },
+ { -0.688191f, -0.587785f, 0.425325f },
+ { -0.681718f, -0.147621f, 0.716567f },
+ { -0.442863f, -0.238856f, 0.864188f },
+ { -0.587785f, -0.425325f, 0.688191f },
+ { -0.309017f, -0.500000f, 0.809017f },
+ { -0.147621f, -0.716567f, 0.681718f },
+ { -0.425325f, -0.688191f, 0.587785f },
+ { -0.162460f, -0.262866f, 0.951056f },
+ { 0.442863f, -0.238856f, 0.864188f },
+ { 0.162460f, -0.262866f, 0.951056f },
+ { 0.309017f, -0.500000f, 0.809017f },
+ { 0.147621f, -0.716567f, 0.681718f },
+ { 0.000000f, -0.525731f, 0.850651f },
+ { 0.425325f, -0.688191f, 0.587785f },
+ { 0.587785f, -0.425325f, 0.688191f },
+ { 0.688191f, -0.587785f, 0.425325f },
+ { -0.955423f, 0.295242f, 0.000000f },
+ { -0.951056f, 0.162460f, 0.262866f },
+ { -1.000000f, 0.000000f, 0.000000f },
+ { -0.850651f, 0.000000f, 0.525731f },
+ { -0.955423f, -0.295242f, 0.000000f },
+ { -0.951056f, -0.162460f, 0.262866f },
+ { -0.864188f, 0.442863f, -0.238856f },
+ { -0.951056f, 0.162460f, -0.262866f },
+ { -0.809017f, 0.309017f, -0.500000f },
+ { -0.864188f, -0.442863f, -0.238856f },
+ { -0.951056f, -0.162460f, -0.262866f },
+ { -0.809017f, -0.309017f, -0.500000f },
+ { -0.681718f, 0.147621f, -0.716567f },
+ { -0.681718f, -0.147621f, -0.716567f },
+ { -0.850651f, 0.000000f, -0.525731f },
+ { -0.688191f, 0.587785f, -0.425325f },
+ { -0.587785f, 0.425325f, -0.688191f },
+ { -0.425325f, 0.688191f, -0.587785f },
+ { -0.425325f, -0.688191f, -0.587785f },
+ { -0.587785f, -0.425325f, -0.688191f },
+ { -0.688191f, -0.587785f, -0.425325f }
+ };
+
+
+
+model::model( char * md2_filename, char *bfilename, Graphics *g )
+{
+ int i;
+
+ modelTexture = new Texture( bfilename, g);
+
+ graph = g;
+
+ FILE *fp = fopen( md2_filename, "rb" );
+ if ( fp == NULL )
+ {
+ ok = false;
+ return ;
+ }
+ fread( ( void * ) & md2h, 1, sizeof( md2h ), fp );
+
+ tex1 = ( struct tex * ) malloc( sizeof( struct tex ) * md2h.numTexCoords );
+
+ fseek( fp, md2h.offsetTexCoords, SEEK_SET );
+ fread( ( void * ) tex1, sizeof( struct tex ), md2h.numTexCoords, fp );
+
+ tc = ( struct texturecoord * ) malloc( sizeof( struct texturecoord ) * md2h.numTexCoords );
+
+ for ( i = 0;i < md2h.numTexCoords;i++ )
+ {
+ tc[ i ].u = ( float ) ( tex1[ i ].u ) / ( float ) ( md2h.skinWidth );
+ tc[ i ].v = ( float ) ( tex1[ i ].v ) / ( float ) ( md2h.skinHeight );
+ }
+ free( tex1 );
+
+ fc = ( struct face * ) malloc( sizeof( struct face ) * md2h.numTriangles );
+
+ fseek( fp, md2h.offsetTriangles, 0 );
+ fread ( ( void * ) fc, sizeof( struct face ), md2h.numTriangles, fp );
+
+ fseek( fp, md2h.offsetFrames, 0 );
+
+ fr = ( struct frame ** ) malloc( sizeof( struct frame * ) * md2h.numFrames );
+
+ for ( i = 0;i < md2h.numFrames;i++ )
+ {
+ fr[ i ] = ( struct frame * ) malloc( sizeof( struct frame ) );
+ fread( ( void * ) ( &( fr[ i ] ->scale[ 0 ] ) ), 3, sizeof( float ), fp );
+ fread( ( void * ) ( &( fr[ i ] ->translate[ 0 ] ) ), 3, sizeof( float ), fp );
+ fread( ( void * ) & ( fr[ i ] ->name[ 0 ] ), 1, sizeof( fr[ i ] ->name ), fp );
+ fr[ i ] ->tr = ( struct triangle ** ) malloc( sizeof( struct triangle* ) * md2h.numVertices );
+ int j;
+ for ( j = 0;j < md2h.numVertices;j++ )
+ {
+ fr[ i ] ->tr[ j ] = ( struct triangle * ) malloc( sizeof( struct triangle ) );
+ fread( ( void * ) & ( fr[ i ] ->tr[ j ] ->vertex[ 0 ] ), 3, sizeof( BYTE ), fp );
+ fread( ( void * ) & ( fr[ i ] ->tr[ j ] ->lightNormalIndex ), 1, sizeof( BYTE ), fp );
+ }
+
+ }
+
+ // fhead=NULL;
+ // ftail=NULL;
+
+ ok = true;
+ change = false;
+
+ mark = NULL;
+
+ FPS = 200.0f;
+
+ // v = ( struct vertex * ) malloc( sizeof( struct vertex ) * ( md2h.numTriangles + 5 ) * 3 );
+ /* 12 einai to plh8os twn floats (vertices, normals, colour ktl*/
+ v = new GLfloat[12 * ( md2h.numTriangles + 5 ) * 3];
+ return ;
+}
+
+
+
+model::~model( void )
+{
+ free( tc );
+ free( fc );
+
+ int i, j;
+ for ( i = 0;i < md2h.numFrames;i++ )
+ {
+ for ( j = 0;j < md2h.numVertices;j++ )
+ free ( fr[ i ] ->tr[ j ] );
+ free( fr[ i ] ->tr );
+ free( fr[ i ] );
+ }
+
+ delete modelTexture;
+
+ free( fr );
+ delete[] v ;
+
+ return ;
+}
+
+
+
+
+
+void model::render( float t )
+{
+ int i;
+ int j = 0;
+ /*
+ if (mark!=NULL)
+ (*mark)=false;
+
+ if (mark!=NULL && strcmp(current_frame_sequence,"run")==0 &&
+ (cpointer->fnumber-current_offset==3 ||
+ cpointer->fnumber-current_offset==0))
+ (*mark)=true;
+
+ t=gettime();
+ if (oldt>t) cpointer=cpointer->next;
+ oldt=t;
+
+ graph->setTexture(modelTexture);
+ */
+ for ( i = 0;i < md2h.numTriangles;i++ )
+ {
+ int k;
+
+ for ( k = 0;k < 3;k++ )
+ {
+ int p = fc[ i ].vindex[ k ];
+ BYTE x, y, z;
+ float xx, yy, zz;
+ float nx1, ny1, nz1;
+
+ framecounter = cpointer->fnumber;
+
+ x = fr[ framecounter ] ->tr[ p ] ->vertex[ 0 ];
+ y = fr[ framecounter ] ->tr[ p ] ->vertex[ 1 ];
+ z = fr[ framecounter ] ->tr[ p ] ->vertex[ 2 ];
+
+ xx = ( float ) x * fr[ framecounter ] ->scale[ 0 ];
+ yy = ( float ) y * fr[ framecounter ] ->scale[ 1 ];
+ zz = ( float ) z * fr[ framecounter ] ->scale[ 2 ];
+
+ xx = xx + fr[ framecounter ] ->translate[ 0 ];
+ yy = yy + fr[ framecounter ] ->translate[ 1 ];
+ zz = zz + fr[ framecounter ] ->translate[ 2 ];
+
+
+ nx1 = normalVectorArray[ fr[ framecounter ] ->tr[ p ] ->lightNormalIndex ].nx;
+ ny1 = normalVectorArray[ fr[ framecounter ] ->tr[ p ] ->lightNormalIndex ].ny;
+ nz1 = normalVectorArray[ fr[ framecounter ] ->tr[ p ] ->lightNormalIndex ].nz;
+
+
+ float xx1, yy1, zz1;
+ float nx2, ny2, nz2;
+
+ framecounter = cpointer->next->fnumber;
+
+ x = fr[ framecounter ] ->tr[ p ] ->vertex[ 0 ];
+ y = fr[ framecounter ] ->tr[ p ] ->vertex[ 1 ];
+ z = fr[ framecounter ] ->tr[ p ] ->vertex[ 2 ];
+
+ xx1 = ( float ) x * fr[ framecounter ] ->scale[ 0 ];
+ yy1 = ( float ) y * fr[ framecounter ] ->scale[ 1 ];
+ zz1 = ( float ) z * fr[ framecounter ] ->scale[ 2 ];
+
+ xx1 = xx1 + fr[ framecounter ] ->translate[ 0 ];
+ yy1 = yy1 + fr[ framecounter ] ->translate[ 1 ];
+ zz1 = zz1 + fr[ framecounter ] ->translate[ 2 ];
+
+ nx2 = normalVectorArray[ fr[ framecounter ] ->tr[ p ] ->lightNormalIndex ].nx;
+ ny2 = normalVectorArray[ fr[ framecounter ] ->tr[ p ] ->lightNormalIndex ].ny;
+ nz2 = normalVectorArray[ fr[ framecounter ] ->tr[ p ] ->lightNormalIndex ].nz;
+
+
+ p = fc[ i ].tindex[ k ];
+
+ v[ 12 * j] = tc[ p ].u;
+ v[ 12 * j + 1] = 0.0 - tc[ p ].v;
+
+ v[ 12 * j + 2] = 1.0;
+ v[ 12 * j + 3] = 1.0;
+ v[ 12 * j + 4] = 1.0;
+ v[ 12 * j + 5] = 1.0;
+
+ v[ 12 * j + 6] = nx1 + t * ( nx2 - nx1 );
+ v[ 12 * j + 7] = nz1 + t * ( nz2 - nz1 );
+ v[ 12 * j + 8] = ny1 + t * ( ny2 - ny1 );
+
+ v[ 12 * j + 9] = xx + t * ( xx1 - xx );
+ v[ 12 * j + 10] = zz + t * ( zz1 - zz );
+ v[ 12 * j + 11] = yy + t * ( yy1 - yy );
+
+
+ j++;
+ }
+ }
+ i = 0;
+
+ // graph->renderMd2(v, (md2h.numTriangles+5)*3);
+ graph->setTexture( modelTexture );
+ unsigned int numOfTris = ( md2h.numTriangles + 5 ) * 3;
+// if ( graph->getAlpha() )
+ // glDisable( GL_DEPTH_TEST );
+
+ //graph->setAlpha(true);
+
+
+// graph->renderTriangles(AM_TRIANGLES, v, numOfTris);
+ graph->renderVertexArray((vertex *)v, numOfTris, AM_TRIANGLES);
+
+
+ //if ( graph->getAlpha() )
+// glEnable( GL_DEPTH_TEST );
+// glDisable(GL_DEPTH_TEST);
+
+ return ;
+}
+
+
+
+
+
+/*
+
+void model::delframelist(void)
+{
+ fnode *tmp;
+ fnode *tmp1;
+
+ if (fhead!=NULL)
+ {
+
+ tmp=fhead->next;
+ tmp1=fhead;
+
+ if (fhead->next==fhead)
+ {
+ free(fhead);
+ fhead=NULL;
+ ftail=NULL;
+ }
+ else
+ {
+ while(1)
+ {
+ if (tmp==fhead) break;
+ free(tmp1);
+ tmp1=tmp;
+ tmp=tmp->next;
+ }
+ free(tmp1);
+ }
+ fhead=NULL;
+ ftail=NULL;
+ }
+ framecounter=-1;
+ nframes=-1;
+ return ;
+}
+*/
+
+/*
+void model::setframesequence(char *name)
+{
+ fnode *tmp;
+ int i, j;
+
+ minMax = true;
+
+ delframelist();
+
+ nframes=0;
+ for (i=0;i<md2h.numFrames;i++)
+ {
+ if (strstr(fr[i]->name,name)!=NULL)
+ {
+
+ for (j=0; j < md2h.numTriangles; j++)
+ {
+ float x,y,z;
+ int k;
+ for (k=0;k<3;k++)
+ {
+ int p=fc[j].vindex[k];
+ x=fr[i]->tr[p]->vertex[0]*fr[i]->scale[0]+fr[i]->translate[0];
+ y=fr[i]->tr[p]->vertex[1]*fr[i]->scale[1]+fr[i]->translate[1];
+ z=fr[i]->tr[p]->vertex[2]*fr[i]->scale[2]+fr[i]->translate[2];
+
+ if (x>xmax) xmax=x;
+ if (x<xmin) xmin=x;
+ if (y<ymin) zmin=z;
+ if (y>ymax) zmax=z;
+ if (z<zmin) ymin=y;
+ if (z>zmax) ymax=y;
+ }
+ }
+ tmp=(fnode *)malloc(sizeof(fnode));
+ tmp->fnumber=i;
+ tmp->next=NULL;
+ if (fhead==NULL)
+ {
+ fhead=tmp;
+ ftail=tmp;
+ current_offset=tmp->fnumber;
+ }
+ else
+ {
+ ftail->next=tmp;
+ ftail=tmp;
+ }
+ nframes++;
+ }
+ }
+ framecounter=0;
+ if (fhead==NULL)
+ {
+ framecounter=-1;
+ return ;
+ }
+
+ cpointer=fhead;
+ current_frame_sequence=name;
+ ftail->next=fhead;
+ oldt=0.0f;
+
+ return ;
+}
+
+*/
+
+int model::getframecounter( void )
+{
+ return framecounter;
+}
+
+
+
+c_model::c_model( model *m )
+{
+ mod = m;
+ FPS = mod->FPS;
+
+ fhead = NULL;
+ ftail = NULL;
+
+ return ;
+}
+
+void c_model::setFrameSequence( char *name )
+{
+ fnode * tmp;
+ int i;
+
+ delFrameSequence();
+
+ xmin = 0;ymin = 0;zmin = 0;
+ xmax = 0;ymax = 0;zmax = 0;
+
+ nframes = 0;
+ for ( i = 0;i < mod->md2h.numFrames;i++ )
+ {
+ if ( strstr( mod->fr[ i ] ->name, name ) != NULL )
+ {
+ tmp = ( fnode * ) malloc( sizeof( fnode ) );
+ tmp->fnumber = i;
+ tmp->next = NULL;
+ if ( fhead == NULL )
+ {
+ fhead = tmp;
+ ftail = tmp;
+ }
+ else
+ {
+ ftail->next = tmp;
+ ftail = tmp;
+ }
+ nframes++;
+ for ( int j = 0;j < mod->md2h.numTriangles;j++ )
+ {
+ float x, y, z;
+ for ( int k = 0;k < 3;k++ )
+ {
+ int p = mod->fc[ j ].vindex[ k ];
+
+
+ x = mod->fr[ i ] ->tr[ p ] ->vertex[ 0 ] * mod->fr[ i ] ->scale[ 0 ] + mod->fr[ i ] ->translate[ 0 ];
+
+
+ y = mod->fr[ i ] ->tr[ p ] ->vertex[ 2 ] * mod->fr[ i ] ->scale[ 2 ] + mod->fr[ i ] ->translate[ 2 ];
+
+
+ z = mod->fr[ i ] ->tr[ p ] ->vertex[ 1 ] * mod->fr[ i ] ->scale[ 1 ] + mod->fr[ i ] ->translate[ 1 ];
+ if ( x < xmin ) xmin = x;
+ if ( x > xmax ) xmax = x;
+ if ( y < ymin ) ymin = y;
+ if ( y > ymax ) ymax = y;
+ if ( z < zmin ) zmin = z;
+ if ( z > zmax ) zmax = z;
+ }
+ }
+ }
+ }
+ if ( fhead == NULL )
+ {
+ cpointer = NULL;
+ return ;
+ }
+
+ cpointer = fhead;
+ current_frame_sequence = name;
+ ftail->next = fhead;
+ oldt = 0.0f;
+
+ return ;
+}
+
+void c_model::delFrameSequence( void )
+{
+ fnode * tmp;
+ fnode *tmp1;
+
+ if ( fhead != NULL )
+ {
+
+ tmp = fhead->next;
+ tmp1 = fhead;
+
+ if ( fhead->next == fhead )
+ {
+ free( fhead );
+ fhead = NULL;
+ ftail = NULL;
+ }
+ else
+ {
+ while ( 1 )
+ {
+ if ( tmp == fhead ) break;
+ free( tmp1 );
+ tmp1 = tmp;
+ tmp = tmp->next;
+ }
+ free( tmp1 );
+ }
+ fhead = NULL;
+ ftail = NULL;
+ }
+ nframes = -1;
+ return ;
+}
+
+void c_model::render()
+{
+ float t;
+ t = gettime();
+ if ( oldt > t ) cpointer = cpointer->next;
+ oldt = t;
+
+ mod->cpointer = cpointer;
+ mod->render( t );
+ return ;
+}
+
+
+
+float c_model::gettime( void )
+{
+ int k = SDL_GetTicks();
+ k = k % ( ( int ) ( FPS + 1.0f ) );
+ return ( float ) k / ( float ) FPS;
+}
+
+
+c_model::~c_model( void )
+{
+ delFrameSequence();
+ return ;
+}
+
--- /dev/null
+/***************************************************************************\r
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *\r
+ * <psybases@gmail.com> *\r
+ * *\r
+ * This program is free software; you can redistribute it and/or modify *\r
+ * it under the terms of the GNU Library General Public License as *\r
+ * published by the Free Software Foundation; either version 2 of the *\r
+ * License, or (at your option) any later version. *\r
+ * *\r
+ * This program is distributed in the hope that it will be useful, *\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\r
+ * GNU General Public License for more details. *\r
+ * *\r
+ * You should have received a copy of the GNU Library General Public *\r
+ * License along with this program; if not, write to the *\r
+ * Free Software Foundation, Inc., *\r
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *\r
+ ***************************************************************************/\r
+\r
+#include "modelLoader.h"\r
+\r
+modelLoader::modelLoader(Graphics *g)\r
+{\r
+ gr=g;\r
+ m[0]=new model("tris.md2", "masked.bmp",g);\r
+ return ;\r
+}\r
+\r
+modelLoader::~modelLoader(void)\r
+{\r
+ int i;\r
+ for (i=0;i<Different_types;i++)\r
+ delete m[i];\r
+\r
+ return ;\r
+}\r
+\r
+c_model * modelLoader::getModel(int type)\r
+{\r
+ c_model * ctmp;\r
+\r
+ ctmp=new c_model(m[type]);\r
+ ctmp->setFrameSequence("stand");\r
+\r
+ return ctmp;\r
+}\r
--- /dev/null
+/***************************************************************************\r
+ * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos *\r
+ * <psybases@gmail.com> *\r
+ * *\r
+ * This program is free software; you can redistribute it and/or modify *\r
+ * it under the terms of the GNU Library General Public License as *\r
+ * published by the Free Software Foundation; either version 2 of the *\r
+ * License, or (at your option) any later version. *\r
+ * *\r
+ * This program is distributed in the hope that it will be useful, *\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\r
+ * GNU General Public License for more details. *\r
+ * *\r
+ * You should have received a copy of the GNU Library General Public *\r
+ * License along with this program; if not, write to the *\r
+ * Free Software Foundation, Inc., *\r
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *\r
+ ***************************************************************************/\r
+\r
+#ifndef _MODELLOADER\r
+#define _MODELLOADER\r
+\r
+#include"Graphics.h"\r
+#include"md2model.h"\r
+\r
+#define Different_types 1\r
+\r
+class modelLoader;\r
+\r
+class modelLoader\r
+{\r
+private:\r
+ model *m[Different_types];\r
+\r
+public:\r
+ Graphics *gr;\r
+ modelLoader(Graphics *g);\r
+ ~modelLoader(void);\r
+\r
+ c_model * getModel(int type);\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include <amaltheia/Graphics.h>
+#include <amaltheia/Input.h>
+#include <amaltheia/Sprite.h>
+#include <amaltheia/System.h>
+
+Graphics *g;
+Input *inp;
+Texture *t;
+vertex v[24];
+
+bool init(void)
+{
+ g = new Graphics(1024, 768, 16, true);
+ g->setBackground(COLOUR_RGBA(127, 127, 127, 255));
+ g->setCullingMode( AM_CULL_NONE);
+ g->createDisplay();
+
+ t = new Texture("amaltheia.png", g);
+ inp = new Input(true, true);
+
+ /*1st quad*/
+ v[0].x = -5.0; v[0].y = 5.0; v[0].z = -5.0;
+ v[0].u = 0; v[0].v = 0; v[0].col = COLOUR_RGBA(55, 55, 255, 255);
+ v[1].x = 5.0; v[1].y = 5.0; v[1].z = -5.0;
+ v[1].u = 1; v[1].v = 0; v[1].col = COLOUR_RGBA(50, 100, 200, 255);
+ v[2].x = -5.0; v[2].y = -5.0; v[2].z = -5.0;
+ v[2].u = 0; v[2].v = 1; v[2].col = COLOUR_RGBA(255, 255, 255, 255);
+ v[3].x = 5.0; v[3].y = -5.0; v[3].z = -5.0;
+ v[3].u = 1; v[3].v = 1; v[3].col = COLOUR_RGBA(50, 100, 200, 255);
+
+ /*2nd quad*/
+ v[4] = v[0]; v[4].z = 5.0;
+ v[4].u = 1 - v[4].u;
+ v[5] = v[1]; v[5].z = 5.0;
+ v[5].u = 1 - v[5].u;
+ v[6] = v[2]; v[6].z = 5.0;
+ v[6].u = 1 - v[6].u;
+ v[7] = v[3]; v[7].z = 5.0;
+ v[7].u = 1 - v[7].u;
+ //3rd
+ v[8] = v[4];
+ v[8].u = 1 - v[8].u;
+ v[9] = v[0];
+ v[9].u = 1 - v[9].u;
+ v[10] = v[6];
+ v[10].u = 1 - v[10].u;
+ v[11] = v[2];
+ v[11].u = 1 - v[11].u;
+
+ //4th
+ v[12] = v[1];
+ v[12].u = 1 - v[12].u;
+ v[13] = v[5];
+ v[13].u = 1 - v[13].u;
+ v[14] =v[3];
+ v[14].u = 1 - v[14].u;
+ v[15] =v[7];
+ v[15].u = 1 - v[15].u;
+
+ //5th
+ v[16] = v[2];
+ v[17] = v[3];
+ v[18] = v[6];
+ v[19] = v[7];
+
+ //6th
+ v[20] = v[0];
+ v[21] = v[1];
+ v[22] = v[4];
+ v[23] = v[5];
+
+ g->setTexture(t);
+
+ return true;
+}
+
+
+bool renderFrame()
+{
+ static float rx = 0.0;
+ static long tm = getTime();
+
+ if(inp->keyboardGetKeyState(KEY_ESC))
+ return false;
+
+ while(getTime() - tm <= 19)
+ return true;
+
+ tm = getTime();
+
+ rx += 0.5;
+
+ g->beginScene();
+ g->setCamera(0,0, -30, 0, 0, 0, 0, 1,0);
+ g->setWorld(0,0,0, rx, 0 ,rx, 1,1,1);
+ g->renderVertexArray(v, 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[4], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[8], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[12], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[16], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[20], 4, AM_TRIANGLE_STRIP);
+
+ g->setWorld(10, 10, 10, 5*rx, 5*rx ,rx, 0.5, .5, .5);
+ g->renderVertexArray(v, 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[4], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[8], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[12], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[16], 4, AM_TRIANGLE_STRIP);
+ g->renderVertexArray(&v[20], 4, AM_TRIANGLE_STRIP);
+
+ g->endScene();
+
+ return true;
+}
+
+
+bool cleanup()
+{
+ delete inp;
+ delete t;
+ delete g;
+
+ return true;
+}
--- /dev/null
+#include <amaltheia/Graphics.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+Graphics *g;
+
+#include <cassert>
+#include <string> // For memset
+#include <ft2build.h>
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
+#include <freetype/ftoutln.h>
+#include <freetype/fttrigon.h>
+
+//#include "FTGLTextureFont.h"
+//#include "FTTextureGlyph.h"
+typedef double FTGL_DOUBLE;
+typedef float FTGL_FLOAT;
+
+// Fixes for deprecated identifiers in 2.1.5
+#ifndef FT_OPEN_MEMORY
+#define FT_OPEN_MEMORY (FT_Open_Flags)1
+#endif
+
+#ifndef FT_RENDER_MODE_MONO
+#define FT_RENDER_MODE_MONO ft_render_mode_mono
+#endif
+
+#ifndef FT_RENDER_MODE_NORMAL
+#define FT_RENDER_MODE_NORMAL ft_render_mode_normal
+#endif
+
+
+
+
+
+inline unsigned int NextPowerOf2( unsigned int in)
+{
+ in -= 1;
+
+ in |= in >> 16;
+ in |= in >> 8;
+ in |= in >> 4;
+ in |= in >> 2;
+ in |= in >> 1;
+
+ return in + 1;
+}
+
+
+class FTPoint
+{
+ public:
+ FTPoint()
+ {
+ values[0] = 0;
+ values[1] = 0;
+ values[2] = 0;
+ }
+ FTPoint( const double x, const double y, const double z)
+ {
+ values[0] = x;
+ values[1] = y;
+ values[2] = z;
+ }
+
+ FTPoint( const FT_Vector& ft_vector)
+ {
+ values[0] = ft_vector.x;
+ values[1] = ft_vector.y;
+ values[2] = 0;
+ }
+
+ FTPoint& operator += ( const FTPoint& point)
+ {
+ values[0] += point.values[0];
+ values[1] += point.values[1];
+ values[2] += point.values[2];
+
+ return *this;
+ }
+
+ FTPoint operator + ( const FTPoint& point)
+ {
+ FTPoint temp;
+ temp.values[0] = values[0] + point.values[0];
+ temp.values[1] = values[1] + point.values[1];
+ temp.values[2] = values[2] + point.values[2];
+
+ return temp;
+ }
+
+ FTPoint operator * ( double multiplier)
+ {
+ FTPoint temp;
+ temp.values[0] = values[0] * multiplier;
+ temp.values[1] = values[1] * multiplier;
+ temp.values[2] = values[2] * multiplier;
+
+ return temp;
+ }
+
+
+ friend FTPoint operator*( double multiplier, FTPoint& point);
+ friend bool operator == ( const FTPoint &a, const FTPoint &b);
+ friend bool operator != ( const FTPoint &a, const FTPoint &b);
+ operator const double*() const
+ {
+ return values;
+ }
+ void X( double x) { values[0] = x;};
+ void Y( double y) { values[1] = y;};
+ void Z( double z) { values[2] = z;};
+ double X() const { return values[0];};
+ double Y() const { return values[1];};
+ double Z() const { return values[2];};
+
+ private:
+ double values[3];
+};
+
+bool operator == ( const FTPoint &a, const FTPoint &b)
+{
+ return((a.values[0] == b.values[0]) && (a.values[1] == b.values[1]) && (a.values[2] == b.values[2]));
+}
+
+bool operator != ( const FTPoint &a, const FTPoint &b)
+{
+ return((a.values[0] != b.values[0]) || (a.values[1] != b.values[1]) || (a.values[2] != b.values[2]));
+}
+
+FTPoint operator*( double multiplier, FTPoint& point)
+{
+ return point * multiplier;
+}
+
+
+class FTBBox
+{
+ public:
+
+ FTBBox()
+ : lowerX(0.0f),
+ lowerY(0.0f),
+ lowerZ(0.0f),
+ upperX(0.0f),
+ upperY(0.0f),
+ upperZ(0.0f)
+ {}
+
+ FTBBox( float lx, float ly, float lz, float ux, float uy, float uz)
+ : lowerX(lx),
+ lowerY(ly),
+ lowerZ(lz),
+ upperX(ux),
+ upperY(uy),
+ upperZ(uz)
+ {}
+
+
+ FTBBox( FT_GlyphSlot glyph)
+ : lowerX(0.0f),
+ lowerY(0.0f),
+ lowerZ(0.0f),
+ upperX(0.0f),
+ upperY(0.0f),
+ upperZ(0.0f)
+ {
+ FT_BBox bbox;
+ FT_Outline_Get_CBox( &(glyph->outline), &bbox);
+
+ lowerX = static_cast<float>( bbox.xMin) / 64.0f;
+ lowerY = static_cast<float>( bbox.yMin) / 64.0f;
+ lowerZ = 0.0f;
+ upperX = static_cast<float>( bbox.xMax) / 64.0f;
+ upperY = static_cast<float>( bbox.yMax) / 64.0f;
+ upperZ = 0.0f;
+
+ }
+
+ ~FTBBox()
+ {}
+
+ FTBBox& Move( FTPoint distance)
+ {
+ lowerX += distance.X();
+ lowerY += distance.Y();
+ lowerZ += distance.Z();
+ upperX += distance.X();
+ upperY += distance.Y();
+ upperZ += distance.Z();
+ return *this;
+ }
+
+ FTBBox& operator += ( const FTBBox& bbox)
+ {
+ lowerX = bbox.lowerX < lowerX? bbox.lowerX: lowerX;
+ lowerY = bbox.lowerY < lowerY? bbox.lowerY: lowerY;
+ lowerZ = bbox.lowerZ < lowerZ? bbox.lowerZ: lowerZ;
+ upperX = bbox.upperX > upperX? bbox.upperX: upperX;
+ upperY = bbox.upperY > upperY? bbox.upperY: upperY;
+ upperZ = bbox.upperZ > upperZ? bbox.upperZ: upperZ;
+
+ return *this;
+ }
+
+ void SetDepth( float depth)
+ {
+ upperZ = lowerZ + depth;
+ }
+
+ float lowerX, lowerY, lowerZ, upperX, upperY, upperZ;
+ protected:
+
+ private:
+};
+
+
+
+
+
+class FTGlyph
+{
+ public:
+ FTGlyph( FT_GlyphSlot glyph, bool useList = true)
+ {
+ useDisplayList = useList;
+ err = 0;
+ if( glyph)
+ {
+ bBox = FTBBox( glyph);
+ advance = FTPoint( glyph->advance.x / 64.0f, glyph->advance.y / 64.0f, 0.0f);
+ }
+ }
+
+ virtual FTGlyph::~FTGlyph()
+ {}
+
+ virtual const FTPoint& Render( const FTPoint& pen) = 0;
+ const FTPoint& Advance() const { return advance;}
+ const FTBBox& BBox() const { return bBox;}
+ FT_Error Error() const { return err;}
+
+ protected:
+ FTPoint advance;
+ FTBBox bBox;
+ bool useDisplayList;
+ FT_Error err;
+
+ private:
+};
+
+
+
+
+
+
+class FTLibrary
+{
+ public:
+ static const FTLibrary& Instance();
+ const FT_Library* const GetLibrary() const { return library;}
+ FT_Error Error() const { return err;}
+ ~FTLibrary();
+
+ private:
+ FTLibrary();
+ FTLibrary( const FT_Library&){}
+ FTLibrary& operator=( const FT_Library&) { return *this; }
+
+ bool Initialise();
+ FT_Library* library;
+ FT_Error err;
+
+};
+
+
+
+
+const FTLibrary& FTLibrary::Instance()
+{
+ static FTLibrary ftlib;
+ return ftlib;
+}
+
+
+FTLibrary::~FTLibrary()
+{
+ if( library != 0)
+ {
+ FT_Done_FreeType( *library);
+
+ delete library;
+ library= 0;
+ }
+
+// if( manager != 0)
+// {
+// FTC_Manager_Done( manager );
+ //
+// delete manager;
+// manager= 0;
+// }
+}
+
+
+FTLibrary::FTLibrary()
+ : library(0),
+ err(0)
+{
+ Initialise();
+}
+
+
+bool FTLibrary::Initialise()
+{
+ if( library != 0)
+ return true;
+
+ library = new FT_Library;
+
+ err = FT_Init_FreeType( library);
+ if( err)
+ {
+ delete library;
+ library = 0;
+ return false;
+ }
+
+// FTC_Manager* manager;
+ //
+// if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager )
+// {
+// delete manager;
+// manager= 0;
+// return false;
+// }
+
+ return true;
+}
+
+
+
+
+class FTSize
+{
+ public:
+ FTSize();
+ virtual ~FTSize();
+ bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution);
+ unsigned int CharSize() const;
+ float Ascender() const;
+ float Descender() const;
+ float Height() const;
+ float Width() const;
+ float Underline() const;
+ FT_Error Error() const { return err; }
+
+ private:
+ FT_Face* ftFace;
+ FT_Size ftSize;
+ unsigned int size;
+ unsigned int xResolution;
+ unsigned int yResolution;
+ FT_Error err;
+
+};
+
+
+
+FTSize::FTSize()
+ : ftFace(0),
+ ftSize(0),
+ size(0),
+ xResolution(0),
+ yResolution(0),
+ err(0)
+{}
+
+
+ FTSize::~FTSize()
+ {}
+
+
+ bool FTSize::CharSize( FT_Face* face, unsigned int pointSize, unsigned int xRes, unsigned int yRes )
+ {
+ if( size != pointSize || xResolution != xRes || yResolution != yRes)
+ {
+ err = FT_Set_Char_Size( *face, 0L, pointSize * 64, xResolution, yResolution);
+
+ if( !err)
+ {
+ ftFace = face;
+ size = pointSize;
+ xResolution = xRes;
+ yResolution = yRes;
+ ftSize = (*ftFace)->size;
+ }
+ else
+ {
+ ftFace = 0;
+ size = 0;
+ xResolution = 0;
+ yResolution = 0;
+ ftSize = 0;
+ }
+ }
+
+ return !err;
+ }
+
+
+ unsigned int FTSize::CharSize() const
+ {
+ return size;
+ }
+
+
+ float FTSize::Ascender() const
+ {
+ return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.ascender) / 64.0f;
+ }
+
+
+ float FTSize::Descender() const
+ {
+ return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.descender) / 64.0f;
+ }
+
+
+ float FTSize::Height() const
+ {
+ if( 0 == ftSize)
+ {
+ return 0.0f;
+ }
+
+ if( FT_IS_SCALABLE((*ftFace)))
+ {
+ return ( (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin) * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
+ }
+ else
+ {
+ return static_cast<float>( ftSize->metrics.height) / 64.0f;
+ }
+ }
+
+
+ float FTSize::Width() const
+ {
+ if( 0 == ftSize)
+ {
+ return 0.0f;
+ }
+
+ if( FT_IS_SCALABLE((*ftFace)))
+ {
+ return ( (*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) * ( static_cast<float>(ftSize->metrics.x_ppem) / static_cast<float>((*ftFace)->units_per_EM));
+ }
+ else
+ {
+ return static_cast<float>( ftSize->metrics.max_advance) / 64.0f;
+ }
+ }
+
+
+ float FTSize::Underline() const
+ {
+ return 0.0f;
+ }
+
+
+
+
+class FTFace
+{
+ public:
+
+ FTFace( const char* fontFilePath);
+ FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes );
+ virtual ~FTFace();
+
+ bool Attach( const char* fontFilePath);
+ bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+ FT_Face* Face() const { return ftFace;}
+ const FTSize& Size( const unsigned int size, const unsigned int res);
+ unsigned int CharMapCount();
+ FT_Encoding* CharMapList();
+ FTPoint KernAdvance( unsigned int index1, unsigned int index2);
+ FT_GlyphSlot Glyph( unsigned int index, FT_Int load_flags);
+ unsigned int GlyphCount() const { return numGlyphs;}
+ FT_Error Error() const { return err; }
+
+ private:
+ FT_Face* ftFace;
+ FTSize charSize;
+ int numGlyphs;
+ FT_Encoding* fontEncodingList;
+ bool hasKerningTable;
+ FT_Error err;
+};
+
+FTFace::FTFace( const char* fontFilePath)
+ : numGlyphs(0),
+ fontEncodingList(0),
+ err(0)
+{
+ const FT_Long DEFAULT_FACE_INDEX = 0;
+ ftFace = new FT_Face;
+
+ err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), fontFilePath, DEFAULT_FACE_INDEX, ftFace);
+
+ if( err)
+ {
+ delete ftFace;
+ ftFace = 0;
+ }
+ else
+ {
+ numGlyphs = (*ftFace)->num_glyphs;
+ hasKerningTable = FT_HAS_KERNING((*ftFace));
+ }
+}
+
+
+FTFace::FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+ : numGlyphs(0),
+ err(0)
+{
+ const FT_Long DEFAULT_FACE_INDEX = 0;
+ ftFace = new FT_Face;
+
+ err = FT_New_Memory_Face( *FTLibrary::Instance().GetLibrary(), (FT_Byte *)pBufferBytes, bufferSizeInBytes, DEFAULT_FACE_INDEX, ftFace);
+
+ if( err)
+ {
+ delete ftFace;
+ ftFace = 0;
+ }
+ else
+ {
+ numGlyphs = (*ftFace)->num_glyphs;
+ }
+}
+
+
+FTFace::~FTFace()
+{
+ if( ftFace)
+ {
+ FT_Done_Face( *ftFace);
+ delete ftFace;
+ ftFace = 0;
+ }
+}
+
+
+bool FTFace::Attach( const char* fontFilePath)
+{
+ err = FT_Attach_File( *ftFace, fontFilePath);
+ return !err;
+}
+
+
+bool FTFace::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+{
+ FT_Open_Args open;
+
+ open.flags = FT_OPEN_MEMORY;
+ open.memory_base = (FT_Byte *)pBufferBytes;
+ open.memory_size = bufferSizeInBytes;
+
+ err = FT_Attach_Stream( *ftFace, &open);
+ return !err;
+}
+
+
+const FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
+{
+ charSize.CharSize( ftFace, size, res, res);
+ err = charSize.Error();
+
+ return charSize;
+}
+
+
+unsigned int FTFace::CharMapCount()
+{
+ return (*ftFace)->num_charmaps;
+}
+
+
+FT_Encoding* FTFace::CharMapList()
+{
+ if( 0 == fontEncodingList)
+ {
+ fontEncodingList = new FT_Encoding[CharMapCount()];
+ for( size_t encodingIndex = 0; encodingIndex < CharMapCount(); ++encodingIndex)
+ {
+ fontEncodingList[encodingIndex] = (*ftFace)->charmaps[encodingIndex]->encoding;
+ }
+ }
+
+ return fontEncodingList;
+}
+
+
+FTPoint FTFace::KernAdvance( unsigned int index1, unsigned int index2)
+{
+ float x, y;
+ x = y = 0.0f;
+
+ if( hasKerningTable && index1 && index2)
+ {
+ FT_Vector kernAdvance;
+ kernAdvance.x = kernAdvance.y = 0;
+
+ err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
+ if( !err)
+ {
+ x = static_cast<float>( kernAdvance.x) / 64.0f;
+ y = static_cast<float>( kernAdvance.y) / 64.0f;
+ }
+ }
+
+ return FTPoint( x, y, 0.0);
+}
+
+
+FT_GlyphSlot FTFace::Glyph( unsigned int index, FT_Int load_flags)
+{
+ err = FT_Load_Glyph( *ftFace, index, load_flags);
+ if( err)
+ {
+ return NULL;
+ }
+
+ return (*ftFace)->glyph;
+}
+
+
+
+
+
+
+
+
+
+ template <typename FT_VECTOR_ITEM_TYPE> class FTVector
+{
+ public:
+ typedef FT_VECTOR_ITEM_TYPE value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+ typedef size_t size_type;
+
+ FTVector()
+ {
+ Capacity = Size = 0;
+ Items = 0;
+ }
+
+
+ virtual ~FTVector()
+ {
+ clear();
+ }
+
+ FTVector& operator =(const FTVector& v)
+ {
+ reserve(v.capacity());
+
+ iterator ptr = begin();
+ const_iterator vbegin = v.begin();
+ const_iterator vend = v.end();
+
+ while( vbegin != vend)
+ {
+ *ptr++ = *vbegin++;
+ }
+
+ Size = v.size();
+ return *this;
+ }
+
+ size_type size() const
+ {
+ return Size;
+ }
+
+ size_type capacity() const
+ {
+ return Capacity;
+ }
+
+ iterator begin()
+ {
+ return Items;
+ }
+
+ const_iterator begin() const
+ {
+ return Items;
+ }
+
+ iterator end()
+ {
+ return begin() + size();
+ }
+
+ const_iterator end() const
+ {
+ return begin() + size();
+ }
+
+ bool empty() const
+ {
+ return size() == 0;
+ }
+
+ reference operator [](size_type pos)
+ {
+ return( *(begin() + pos));
+ }
+
+ const_reference operator []( size_type pos) const
+ {
+ return( *(begin() + pos));
+ }
+
+ void clear()
+ {
+ if( Capacity)
+ {
+ delete [] Items;
+ Capacity = Size = 0;
+ Items = 0;
+ }
+ }
+
+ void reserve( size_type n)
+ {
+ if( capacity() < n)
+ {
+ expand(n);
+ }
+ }
+
+ void push_back(const value_type& x)
+ {
+ if( size() == capacity())
+ {
+ expand();
+ }
+
+ ( *this)[size()] = x;
+ ++Size;
+ }
+
+ void resize(size_type n, value_type x)
+ {
+ if( n == size())
+ {
+ return;
+ }
+
+ reserve(n);
+ iterator begin, end;
+
+ if( n >= Size)
+ {
+ begin = this->end();
+ end = this->begin() + n;
+ }
+ else
+ {
+ begin = this->begin() + n;
+ end = this->end();
+ }
+
+ while( begin != end)
+ {
+ *begin++ = x;
+ }
+
+ Size = n;
+ }
+
+
+ private:
+ void expand(size_type capacity_hint = 0)
+ {
+ size_type new_capacity =( capacity() == 0) ? 256 : capacity()* 2;
+ if( capacity_hint)
+ {
+ while( new_capacity < capacity_hint)
+ {
+ new_capacity *= 2;
+ }
+ }
+
+ value_type *new_items = new value_type[new_capacity];
+
+ iterator begin = this->begin();
+ iterator end = this->end();
+ value_type *ptr = new_items;
+
+ while( begin != end)
+ {
+ *ptr++ = *begin++;
+ }
+
+ if( Capacity)
+ {
+ delete [] Items;
+ }
+
+ Items = new_items;
+ Capacity = new_capacity;
+ }
+
+ size_type Capacity;
+ size_type Size;
+ value_type* Items;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+class FTCharToGlyphIndexMap
+{
+ public:
+
+ typedef unsigned long CharacterCode;
+ typedef signed long GlyphIndex;
+
+ enum
+ {
+ NumberOfBuckets = 256,
+ BucketSize = 256,
+ IndexNotFound = -1
+ };
+
+ FTCharToGlyphIndexMap()
+ {
+ this->Indices = 0;
+ }
+
+ virtual ~FTCharToGlyphIndexMap()
+ {
+ if( this->Indices)
+ {
+ // Free all buckets
+ this->clear();
+
+ // Free main structure
+ delete [] this->Indices;
+ this->Indices = 0;
+ }
+ }
+
+ void clear()
+ {
+ if(this->Indices)
+ {
+ for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
+ {
+ if( this->Indices[i])
+ {
+ delete [] this->Indices[i];
+ this->Indices[i] = 0;
+ }
+ }
+ }
+ }
+
+ const GlyphIndex find( CharacterCode c)
+ {
+ if( !this->Indices)
+ {
+ return 0;
+ }
+
+ // Find position of char code in buckets
+ div_t pos = div( c, FTCharToGlyphIndexMap::BucketSize);
+
+ if( !this->Indices[pos.quot])
+ {
+ return 0;
+ }
+
+ const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem];
+ if( *ptr == FTCharToGlyphIndexMap::IndexNotFound)
+ {
+ return 0;
+ }
+
+ return *ptr;
+ }
+
+ void insert( CharacterCode c, GlyphIndex g)
+ {
+ if( !this->Indices)
+ {
+ this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets];
+ for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
+ {
+ this->Indices[i] = 0;
+ }
+ }
+
+ // Find position of char code in buckets
+ div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
+
+ // Allocate bucket if does not exist yet
+ if( !this->Indices[pos.quot])
+ {
+ this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize];
+ for( int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++)
+ {
+ this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound;
+ }
+ }
+
+ this->Indices[pos.quot][pos.rem] = g;
+ }
+
+ private:
+ GlyphIndex** Indices;
+};
+
+
+
+
+
+class FTCharmap
+{
+ public:
+ FTCharmap( FTFace* face);
+ virtual ~FTCharmap();
+
+ FT_Encoding Encoding() const { return ftEncoding;}
+ bool CharMap( FT_Encoding encoding);
+ unsigned int GlyphListIndex( const unsigned int characterCode);
+ unsigned int FontIndex( const unsigned int characterCode);
+ void InsertIndex( const unsigned int characterCode, const unsigned int containerIndex);
+ FT_Error Error() const { return err;}
+
+ private:
+ FT_Encoding ftEncoding;
+ const FT_Face ftFace;
+ typedef FTCharToGlyphIndexMap CharacterMap;
+ CharacterMap charMap;
+
+ FT_Error err;
+
+};
+
+
+
+
+
+FTCharmap::FTCharmap( FTFace* face)
+ : ftFace( *(face->Face())),
+ err(0)
+{
+ if( !ftFace->charmap)
+ {
+ err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]);
+ }
+
+ ftEncoding = ftFace->charmap->encoding;
+}
+
+
+FTCharmap::~FTCharmap()
+{
+ charMap.clear();
+}
+
+
+bool FTCharmap::CharMap( FT_Encoding encoding)
+{
+ if( ftEncoding == encoding)
+ {
+ return true;
+ }
+
+ err = FT_Select_Charmap( ftFace, encoding );
+
+ if( !err)
+ {
+ ftEncoding = encoding;
+ }
+ else
+ {
+ ftEncoding = ft_encoding_none;
+ }
+
+ charMap.clear();
+ return !err;
+}
+
+
+unsigned int FTCharmap::GlyphListIndex( unsigned int characterCode )
+{
+ return charMap.find( characterCode);
+}
+
+
+unsigned int FTCharmap::FontIndex( unsigned int characterCode )
+{
+ return FT_Get_Char_Index( ftFace, characterCode);
+}
+
+
+void FTCharmap::InsertIndex( const unsigned int characterCode, const unsigned int containerIndex)
+{
+ charMap.insert( characterCode, containerIndex);
+}
+
+
+
+
+class FTGlyphContainer
+{
+ typedef FTVector<FTGlyph*> GlyphVector;
+ public:
+ FTGlyphContainer( FTFace* face);
+ ~FTGlyphContainer();
+ bool CharMap( FT_Encoding encoding);
+ unsigned int FontIndex( const unsigned int characterCode ) const;
+ void Add( FTGlyph* glyph, const unsigned int characterCode);
+ const FTGlyph* const Glyph( const unsigned int characterCode) const;
+ FTBBox BBox( const unsigned int characterCode) const;
+ float Advance( const unsigned int characterCode, const unsigned int nextCharacterCode);
+
+ FTPoint Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition);
+
+ FT_Error Error() const { return err;}
+
+ private:
+ FTFace* face;
+ FTCharmap* charMap;
+
+ GlyphVector glyphs;
+
+ FT_Error err;
+};
+
+
+FTGlyphContainer::FTGlyphContainer( FTFace* f)
+ : face(f),
+ err(0)
+{
+ glyphs.push_back( NULL);
+ charMap = new FTCharmap( face);
+}
+
+
+FTGlyphContainer::~FTGlyphContainer()
+{
+ GlyphVector::iterator glyphIterator;
+ for( glyphIterator = glyphs.begin(); glyphIterator != glyphs.end(); ++glyphIterator)
+ {
+ delete *glyphIterator;
+ }
+
+ glyphs.clear();
+ delete charMap;
+}
+
+
+bool FTGlyphContainer::CharMap( FT_Encoding encoding)
+{
+ bool result = charMap->CharMap( encoding);
+ err = charMap->Error();
+ return result;
+}
+
+
+unsigned int FTGlyphContainer::FontIndex( const unsigned int characterCode) const
+{
+ return charMap->FontIndex( characterCode);
+}
+
+
+void FTGlyphContainer::Add( FTGlyph* tempGlyph, const unsigned int characterCode)
+{
+ charMap->InsertIndex( characterCode, glyphs.size());
+ glyphs.push_back( tempGlyph);
+}
+
+
+const FTGlyph* const FTGlyphContainer::Glyph( const unsigned int characterCode) const
+{
+ signed int index = charMap->GlyphListIndex( characterCode);
+ return glyphs[index];
+}
+
+
+FTBBox FTGlyphContainer::BBox( const unsigned int characterCode) const
+{
+ return glyphs[charMap->GlyphListIndex( characterCode)]->BBox();
+}
+
+
+float FTGlyphContainer::Advance( const unsigned int characterCode, const unsigned int nextCharacterCode)
+{
+ unsigned int left = charMap->FontIndex( characterCode);
+ unsigned int right = charMap->FontIndex( nextCharacterCode);
+
+ float width = face->KernAdvance( left, right).X();
+ width += glyphs[charMap->GlyphListIndex( characterCode)]->Advance().X();
+
+ return width;
+}
+
+
+FTPoint FTGlyphContainer::Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition)
+{
+ FTPoint kernAdvance, advance;
+
+ unsigned int left = charMap->FontIndex( characterCode);
+ unsigned int right = charMap->FontIndex( nextCharacterCode);
+
+ kernAdvance = face->KernAdvance( left, right);
+
+ if( !face->Error())
+ {
+ advance = glyphs[charMap->GlyphListIndex( characterCode)]->Render( penPosition);
+ }
+
+ kernAdvance += advance;
+ return kernAdvance;
+}
+
+
+
+
+
+
+
+
+
+class FTFont
+{
+ public:
+
+ FTFont( const char* fontFilePath);
+ FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+ virtual ~FTFont();
+
+ bool Attach( const char* fontFilePath);
+ bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+ bool CharMap( FT_Encoding encoding );
+ unsigned int CharMapCount();
+ FT_Encoding* CharMapList();
+ virtual bool FaceSize( const unsigned int size, const unsigned int res = 72);
+ unsigned int FaceSize() const;
+ virtual void Depth( float depth){}
+ void UseDisplayList( bool useList);
+ float Ascender() const;
+ float Descender() const;
+ float LineHeight() const;
+ void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+ void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+ float Advance( const wchar_t* string);
+ float Advance( const char* string);
+ virtual void Render( const char* string );
+ virtual void Render( const wchar_t* string );
+ FT_Error Error() const { return err;}
+
+ protected:
+ virtual FTGlyph* MakeGlyph( unsigned int g) = 0;
+ FTFace face;
+ FTSize charSize;
+ bool useDisplayLists;
+ FT_Error err;
+
+ private:
+ inline bool CheckGlyph( const unsigned int chr);
+ FTGlyphContainer* glyphList;
+ FTPoint pen;
+};
+
+
+
+FTFont::FTFont( const char* fontFilePath) : face( fontFilePath), useDisplayLists(true), glyphList(0)
+{
+ err = face.Error();
+ if( err == 0)
+ {
+ glyphList = new FTGlyphContainer( &face);
+ }
+}
+
+
+
+
+class FTTextureGlyph : public FTGlyph
+{
+ public:
+ FTTextureGlyph( FT_GlyphSlot glyph, int id, int xOffset, int yOffset, int width, int height);
+ virtual ~FTTextureGlyph();
+ virtual const FTPoint& Render( const FTPoint& pen);
+ static void FTTextureGlyph::ResetActiveTexture(){ activeTextureID = 0;}
+
+ private:
+
+ int destWidth;
+ int destHeight;
+ FTPoint pos;
+ FTPoint uv[2];
+ int glTextureID;
+ static int activeTextureID;
+
+};
+
+
+int FTTextureGlyph::activeTextureID = 0;
+
+FTTextureGlyph::FTTextureGlyph( FT_GlyphSlot glyph, int id, int xOffset, int yOffset, int width, int height)
+ : FTGlyph( glyph),
+ destWidth(0),
+ destHeight(0),
+ glTextureID(id)
+{
+ err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL);
+ if( err || glyph->format != ft_glyph_format_bitmap)
+ {
+ return;
+ }
+
+ FT_Bitmap bitmap = glyph->bitmap;
+
+ destWidth = bitmap.width;
+ destHeight = bitmap.rows;
+
+ if( destWidth && destHeight)
+ {
+ glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
+ glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
+
+ glBindTexture( GL_TEXTURE_2D, glTextureID);
+ glTexSubImage2D( GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
+
+ glPopClientAttrib();
+ }
+
+
+ uv[0].X( static_cast<float>(xOffset) / static_cast<float>(width));
+ uv[0].Y( static_cast<float>(yOffset) / static_cast<float>(height));
+ uv[1].X( static_cast<float>( xOffset + destWidth) / static_cast<float>(width));
+ uv[1].Y( static_cast<float>( yOffset + destHeight) / static_cast<float>(height));
+
+ pos.X( glyph->bitmap_left);
+ pos.Y( glyph->bitmap_top);
+}
+
+
+FTTextureGlyph::~FTTextureGlyph()
+{}
+
+
+const FTPoint& FTTextureGlyph::Render( const FTPoint& pen)
+{
+ if( activeTextureID != glTextureID)
+ {
+ glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID);
+ activeTextureID = glTextureID;
+ }
+
+ glTranslatef( pen.X(), pen.Y(), 0.0f);
+
+ glBegin( GL_QUADS);
+ glTexCoord2f( uv[0].X(), uv[0].Y());
+ glVertex2f( pos.X(), pos.Y());
+
+ glTexCoord2f( uv[0].X(), uv[1].Y());
+ glVertex2f( pos.X(), pos.Y() - destHeight);
+
+ glTexCoord2f( uv[1].X(), uv[1].Y());
+ glVertex2f( destWidth + pos.X(), pos.Y() - destHeight);
+
+ glTexCoord2f( uv[1].X(), uv[0].Y());
+ glVertex2f( destWidth + pos.X(), pos.Y());
+ glEnd();
+
+ return advance;
+}
+
+
+
+
+
+class myFont : public FTFont
+{
+
+ private:
+ inline virtual FTGlyph* MakeGlyph( unsigned int glyphIndex)
+ {
+ FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
+
+ if( ftGlyph)
+ {
+ glyphHeight = static_cast<int>( charSize.Height());
+ glyphWidth = static_cast<int>( charSize.Width());
+
+ if( textureIDList.empty())
+ {
+ textureIDList.push_back( CreateTexture());
+ xOffset = yOffset = padding;
+ }
+
+ if( xOffset > ( textureWidth - glyphWidth))
+ {
+ xOffset = padding;
+ yOffset += glyphHeight;
+
+ if( yOffset > ( textureHeight - glyphHeight))
+ {
+ textureIDList.push_back( CreateTexture());
+ yOffset = padding;
+ }
+ }
+
+ FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
+ xOffset, yOffset, textureWidth, textureHeight);
+ xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
+
+ --remGlyphs;
+ return tempGlyph;
+ }
+
+ err = face.Error();
+ return NULL;
+ }
+
+ inline void CalculateTextureSize()
+ {
+ if( !maximumGLTextureSize)
+ {
+ glGetIntegerv( GL_MAX_TEXTURE_SIZE, (int*)&maximumGLTextureSize);
+ assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
+ }
+
+ textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
+ textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
+
+ int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
+
+ textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
+ textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
+ }
+
+
+ inline uint CreateTexture()
+ {
+ CalculateTextureSize();
+
+ int totalMemory = textureWidth * textureHeight;
+ unsigned char* textureMemory = new unsigned char[totalMemory];
+ memset( textureMemory, 0, totalMemory);
+
+ unsigned int textID;
+ glGenTextures( 1, (unsigned int*)&textID);
+
+ glBindTexture( GL_TEXTURE_2D, textID);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
+
+ delete [] textureMemory;
+
+ return textID;
+ }
+
+
+
+ int maximumGLTextureSize;
+ int textureWidth;
+ int textureHeight;
+ FTVector<GLuint> textureIDList;
+ int glyphHeight;
+ int glyphWidth;
+ unsigned int padding;
+ unsigned int numGlyphs;
+ unsigned int remGlyphs;
+ int xOffset;
+ int yOffset;
+
+
+ public:
+
+
+ myFont( const char* fontFilePath) : FTFont( fontFilePath),
+ maximumGLTextureSize(0),
+ textureWidth(0),
+ textureHeight(0),
+ glyphHeight(0),
+ glyphWidth(0),
+ padding(3),
+ xOffset(0),
+ yOffset(0)
+{
+ remGlyphs = numGlyphs = face.GlyphCount();
+}
+
+~myFont()
+{
+ glDeleteTextures( textureIDList.size(), (const unsigned int*)&textureIDList[0]);
+}
+
+
+void print( char *str, int x1, int y1, int x2, int y2, colour c )
+{
+ g->enter2dMode();
+ glColor4f( c.r, c.g, c.b, c.a);
+ float h= LineHeight()*0.64f; /* factor 0.64*/
+ glTranslatef(x1, y1 + h, 0);
+ glScalef(1.0, -1.0, 1.0);
+ Render(str);
+// ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
+ g->leave2dMode();
+}
+
+
+
+bool FaceSize( const unsigned int size, const unsigned int res)
+{
+ if( !textureIDList.empty())
+ {
+ glDeleteTextures( textureIDList.size(), (const uint*)&textureIDList[0]);
+ textureIDList.clear();
+ remGlyphs = numGlyphs = face.GlyphCount();
+ }
+
+ return FTFont::FaceSize( size, res);
+}
+
+
+void Render( const char* string)
+{
+ glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
+
+ FTTextureGlyph::ResetActiveTexture();
+
+ FTFont::Render( string);
+
+ glPopAttrib();
+}
+
+
+void Render( const wchar_t* string)
+{
+ glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
+
+ FTTextureGlyph::ResetActiveTexture();
+
+ FTFont::Render( string);
+
+ glPopAttrib();
+}
+
+};
+
+
+
+myFont *f;
+Font *t;
+
+bool init(void)
+{
+ g = new Graphics(1024, 768); // bring me a 1024x768 resolution
+ g->createDisplay();
+// // g->setBackground(COLOUR_RGBA(0, 255, 0, 0)); //green background
+ f = new myFont("Test.ttf");
+ f->FaceSize(16, 72);
+ f->CharMap(ft_encoding_unicode);
+
+ t = new Font(g, "Test.ttf", 16);
+ return true;
+}
+
+
+bool renderFrame()
+{
+ g->beginScene();
+ f->print("MPLA", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
+// t->print("hello", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
+ g->endScene();
+
+ sleep(7);
+ return false;
+}
+
+bool cleanup()
+{
+ delete g;
+ return true;
+}
+
--- /dev/null
+#include <amaltheia/Graphics.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+
+#include <cassert>
+#include <string> // For memset
+#include <ft2build.h>
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
+#include <freetype/ftoutln.h>
+#include <freetype/fttrigon.h>
+
+
+Graphics *g;
+
+//#include "FTGLTextureFont.h"
+//#include "FTTextureGlyph.h"
+typedef double FTGL_DOUBLE;
+typedef float FTGL_FLOAT;
+
+// Fixes for deprecated identifiers in 2.1.5
+#ifndef FT_OPEN_MEMORY
+#define FT_OPEN_MEMORY (FT_Open_Flags)1
+#endif
+
+#ifndef FT_RENDER_MODE_MONO
+#define FT_RENDER_MODE_MONO ft_render_mode_mono
+#endif
+
+#ifndef FT_RENDER_MODE_NORMAL
+#define FT_RENDER_MODE_NORMAL ft_render_mode_normal
+#endif
+
+
+
+
+
+inline unsigned int NextPowerOf2( unsigned int in)
+{
+ in -= 1;
+
+ in |= in >> 16;
+ in |= in >> 8;
+ in |= in >> 4;
+ in |= in >> 2;
+ in |= in >> 1;
+
+ return in + 1;
+}
+
+
+class FTPoint
+{
+ public:
+ FTPoint()
+ {
+ values[0] = 0;
+ values[1] = 0;
+ values[2] = 0;
+ }
+ FTPoint( const double x, const double y, const double z)
+ {
+ values[0] = x;
+ values[1] = y;
+ values[2] = z;
+ }
+
+ FTPoint( const FT_Vector& ft_vector)
+ {
+ values[0] = ft_vector.x;
+ values[1] = ft_vector.y;
+ values[2] = 0;
+ }
+
+ FTPoint& operator += ( const FTPoint& point)
+ {
+ values[0] += point.values[0];
+ values[1] += point.values[1];
+ values[2] += point.values[2];
+
+ return *this;
+ }
+
+ FTPoint operator + ( const FTPoint& point)
+ {
+ FTPoint temp;
+ temp.values[0] = values[0] + point.values[0];
+ temp.values[1] = values[1] + point.values[1];
+ temp.values[2] = values[2] + point.values[2];
+
+ return temp;
+ }
+
+ FTPoint operator * ( double multiplier)
+ {
+ FTPoint temp;
+ temp.values[0] = values[0] * multiplier;
+ temp.values[1] = values[1] * multiplier;
+ temp.values[2] = values[2] * multiplier;
+
+ return temp;
+ }
+
+
+ friend FTPoint operator*( double multiplier, FTPoint& point);
+ friend bool operator == ( const FTPoint &a, const FTPoint &b);
+ friend bool operator != ( const FTPoint &a, const FTPoint &b);
+ operator const double*() const
+ {
+ return values;
+ }
+ void X( double x) { values[0] = x;};
+ void Y( double y) { values[1] = y;};
+ void Z( double z) { values[2] = z;};
+ double X() const { return values[0];};
+ double Y() const { return values[1];};
+ double Z() const { return values[2];};
+
+ private:
+ double values[3];
+};
+
+bool operator == ( const FTPoint &a, const FTPoint &b)
+{
+ return((a.values[0] == b.values[0]) && (a.values[1] == b.values[1]) && (a.values[2] == b.values[2]));
+}
+
+bool operator != ( const FTPoint &a, const FTPoint &b)
+{
+ return((a.values[0] != b.values[0]) || (a.values[1] != b.values[1]) || (a.values[2] != b.values[2]));
+}
+
+FTPoint operator*( double multiplier, FTPoint& point)
+{
+ return point * multiplier;
+}
+
+
+class FTBBox
+{
+ public:
+
+ FTBBox()
+ : lowerX(0.0f),
+ lowerY(0.0f),
+ lowerZ(0.0f),
+ upperX(0.0f),
+ upperY(0.0f),
+ upperZ(0.0f)
+ {}
+
+ FTBBox( float lx, float ly, float lz, float ux, float uy, float uz)
+ : lowerX(lx),
+ lowerY(ly),
+ lowerZ(lz),
+ upperX(ux),
+ upperY(uy),
+ upperZ(uz)
+ {}
+
+
+ FTBBox( FT_GlyphSlot glyph)
+ : lowerX(0.0f),
+ lowerY(0.0f),
+ lowerZ(0.0f),
+ upperX(0.0f),
+ upperY(0.0f),
+ upperZ(0.0f)
+ {
+ FT_BBox bbox;
+ FT_Outline_Get_CBox( &(glyph->outline), &bbox);
+
+ lowerX = static_cast<float>( bbox.xMin) / 64.0f;
+ lowerY = static_cast<float>( bbox.yMin) / 64.0f;
+ lowerZ = 0.0f;
+ upperX = static_cast<float>( bbox.xMax) / 64.0f;
+ upperY = static_cast<float>( bbox.yMax) / 64.0f;
+ upperZ = 0.0f;
+
+ }
+
+ ~FTBBox()
+ {}
+
+ FTBBox& Move( FTPoint distance)
+ {
+ lowerX += distance.X();
+ lowerY += distance.Y();
+ lowerZ += distance.Z();
+ upperX += distance.X();
+ upperY += distance.Y();
+ upperZ += distance.Z();
+ return *this;
+ }
+
+ FTBBox& operator += ( const FTBBox& bbox)
+ {
+ lowerX = bbox.lowerX < lowerX? bbox.lowerX: lowerX;
+ lowerY = bbox.lowerY < lowerY? bbox.lowerY: lowerY;
+ lowerZ = bbox.lowerZ < lowerZ? bbox.lowerZ: lowerZ;
+ upperX = bbox.upperX > upperX? bbox.upperX: upperX;
+ upperY = bbox.upperY > upperY? bbox.upperY: upperY;
+ upperZ = bbox.upperZ > upperZ? bbox.upperZ: upperZ;
+
+ return *this;
+ }
+
+ void SetDepth( float depth)
+ {
+ upperZ = lowerZ + depth;
+ }
+
+ float lowerX, lowerY, lowerZ, upperX, upperY, upperZ;
+ protected:
+
+ private:
+};
+
+
+
+
+
+class FTGlyph
+{
+ public:
+ FTGlyph( FT_GlyphSlot glyph, bool useList = true)
+ {
+ useDisplayList = useList;
+ err = 0;
+ if( glyph)
+ {
+ bBox = FTBBox( glyph);
+ advance = FTPoint( glyph->advance.x / 64.0f, glyph->advance.y / 64.0f, 0.0f);
+ }
+ }
+
+ virtual FTGlyph::~FTGlyph()
+ {}
+
+ virtual const FTPoint& Render( const FTPoint& pen) = 0;
+ const FTPoint& Advance() const { return advance;}
+ const FTBBox& BBox() const { return bBox;}
+ FT_Error Error() const { return err;}
+
+ protected:
+ FTPoint advance;
+ FTBBox bBox;
+ bool useDisplayList;
+ FT_Error err;
+
+ private:
+};
+
+
+
+
+
+
+class FTLibrary
+{
+ public:
+ static const FTLibrary& Instance();
+ const FT_Library* const GetLibrary() const { return library;}
+ FT_Error Error() const { return err;}
+ ~FTLibrary();
+
+ private:
+ FTLibrary();
+ FTLibrary( const FT_Library&){}
+ FTLibrary& operator=( const FT_Library&) { return *this; }
+
+ bool Initialise();
+ FT_Library* library;
+ FT_Error err;
+
+};
+
+
+
+
+const FTLibrary& FTLibrary::Instance()
+{
+ static FTLibrary ftlib;
+ return ftlib;
+}
+
+
+FTLibrary::~FTLibrary()
+{
+ if( library != 0)
+ {
+ FT_Done_FreeType( *library);
+
+ delete library;
+ library= 0;
+ }
+
+// if( manager != 0)
+// {
+// FTC_Manager_Done( manager );
+ //
+// delete manager;
+// manager= 0;
+// }
+}
+
+
+FTLibrary::FTLibrary()
+ : library(0),
+ err(0)
+{
+ Initialise();
+}
+
+
+bool FTLibrary::Initialise()
+{
+ if( library != 0)
+ return true;
+
+ library = new FT_Library;
+
+ err = FT_Init_FreeType( library);
+ if( err)
+ {
+ delete library;
+ library = 0;
+ return false;
+ }
+
+// FTC_Manager* manager;
+ //
+// if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager )
+// {
+// delete manager;
+// manager= 0;
+// return false;
+// }
+
+ return true;
+}
+
+
+
+
+class FTSize
+{
+ public:
+ FTSize();
+ virtual ~FTSize();
+ bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution);
+ unsigned int CharSize() const;
+ float Ascender() const;
+ float Descender() const;
+ float Height() const;
+ float Width() const;
+ float Underline() const;
+ FT_Error Error() const { return err; }
+
+ private:
+ FT_Face* ftFace;
+ FT_Size ftSize;
+ unsigned int size;
+ unsigned int xResolution;
+ unsigned int yResolution;
+ FT_Error err;
+
+};
+
+
+
+FTSize::FTSize()
+ : ftFace(0),
+ ftSize(0),
+ size(0),
+ xResolution(0),
+ yResolution(0),
+ err(0)
+{}
+
+
+ FTSize::~FTSize()
+ {}
+
+
+ bool FTSize::CharSize( FT_Face* face, unsigned int pointSize, unsigned int xRes, unsigned int yRes )
+ {
+ if( size != pointSize || xResolution != xRes || yResolution != yRes)
+ {
+ err = FT_Set_Char_Size( *face, 0L, pointSize * 64, xResolution, yResolution);
+
+ if( !err)
+ {
+ ftFace = face;
+ size = pointSize;
+ xResolution = xRes;
+ yResolution = yRes;
+ ftSize = (*ftFace)->size;
+ }
+ else
+ {
+ ftFace = 0;
+ size = 0;
+ xResolution = 0;
+ yResolution = 0;
+ ftSize = 0;
+ }
+ }
+
+ return !err;
+ }
+
+
+ unsigned int FTSize::CharSize() const
+ {
+ return size;
+ }
+
+
+ float FTSize::Ascender() const
+ {
+ return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.ascender) / 64.0f;
+ }
+
+
+ float FTSize::Descender() const
+ {
+ return ftSize == 0 ? 0.0f : static_cast<float>( ftSize->metrics.descender) / 64.0f;
+ }
+
+
+ float FTSize::Height() const
+ {
+ if( 0 == ftSize)
+ {
+ return 0.0f;
+ }
+
+ if( FT_IS_SCALABLE((*ftFace)))
+ {
+ return ( (*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin) * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM);
+ }
+ else
+ {
+ return static_cast<float>( ftSize->metrics.height) / 64.0f;
+ }
+ }
+
+
+ float FTSize::Width() const
+ {
+ if( 0 == ftSize)
+ {
+ return 0.0f;
+ }
+
+ if( FT_IS_SCALABLE((*ftFace)))
+ {
+ return ( (*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) * ( static_cast<float>(ftSize->metrics.x_ppem) / static_cast<float>((*ftFace)->units_per_EM));
+ }
+ else
+ {
+ return static_cast<float>( ftSize->metrics.max_advance) / 64.0f;
+ }
+ }
+
+
+ float FTSize::Underline() const
+ {
+ return 0.0f;
+ }
+
+
+
+
+class FTFace
+{
+ public:
+
+ FTFace( const char* fontFilePath);
+ FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes );
+ virtual ~FTFace();
+
+ bool Attach( const char* fontFilePath);
+ bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+ FT_Face* Face() const { return ftFace;}
+ const FTSize& Size( const unsigned int size, const unsigned int res);
+ unsigned int CharMapCount();
+ FT_Encoding* CharMapList();
+ FTPoint KernAdvance( unsigned int index1, unsigned int index2);
+ FT_GlyphSlot Glyph( unsigned int index, FT_Int load_flags);
+ unsigned int GlyphCount() const { return numGlyphs;}
+ FT_Error Error() const { return err; }
+
+ private:
+ FT_Face* ftFace;
+ FTSize charSize;
+ int numGlyphs;
+ FT_Encoding* fontEncodingList;
+ bool hasKerningTable;
+ FT_Error err;
+};
+
+FTFace::FTFace( const char* fontFilePath)
+ : numGlyphs(0),
+ fontEncodingList(0),
+ err(0)
+{
+ const FT_Long DEFAULT_FACE_INDEX = 0;
+ ftFace = new FT_Face;
+
+ err = FT_New_Face( *FTLibrary::Instance().GetLibrary(), fontFilePath, DEFAULT_FACE_INDEX, ftFace);
+
+ if( err)
+ {
+ delete ftFace;
+ ftFace = 0;
+ }
+ else
+ {
+ numGlyphs = (*ftFace)->num_glyphs;
+ hasKerningTable = FT_HAS_KERNING((*ftFace));
+ }
+}
+
+
+FTFace::FTFace( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+ : numGlyphs(0),
+ err(0)
+{
+ const FT_Long DEFAULT_FACE_INDEX = 0;
+ ftFace = new FT_Face;
+
+ err = FT_New_Memory_Face( *FTLibrary::Instance().GetLibrary(), (FT_Byte *)pBufferBytes, bufferSizeInBytes, DEFAULT_FACE_INDEX, ftFace);
+
+ if( err)
+ {
+ delete ftFace;
+ ftFace = 0;
+ }
+ else
+ {
+ numGlyphs = (*ftFace)->num_glyphs;
+ }
+}
+
+
+FTFace::~FTFace()
+{
+ if( ftFace)
+ {
+ FT_Done_Face( *ftFace);
+ delete ftFace;
+ ftFace = 0;
+ }
+}
+
+
+bool FTFace::Attach( const char* fontFilePath)
+{
+ err = FT_Attach_File( *ftFace, fontFilePath);
+ return !err;
+}
+
+
+bool FTFace::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+{
+ FT_Open_Args open;
+
+ open.flags = FT_OPEN_MEMORY;
+ open.memory_base = (FT_Byte *)pBufferBytes;
+ open.memory_size = bufferSizeInBytes;
+
+ err = FT_Attach_Stream( *ftFace, &open);
+ return !err;
+}
+
+
+const FTSize& FTFace::Size( const unsigned int size, const unsigned int res)
+{
+ charSize.CharSize( ftFace, size, res, res);
+ err = charSize.Error();
+
+ return charSize;
+}
+
+
+unsigned int FTFace::CharMapCount()
+{
+ return (*ftFace)->num_charmaps;
+}
+
+
+FT_Encoding* FTFace::CharMapList()
+{
+ if( 0 == fontEncodingList)
+ {
+ fontEncodingList = new FT_Encoding[CharMapCount()];
+ for( size_t encodingIndex = 0; encodingIndex < CharMapCount(); ++encodingIndex)
+ {
+ fontEncodingList[encodingIndex] = (*ftFace)->charmaps[encodingIndex]->encoding;
+ }
+ }
+
+ return fontEncodingList;
+}
+
+
+FTPoint FTFace::KernAdvance( unsigned int index1, unsigned int index2)
+{
+ float x, y;
+ x = y = 0.0f;
+
+ if( hasKerningTable && index1 && index2)
+ {
+ FT_Vector kernAdvance;
+ kernAdvance.x = kernAdvance.y = 0;
+
+ err = FT_Get_Kerning( *ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance);
+ if( !err)
+ {
+ x = static_cast<float>( kernAdvance.x) / 64.0f;
+ y = static_cast<float>( kernAdvance.y) / 64.0f;
+ }
+ }
+
+ return FTPoint( x, y, 0.0);
+}
+
+
+FT_GlyphSlot FTFace::Glyph( unsigned int index, FT_Int load_flags)
+{
+ err = FT_Load_Glyph( *ftFace, index, load_flags);
+ if( err)
+ {
+ return NULL;
+ }
+
+ return (*ftFace)->glyph;
+}
+
+
+
+
+
+
+
+
+
+ template <typename FT_VECTOR_ITEM_TYPE> class FTVector
+{
+ public:
+ typedef FT_VECTOR_ITEM_TYPE value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+ typedef size_t size_type;
+
+ FTVector()
+ {
+ Capacity = Size = 0;
+ Items = 0;
+ }
+
+
+ virtual ~FTVector()
+ {
+ clear();
+ }
+
+ FTVector& operator =(const FTVector& v)
+ {
+ reserve(v.capacity());
+
+ iterator ptr = begin();
+ const_iterator vbegin = v.begin();
+ const_iterator vend = v.end();
+
+ while( vbegin != vend)
+ {
+ *ptr++ = *vbegin++;
+ }
+
+ Size = v.size();
+ return *this;
+ }
+
+ size_type size() const
+ {
+ return Size;
+ }
+
+ size_type capacity() const
+ {
+ return Capacity;
+ }
+
+ iterator begin()
+ {
+ return Items;
+ }
+
+ const_iterator begin() const
+ {
+ return Items;
+ }
+
+ iterator end()
+ {
+ return begin() + size();
+ }
+
+ const_iterator end() const
+ {
+ return begin() + size();
+ }
+
+ bool empty() const
+ {
+ return size() == 0;
+ }
+
+ reference operator [](size_type pos)
+ {
+ return( *(begin() + pos));
+ }
+
+ const_reference operator []( size_type pos) const
+ {
+ return( *(begin() + pos));
+ }
+
+ void clear()
+ {
+ if( Capacity)
+ {
+ delete [] Items;
+ Capacity = Size = 0;
+ Items = 0;
+ }
+ }
+
+ void reserve( size_type n)
+ {
+ if( capacity() < n)
+ {
+ expand(n);
+ }
+ }
+
+ void push_back(const value_type& x)
+ {
+ if( size() == capacity())
+ {
+ expand();
+ }
+
+ ( *this)[size()] = x;
+ ++Size;
+ }
+
+ void resize(size_type n, value_type x)
+ {
+ if( n == size())
+ {
+ return;
+ }
+
+ reserve(n);
+ iterator begin, end;
+
+ if( n >= Size)
+ {
+ begin = this->end();
+ end = this->begin() + n;
+ }
+ else
+ {
+ begin = this->begin() + n;
+ end = this->end();
+ }
+
+ while( begin != end)
+ {
+ *begin++ = x;
+ }
+
+ Size = n;
+ }
+
+
+ private:
+ void expand(size_type capacity_hint = 0)
+ {
+ size_type new_capacity =( capacity() == 0) ? 256 : capacity()* 2;
+ if( capacity_hint)
+ {
+ while( new_capacity < capacity_hint)
+ {
+ new_capacity *= 2;
+ }
+ }
+
+ value_type *new_items = new value_type[new_capacity];
+
+ iterator begin = this->begin();
+ iterator end = this->end();
+ value_type *ptr = new_items;
+
+ while( begin != end)
+ {
+ *ptr++ = *begin++;
+ }
+
+ if( Capacity)
+ {
+ delete [] Items;
+ }
+
+ Items = new_items;
+ Capacity = new_capacity;
+ }
+
+ size_type Capacity;
+ size_type Size;
+ value_type* Items;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+class FTCharToGlyphIndexMap
+{
+ public:
+
+ typedef unsigned long CharacterCode;
+ typedef signed long GlyphIndex;
+
+ enum
+ {
+ NumberOfBuckets = 256,
+ BucketSize = 256,
+ IndexNotFound = -1
+ };
+
+ FTCharToGlyphIndexMap()
+ {
+ this->Indices = 0;
+ }
+
+ virtual ~FTCharToGlyphIndexMap()
+ {
+ if( this->Indices)
+ {
+ // Free all buckets
+ this->clear();
+
+ // Free main structure
+ delete [] this->Indices;
+ this->Indices = 0;
+ }
+ }
+
+ void clear()
+ {
+ if(this->Indices)
+ {
+ for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
+ {
+ if( this->Indices[i])
+ {
+ delete [] this->Indices[i];
+ this->Indices[i] = 0;
+ }
+ }
+ }
+ }
+
+ const GlyphIndex find( CharacterCode c)
+ {
+ if( !this->Indices)
+ {
+ return 0;
+ }
+
+ // Find position of char code in buckets
+ div_t pos = div( c, FTCharToGlyphIndexMap::BucketSize);
+
+ if( !this->Indices[pos.quot])
+ {
+ return 0;
+ }
+
+ const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem];
+ if( *ptr == FTCharToGlyphIndexMap::IndexNotFound)
+ {
+ return 0;
+ }
+
+ return *ptr;
+ }
+
+ void insert( CharacterCode c, GlyphIndex g)
+ {
+ if( !this->Indices)
+ {
+ this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets];
+ for( int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++)
+ {
+ this->Indices[i] = 0;
+ }
+ }
+
+ // Find position of char code in buckets
+ div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize);
+
+ // Allocate bucket if does not exist yet
+ if( !this->Indices[pos.quot])
+ {
+ this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize];
+ for( int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++)
+ {
+ this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound;
+ }
+ }
+
+ this->Indices[pos.quot][pos.rem] = g;
+ }
+
+ private:
+ GlyphIndex** Indices;
+};
+
+
+
+
+
+class FTCharmap
+{
+ public:
+ FTCharmap( FTFace* face);
+ virtual ~FTCharmap();
+
+ FT_Encoding Encoding() const { return ftEncoding;}
+ bool CharMap( FT_Encoding encoding);
+ unsigned int GlyphListIndex( const unsigned int characterCode);
+ unsigned int FontIndex( const unsigned int characterCode);
+ void InsertIndex( const unsigned int characterCode, const unsigned int containerIndex);
+ FT_Error Error() const { return err;}
+
+ private:
+ FT_Encoding ftEncoding;
+ const FT_Face ftFace;
+ typedef FTCharToGlyphIndexMap CharacterMap;
+ CharacterMap charMap;
+
+ FT_Error err;
+
+};
+
+
+
+
+
+FTCharmap::FTCharmap( FTFace* face)
+ : ftFace( *(face->Face())),
+ err(0)
+{
+ if( !ftFace->charmap)
+ {
+ err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]);
+ }
+
+ ftEncoding = ftFace->charmap->encoding;
+}
+
+
+FTCharmap::~FTCharmap()
+{
+ charMap.clear();
+}
+
+
+bool FTCharmap::CharMap( FT_Encoding encoding)
+{
+ if( ftEncoding == encoding)
+ {
+ return true;
+ }
+
+ err = FT_Select_Charmap( ftFace, encoding );
+
+ if( !err)
+ {
+ ftEncoding = encoding;
+ }
+ else
+ {
+ ftEncoding = ft_encoding_none;
+ }
+
+ charMap.clear();
+ return !err;
+}
+
+
+unsigned int FTCharmap::GlyphListIndex( unsigned int characterCode )
+{
+ return charMap.find( characterCode);
+}
+
+
+unsigned int FTCharmap::FontIndex( unsigned int characterCode )
+{
+ return FT_Get_Char_Index( ftFace, characterCode);
+}
+
+
+void FTCharmap::InsertIndex( const unsigned int characterCode, const unsigned int containerIndex)
+{
+ charMap.insert( characterCode, containerIndex);
+}
+
+
+
+
+class FTGlyphContainer
+{
+ typedef FTVector<FTGlyph*> GlyphVector;
+ public:
+ FTGlyphContainer( FTFace* face);
+ ~FTGlyphContainer();
+ bool CharMap( FT_Encoding encoding);
+ unsigned int FontIndex( const unsigned int characterCode ) const;
+ void Add( FTGlyph* glyph, const unsigned int characterCode);
+ const FTGlyph* const Glyph( const unsigned int characterCode) const;
+ FTBBox BBox( const unsigned int characterCode) const;
+ float Advance( const unsigned int characterCode, const unsigned int nextCharacterCode);
+
+ FTPoint Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition);
+
+ FT_Error Error() const { return err;}
+
+ private:
+ FTFace* face;
+ FTCharmap* charMap;
+
+ GlyphVector glyphs;
+
+ FT_Error err;
+};
+
+
+FTGlyphContainer::FTGlyphContainer( FTFace* f)
+ : face(f),
+ err(0)
+{
+ glyphs.push_back( NULL);
+ charMap = new FTCharmap( face);
+}
+
+
+FTGlyphContainer::~FTGlyphContainer()
+{
+ GlyphVector::iterator glyphIterator;
+ for( glyphIterator = glyphs.begin(); glyphIterator != glyphs.end(); ++glyphIterator)
+ {
+ delete *glyphIterator;
+ }
+
+ glyphs.clear();
+ delete charMap;
+}
+
+
+bool FTGlyphContainer::CharMap( FT_Encoding encoding)
+{
+ bool result = charMap->CharMap( encoding);
+ err = charMap->Error();
+ return result;
+}
+
+
+unsigned int FTGlyphContainer::FontIndex( const unsigned int characterCode) const
+{
+ return charMap->FontIndex( characterCode);
+}
+
+
+void FTGlyphContainer::Add( FTGlyph* tempGlyph, const unsigned int characterCode)
+{
+ charMap->InsertIndex( characterCode, glyphs.size());
+ glyphs.push_back( tempGlyph);
+}
+
+
+const FTGlyph* const FTGlyphContainer::Glyph( const unsigned int characterCode) const
+{
+ signed int index = charMap->GlyphListIndex( characterCode);
+ return glyphs[index];
+}
+
+
+FTBBox FTGlyphContainer::BBox( const unsigned int characterCode) const
+{
+ return glyphs[charMap->GlyphListIndex( characterCode)]->BBox();
+}
+
+
+float FTGlyphContainer::Advance( const unsigned int characterCode, const unsigned int nextCharacterCode)
+{
+ unsigned int left = charMap->FontIndex( characterCode);
+ unsigned int right = charMap->FontIndex( nextCharacterCode);
+
+ float width = face->KernAdvance( left, right).X();
+ width += glyphs[charMap->GlyphListIndex( characterCode)]->Advance().X();
+
+ return width;
+}
+
+
+FTPoint FTGlyphContainer::Render( const unsigned int characterCode, const unsigned int nextCharacterCode, FTPoint penPosition)
+{
+ FTPoint kernAdvance, advance;
+
+ unsigned int left = charMap->FontIndex( characterCode);
+ unsigned int right = charMap->FontIndex( nextCharacterCode);
+
+ kernAdvance = face->KernAdvance( left, right);
+
+ if( !face->Error())
+ {
+ advance = glyphs[charMap->GlyphListIndex( characterCode)]->Render( penPosition);
+ }
+
+ kernAdvance += advance;
+ return kernAdvance;
+}
+
+
+
+
+
+
+
+
+
+class FTFont
+{
+ public:
+
+ FTFont( const char* fontFilePath);
+ FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+ virtual ~FTFont();
+
+ bool Attach( const char* fontFilePath);
+ bool Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes);
+ bool CharMap( FT_Encoding encoding );
+ unsigned int CharMapCount();
+ FT_Encoding* CharMapList();
+ virtual bool FaceSize( const unsigned int size, const unsigned int res = 72);
+ unsigned int FaceSize() const;
+ virtual void Depth( float depth){}
+ void UseDisplayList( bool useList);
+ float Ascender() const;
+ float Descender() const;
+ float LineHeight() const;
+ void BBox( const char* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+ void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz);
+ float Advance( const wchar_t* string);
+ float Advance( const char* string);
+ virtual void Render( const char* string );
+ virtual void Render( const wchar_t* string );
+ FT_Error Error() const { return err;}
+
+ protected:
+ virtual FTGlyph* MakeGlyph( unsigned int g) = 0;
+ FTFace face;
+ FTSize charSize;
+ bool useDisplayLists;
+ FT_Error err;
+
+ private:
+ inline bool CheckGlyph( const unsigned int chr);
+ FTGlyphContainer* glyphList;
+ FTPoint pen;
+};
+
+
+
+FTFont::FTFont( const char* fontFilePath) : face(fontFilePath), useDisplayLists(true), glyphList(0)
+{
+ err = face.Error();
+ if( err == 0)
+ {
+ glyphList = new FTGlyphContainer( &face);
+ }
+}
+
+
+
+
+FTFont::FTFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+ : face( pBufferBytes, bufferSizeInBytes),
+ glyphList(0)
+{
+ err = face.Error();
+ if( err == 0)
+ {
+ glyphList = new FTGlyphContainer( &face);
+ }
+}
+
+
+FTFont::~FTFont()
+{
+ delete glyphList;
+}
+
+
+bool FTFont::Attach( const char* fontFilePath)
+{
+ if( face.Attach( fontFilePath))
+ {
+ err = 0;
+ return true;
+ }
+ else
+ {
+ err = face.Error();
+ return false;
+ }
+}
+
+
+bool FTFont::Attach( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
+{
+ if( face.Attach( pBufferBytes, bufferSizeInBytes))
+ {
+ err = 0;
+ return true;
+ }
+ else
+ {
+ err = face.Error();
+ return false;
+ }
+}
+
+
+bool FTFont::FaceSize( const unsigned int size, const unsigned int res )
+{
+ charSize = face.Size( size, res);
+ err = face.Error();
+
+ if( err != 0)
+ {
+ return false;
+ }
+
+ if( glyphList != NULL)
+ {
+ delete glyphList;
+ }
+
+ glyphList = new FTGlyphContainer( &face);
+ return true;
+}
+
+
+unsigned int FTFont::FaceSize() const
+{
+ return charSize.CharSize();
+}
+
+
+bool FTFont::CharMap( FT_Encoding encoding)
+{
+ bool result = glyphList->CharMap( encoding);
+ err = glyphList->Error();
+ return result;
+}
+
+
+unsigned int FTFont::CharMapCount()
+{
+ return face.CharMapCount();
+}
+
+
+FT_Encoding* FTFont::CharMapList()
+{
+ return face.CharMapList();
+}
+
+
+void FTFont::UseDisplayList( bool useList)
+{
+ useDisplayLists = useList;
+}
+
+float FTFont::Ascender() const
+{
+ return charSize.Ascender();
+}
+
+
+float FTFont::Descender() const
+{
+ return charSize.Descender();
+}
+
+float FTFont::LineHeight() const
+{
+ return charSize.Height();
+}
+
+void FTFont::BBox( const char* string,
+ float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+{
+ FTBBox totalBBox;
+
+ if((NULL != string) && ('\0' != *string))
+ {
+ const unsigned char* c = (unsigned char*)string;
+ float advance = 0;
+
+ if(CheckGlyph( *c))
+ {
+ totalBBox = glyphList->BBox( *c);
+ advance = glyphList->Advance( *c, *(c + 1));
+ }
+
+ while( *++c)
+ {
+ if(CheckGlyph( *c))
+ {
+ FTBBox tempBBox = glyphList->BBox( *c);
+ tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
+ totalBBox += tempBBox;
+ advance += glyphList->Advance( *c, *(c + 1));
+ }
+ }
+ }
+
+ llx = totalBBox.lowerX;
+ lly = totalBBox.lowerY;
+ llz = totalBBox.lowerZ;
+ urx = totalBBox.upperX;
+ ury = totalBBox.upperY;
+ urz = totalBBox.upperZ;
+}
+
+
+void FTFont::BBox( const wchar_t* string,
+ float& llx, float& lly, float& llz, float& urx, float& ury, float& urz)
+{
+ FTBBox totalBBox;
+
+ if((NULL != string) && ('\0' != *string))
+ {
+ const wchar_t* c = string;
+ float advance = 0;
+
+ if(CheckGlyph( *c))
+ {
+ totalBBox = glyphList->BBox( *c);
+ advance = glyphList->Advance( *c, *(c + 1));
+ }
+
+ while( *++c)
+ {
+ if(CheckGlyph( *c))
+ {
+ FTBBox tempBBox = glyphList->BBox( *c);
+ tempBBox.Move( FTPoint( advance, 0.0f, 0.0f));
+ totalBBox += tempBBox;
+ advance += glyphList->Advance( *c, *(c + 1));
+ }
+ }
+ }
+
+ llx = totalBBox.lowerX;
+ lly = totalBBox.lowerY;
+ llz = totalBBox.lowerZ;
+ urx = totalBBox.upperX;
+ ury = totalBBox.upperY;
+ urz = totalBBox.upperZ;
+}
+
+
+float FTFont::Advance( const wchar_t* string)
+{
+ const wchar_t* c = string;
+ float width = 0.0f;
+
+ while( *c)
+ {
+ if(CheckGlyph( *c))
+ {
+ width += glyphList->Advance( *c, *(c + 1));
+ }
+ ++c;
+ }
+
+ return width;
+}
+
+
+float FTFont::Advance( const char* string)
+{
+ const unsigned char* c = (unsigned char*)string;
+ float width = 0.0f;
+
+ while( *c)
+ {
+ if(CheckGlyph( *c))
+ {
+ width += glyphList->Advance( *c, *(c + 1));
+ }
+ ++c;
+ }
+
+ return width;
+}
+
+
+void FTFont::Render( const char* string )
+{
+ const unsigned char* c = (unsigned char*)string;
+ pen.X(0); pen.Y(0);
+
+ while( *c)
+ {
+ if(CheckGlyph( *c))
+ {
+ pen = glyphList->Render( *c, *(c + 1), pen);
+ }
+ ++c;
+ }
+}
+
+
+void FTFont::Render( const wchar_t* string )
+{
+ const wchar_t* c = string;
+ pen.X(0); pen.Y(0);
+
+ while( *c)
+ {
+ if(CheckGlyph( *c))
+ {
+ pen = glyphList->Render( *c, *(c + 1), pen);
+ }
+ ++c;
+ }
+}
+
+
+bool FTFont::CheckGlyph( const unsigned int characterCode)
+{
+ if( NULL == glyphList->Glyph( characterCode))
+ {
+ unsigned int glyphIndex = glyphList->FontIndex( characterCode);
+ FTGlyph* tempGlyph = MakeGlyph( glyphIndex);
+ if( NULL == tempGlyph)
+ {
+ if( 0 == err)
+ {
+ err = 0x13;
+ }
+
+ return false;
+ }
+ glyphList->Add( tempGlyph, characterCode);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+class FTTextureGlyph : public FTGlyph
+{
+ public:
+ FTTextureGlyph( FT_GlyphSlot glyph, Texture * tid, int xOffset, int yOffset, int width, int height);
+ virtual ~FTTextureGlyph();
+ virtual const FTPoint& Render( const FTPoint& pen);
+ static void FTTextureGlyph::ResetActiveTexture()
+ {
+ activeTextureID = 0;
+ activeTexture = 0;
+ }
+
+ private:
+ int destWidth;
+ int destHeight;
+ FTPoint pos;
+ FTPoint uv[2];
+ int glTextureID;
+ Texture* textureID;
+ static int activeTextureID;
+ static Texture* activeTexture;
+
+};
+
+
+int FTTextureGlyph::activeTextureID = 0;
+Texture* FTTextureGlyph::activeTexture = 0;
+
+FTTextureGlyph::FTTextureGlyph( FT_GlyphSlot glyph, Texture *tid, int xOffset, int yOffset, int width, int height)
+ : FTGlyph(glyph)
+{
+ destWidth = 0;
+ destHeight = 0;
+
+ textureID = tid;
+ glTextureID = tid->gl_Tex;
+
+ err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL);
+ if( err || glyph->format != ft_glyph_format_bitmap)
+ {
+ return;
+ }
+
+ FT_Bitmap bitmap = glyph->bitmap;
+
+ destWidth = bitmap.width;
+ destHeight = bitmap.rows;
+
+ int tW=0, tH=0;
+ if( destWidth && destHeight)
+ {
+ glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT);
+ glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
+
+
+ g->setTexture(tid);
+// glBindTexture( GL_TEXTURE_2D, glTextureID);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,GL_TEXTURE_WIDTH, &tW);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,GL_TEXTURE_HEIGHT, &tH);
+ tid->texSubImage2D(xOffset, yOffset, destWidth, destHeight, AM_ALPHA, AM_UBYTE, bitmap.buffer);
+
+ // glTexSubImage2D( GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
+
+ printf("TW=%d tH=%d txoff=%d yoff=%d w=%d h=%d\n", tW, tH, xOffset, yOffset, destWidth, destHeight);
+ glPopClientAttrib();
+ }
+
+
+ uv[0].X( static_cast<float>(xOffset) / static_cast<float>(width));
+ uv[0].Y( static_cast<float>(yOffset) / static_cast<float>(height));
+ uv[1].X( static_cast<float>( xOffset + destWidth) / static_cast<float>(width));
+ uv[1].Y( static_cast<float>( yOffset + destHeight) / static_cast<float>(height));
+
+ pos.X( glyph->bitmap_left);
+ pos.Y( glyph->bitmap_top);
+}
+
+
+FTTextureGlyph::~FTTextureGlyph()
+{ }
+
+
+const FTPoint& FTTextureGlyph::Render( const FTPoint& pen)
+{
+ if( activeTextureID != glTextureID)
+ {
+ g->setTexture(textureID);
+ printf("setT = %d\n", textureID->gl_Tex);
+ activeTexture = textureID;
+ //activeTextureID = glTextureID;
+// glBindTexture( GL_TEXTURE_2D, glTextureID);
+
+ }
+
+ vertex array[4];
+
+
+
+ //g->setWorld(pen.X(), pen.Y(), 0.0f, 0,0,0, 1,1,1);
+ glTranslatef( pen.X(), pen.Y(), 0.0f);
+
+ array[0].u = uv[0].X();
+ array[0].v = 1 - uv[0].Y();
+ array[0].x = pos.X();
+ array[0].y = pos.Y();
+ array[0].z = 0;
+ array[0].col = COLOUR_RGBA(255,255,255,255);
+ array[0].nx = array[0].ny = array[0].nz = 0;
+
+ array[1].u = uv[0].X();
+ array[1].v = 1 - uv[1].Y();
+ array[1].x = pos.X();
+ array[1].y = pos.Y() - destHeight;
+ array[1].z = 0;
+ array[1].col = COLOUR_RGBA(255,255,255,255);
+ array[1].nx = array[1].ny = array[1].nz = 0;
+
+ array[2].u = uv[1].X();
+ array[2].v = 1 - uv[1].Y();
+ array[2].x = pos.X() + destWidth;
+ array[2].y = pos.Y() - destHeight;
+ array[2].z = 0;
+ array[2].col = COLOUR_RGBA(255,255,255,255);
+ array[2].nx = array[2].ny = array[2].nz = 0;
+
+ array[3].u = uv[1].X();
+ array[3].v = 1 - uv[0].Y();
+ array[3].x = pos.X() + destWidth;
+ array[3].y = pos.Y();
+ array[3].z = 0;
+ array[3].col = COLOUR_RGBA(255,255,255,255);
+ array[3].nx = array[3].ny = array[3].nz = 0;
+
+ //g->renderVertexArray(array, 4, AM_TRIANGLE_STRIP);
+ g->addTriangle(array[0], array[1], array[2]);
+ g->addTriangle(array[2], array[3], array[0]);
+
+/* glBegin( GL_QUADS);
+ glTexCoord2f( uv[0].X(), uv[0].Y());
+ glVertex2f( pos.X(), pos.Y());
+
+ glTexCoord2f( uv[0].X(), uv[1].Y());
+ glVertex2f( pos.X(), pos.Y() - destHeight);
+
+ glTexCoord2f( uv[1].X(), uv[1].Y());
+ glVertex2f( destWidth + pos.X(), pos.Y() - destHeight);
+
+ glTexCoord2f( uv[1].X(), uv[0].Y());
+ glVertex2f( destWidth + pos.X(), pos.Y());
+ glEnd();
+ */
+ return advance;
+}
+
+
+
+
+
+class myFont : public FTFont
+{
+
+ private:
+ inline virtual FTGlyph* MakeGlyph( unsigned int glyphIndex)
+ {
+ FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
+
+ if( ftGlyph)
+ {
+ glyphHeight = static_cast<int>( charSize.Height());
+ glyphWidth = static_cast<int>( charSize.Width());
+
+ if( textureIDList.empty())
+ {
+ textureIDList.push_back( CreateTexture());
+ xOffset = yOffset = padding;
+ }
+
+ if( xOffset > ( textureWidth - glyphWidth))
+ {
+ xOffset = padding;
+ yOffset += glyphHeight;
+
+ if( yOffset > ( textureHeight - glyphHeight))
+ {
+ textureIDList.push_back( CreateTexture());
+ yOffset = padding;
+ }
+ }
+
+ FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
+ xOffset, yOffset, textureWidth, textureHeight);
+ xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
+
+ --remGlyphs;
+ return tempGlyph;
+ }
+
+ err = face.Error();
+ return NULL;
+ }
+
+ inline void CalculateTextureSize()
+ {
+
+ if( !maximumGLTextureSize)
+ {
+ glGetIntegerv( GL_MAX_TEXTURE_SIZE, (int*)&maximumGLTextureSize);
+ assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
+ }
+ printf("maximumGLTextureSize=%d\n", maximumGLTextureSize);
+ textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
+ textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
+
+ int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
+
+ textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
+ textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
+ }
+
+
+ inline Texture * CreateTexture()
+ {
+
+ CalculateTextureSize();
+
+ int totalMemory = textureWidth * textureHeight;
+ unsigned char* textureMemory = new unsigned char[totalMemory];
+ memset( textureMemory, 0, totalMemory);
+
+ Texture *texID = new Texture(textureMemory, textureWidth, textureHeight, AM_ALPHA, AM_UBYTE, g);
+
+ delete [] textureMemory;
+
+ printf("now returning texID=%p\n", texID);
+ return texID;
+ /*
+ CalculateTextureSize();
+
+ int totalMemory = textureWidth * textureHeight;
+ unsigned char* textureMemory = new unsigned char[totalMemory];
+ memset( textureMemory, 0, totalMemory);
+
+ GLuint textID;
+ /* glGenTextures( 1, (GLuint*)&textID);
+ glBindTexture( GL_TEXTURE_2D, textID);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
+ */
+ /*
+ Texture *tex = new Texture(textureMemory, textureWidth, textureHeight, AM_ALPHA, AM_UBYTE, g);
+// g->setTexture(tex);
+ textID = tex->gl_Tex;
+ delete [] textureMemory;
+ printf("@ createTexture returning %d\n", textID);
+ return textID;*/
+
+ }
+
+
+
+ int maximumGLTextureSize;
+ int textureWidth;
+ int textureHeight;
+ FTVector<Texture *> textureIDList;
+ int glyphHeight;
+ int glyphWidth;
+ unsigned int padding;
+ unsigned int numGlyphs;
+ unsigned int remGlyphs;
+ int xOffset;
+ int yOffset;
+
+
+ public:
+
+ myFont( const char* fontFilePath) : FTFont( fontFilePath),
+ maximumGLTextureSize(0),
+ textureWidth(0),
+ textureHeight(0),
+ glyphHeight(0),
+ glyphWidth(0),
+ padding(3),
+ xOffset(0),
+ yOffset(0)
+{
+ remGlyphs = numGlyphs = face.GlyphCount();
+}
+
+~myFont()
+{
+ ;//glDeleteTextures( textureIDList.size(), (const unsigned int*)&textureIDList[0]);
+}
+
+
+void print( char *str, int x1, int y1, int x2, int y2, colour c )
+{
+ g->enter2dMode();
+ glColor4f( c.r, c.g, c.b, c.a);
+ float h= LineHeight()*0.64f; /* factor 0.64*/
+ glTranslatef(x1, y1 + h, 0);
+ glScalef(1.0, -1.0, 1.0);
+ Render(str);
+// ft_print( our_font, x1 , g->getHeight() - y1 - fontSize, str);
+ g->leave2dMode();
+}
+
+
+
+bool FaceSize( const unsigned int size, const unsigned int res)
+{
+ if( !textureIDList.empty())
+ {
+ glDeleteTextures( textureIDList.size(), (const uint*)&textureIDList[0]);
+ textureIDList.clear();
+ remGlyphs = numGlyphs = face.GlyphCount();
+ }
+
+ return FTFont::FaceSize( size, res);
+}
+
+
+void Render( const char* string)
+{
+// glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+ bool a = g->isAlpha();
+ g->enableAlpha(true);
+// glEnable(GL_BLEND);
+
+// glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
+
+ FTTextureGlyph::ResetActiveTexture();
+
+ FTFont::Render( string);
+
+// glPopAttrib();
+ g->enableAlpha(a);
+}
+
+
+void Render( const wchar_t* string)
+{
+// glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+
+ //glEnable(GL_BLEND);
+ //glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
+ bool a = g->isAlpha();
+ g->enableAlpha(true);
+
+ FTTextureGlyph::ResetActiveTexture();
+
+ FTFont::Render( string);
+ g->enableAlpha(a);
+// glPopAttrib();
+}
+
+};
+
+
+
+myFont *f;
+Font *t;
+
+bool init(void)
+{
+ g = new Graphics(1024, 768); // bring me a 1024x768 resolution
+ g->createDisplay();
+ g->setBackground(COLOUR_RGBA(155, 155, 155, 255)); //green background
+ f = new myFont("Test.ttf");
+ f->FaceSize(16, 72);
+ f->CharMap(ft_encoding_unicode);
+
+ t = new Font(g, "Test.ttf", 16);
+ return true;
+}
+
+
+bool renderFrame()
+{
+ g->beginScene();
+
+ f->print("MPLA", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
+// t->print("hello", 10,10, 200,200, COLOUR_RGBA(255,255,255,255));
+ g->endScene();
+
+ sleep(4);
+ return false;
+}
+
+bool cleanup()
+{
+ delete g;
+ return true;
+}
+
-CFLAGS := -I. -DWITH_SDL
-LDFLAGS := -lSDL
-OBJS:=main.o Engine/Log.o SchemeReader.o Engine/Settings.o Engine/mmanager.o Engine/Kernel.o Engine/ProfileLogHandler.o Engine/VideoUpdate.o Engine/GlobalTimer.o Engine/SoundTask.o Engine/profiler.o Playground.o Engine/InputTask.o
+MAKE := make
+CFLAGS := -I. -DWITH_SDL $(shell pkg-config --cflags ftgl)
+LDFLAGS := -lSDL $(shell pkg-config --libs ftgl) -lGL -lGLU -lILUT
+OBJS := main.o Engine/Log.o SchemeReader.o Engine/Settings.o \
+ Engine/mmanager.o Engine/Kernel.o Engine/ProfileLogHandler.o \
+ Engine/VideoUpdate.o Engine/GlobalTimer.o Engine/SoundTask.o \
+ Engine/profiler.o Playground.o Engine/InputTask.o \
+ Amaltheia/Graphics.o
+
all: abm2
g++ $(CFLAGS) -c $< -o $@
clean:
- rm -f *.o Engine/*.o
+ rm -f *.o Engine/*.o Amaltheia/*.o
+
+less:
+ $(MAKE) 2>&1 | less