From: Matthijs Kooijman Date: Mon, 11 Jun 2007 10:58:08 +0000 (+0200) Subject: * Add "less" target to view make output through less. X-Git-Url: https://git.stderr.nl/gitweb?p=matthijs%2FABM2.git;a=commitdiff_plain;h=9dae6dd1f05eed22b6ce5e75bd1e5893d5ee1ac6 * Add "less" target to view make output through less. * Add Amaltheia library. --- diff --git a/ABM2/Amaltheia/Graphics.cpp b/ABM2/Amaltheia/Graphics.cpp new file mode 100644 index 0000000..270f6c5 --- /dev/null +++ b/ABM2/Amaltheia/Graphics.cpp @@ -0,0 +1,1705 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 +// #include +#include +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +#include + +// 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=" < 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 ; +} diff --git a/ABM2/Amaltheia/Graphics.h b/ABM2/Amaltheia/Graphics.h new file mode 100644 index 0000000..18516b1 --- /dev/null +++ b/ABM2/Amaltheia/Graphics.h @@ -0,0 +1,751 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 + #define _USE_MATH_DEFINES +#endif + +/* #define GLX_GLXEXT_PROTOTYPES + #include + #include */ + + +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: +, , */ +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: +, , */ +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: + */ + 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: + */ + void setWidth( int w = 1024 ); + +/* Method: getWidth + Returns the width of the display + + returns: + the current display's width in pixels + + see also: + */ + int getWidth(); + +/* Method: setHeight + Sets the height of the display + +parameters: + h - the desired height + +see also: + */ + void setHeight( int h = 768 ); + +/* Method: getHeight + Returns the height of the display + +returns: + the height of the display in pixels + +see also: + */ + int getHeight(); + + /*method: setBpp + Sets the Bits per Pixel for the display + + parameters: + bpp - bits per pixel + + see also: + */ + void setBpp( int bpp = 16); + + /*method: getBpp + Returns the current BPP of the display + + returns: + bits per pixel + + see also: + */ + 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: + */ + void enableLighting( bool ); + + /*method: isLighting + Is lighting enabled? + + returns: + *true* if lighting is enabled, *false* otherwise + +see also: + */ + bool isLighting(); + + /*method: enableDepthBuffer + Enables/disables the depth (Z) buffer + + parameters: + *true* to enable the Z-buffer, *false* to disable it + + see also: + */ + void enableDepthBuffer( bool ); + + /*method: isDepthBuffer + Is the depth buffer enabled? + + returns: + *true* if the depth buffer is enabled, *false* otherwise + + see also: + */ + bool isDepthBuffer(); + + /*method: enableAlpha + Enables/disables alpha blending + + parameters: + *true* to enable alpha blending, *false* to disable it + + see also: + */ + void enableAlpha( bool ); + + /*method: isAlpha + Is alpha blending enabled? + + returns: + *true* is alpha blending is enabled, *false* otherwise + + see also: + */ + bool isAlpha(); + + + void enableCursor( bool ); + bool isCursor(); + + + /* method: createDisplay + Creates the display. You should call this method *once*. + + see also: + */ + 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: + */ + 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. and methods must be pair, so you must + call once, before calling . + + see also: + */ + 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: + */ + int setCamera( float camx, float camy, float camz, + float lookx, float looky, float lookz, + float upx, float upy, float upz ); + +/*method: getCamera + Returns a struct containing the position and the direction of the camera + + returns: + a struct + + see also: + */ + 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: + */ + void setBackground( colour c ); + + /* method: getBackground + + returns: + the colour of the display background + + see also: + */ + colour getBackground(); + + /* method: setTexture + Sets which will be the current texture to use. + + parameters: + tex - a pointer to a object + + see also: + , class*/ + void setTexture( Texture *tex ); + + /*method: getTexture + + returns: + a pointer to the current object + + see also: + , 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: + */ + void setCullingMode(int mode); + + /*method: getCullingMode + + returns: + The current culling mode + + see also: + */ + int getCullingMode(); + + + /*method: renderTriangle + Renders a triangle in the display + + parameters: + v1, v2, v3 - the 3 vertices that specify the triangle + + see also: + struct, */ + 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: + , 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 variable which defines the properties of the 'numLight' light + +see also: + struct , */ + void setLight( int numLight, const light& lt ); + + /*method: showLight + Enables/disables light 'numLight'. Light 'numLight' must first have been created with the method. + + parameters: + numLight - the number of the light to enable/disable + + state - *true* to enable the light, *false* otherwise + + see also: + struct , */ + 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: + */ + 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: + */ + 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: +*/ + +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 diff --git a/ABM2/Amaltheia/Input.cpp b/ABM2/Amaltheia/Input.cpp new file mode 100644 index 0000000..3b91be7 --- /dev/null +++ b/ABM2/Amaltheia/Input.cpp @@ -0,0 +1,451 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 +#include + + +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; + } + */ +} + diff --git a/ABM2/Amaltheia/Input.h b/ABM2/Amaltheia/Input.h new file mode 100644 index 0000000..aae4561 --- /dev/null +++ b/ABM2/Amaltheia/Input.h @@ -0,0 +1,418 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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: + , and */ + 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: + */ + 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: + */ + 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: + */ + 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: + */ + 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 + + 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 diff --git a/ABM2/Amaltheia/Network.cpp b/ABM2/Amaltheia/Network.cpp new file mode 100644 index 0000000..396818b --- /dev/null +++ b/ABM2/Amaltheia/Network.cpp @@ -0,0 +1,266 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include + + +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; +} diff --git a/ABM2/Amaltheia/Network.h b/ABM2/Amaltheia/Network.h new file mode 100644 index 0000000..9d72fe7 --- /dev/null +++ b/ABM2/Amaltheia/Network.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 +#include +#include +#include + +#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 diff --git a/ABM2/Amaltheia/Sprite.cpp b/ABM2/Amaltheia/Sprite.cpp new file mode 100644 index 0000000..a8c10a8 --- /dev/null +++ b/ABM2/Amaltheia/Sprite.cpp @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 + + +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 ; +} diff --git a/ABM2/Amaltheia/Sprite.h b/ABM2/Amaltheia/Sprite.h new file mode 100644 index 0000000..f7a0c34 --- /dev/null +++ b/ABM2/Amaltheia/Sprite.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 diff --git a/ABM2/Amaltheia/System.cpp b/ABM2/Amaltheia/System.cpp new file mode 100644 index 0000000..79a4028 --- /dev/null +++ b/ABM2/Amaltheia/System.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 + + +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); +} diff --git a/ABM2/Amaltheia/System.h b/ABM2/Amaltheia/System.h new file mode 100644 index 0000000..b3ff24b --- /dev/null +++ b/ABM2/Amaltheia/System.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 +#include + +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 + diff --git a/ABM2/Amaltheia/main.cpp b/ABM2/Amaltheia/main.cpp new file mode 100644 index 0000000..221903a --- /dev/null +++ b/ABM2/Amaltheia/main.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 + +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 +} + diff --git a/ABM2/Amaltheia/md2model.h b/ABM2/Amaltheia/md2model.h new file mode 100644 index 0000000..818af0a --- /dev/null +++ b/ABM2/Amaltheia/md2model.h @@ -0,0 +1,156 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 diff --git a/ABM2/Amaltheia/md2reader.cpp b/ABM2/Amaltheia/md2reader.cpp new file mode 100644 index 0000000..1ce8963 --- /dev/null +++ b/ABM2/Amaltheia/md2reader.cpp @@ -0,0 +1,679 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 +#include +#include +#include +#include +// 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;iname,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 (xymax) zmax=z; + if (zzmax) 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 ; +} + diff --git a/ABM2/Amaltheia/modelLoader.cpp b/ABM2/Amaltheia/modelLoader.cpp new file mode 100644 index 0000000..5cd9b60 --- /dev/null +++ b/ABM2/Amaltheia/modelLoader.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 "modelLoader.h" + +modelLoader::modelLoader(Graphics *g) +{ + gr=g; + m[0]=new model("tris.md2", "masked.bmp",g); + return ; +} + +modelLoader::~modelLoader(void) +{ + int i; + for (i=0;isetFrameSequence("stand"); + + return ctmp; +} diff --git a/ABM2/Amaltheia/modelLoader.h b/ABM2/Amaltheia/modelLoader.h new file mode 100644 index 0000000..01aa42c --- /dev/null +++ b/ABM2/Amaltheia/modelLoader.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dimitris Saougos & Filippos Papadopoulos * + * * + * * + * 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 _MODELLOADER +#define _MODELLOADER + +#include"Graphics.h" +#include"md2model.h" + +#define Different_types 1 + +class modelLoader; + +class modelLoader +{ +private: + model *m[Different_types]; + +public: + Graphics *gr; + modelLoader(Graphics *g); + ~modelLoader(void); + + c_model * getModel(int type); +}; + +#endif diff --git a/ABM2/Amaltheia/myApp.cpp b/ABM2/Amaltheia/myApp.cpp new file mode 100644 index 0000000..4887fd4 --- /dev/null +++ b/ABM2/Amaltheia/myApp.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +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; +} diff --git a/ABM2/Amaltheia/myFont-workingGL.cpp b/ABM2/Amaltheia/myFont-workingGL.cpp new file mode 100644 index 0000000..32509c2 --- /dev/null +++ b/ABM2/Amaltheia/myFont-workingGL.cpp @@ -0,0 +1,1526 @@ +#include + +#include +#include + +Graphics *g; + +#include +#include // For memset +#include +#include +#include +#include +#include + +//#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( bbox.xMin) / 64.0f; + lowerY = static_cast( bbox.yMin) / 64.0f; + lowerZ = 0.0f; + upperX = static_cast( bbox.xMax) / 64.0f; + upperY = static_cast( 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( ftSize->metrics.ascender) / 64.0f; + } + + + float FTSize::Descender() const + { + return ftSize == 0 ? 0.0f : static_cast( 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( 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(ftSize->metrics.x_ppem) / static_cast((*ftFace)->units_per_EM)); + } + else + { + return static_cast( 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( kernAdvance.x) / 64.0f; + y = static_cast( 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 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 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(xOffset) / static_cast(width)); + uv[0].Y( static_cast(yOffset) / static_cast(height)); + uv[1].X( static_cast( xOffset + destWidth) / static_cast(width)); + uv[1].Y( static_cast( yOffset + destHeight) / static_cast(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( charSize.Height()); + glyphWidth = static_cast( 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( 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( (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 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; +} + diff --git a/ABM2/Amaltheia/myFont.cpp b/ABM2/Amaltheia/myFont.cpp new file mode 100644 index 0000000..c054535 --- /dev/null +++ b/ABM2/Amaltheia/myFont.cpp @@ -0,0 +1,1897 @@ +#include + +#include +#include + + +#include +#include // For memset +#include +#include +#include +#include +#include + + +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( bbox.xMin) / 64.0f; + lowerY = static_cast( bbox.yMin) / 64.0f; + lowerZ = 0.0f; + upperX = static_cast( bbox.xMax) / 64.0f; + upperY = static_cast( 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( ftSize->metrics.ascender) / 64.0f; + } + + + float FTSize::Descender() const + { + return ftSize == 0 ? 0.0f : static_cast( 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( 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(ftSize->metrics.x_ppem) / static_cast((*ftFace)->units_per_EM)); + } + else + { + return static_cast( 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( kernAdvance.x) / 64.0f; + y = static_cast( 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 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 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(xOffset) / static_cast(width)); + uv[0].Y( static_cast(yOffset) / static_cast(height)); + uv[1].X( static_cast( xOffset + destWidth) / static_cast(width)); + uv[1].Y( static_cast( yOffset + destHeight) / static_cast(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( charSize.Height()); + glyphWidth = static_cast( 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( 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( (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 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; +} + diff --git a/ABM2/Makefile b/ABM2/Makefile index 9f5c3b7..143c31f 100644 --- a/ABM2/Makefile +++ b/ABM2/Makefile @@ -1,6 +1,12 @@ -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 @@ -11,4 +17,7 @@ abm2: $(OBJS) g++ $(CFLAGS) -c $< -o $@ clean: - rm -f *.o Engine/*.o + rm -f *.o Engine/*.o Amaltheia/*.o + +less: + $(MAKE) 2>&1 | less