Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/graphics/font/glfont.cc @ 3740

Last change on this file since 3740 was 3740, checked in by bensch, 19 years ago

orxonox/branches/textEngine: now the TextEngine generates Display-Lists

File size: 20.1 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   ***
16   * This file is extended to the needs of the orxonox-project.         *
17   * Originally it came from the glfont.c-example from SDL_ttf.         *
18   *                                                                  ***
19
20   for some fonts and licenses visit: =http://www.dafont.com/en/font.php=
21
22   !! IMPORTANT !! When using ttf fonts clear the license issues prior to
23   adding them to orxonox. This is really important, because we do not
24   want to defend anyone.
25*/
26
27#include "glfont.h"
28
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32
33#include "graphics_engine.h"
34#include "p_node.h"
35#include "vector.h"
36#include "debug.h"
37
38/**
39   \brief constructs a Font
40   \param fontFile the File to load the font from
41*/
42GLFont::GLFont(const char* fontFile)
43{
44  this->init(fontFile);
45}
46
47/**
48   \brief destructs a font
49*/
50GLFont::~GLFont(void)
51{
52  delete this->currentText;
53
54  if (this->glyphArray)
55    {
56      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
57        delete this->glyphArray[i];
58      delete []this->glyphArray;
59    }
60
61  if (this->font)
62    TTF_CloseFont(this->font);
63}
64
65/**
66   \brief function to enable TTF_Fonts
67*/
68void GLFont::enableFonts(void)
69{
70  if (!GLFont::ttfInitialized)
71    {
72      if(TTF_Init()==-1)
73        PRINTF(1)("TTF_Init: %s\n", TTF_GetError());
74
75      GLFont::checkVersion();
76      GLFont::ttfInitialized = true;
77    }
78  else
79    PRINTF(4)("Fonts already initialized\n");
80     
81}
82
83/**
84   \brief function to disable TTF_fonts
85*/
86void GLFont::disableFonts(void)
87{
88  if (GLFont::ttfInitialized)
89    {
90      TTF_Quit();
91      GLFont::ttfInitialized = false;
92    }
93  else
94    PRINTF(4)("Fonts were not initialized.\n");
95}
96
97//! A simple variable for checking if ttf was initialized
98bool GLFont::ttfInitialized = false;
99
100/**
101   \brief initializes a new Font
102   \param fontFile The file to load a Font from
103   \param fontSize the Size in pixels of the Font
104*/
105bool GLFont::init(const char* fontFile, unsigned int fontSize)
106{
107  if (!GLFont::ttfInitialized)
108    GLFont::enableFonts();
109
110  // setting default values.
111  this->font = NULL;
112  this->fontFile = NULL;
113  this->glyphArray = NULL;
114
115  this->currentText = new Text;
116
117  this->currentText->bindNode = NULL;
118  this->currentText->text = NULL;
119  this->currentText->texture = 0;
120 
121  this->setSize(fontSize);
122 
123  this->currentText->renderStyle = TTF_STYLE_NORMAL;
124
125  this->setFont(fontFile);
126
127  this->setColor(0, 255, 0);
128  this->setPosition(0, 0);
129
130  this->setText(FONT_DEFAULT_TEXT);
131 
132  this->setColor(0,255,0);
133
134  this->createTexture();
135
136  this->createFastTexture();
137}
138
139/**
140   \brief sets The Font.
141   \param fontFile The file containing the font.
142   \returns true if loaded, false if something went wrong, or if a font was loaded before.
143*/
144bool GLFont::setFont(const char* fontFile)
145{
146  if (!this->fontFile)
147    {
148      this->fontFile = new char[strlen(fontFile)+1];
149      strcpy(this->fontFile, fontFile);
150     
151      this->font = TTF_OpenFont(this->fontFile, this->fontSize);
152      if(!this->font) 
153        {
154          PRINTF(1)("TTF_OpenFont: %s\n", TTF_GetError());
155          return false;
156      }
157      return true;
158    }
159  else
160    {
161      PRINTF(2)("Font already initialized, unable to change it now.\n");
162      return false;
163    }
164}
165
166void GLFont::setBindNode(PNode* bindNode)
167{
168  this->currentText->bindNode = bindNode;
169}
170
171
172/**
173   \brief Sets a new Text to the font
174   \param text the new text to set
175*/
176void GLFont::setText(const char* text)
177{
178  if (this->currentText->text)
179    delete []this->currentText->text;
180  this->currentText->text = new char[strlen(text)+1];
181  strcpy(this->currentText->text, text);
182}
183
184/**
185   \brief sets a specific renderStyle
186   \param renderStyle the Style to render: a char-array containing:
187   i: italic, b: bold, u, underline
188*/
189void GLFont::setStyle(char* renderStyle)
190{
191  this->currentText->renderStyle = TTF_STYLE_NORMAL;
192 
193  for (int i = 0; i < strlen(renderStyle); i++)
194    if (strncmp(renderStyle+i, "b", 1) == 0) 
195      this->currentText->renderStyle |= TTF_STYLE_BOLD;
196    else if (strncmp(renderStyle+i, "i", 1) == 0)
197      this->currentText->renderStyle |= TTF_STYLE_ITALIC;
198    else if (strncmp(renderStyle+i, "u", 1) == 0) 
199      this->currentText->renderStyle |= TTF_STYLE_UNDERLINE;
200
201  if (this->font)
202    TTF_SetFontStyle(this->font, this->currentText->renderStyle);
203  else
204    PRINTF(2)("Font was not initialized, please do so before setting the Font-Style.\n");
205}
206
207/**
208   \brief Sets a new Size to the font
209   \param fontSize The new Size in pixels.
210*/
211void GLFont::setSize(unsigned int fontSize)
212{
213  this->fontSize = fontSize;
214}
215
216/**
217   \brief sets a new color to the font
218   \param r Red
219   \param g Green
220   \param b Blue
221*/
222void GLFont::setColor(Uint8 r, Uint8 g, Uint8 b)
223{
224  this->currentText->color.r = r;
225  this->currentText->color.g = g;
226  this->currentText->color.b = b;
227}
228
229/**
230   \brief sets a Position.
231   \param x the x-position in pixels from the left border
232   \param y the y-position in pixels from the top border
233*/
234void GLFont::setPosition(int x, int y)
235{
236  this->currentText->textPosSize.x = x;
237  this->currentText->textPosSize.y = y;
238}
239
240/**
241   \brief draws the Font
242   \todo FIX this is to slow/static
243*/
244void GLFont::draw(void)
245{
246  GLdouble modMat[16];
247  GLint viewPort[4];
248  glGetDoublev(GL_PROJECTION_MATRIX, this->projMat);
249  glGetDoublev(GL_MODELVIEW_MATRIX, modMat);
250  glGetIntegerv(GL_VIEWPORT, viewPort);
251  this->enter2DMode();
252
253
254  Vector pos;
255  if (this->currentText->bindNode)
256    {
257      GLdouble x = this->currentText->bindNode->getAbsCoor().x;
258      GLdouble y = this->currentText->bindNode->getAbsCoor().y;
259      GLdouble z = this->currentText->bindNode->getAbsCoor().z;
260      GLdouble tmp[3];
261      gluProject(x, y, z, modMat, projMat, viewPort, tmp, tmp+1, tmp+2);
262      printf("test %f %f %f,\n", tmp[0], tmp[1], tmp[2]);
263      pos.x = tmp[0] + this->currentText->textPosSize.x;
264      pos.y = GraphicsEngine::getInstance()->getResolutionY() - tmp[1] + this->currentText->textPosSize.y;
265      pos.z = tmp[2];
266    }
267  else 
268    {
269      pos.x = this->currentText->textPosSize.x;
270      pos.y = this->currentText->textPosSize.y;
271      pos.z = 0;
272    }
273  glBindTexture(GL_TEXTURE_2D, this->currentText->texture);
274  glEnable(GL_TEXTURE_2D);
275  glBegin(GL_QUADS);
276 
277  glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.minV);
278  glVertex2i(pos.x,   pos.);
279
280  glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.minV);
281  glVertex2i(pos.x + this->currentText->textPosSize.w, pos.);
282
283  glTexCoord2f(this->currentText->texCoord.maxU, this->currentText->texCoord.maxV);
284  glVertex2i(pos.x + this->currentText->textPosSize.w, pos.y + this->currentText->textPosSize.h);
285
286  glTexCoord2f(this->currentText->texCoord.minU, this->currentText->texCoord.maxV);
287  glVertex2i(pos.x, pos.y + this->currentText->textPosSize.h);
288
289  glEnd();
290
291  this->leave2DMode();
292}
293
294/**
295   \brief creates a texture out of the given parameters
296
297   this has to be called every time by the user, to if changes were made.
298*/
299void GLFont::createTexture(void)
300{
301  SDL_Surface* tmpSurf;
302  if (this->currentText->texture)
303    glDeleteTextures(1, &this->currentText->texture);
304  tmpSurf = TTF_RenderText_Blended(this->font,
305                                   this->currentText->text,
306                                   this->currentText->color);
307  if (tmpSurf)
308    this->currentText->texture = loadTexture(tmpSurf, &this->currentText->texCoord);
309
310  this->currentText->textPosSize.w = tmpSurf->w;
311  this->currentText->textPosSize.h = tmpSurf->h;
312  SDL_FreeSurface(tmpSurf);
313}
314
315
316/**
317   \returns the maximum height of the Font, if the font was initialized, 0 otherwise
318*/
319int GLFont::getMaxHeight(void)
320{
321  if (this->font)
322    return TTF_FontHeight(this->font);
323  else
324    return 0;
325}
326
327/**
328   \returns the maximum ascent of the Font, if the font was initialized, 0 otherwise
329
330   the ascent is the pixels of the font above the baseline
331*/
332int GLFont::getMaxAscent(void)
333{
334  if (this->font)
335    return TTF_FontAscent(this->font);
336  else
337    return 0;
338}
339
340/**
341   \returns the maximum descent of the Font, if the font was initialized, 0 otherwise
342
343   the descent is the pixels of the font below the baseline
344*/
345int GLFont::getMaxDescent(void)
346{
347  if (this->font)
348    return TTF_FontDescent(this->font);
349  else
350    return 0;
351}
352
353/**
354   \param character The character to get info about.
355   \returns a Glyph struct of a character. This Glyph is a pointer,
356   and MUST be deleted by the user..
357
358   This only works for horizontal fonts. see
359   http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
360   for more info about vertical Fonts
361*/
362Glyph* GLFont::getGlyphMetrics(Uint16 character)
363{
364  Glyph* rg = new Glyph;
365  rg->character = character;
366  TTF_GlyphMetrics(this->font, rg->character,
367                   &rg->minX, &rg->maxX,
368                   &rg->minY, &rg->maxY,
369                   &rg->advance);
370  rg->height = rg->maxY - rg->minY;
371  rg->width = rg->maxX - rg->minX;
372  rg->bearingX = (rg->advance - rg->width) / 2;
373  rg->bearingY = rg->maxY;
374  return rg;
375}
376
377/**
378   \brief entering 2D Mode
379   
380   this is a GL-Projection-mode, that is orthogonal, for placing the font in fron of everything else
381*/
382void GLFont::enter2DMode(void)
383{
384  SDL_Surface *screen = SDL_GetVideoSurface();
385 
386  /* Note, there may be other things you need to change,
387     depending on how you have your OpenGL state set up.
388  */
389  glPushAttrib(GL_ENABLE_BIT);
390  glDisable(GL_DEPTH_TEST);
391  glDisable(GL_CULL_FACE);
392  glDisable(GL_LIGHTING);  // will be set back when leaving 2D-mode
393  glEnable(GL_TEXTURE_2D);
394
395  /* This allows alpha blending of 2D textures with the scene */
396  glEnable(GL_BLEND);
397  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
398 
399  glViewport(0, 0, screen->w, screen->h);
400 
401  glMatrixMode(GL_PROJECTION);
402  glPushMatrix();
403  glLoadIdentity();
404 
405  glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
406 
407  glMatrixMode(GL_MODELVIEW);
408  glPushMatrix();
409  glLoadIdentity();
410 
411  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
412}
413
414/**
415   \brief leaves the 2DMode again also \see GLFont::enter2DMode(void)
416*/
417void GLFont::leave2DMode(void)
418{
419        glMatrixMode(GL_MODELVIEW);
420        glPopMatrix();
421
422        glMatrixMode(GL_PROJECTION);
423        glPopMatrix();
424
425        glPopAttrib();
426}
427
428
429GLuint GLFont::createFastTexture(void)
430{
431  /* interesting GLYPHS:
432   *  33-47: Special Characters.
433   *  48-57: 0-9
434   *  58-63: some more special chars (minor)
435   *  65-90: A-Z
436   *  97-122: a-z
437   */
438  int numberOfGlyphs = 90;
439
440  this->initGlyphs(33, numberOfGlyphs);
441
442  int rectSize = this->findOptimalFastTextureSize();
443
444  // setting default values. (maybe not needed afterwards)
445  //  SDL_Color tmpColor;  tmpColor.r = tmpColor.g = tmpColor.b = 0;
446  // Surface definition.
447  SDL_Rect tmpRect; // this represents a Rectangle for blitting.
448  SDL_Surface* tmpSurf =  SDL_CreateRGBSurface(
449                                               SDL_SWSURFACE,
450                                               rectSize, rectSize,
451                                               32,
452#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
453                                               0x000000FF, 
454                                               0x0000FF00, 
455                                               0x00FF0000, 
456                                               0xFF000000
457#else
458                                               0xFF000000,
459                                               0x00FF0000, 
460                                               0x0000FF00, 
461                                               0x000000FF
462#endif
463                                               );
464
465  tmpRect.x = 0; tmpRect.y = 0; tmpRect.w = tmpSurf->w; tmpRect.h = tmpSurf->h;
466  SDL_SetClipRect(tmpSurf, &tmpRect);
467  int maxLineHeight = 0;
468
469  // all the interessting Glyphs
470  for (int i = 33; i <= 122; i++)
471    {
472      SDL_Surface* glyphSurf = NULL;
473      Glyph* tmpGlyph;
474
475      if (tmpGlyph = this->glyphArray[i])
476        {
477          if (tmpGlyph->height > maxLineHeight)
478            maxLineHeight = tmpGlyph->height;
479         
480          if (tmpRect.x+tmpGlyph->width > tmpSurf->w)
481            {
482              tmpRect.x = 0;
483              tmpRect.y = tmpRect.y + maxLineHeight + 1;
484              maxLineHeight = 0;
485            }
486          if (tmpRect.y + maxLineHeight > tmpSurf->h)
487            {
488              PRINTF(1)("Protection, so font cannot write over the boundraries error (this should not heappen\n");
489              break;
490            }
491          // reading in the new Glyph
492          glyphSurf = TTF_RenderGlyph_Blended(this->font,
493                                              i,
494                                              this->currentText->color);
495          //                                     tmpColor);
496          if( glyphSurf ) 
497            {
498              SDL_BlitSurface(glyphSurf, NULL, tmpSurf, &tmpRect);
499              TexCoord tmpTexCoord;
500              tmpTexCoord.minU = (float)tmpRect.x/(float)tmpSurf->w;
501              tmpTexCoord.maxU = (float)(tmpRect.x+tmpGlyph->width)/(float)tmpSurf->w;
502              tmpTexCoord.minV = (float)tmpRect.y/(float)tmpSurf->w;
503              tmpTexCoord.maxV = (float)(tmpRect.y+tmpGlyph->height)/(float)tmpSurf->w;
504              tmpGlyph->displayList = glGenLists(1);
505              glNewList(tmpGlyph->displayList, GL_COMPILE);
506              glBegin(GL_QUADS);
507              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.minV);
508              glVertex2d(0, 0);
509              glTexCoord2f(tmpTexCoord.minU, tmpTexCoord.maxV);
510              glVertex2d(0, 1);
511              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.maxV);
512              glVertex2d(1, 1);
513              glTexCoord2f(tmpTexCoord.maxU, tmpTexCoord.minV);
514              glVertex2d(1, 0);
515              glEnd();
516              glEndList();
517              SDL_FreeSurface(glyphSurf);
518
519              tmpRect.x += tmpGlyph->width + 1;
520
521              // Outputting Glyphs to BMP-files.
522              /*
523                char outname[64];
524                if (i < 10)
525                sprintf( outname, "glyph-00%d.bmp", i );
526                else if (i <100)
527                sprintf( outname, "glyph-0%d.bmp", i );
528                else
529                sprintf( outname, "glyph-%d.bmp", i );
530                SDL_SaveBMP(tmpSurf, outname);
531              */
532            }
533        }
534    }
535
536  GLuint tmpRet = this->loadTexture(tmpSurf, NULL);
537  SDL_FreeSurface(tmpSurf);
538  return tmpRet;
539}
540
541/**
542   \brief Loads a Font from an SDL_surface into a texture.
543   \param surface The surface to make the texture of
544   \param texCoord The texture coordinates of the 4 corners of the texture
545   \returns the ID of the texture
546*/
547GLuint GLFont::loadTexture(SDL_Surface *surface, TexCoord* texCoord)
548{
549  GLuint texture;
550  int w, h;
551  SDL_Surface *image;
552  SDL_Rect area;
553  Uint32 saved_flags;
554  Uint8  saved_alpha;
555 
556  /* Use the surface width and height expanded to powers of 2 */
557  w = powerOfTwo(surface->w);
558  h = powerOfTwo(surface->h);
559  if (texCoord)
560    {
561      texCoord->minU = 0.0f;
562      texCoord->minV = 0.0f;
563      texCoord->maxU = (GLfloat)surface->w / w;
564      texCoord->maxV = (GLfloat)surface->h / h;
565    }
566  image = SDL_CreateRGBSurface(
567                               SDL_SWSURFACE,
568                               w, h,
569                               32,
570#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
571                               0x000000FF, 
572                               0x0000FF00, 
573                               0x00FF0000, 
574                               0xFF000000
575#else
576                               0xFF000000,
577                               0x00FF0000, 
578                               0x0000FF00, 
579                               0x000000FF
580#endif
581                               );
582  if ( image == NULL ) {
583    return 0;
584  }
585 
586  /* Save the alpha blending attributes */
587  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
588  saved_alpha = surface->format->alpha;
589  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
590    SDL_SetAlpha(surface, 0, 0);
591  }
592 
593  /* Copy the surface into the GL texture image */
594  area.x = 0;
595  area.y = 0;
596  area.w = surface->w;
597  area.h = surface->h;
598  SDL_BlitSurface(surface, &area, image, &area);
599 
600  /* Restore the alpha blending attributes */
601  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
602    SDL_SetAlpha(surface, saved_flags, saved_alpha);
603  }
604 
605  /* Create an OpenGL texture for the image */
606  glGenTextures(1, &texture);
607  glBindTexture(GL_TEXTURE_2D, texture);
608  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
609  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
610  glTexImage2D(GL_TEXTURE_2D,
611               0,
612               GL_RGBA,
613               w, h,
614               0,
615               GL_RGBA,
616               GL_UNSIGNED_BYTE,
617               image->pixels);
618  SDL_FreeSurface(image); /* No longer needed */
619 
620  return texture;
621}
622
623/**
624   \brief stores Glyph Metrics in an Array.
625   \param from The Glyph to start from.
626   \param count The number of Glyphs to start From.
627*/
628void GLFont::initGlyphs(Uint16 from, Uint16 count)
629{
630  /* initialize the Array, and set all its entries to NULL
631   *  only if the Glyph-array has not been initialized
632   */
633  if (!this->glyphArray)
634    {
635      this->glyphArray = new Glyph*[FONT_HIGHEST_KNOWN_CHAR];
636      for (int i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
637        this->glyphArray[i] = NULL;
638    }
639 
640  Uint16 lastGlyph = from + count;
641 
642  for (int i = from; i <= lastGlyph; i++)
643    {
644      // setting up all the Glyphs we like.
645      glyphArray[i] = getGlyphMetrics(i);
646    }
647  return;
648}
649
650/**
651   \returns the optimal size to use as the texture size
652
653   \todo: this algorithm can be a lot more faster, althought it does
654   not really matter within the init-context, and 128 glyphs.
655
656   This function searches for a 2^n sizes texture-size, this is for
657   openGL-version < 1.2 compatibility. and because it is realy easy like this.
658*/
659int GLFont::findOptimalFastTextureSize(void)
660{
661  int i;
662  int x,y; // the counters
663  int maxLineHeight;
664  int size = 32;      // starting Value, we have to start somewhere 32 seems reasonable.
665  bool sizeOK = false;
666  Glyph* tmpGlyph;
667
668  while (!sizeOK)
669    {
670      x = 0; y = 0;
671      maxLineHeight = 0;
672      for (i = 0; i < FONT_HIGHEST_KNOWN_CHAR; i++)
673        {
674          if(tmpGlyph = this->glyphArray[i])
675            {
676              // getting the height of the highest Glyph in the Line.
677              if (tmpGlyph->height > maxLineHeight)
678                maxLineHeight = tmpGlyph->height;
679
680              if (x + tmpGlyph->width > size)
681                {
682                  x = 0;
683                  y = y + maxLineHeight;
684                  maxLineHeight = 0;
685                }
686              if (y + maxLineHeight + 1 > size)
687                break;
688              x += tmpGlyph->width + 1;
689
690            }
691        }
692      if (i == FONT_HIGHEST_KNOWN_CHAR)
693        sizeOK = true;
694      else
695        size *= 2;
696    }
697  return size;
698 
699}
700
701/**
702   \brief Quick utility function for texture creation
703   \param input an integer
704   \returns the next bigger 2^n-integer than input
705*/
706int GLFont::powerOfTwo(int input)
707{
708  int value = 1;
709 
710  while ( value < input ) {
711    value <<= 1;
712  }
713  return value;
714}
715
716
717/**
718   \brief checks if the compiled version and the local version of SDL_ttf match.
719   \returns true if match, false otherwise
720*/
721bool GLFont::checkVersion(void)
722{
723  SDL_version compile_version;
724  SDL_version link_version;
725  TTF_VERSION(&compile_version);
726  link_version = *TTF_Linked_Version();
727
728  if (compile_version.major == link_version.major &&
729      compile_version.minor == link_version.minor &&
730      compile_version.patch == link_version.patch)
731    {
732      return true;
733    }
734  else
735    {
736      PRINTF(2)("compiled with SDL_ttf version: %d.%d.%d\n", 
737                compile_version.major,
738                compile_version.minor,
739                compile_version.patch);
740     
741      PRINTF(2)("running with SDL_ttf version: %d.%d.%d\n", 
742                link_version.major,
743                link_version.minor,
744                link_version.patch);
745      return false;
746    }
747}
748
749
750
751/**
752   \brief a simple function to get some interesting information about this class
753*/
754void GLFont::debug(void)
755{
756
757  // print the loaded font's style
758  int style;
759  style=TTF_GetFontStyle(this->font);
760  PRINTF(0)("The font style is:");
761  if(style==TTF_STYLE_NORMAL)
762    PRINTF(0)(" normal");
763  else {
764    if(style&TTF_STYLE_BOLD)
765      PRINTF(0)(" bold");
766    if(style&TTF_STYLE_ITALIC)
767      PRINTF(0)(" italic");
768    if(style&TTF_STYLE_UNDERLINE)
769      PRINTF(0)(" underline");
770  }
771  PRINTF(0)("\n");
772
773
774}
775
776
777void m_inverse(const float *m, float *out)
778{
779    float det;
780    det=  m[0]*m[5]*m[10];
781    det+= m[4]*m[9]*m[2];
782    det+= m[8]*m[1]*m[6];
783    det-= m[8]*m[5]*m[2];
784    det-= m[4]*m[1]*m[10];
785    det-= m[0]*m[9]*m[6];
786   
787    if(det!= 0.0)
788        det=1.0/det;
789    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
790    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
791    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
792    out[3]= 0.0;
793    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
794    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
795    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
796    out[7]= 0.0;
797    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
798    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
799    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
800    out[11]= 0.0;
801    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
802    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
803    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
804    out[15]= 1.0;
805}
806
807
808Vector mvMult(const float *mat, const Vector* vec)
809{
810  Vector tmp;
811  tmp.x = mat[0]*vec->x+mat[1]*vec->y+mat[2]*vec->z;
812  tmp.y = mat[4]*vec->x+mat[5]*vec->y+mat[6]*vec->z;
813  tmp.z = mat[8]*vec->x+mat[9]*vec->y+mat[10]*vec->z;
814  return tmp;
815}
Note: See TracBrowser for help on using the repository browser.