"Fossies" - the Fresh Open Source Software Archive

Member "gamgi0.17.5x/src/io/gamgi_io_x3d_render.c" (23 Feb 2022, 34705 Bytes) of package /linux/misc/gamgi-all-0.17.5x.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /******************************************
    2  *
    3  * $GAMGI/src/io/gamgi_io_x3d_render.c
    4  *
    5  * Copyright (C) 2008 Tiago Farto
    6  *
    7  * Distributed under the terms of the GNU
    8  * General Public License: $GAMGI/LICENSE
    9  *
   10  */
   11 
   12 #include "gamgi_engine.h"
   13 #include "gamgi_io.h"
   14 #include "gamgi_gtk.h"
   15 #include "gamgi_mesa.h"
   16 #include "gamgi_math.h"
   17 #include "gamgi_phys.h"
   18 #include "gamgi_global.h"
   19 
   20 #include "gamgi_engine_list.h"
   21 #include "gamgi_engine_array.h"
   22 #include "gamgi_math_vector.h"
   23 #include "gamgi_io_file.h"
   24 #include "gamgi_io_font_sun.h"
   25 #include "gamgi_io_font_hershey.h"
   26 #include "gamgi_io_x3d_render.h"
   27 #include "gamgi_mesa_atom.h"
   28 #include "gamgi_mesa_bond.h"
   29 #include "gamgi_mesa_text.h"
   30 
   31 #define GAMGI_IO_X3D_TOTAL 500
   32 #define GAMGI_IO_X3D_STEP 2
   33 #define GAMGI_IO_X3D_POINT_SIZE 0.025
   34 
   35 /*
   36  * OGLFT: A library for drawing text with OpenGL using the FreeType library
   37  * Copyright (C) 2002 lignum Computing, Inc.
   38  * Author: Allen Barnett
   39  *
   40  * This program is free software; you can redistribute it and/or modify
   41  * it under the terms of the GNU General Public License as published by
   42  * the Free Software Foundation; either version 2 of the License, or
   43  * (at your option) any later version.
   44  *
   45  * This program is distributed in the hope that it will be useful,
   46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48  * GNU General Public License for more details.
   49  *
   50  * You should have received a copy of the GNU General Public License
   51  * along with this program; if not, write to the Free Software
   52  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   53  */
   54 
   55 /*********************************
   56  * Code taken from: OGLFT-0.9    *
   57  *                               *
   58  * Functions with OGLFT code:    *
   59  * static_glu_begin              *
   60  * static_glu_vertex             *
   61  * static_glu_combine            *
   62  * static_vertical_move          *
   63  * static_vertical_line          *
   64  * static_vertical_conic         *
   65  * static_vertical_cubic         *
   66  * x3d_font_face                 *
   67  * static_extruded_create        *
   68  * static_extruded_remove        *
   69  * gamgi_io_x3d_render_solid     *
   70  *                               *
   71  * Code taken by: Carlos Pereira *
   72  *********************************/
   73 
   74 /*
   75  * GLE: The Tubing and Extrusion Library
   76  * Copyright (C) 1991,1994,2003 Linas Vepstas
   77  *
   78  * The GLE library is distributed under two licenses:
   79  * GNU General Public License (GPL) and Public Domain
   80  *
   81  *  This program is free software; you can redistribute it and/or modify
   82  * it under the terms of the GNU General Public License as published by
   83  * the Free Software Foundation; either version 2 of the License, or
   84  * (at your option) any later version.
   85  *
   86  * This program is distributed in the hope that it will be useful,
   87  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   88  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   89  * GNU General Public License for more details.
   90  *
   91  * You should have received a copy of the GNU General Public License
   92  * along with this program; if not, write to the Free Software
   93  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   94  */
   95 
   96 /***********************************************
   97  * Code taken from: GLE-3.1.0                  *
   98  *                                             *
   99  * Functions with GLE code: x3d_font_extrusion *
  100  *                                             *
  101  * Code taken by: Carlos Pereira               *
  102  ***********************************************/
  103 
  104 /************* internal function ***********
  105  *                                         *
  106  *               STATIC_POINT              *
  107  *                                         *
  108  *           render a X3D point            *
  109  *******************************************/
  110 
  111 static void static_point (FILE *fp, int n_points, double *points, 
  112 float *color, int type, int width, int pattern, gamgi_bool *error)
  113 {
  114 char string[GAMGI_ENGINE_LINE];
  115 float p[3];
  116 int i;
  117 
  118 if (n_points <= 0) return;
  119 
  120 /***************
  121  * Shape start *
  122  ***************/
  123 
  124 gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  125 
  126 /********************
  127  * Appearance start *
  128  ********************/
  129 
  130 if (color != NULL || width == TRUE || pattern == TRUE)
  131   {
  132   gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  133 
  134   /************************
  135    * LineProperties start *
  136    ************************/
  137 
  138   if (width == TRUE || pattern == TRUE)
  139     gamgi_io_file_fprintf (fp, "<LineProperties ", error);
  140 
  141   if (width  == TRUE)
  142     {
  143     sprintf (string, "linewidthScaleFactor=\"%d\" ", width);
  144     gamgi_io_file_fprintf (fp, string, error);
  145     }
  146 
  147   if (pattern == TRUE)
  148     {
  149     sprintf (string, "linetype=\"%d\" ", pattern);
  150     gamgi_io_file_fprintf (fp, string, error);
  151     }
  152 
  153   /**********************
  154    * LineProperties end *
  155    **********************/
  156 
  157   if (width == TRUE || pattern == TRUE)
  158     gamgi_io_file_fprintf (fp, "/>\n", error);
  159             
  160   if (color != NULL)
  161     {
  162     sprintf (string, "<Material emissiveColor=\"%f %f %f\"/>\n", 
  163     color[0], color[1], color[2]);
  164     gamgi_io_file_fprintf (fp, string, error);
  165     }
  166 
  167   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  168   }
  169 
  170 /******************
  171  * Appearance end *
  172  ******************/
  173 
  174 /************************
  175  * IndexedlineSet start *
  176  ************************/
  177 
  178 gamgi_io_file_fprintf (fp, "<IndexedLineSet coordIndex=\"\n", error);
  179 
  180 for (i = 0; i < n_points; i++)
  181   {
  182   if (type == 1)
  183     sprintf (string, "%d %d -1 %d %d -1 %d %d -1 %d %d -1\n", 
  184     i*8 + 0, i*8 + 1, i*8 + 2, i*8 + 3, i*8 + 4, i*8 + 5, i*8 + 6, i*8 + 7);
  185   else
  186     sprintf (string, "%d %d -1 %d %d -1 %d %d -1\n", 
  187     i*6 + 0, i*6 + 1, i*6 + 2, i*6 + 3, i*6 + 4, i*6 + 5);
  188 
  189   gamgi_io_file_fprintf (fp, string, error);
  190   }
  191 
  192 gamgi_io_file_fprintf (fp, "\">\n", error);
  193 
  194 /********************
  195  * Coordinate start *
  196  ********************/
  197 
  198 gamgi_io_file_fprintf (fp, "<Coordinate point=\"\n", error);
  199 
  200 for (i = 0; i < n_points; i++)
  201   {
  202   p[0] = points[3*i + 0];
  203   p[1] = points[3*i + 1];
  204   p[2] = points[3*i + 2];
  205 
  206   if (type == 1)            
  207     {
  208     sprintf (string, "%f %f %f %f %f %f\n",
  209     p[0] - GAMGI_IO_X3D_POINT_SIZE, p[1] + GAMGI_IO_X3D_POINT_SIZE,
  210     p[2] - GAMGI_IO_X3D_POINT_SIZE, p[0] + GAMGI_IO_X3D_POINT_SIZE,
  211     p[1] - GAMGI_IO_X3D_POINT_SIZE, p[2] + GAMGI_IO_X3D_POINT_SIZE);
  212     gamgi_io_file_fprintf (fp, string, error);
  213 
  214     sprintf (string, "%f %f %f %f %f %f\n",
  215     p[0] + GAMGI_IO_X3D_POINT_SIZE, p[1] + GAMGI_IO_X3D_POINT_SIZE,
  216     p[2] - GAMGI_IO_X3D_POINT_SIZE, p[0] - GAMGI_IO_X3D_POINT_SIZE,
  217     p[1] - GAMGI_IO_X3D_POINT_SIZE, p[2] + GAMGI_IO_X3D_POINT_SIZE);
  218     gamgi_io_file_fprintf (fp, string, error);
  219 
  220     sprintf (string, "%f %f %f %f %f %f\n",
  221     p[0] - GAMGI_IO_X3D_POINT_SIZE, p[1] + GAMGI_IO_X3D_POINT_SIZE,
  222     p[2] + GAMGI_IO_X3D_POINT_SIZE, p[0] + GAMGI_IO_X3D_POINT_SIZE,
  223     p[1] - GAMGI_IO_X3D_POINT_SIZE, p[2] - GAMGI_IO_X3D_POINT_SIZE);
  224     gamgi_io_file_fprintf (fp, string, error);
  225 
  226     sprintf (string, "%f %f %f %f %f %f\n",
  227     p[0] + GAMGI_IO_X3D_POINT_SIZE, p[1] + GAMGI_IO_X3D_POINT_SIZE,
  228     p[2] + GAMGI_IO_X3D_POINT_SIZE, p[0] - GAMGI_IO_X3D_POINT_SIZE,
  229     p[1] - GAMGI_IO_X3D_POINT_SIZE, p[2] - GAMGI_IO_X3D_POINT_SIZE);
  230     gamgi_io_file_fprintf (fp, string, error);
  231     }
  232   else
  233     {
  234     sprintf (string, "%f %f %f %f %f %f\n",
  235     p[0] + GAMGI_IO_X3D_POINT_SIZE, p[1], p[2],
  236     p[0] - GAMGI_IO_X3D_POINT_SIZE, p[1], p[2]);
  237     gamgi_io_file_fprintf (fp, string, error);
  238 
  239     sprintf (string, "%f %f %f %f %f %f\n",
  240     p[0], p[1] + GAMGI_IO_X3D_POINT_SIZE, p[2],
  241     p[0], p[1] - GAMGI_IO_X3D_POINT_SIZE, p[2]);
  242     gamgi_io_file_fprintf (fp, string, error);
  243 
  244     sprintf (string, "%f %f %f %f %f %f\n",
  245     p[0], p[1], p[2] + GAMGI_IO_X3D_POINT_SIZE,
  246     p[0], p[1], p[2] - GAMGI_IO_X3D_POINT_SIZE);
  247     gamgi_io_file_fprintf (fp, string, error);
  248     }
  249   }
  250 
  251 /***************************************
  252  * Coordinate+IndexedLineSet+Shape end *
  253  ***************************************/
  254 
  255 gamgi_io_file_fprintf (fp, "\"/>\n", error);
  256 gamgi_io_file_fprintf (fp, "</IndexedLineSet>\n", error);
  257 gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  258 }
  259 
  260 /************* external function ***********
  261  *                                         *
  262  *        GAMGI_IO_X3D_RENDER_CROSS        *
  263  *                                         *
  264  *    draws points of the type "cross"     * 
  265  *******************************************/
  266 
  267 void gamgi_io_x3d_render_cross (FILE *fp, int n_points, 
  268 double *points, float *color, gamgi_bool *error)
  269 {
  270 static_point (fp, n_points, points, color, 0, 4, 0, error);
  271 }
  272 
  273 
  274 /************* external function ***********
  275  *                                         *
  276  *        GAMGI_IO_X3D_RENDER_CHESS        *
  277  *                                         *
  278  *    draws points of the type "chess"     *
  279  *******************************************/
  280 
  281 void gamgi_io_x3d_render_chess (FILE *fp, int n_points, 
  282 double *points,  float *color, gamgi_bool *error)
  283 {
  284 static_point (fp, n_points, points, color, 1, 4, 0, error);
  285 }
  286 
  287 /************* external function ***********
  288  *                                         *
  289  *        GAMGI_IO_X3D_RENDER_POINTS       *
  290  *                                         *
  291  *    draws points of the type "normal"    *
  292  *******************************************/
  293 
  294 void gamgi_io_x3d_render_points (FILE *fp, int n_points, 
  295 double *points, float *color, gamgi_bool *error)
  296 {
  297 static_point (fp, n_points, points, color, 0, 3, 0, error);
  298 }
  299 
  300 /************* external function ***********
  301  *                                         *
  302  *        GAMGI_IO_X3D_RENDER_LOOPS        *
  303  *                                         *
  304  *    draws line loops (connected lines)   *
  305  *******************************************/
  306 
  307 void gamgi_io_x3d_render_loops (FILE *fp, int *loops, 
  308 double *points, gamgi_bool * error)
  309 {
  310 char string[GAMGI_ENGINE_LINE];
  311 int i, j, c, p, n_loops;
  312     
  313 if (loops == NULL) return;
  314 
  315 n_loops = loops[0];
  316     
  317 gamgi_io_file_fprintf (fp, "<IndexedLineSet coordIndex='", error);
  318 
  319 p = 1;
  320 c = 0;
  321 for (i = 0; i < n_loops; i++)
  322   {
  323   for (j = 0; j < loops[p]; j++)
  324     {
  325     sprintf (string, "%d ", c);
  326     gamgi_io_file_fprintf(fp, string, error);
  327     c++;
  328     }
  329   sprintf (string, "%d -1", c - loops[p]);
  330   gamgi_io_file_fprintf(fp, string, error);
  331   if (i != n_loops - 1)
  332   gamgi_io_file_fprintf(fp, " ", error);
  333         
  334   p += loops[p]+1;
  335   }
  336     
  337 gamgi_io_file_fprintf (fp, "'>\n<Coordinate point='", error);
  338     
  339 i = 1;
  340 while (n_loops-- > 0)
  341   {
  342   p = loops[i++];
  343   while (p-- > 0)
  344     {
  345     sprintf (string, "%f %f %f", 
  346     points[3*loops[i]], points[3*loops[i]+1], points[3*loops[i]+2]);
  347     gamgi_io_file_fprintf (fp, string, error);
  348     i++;
  349             
  350     if (p > 0 || n_loops > 0) gamgi_io_file_fprintf (fp, ", ", error);
  351     }
  352   }
  353 gamgi_io_file_fprintf(fp, "'/>\n</IndexedLineSet>\n", error);
  354 }
  355 
  356 /************* external function ***********
  357  *                                         *
  358  *        GAMGI_IO_X3D_RENDER_LINES        *
  359  *                                         *
  360  *               draws lines               *
  361  *******************************************/
  362 
  363 void gamgi_io_x3d_render_lines (FILE *fp, 
  364 int *lines, double *points, gamgi_bool *error)
  365 {
  366 char string[GAMGI_ENGINE_LINE];
  367 int i, n_lines;
  368 
  369 n_lines = lines[0];
  370 if (n_lines == 0) return;
  371 
  372 gamgi_io_file_fprintf(fp, "<IndexedLineSet coordIndex='", error);
  373     
  374 for (i = 0; i <n_lines; i++)
  375   {
  376   sprintf (string, "%d %d -1", i*2, i*2+1);
  377   gamgi_io_file_fprintf (fp, string, error);
  378 
  379   if (i != n_lines - 1)
  380     gamgi_io_file_fprintf (fp, " ", error);
  381   }
  382     
  383 gamgi_io_file_fprintf(fp, "'>\n<Coordinate point='", error);
  384     
  385 i = 1;
  386 while (n_lines-- > 0)
  387   {
  388   sprintf (string, "%f %f %f, ", 
  389   points[3*lines[i]], points[3*lines[i]+1], points[3*lines[i]+2]);
  390   gamgi_io_file_fprintf(fp, string, error);
  391   i++;
  392   sprintf (string, "%f %f %f", 
  393   points[3*lines[i]], points[3*lines[i]+1], points[3*lines[i]+2]);
  394   gamgi_io_file_fprintf(fp, string, error);
  395   i++;
  396 
  397   if (n_lines>0)
  398   gamgi_io_file_fprintf(fp, ", ", error);
  399   }
  400 
  401 gamgi_io_file_fprintf(fp, "'/>\n</IndexedLineSet>\n", error);
  402 }
  403 
  404 /************* external function ***********
  405  *                                         *
  406  *      GAMGI_IO_X3D_RENDER_TRIANGLES      *
  407  *                                         *
  408  *       render a triangle-based face      *
  409  *******************************************/
  410 
  411 void gamgi_io_x3d_render_triangles (FILE *fp,
  412 int n_triangles, double *points, gamgi_bool *error)
  413 {
  414 char string[GAMGI_ENGINE_LINE];
  415 int n_points, i;
  416 
  417 if (n_triangles == 0) return;
  418 n_points = 3 * n_triangles;
  419 
  420 gamgi_io_file_fprintf (fp, "<IndexedTriangleSet ", error);
  421 gamgi_io_file_fprintf (fp, "solid=\"false\" ", error);
  422 gamgi_io_file_fprintf (fp, "ccw=\"true\" ", error);
  423 gamgi_io_file_fprintf (fp, "normalPerVertex=\"false\" ", error);
  424 gamgi_io_file_fprintf (fp, "index=\"\n", error);
  425 
  426 for (i = 0; i < n_points; i += 3)
  427   {
  428   sprintf (string, "%d %d %d\n", i + 0, i + 1, i + 2);
  429   gamgi_io_file_fprintf (fp, string, error);
  430   }
  431 gamgi_io_file_fprintf (fp, "\">\n<Coordinate point=\"\n", error);
  432 
  433 for (i = 0; i < n_points; i++)
  434   {
  435   sprintf (string, "%f %f %f\n",
  436   points[3 * i + 0], points[3 * i + 1] + 10, points[3 * i + 2]);
  437   gamgi_io_file_fprintf (fp, string, error);
  438   }
  439 
  440 gamgi_io_file_fprintf (fp, "\"/>\n</IndexedTriangleSet>\n", error);
  441 }
  442 
  443 /************* external function ***********
  444  *                                         *
  445  *      GAMGI_IO_X3D_RENDER_LINE_STRIP     *
  446  *                                         *
  447  *            draws a line strip           *
  448  *******************************************/
  449 
  450 void gamgi_io_x3d_render_line_strip (FILE *fp, 
  451 int n_points, double * points, gamgi_bool * error)
  452 {
  453 char string[GAMGI_ENGINE_LINE];
  454 int i;
  455     
  456 if (n_points == 0) return;
  457     
  458 gamgi_io_file_fprintf(fp, "<IndexedLineSet coordIndex='", error);
  459     
  460 for (i = 0; i < n_points; i++)
  461   {
  462   sprintf (string, "%d", i);
  463   gamgi_io_file_fprintf(fp, string, error);
  464         
  465   if (i != n_points - 1)
  466     gamgi_io_file_fprintf (fp, " ", error);
  467   else
  468    gamgi_io_file_fprintf(fp, " -1'>\n<Coordinate point='", error);
  469   }
  470 
  471 while (n_points-- > 0)
  472   {
  473   sprintf (string, "%f %f %f", 
  474   *(points+3*n_points), *(points+3*n_points+1), *(points+3*n_points+2));
  475   gamgi_io_file_fprintf (fp, string, error);
  476 
  477   if (n_points > 0)
  478   gamgi_io_file_fprintf (fp, ", ", error);
  479   }
  480 
  481 gamgi_io_file_fprintf (fp, "'/>\n</IndexedLineSet>\n", error);
  482 }
  483 
  484 /************* external function ***********
  485  *                                         *
  486  *        GAMGI_IO_X3D_RENDER_POLYGONS     *
  487  *                                         *
  488  *                draws polygons           *
  489  *******************************************/
  490 
  491 void gamgi_io_x3d_render_polygons (FILE *fp, 
  492 int *loops, double *points, gamgi_bool * error)
  493 {
  494     char str[256];
  495     int p, i, j, n_loops, c;
  496     int * n_vertices;
  497     
  498     double ** point;
  499     
  500     p = 0;
  501     c = 0;
  502     
  503     n_loops = loops[p++];
  504     n_vertices = malloc(sizeof(int)*n_loops);
  505     point = malloc(sizeof(double *)*n_loops);
  506     
  507     gamgi_io_file_fprintf(fp, "<IndexedFaceSet solid='false' coordIndex='", error);
  508 
  509     for(i=0; i<n_loops; i++)
  510     {
  511         n_vertices[i] = loops[p++];
  512         point[i] = malloc(n_vertices[i]*sizeof(double)*3);
  513         
  514         for(j=0; j<n_vertices[i]; j++)
  515         {
  516             if(i==0 && j==0)
  517                 sprintf(str, "%d", c);
  518             else
  519                 sprintf(str, " %d", c);
  520             
  521             gamgi_io_file_fprintf(fp, str, error);
  522             
  523             c++;
  524             
  525             point[i][j*3] = points[3 * loops[p]];
  526             point[i][j*3+1] = points[3 * loops[p]+1];
  527             point[i][j*3+2] = points[3 * loops[p]+2];
  528             
  529             p++;
  530         }
  531         
  532         sprintf(str, " -1");
  533         
  534         gamgi_io_file_fprintf(fp, str, error);
  535     }
  536     
  537     gamgi_io_file_fprintf(fp, "'>\n<Coordinate point='", error);
  538     for(i=0; i<n_loops; i++)
  539     {
  540         for(j=0; j<n_vertices[i]; j++)
  541         {
  542             sprintf(str, "%f %f %f", point[i][j*3], point[i][j*3+1], point[i][j*3+2]);
  543             gamgi_io_file_fprintf(fp, str, error);
  544             if(!(i==n_loops-1&&j==n_vertices[i]-1))
  545                 gamgi_io_file_fprintf(fp, ", ", error);
  546         }
  547     }
  548         
  549     gamgi_io_file_fprintf(fp, "'/>\n</IndexedFaceSet>\n", error);
  550     
  551     for(i=0; i<n_loops; i++) free(point[i]);
  552     free(point);
  553 }
  554 
  555 
  556 /* draws colored polygons */
  557 void gamgi_io_x3d_render_polygons_color (FILE *fp, int *loops, 
  558 double *points, int *paints, float *colors, gamgi_bool * error)
  559 {
  560     char str[256];
  561     int p, i, j, n_loops, c;
  562     int * n_vertices;
  563     
  564     double ** point;
  565     
  566     p = 0;
  567     c = 0;
  568     
  569     n_loops = loops[p++];
  570     n_vertices = malloc(sizeof(int)*n_loops);
  571     point = malloc(sizeof(double *)*n_loops);
  572     
  573     gamgi_io_file_fprintf(fp, "<IndexedFaceSet solid='false' coordIndex='", error);
  574 
  575     for(i=0; i<n_loops; i++)
  576     {
  577         n_vertices[i] = loops[p++];
  578         point[i] = malloc(n_vertices[i]*sizeof(double)*3);
  579 
  580         for(j=0; j<n_vertices[i]; j++)
  581         {
  582             if(i==0 && j==0)
  583                 sprintf(str, "%d", c);
  584             else
  585                 sprintf(str, " %d", c);
  586             
  587             gamgi_io_file_fprintf(fp, str, error);
  588             
  589             c++;
  590             
  591             point[i][j*3] = points[3 * loops[p]];
  592             point[i][j*3+1] = points[3 * loops[p]+1];
  593             point[i][j*3+2] = points[3 * loops[p]+2];
  594             
  595             p++;
  596         }
  597         
  598         sprintf(str, " -1");
  599         
  600         gamgi_io_file_fprintf(fp, str, error);
  601     }
  602     
  603     gamgi_io_file_fprintf(fp, "' colorPerVertex='false' colorIndex='", error);
  604 
  605     c=-1;
  606     p=1;
  607     for(i=0; i<n_loops; i++)
  608     {
  609         if(paints[0] == p)
  610         {
  611             c++;
  612             paints++;
  613         }
  614         
  615         p += loops[p]+1;
  616         
  617         sprintf(str, "%d", c);
  618         gamgi_io_file_fprintf(fp, str, error);
  619 
  620         if(i<n_loops)
  621             gamgi_io_file_fprintf(fp, " ", error);
  622     }
  623     
  624     gamgi_io_file_fprintf(fp, "'>\n<Coordinate point='", error);
  625     for(i=0; i<n_loops; i++)
  626     {
  627         for(j=0; j<n_vertices[i]; j++)
  628         {
  629             sprintf(str, "%f %f %f", point[i][j*3], point[i][j*3+1], point[i][j*3+2]);
  630             gamgi_io_file_fprintf(fp, str, error);
  631             if(!(i==n_loops-1&&j==n_vertices[i]-1))
  632                 gamgi_io_file_fprintf(fp, ", ", error);
  633         }
  634     }
  635         
  636     gamgi_io_file_fprintf(fp, "'/>\n<Color color='", error);
  637 
  638     for(i=0; i<=c; i++)
  639     {
  640         sprintf(str, "%f %f %f", colors[0], colors[1], colors[2]);
  641         gamgi_io_file_fprintf(fp, str, error);
  642         colors += 3;
  643         
  644         if(i!=c)
  645             gamgi_io_file_fprintf(fp, ", ", error);
  646     }
  647     
  648     gamgi_io_file_fprintf(fp, "'/>\n</IndexedFaceSet>\n", error);
  649     
  650     
  651     
  652     for(i=0; i<n_loops; i++) free(point[i]);
  653     free(point);
  654 }
  655 
  656 /************* internal function ***************
  657  *                                             *
  658  *           GAMGI_IO_X3D_RENDER_WIRED         *
  659  *                                             *
  660  * draws wired text using the hard coded fonts *
  661  ***********************************************/
  662 
  663 void gamgi_io_x3d_render_wired (FILE *fp, gamgi_text *text, gamgi_bool *error)
  664 {
  665 int c = 0;
  666 int i, j;
  667 int *driver;
  668 float *points;
  669 char str[256];
  670 float spacing;
  671 
  672 printf ("ola\n");
  673 
  674 gamgi_mesa_text_data_wired (text->font, (const float **) &points, (const int **) &driver);
  675 gamgi_io_file_fprintf (fp, "<IndexedLineSet coordIndex='", error);
  676     
  677         
  678     for(i=0; i<text->length; i++)
  679     {
  680         j = driver[text->string[i]-GAMGI_IO_ASCII_START];
  681     
  682         while(points[j] != GAMGI_IO_CHAR)
  683         {
  684             if(points[j] == GAMGI_IO_STROKE)
  685             {
  686                 gamgi_io_file_fprintf(fp, "-1, ", error);
  687                 j++;
  688             }
  689             else
  690             {
  691                 sprintf(str, "%d, ", c);
  692                 gamgi_io_file_fprintf(fp, str, error);          
  693                 c++;
  694                 j+=2;
  695             }
  696         }
  697         
  698         if(i<text->length-1)
  699             gamgi_io_file_fprintf(fp, "-1, ", error);
  700     }
  701     
  702     gamgi_io_file_fprintf(fp, "-1'>\n<Coordinate point='", error);
  703     spacing = 0.0f;
  704     
  705     for(i=0; i<text->length; i++)
  706     {
  707         j = driver[text->string[i]-GAMGI_IO_ASCII_START];
  708         
  709         while(points[j] != GAMGI_IO_CHAR)
  710         {
  711             if(points[j] != GAMGI_IO_STROKE)
  712             {
  713                 sprintf(str, "%f %f 0.0", points[j]/GAMGI_MESA_STROKED_SCALE+spacing, points[j+1]/GAMGI_MESA_STROKED_SCALE);
  714                 gamgi_io_file_fprintf(fp, str, error);
  715                 j+=2;
  716                 
  717                 if(i<text->length-1 || points[j] != GAMGI_IO_CHAR)
  718                     gamgi_io_file_fprintf(fp, ", ", error);
  719             }
  720             else
  721             {
  722                 j++;
  723             }
  724         }
  725         
  726         spacing += points[text->string[i]-GAMGI_IO_ASCII_START+2]/GAMGI_MESA_STROKED_SCALE;
  727     }
  728     
  729     gamgi_io_file_fprintf(fp, "'/>\n</IndexedLineSet>\n", error);
  730 }
  731 
  732 void x3d_font_extrusion(glu_tessdata * data)
  733 {
  734     int i;
  735     double depth = GAMGI_MESA_EXTRUDED_DEPTH * GAMGI_MESA_EXTRUDED_SCALE;
  736     
  737     int n_contour = data->extruded->contour->offset;
  738     double *contour = data->extruded->contour->array;
  739     double scale = data->extruded->scale;
  740     
  741     int itemp[4];
  742     double dtemp[3];
  743 
  744     data->polygon = GL_TRIANGLE_STRIP;
  745     data->vertex = 0;
  746     
  747     for(i = 0; i <= n_contour; i++)
  748     {       
  749         if(i == n_contour)
  750             i = n_contour = 0;
  751 
  752         if(data->vertex>1)
  753         {
  754             itemp[0] = data->vcount/3-2;
  755             itemp[1] = data->vcount/3-1;
  756             itemp[2] = data->vcount/3;
  757             itemp[3] = -1;
  758             
  759             data->ocount += 4;
  760             
  761             gamgi_engine_iarray_push(data->order, itemp);
  762         }
  763         
  764         if(contour[2*i + 0] == contour[2*i + 0])
  765             dtemp[0] = data->x + contour[2*i + 0] * scale;
  766         else
  767             dtemp[0] = data->x;
  768         
  769         if(contour[2*i + 1] == contour[2*i + 1])
  770             dtemp[1] = data->y + contour[2*i + 1] * scale;
  771         else
  772             dtemp[1] = data->y;
  773         
  774         dtemp[2] = data->z - depth / 2.0;
  775         
  776         data->vcount += 3;
  777         data->vertex++;
  778         
  779         gamgi_engine_darray_push(data->vert, dtemp);
  780         
  781         if(data->vertex>1)
  782         {
  783             itemp[0] = data->vcount/3-2;
  784             itemp[1] = data->vcount/3-1;
  785             itemp[2] = data->vcount/3;
  786             itemp[3] = -1;
  787             
  788             data->ocount += 4;
  789             
  790             gamgi_engine_iarray_push(data->order, itemp);
  791         }
  792         
  793         if(contour[2*i + 0] == contour[2*i + 0])
  794             dtemp[0] = data->x + contour[2*i + 0] * scale;
  795         else
  796             dtemp[0] = data->x;
  797         
  798         if(contour[2*i + 1] == contour[2*i + 1])
  799             dtemp[1] = data->y + contour[2*i + 1] * scale;
  800         else
  801             dtemp[1] = data->y;
  802         
  803         dtemp[2] = data->z + depth / 2.0;
  804         
  805         data->vcount += 3;
  806         data->vertex++;
  807         
  808         gamgi_engine_darray_push(data->vert, dtemp);
  809     }
  810 }
  811 
  812 
  813 static void static_glu_begin (GLenum polygon, glu_tessdata *data)
  814 { 
  815 data->polygon = polygon;
  816 data->vertex = 0;
  817     
  818 if (polygon == GL_TRIANGLE_FAN)
  819   data->fancenter = data->vcount / 3;
  820 }
  821 
  822 static void static_glu_vertex (double* vertex, glu_tessdata *data)
  823 {   
  824 int temp[4];
  825 double point[3];
  826 
  827 switch (data->polygon)
  828   {
  829   case GL_TRIANGLES:        /* 0, 1, 2, -1, 3, 4, 5, -1... */
  830   if ((data->vertex + 1) % 3 == 0)
  831     {
  832     temp[0] = data->vcount / 3 - 2;
  833     temp[1] = data->vcount / 3 - 1;
  834     temp[2] = data->vcount / 3 - 0;
  835     temp[3] = -1;
  836                 
  837     data->ocount += 4;
  838     gamgi_engine_iarray_push(data->order, temp);
  839     }
  840   break;
  841 
  842   case GL_TRIANGLE_STRIP:   /*Strip: 0,1,2,-1,1,2,3,-1,2,3,4,-1... "n-2, n-1, n, -1" */
  843   if (data->vertex > 1)
  844     {
  845     temp[0] = data->vcount / 3 - 2;
  846     temp[1] = data->vcount / 3 - 1;
  847     temp[2] = data->vcount / 3 - 0;
  848     temp[3] = -1;
  849                 
  850     data->ocount += 4;
  851     gamgi_engine_iarray_push(data->order, temp);
  852     }
  853   break;
  854 
  855   case GL_TRIANGLE_FAN:     /* Fan: 0,1,2,-1,0,2,3,-1,0,3,4,-1... "0, n-1, n, -1" */
  856   if (data->vertex > 1)
  857     {
  858     temp[0] = data->fancenter;
  859     temp[1] = data->vcount / 3 - 1;
  860     temp[2] = data->vcount / 3;
  861     temp[3] = -1;
  862                 
  863     data->ocount += 4;
  864     gamgi_engine_iarray_push(data->order, temp);
  865     }
  866   break;
  867   }
  868 
  869 point[0] = vertex[0] + data->x;
  870 point[1] = vertex[1] + data->y;
  871 point[2] = vertex[2] + data->z;
  872     
  873 data->vcount += 3;
  874 data->vertex++;
  875     
  876 gamgi_engine_darray_push(data->vert, point);
  877 }
  878 
  879 
  880 static void static_glu_combine (double coords[3], void *vertices[4], 
  881 float weights[4], void** output, glu_tessdata *data)
  882 {
  883 double *vertex;
  884 gamgi_extruded *extruded = data->extruded;
  885 
  886 /***************************************************
  887  * vertices and weights data is used to calculate  *
  888  * averaged points and is not used in this context *
  889  ***************************************************/
  890 
  891 vertex = (double *) malloc (3 * sizeof(double));
  892 gamgi_math_vector_copy(coords, vertex);
  893 
  894 *output = vertex;
  895 extruded->extra = gamgi_engine_slist_add_start (extruded->extra);
  896 extruded->extra->data = vertex;
  897 }
  898 
  899 static int static_vertical_move (FT_Vector *to, glu_tessdata *data)
  900 {
  901 if (data->extruded->open == TRUE)
  902   {
  903   gamgi_engine_darray_push(data->extruded->normals, data->extruded->normals->array);
  904 
  905   x3d_font_extrusion (data);
  906 
  907   gamgi_engine_darray_pop(data->extruded->contour, 0);
  908   gamgi_engine_darray_pop(data->extruded->normals, 0); 
  909   }
  910 
  911 data->extruded->last[0] = to->x;
  912 data->extruded->last[1] = to->y;
  913 data->extruded->last[2] = 0.0;
  914 
  915 data->extruded->open = TRUE;
  916 
  917 return 0;
  918 }
  919 
  920 static int static_vertical_line (FT_Vector *to, glu_tessdata *data)
  921 {
  922 double vertex[2];
  923 double normal[2];
  924 gamgi_extruded * extruded = data->extruded;
  925 
  926 vertex[0] = to->x;
  927 vertex[1] = to->y;
  928 
  929 normal[0] = extruded->normal_y * (vertex[1] - extruded->last[1]);
  930 normal[1] = extruded->normal_x * (vertex[0] - extruded->last[0]);
  931 
  932 gamgi_engine_darray_push (extruded->contour, vertex);
  933 gamgi_engine_darray_push (extruded->normals, normal);
  934 
  935 extruded->last[0] = vertex[0];
  936 extruded->last[1] = vertex[1];
  937 extruded->last[2] = 0.0;
  938 
  939 return 0;
  940 }
  941 
  942 static int static_vertical_conic (FT_Vector *control, FT_Vector *to, glu_tessdata *data)
  943 {
  944 double vertex[2];
  945 double normal[2];
  946 double to_vertex[2];
  947 double control_vertex[2];
  948 double b[2], c[2], d[2], f[2], df[2], d2f[2];
  949 int i;
  950 gamgi_extruded * extruded = data->extruded;
  951 
  952 to_vertex[0] = to->x;
  953 to_vertex[1] = to->y;
  954 
  955 control_vertex[0] = control->x;
  956 control_vertex[1] = control->y;
  957 
  958 b[0] = extruded->last[0] - 2 * control_vertex[0] + to_vertex[0];
  959 b[1] = extruded->last[1] - 2 * control_vertex[1] + to_vertex[1];
  960 
  961 c[0] = -2 * extruded->last[0] + 2 * control_vertex[0];
  962 c[1] = -2 * extruded->last[1] + 2 * control_vertex[1];
  963 
  964 d[0] = extruded->last[0];
  965 d[1] = extruded->last[1];
  966 
  967 f[0] = d[0];
  968 f[1] = d[1];
  969 df[0] = c[0] * extruded->delta1 + b[0] * extruded->delta2;
  970 df[1] = c[1] * extruded->delta1 + b[1] * extruded->delta2;
  971 d2f[0] = 2 * b[0] * extruded->delta2;
  972 d2f[1] = 2 * b[1] * extruded->delta2;
  973 
  974 for (i = 0; i < GAMGI_MESA_EXTRUDED_STEPS - 1; i++) 
  975   {
  976   f[0] += df[0];
  977   f[1] += df[1];
  978 
  979   vertex[0] = f[0];
  980   vertex[1] = f[1];
  981 
  982   normal[0] = extruded->normal_y * df[1];
  983   normal[1] = extruded->normal_x * df[0];
  984 
  985   gamgi_engine_darray_push (extruded->contour, vertex);
  986   gamgi_engine_darray_push (extruded->normals, normal);
  987 
  988   df[0] += d2f[0];
  989   df[1] += d2f[1];
  990   }
  991 
  992 vertex[0] = to->x;
  993 vertex[1] = to->y;
  994 
  995 normal[0] = extruded->normal_y * df[1];
  996 normal[1] = extruded->normal_x * df[0];
  997 
  998 gamgi_engine_darray_push (extruded->contour, vertex);
  999 gamgi_engine_darray_push (extruded->normals, normal);
 1000 
 1001 extruded->last[0] = to_vertex[0];
 1002 extruded->last[1] = to_vertex[1];
 1003 extruded->last[2] = 0.0;
 1004 
 1005 return 0;
 1006 }
 1007 
 1008 static int static_vertical_cubic (FT_Vector *control1, 
 1009 FT_Vector *control2, FT_Vector* to, glu_tessdata * data)
 1010 {
 1011 gamgi_extruded *extruded = data->extruded;
 1012 double vertex[2];
 1013 double normal[2];
 1014 double to_vertex[2];
 1015 double control1_vertex[2];
 1016 double control2_vertex[2];
 1017 double a[2], b[2], c[2], d[2], f[2], df[2], d2f[2], d3f[2];
 1018 int i;
 1019 
 1020 to_vertex[0] = to->x;
 1021 to_vertex[1] = to->y;
 1022 
 1023 control1_vertex[0] = control1->x;
 1024 control1_vertex[1] = control1->y;
 1025 
 1026 control2_vertex[0] = control2->x;
 1027 control2_vertex[1] = control2->y;
 1028 
 1029 a[0] = -extruded->last[0] + 3 * control1_vertex[0]
 1030 -3 * control2_vertex[0] + to_vertex[0];
 1031 a[1] = -extruded->last[1] + 3 * control1_vertex[1]
 1032 -3 * control2_vertex[1] + to_vertex[1];
 1033 
 1034 b[0] = 3 * extruded->last[0] - 6 * control1_vertex[0] + 
 1035 3 * control2_vertex[0];
 1036 b[1] = 3 * extruded->last[1] - 6 * control1_vertex[1] + 
 1037 3 * control2_vertex[1];
 1038 
 1039 c[0] = -3 * extruded->last[0] + 3 * control1_vertex[0];
 1040 c[1] = -3 * extruded->last[1] + 3 * control1_vertex[1];
 1041 
 1042 d[0] = extruded->last[0];
 1043 d[1] = extruded->last[1];
 1044 
 1045 f[0] = d[0];
 1046 f[1] = d[1];
 1047 df[0] = c[0] * extruded->delta1 + b[0] * extruded->delta2 + a[0] * extruded->delta3;
 1048 df[1] = c[1] * extruded->delta1 + b[1] * extruded->delta2 + a[1] * extruded->delta3;
 1049 d2f[0] = 2 * b[0] * extruded->delta2 + 6 * a[0] * extruded->delta3;
 1050 d2f[1] = 2 * b[1] * extruded->delta2 + 6 * a[1] * extruded->delta3;
 1051 d3f[0] = 6 * a[0] * extruded->delta3;
 1052 d3f[1] = 6 * a[1] * extruded->delta3;
 1053 
 1054 for (i = 0; i < GAMGI_MESA_EXTRUDED_STEPS - 1; i++)
 1055   {
 1056   f[0] += df[0];
 1057   f[1] += df[1];
 1058 
 1059   vertex[0] = f[0];
 1060   vertex[1] = f[1];
 1061 
 1062   normal[0] = extruded->normal_y * df[1];
 1063   normal[1] = extruded->normal_x * df[0];
 1064 
 1065   gamgi_engine_darray_push (extruded->contour, vertex);
 1066   gamgi_engine_darray_push (extruded->normals, normal);
 1067 
 1068   df[0] += d2f[0];
 1069   df[1] += d2f[1];
 1070   d2f[0] += d3f[0];
 1071   d2f[1] += d3f[1];
 1072   }
 1073 
 1074 vertex[0] = to->x;
 1075 vertex[1] = to->y;
 1076 
 1077 normal[0] = extruded->normal_y * df[1];
 1078 normal[1] = extruded->normal_x * df[0];
 1079 
 1080 gamgi_engine_darray_push (extruded->contour, vertex);
 1081 gamgi_engine_darray_push (extruded->normals, normal);
 1082 
 1083 extruded->last[0] = to_vertex[0];
 1084 extruded->last[1] = to_vertex[1];
 1085 extruded->last[2] = 0.0;
 1086 
 1087 return 0;
 1088 }
 1089 
 1090 static void x3d_font_face (FT_OutlineGlyph glyph, glu_tessdata *data)
 1091 {
 1092 gluTessBeginPolygon (data->extruded->tesselator, data);
 1093 data->extruded->open = FALSE;
 1094 
 1095 FT_Outline_Decompose (&glyph->outline, &data->extruded->horizontal, data->extruded);
 1096 
 1097 if (data->extruded->open == TRUE)
 1098   gluTessEndContour (data->extruded->tesselator);
 1099 
 1100 gluTessEndPolygon (data->extruded->tesselator);
 1101 }
 1102 
 1103 gamgi_extruded *static_extruded_create (gamgi_enum font, 
 1104 FT_Library *freetype, FT_Face *face)
 1105 {
 1106 gamgi_extruded *extruded;
 1107 char fullname[GAMGI_IO_FULLNAME];
 1108 char filename[GAMGI_ENGINE_TOKEN];
 1109 
 1110 gamgi_mesa_text_data_solid (font, filename);
 1111 
 1112 sprintf (fullname, "%s/%s", gamgi->text->path, filename);
 1113 
 1114 FT_Init_FreeType (freetype);
 1115 
 1116 FT_New_Face (*freetype, fullname, 0, face);
 1117 
 1118 if ((*face)->charmap == 0 && (*face)->num_charmaps > 0)
 1119   FT_Select_Charmap (*face, (*face)->charmaps[0]->encoding);
 1120 
 1121 extruded = (gamgi_extruded *) malloc (sizeof (gamgi_extruded));
 1122 
 1123 extruded->horizontal.move_to = (FT_Outline_MoveTo_Func) gamgi_mesa_text_horizontal_move;
 1124 extruded->horizontal.line_to = (FT_Outline_LineTo_Func) gamgi_mesa_text_horizontal_line;
 1125 extruded->horizontal.conic_to = (FT_Outline_ConicTo_Func) gamgi_mesa_text_horizontal_conic;
 1126 extruded->horizontal.cubic_to = (FT_Outline_CubicTo_Func) gamgi_mesa_text_horizontal_cubic;
 1127 extruded->horizontal.shift = 0;
 1128 extruded->horizontal.delta = 0;
 1129 
 1130 extruded->vertical.move_to = (FT_Outline_MoveTo_Func) static_vertical_move;
 1131 extruded->vertical.line_to = (FT_Outline_LineTo_Func) static_vertical_line;
 1132 extruded->vertical.conic_to = (FT_Outline_ConicTo_Func) static_vertical_conic;
 1133 extruded->vertical.cubic_to = (FT_Outline_CubicTo_Func) static_vertical_cubic;
 1134 extruded->vertical.shift = 0;
 1135 extruded->vertical.delta = 0;
 1136 
 1137 extruded->delta1 = 1.0 / GAMGI_MESA_EXTRUDED_STEPS;
 1138 extruded->delta2 = extruded->delta1 * extruded->delta1;
 1139 extruded->delta3 = extruded->delta2 * extruded->delta1;
 1140 
 1141 FT_Set_Char_Size (*face, 0, (*face)->units_per_EM, 0, 0);
 1142 extruded->scale = GAMGI_MESA_EXTRUDED_SCALE / (*face)->units_per_EM;
 1143 
 1144 extruded->vertices = NULL;
 1145 extruded->extra = NULL;
 1146 
 1147 extruded->contour = gamgi_engine_darray_create(GAMGI_MESA_EXTRUDED_START, 
 1148 GAMGI_MESA_EXTRUDED_STEP, 2);
 1149 extruded->normals = gamgi_engine_darray_create(GAMGI_MESA_EXTRUDED_START, 
 1150 GAMGI_MESA_EXTRUDED_STEP, 2);
 1151 
 1152 extruded->tesselator = gluNewTess ();
 1153 
 1154 gluTessCallback (extruded->tesselator, GLU_TESS_VERTEX_DATA, 
 1155 (gamgi_tesselation) static_glu_vertex);
 1156 gluTessCallback (extruded->tesselator, GLU_TESS_BEGIN_DATA, 
 1157 (gamgi_tesselation) static_glu_begin);
 1158 gluTessCallback(extruded->tesselator, GLU_TESS_COMBINE_DATA, 
 1159 (gamgi_tesselation) static_glu_combine);
 1160 
 1161 return extruded;
 1162 }
 1163 
 1164 gamgi_bool static_extruded_remove (FT_Library freetype, 
 1165 FT_Face face, gamgi_extruded *extruded)
 1166 {
 1167 gamgi_bool valid = TRUE;
 1168 
 1169 gluDeleteTess (extruded->tesselator);
 1170 gamgi_engine_darray_remove (extruded->contour);
 1171 gamgi_engine_darray_remove (extruded->normals);
 1172 free (extruded);
 1173 
 1174 if (FT_Done_Face (face) != 0) valid = FALSE;
 1175 if (FT_Done_FreeType (freetype) != 0) valid = FALSE;
 1176 
 1177 return valid;
 1178 }
 1179 
 1180 /************* external function ***********
 1181  *                                         *
 1182  *          GAMGI_IO_X3D_RENDER_SOLID      *
 1183  *                                         *
 1184  *              draws solid text           *
 1185  *******************************************/
 1186 
 1187 void gamgi_io_x3d_render_solid (FILE *fp, gamgi_text *text, gamgi_bool *error)
 1188 {
 1189 glu_tessdata tessdata;
 1190 FT_OutlineGlyph glyph;
 1191 FT_Library freetype;
 1192 FT_Face face;
 1193 gamgi_slist *slist;
 1194 char string[GAMGI_ENGINE_LINE];
 1195 double *vert;
 1196 double depth;
 1197 int *order;
 1198 int ascii, index;
 1199 int i;
 1200 
 1201 tessdata.extruded = static_extruded_create (text->font, &freetype, &face);
 1202 tessdata.vcount = 0;
 1203 tessdata.ocount = 0;
 1204 tessdata.x = tessdata.y = 0.0f;
 1205 
 1206 tessdata.vert = gamgi_engine_darray_create (GAMGI_IO_X3D_TOTAL, GAMGI_IO_X3D_STEP, 3);
 1207 tessdata.order = gamgi_engine_iarray_create (GAMGI_IO_X3D_TOTAL, GAMGI_IO_X3D_STEP, 4);
 1208 
 1209 for (i = 0; i < text->length; i++)
 1210   {     
 1211   ascii = text->string[i];
 1212 
 1213   index = FT_Get_Char_Index(face, ascii);
 1214   FT_Load_Glyph(face, index, FT_LOAD_NO_SCALE);
 1215   FT_Get_Glyph(face->glyph, (FT_Glyph *) (void *) &glyph);
 1216 
 1217   if (glyph->outline.flags & FT_OUTLINE_REVERSE_FILL)
 1218     {
 1219     tessdata.extruded->normal_x = -1;
 1220     tessdata.extruded->normal_y = 1;
 1221     }
 1222   else
 1223     {
 1224     tessdata.extruded->normal_x = 1;
 1225     tessdata.extruded->normal_y = -1;
 1226     }
 1227 
 1228   depth = GAMGI_MESA_EXTRUDED_DEPTH * GAMGI_MESA_EXTRUDED_SCALE;
 1229         
 1230   tessdata.z = depth/2;
 1231   x3d_font_face(glyph, &tessdata);
 1232 
 1233   tessdata.z = -depth/2;
 1234   x3d_font_face(glyph, &tessdata);
 1235 
 1236   tessdata.z = 0.0;
 1237 
 1238   tessdata.extruded->open = FALSE;
 1239   FT_Outline_Decompose (&glyph->outline, &tessdata.extruded->vertical, &tessdata);
 1240   if (tessdata.extruded->open == TRUE)
 1241     {
 1242     gamgi_engine_darray_push (tessdata.extruded->normals, tessdata.extruded->normals->array);
 1243     x3d_font_extrusion (&tessdata);
 1244     gamgi_engine_darray_pop(tessdata.extruded->contour, 0);
 1245     gamgi_engine_darray_pop(tessdata.extruded->normals, 0);
 1246     }
 1247   
 1248   tessdata.x += face->glyph->advance.x * tessdata.extruded->scale;
 1249   tessdata.y += face->glyph->advance.y * tessdata.extruded->scale;
 1250 
 1251   FT_Done_Glyph((FT_Glyph) glyph);
 1252 
 1253   for (slist = tessdata.extruded->vertices; slist != NULL; slist = slist->next)
 1254     {
 1255     free(slist->data);
 1256     slist = gamgi_engine_slist_remove_start(slist);
 1257     }
 1258   tessdata.extruded->vertices = NULL;
 1259   }
 1260     
 1261 static_extruded_remove (freetype, face, tessdata.extruded);
 1262     
 1263 gamgi_io_file_fprintf (fp, "<IndexedFaceSet solid='false' coordIndex='", error);
 1264     
 1265 order = tessdata.order->array;
 1266     
 1267 for (i = 0; i < tessdata.ocount-1; i++)
 1268   {
 1269   sprintf (string, "%d, ", order[i]);
 1270   gamgi_io_file_fprintf(fp, string, error);
 1271   }
 1272 sprintf (string, "%d", order[i]);
 1273 gamgi_io_file_fprintf (fp, string, error);
 1274 
 1275 gamgi_io_file_fprintf (fp, "'>\n<Coordinate point='", error);
 1276     
 1277 vert = tessdata.vert->array;
 1278     
 1279 for (i = 0; i < tessdata.vcount / 3 - 1; i++)
 1280   {
 1281   sprintf (string, "%f %f %f, ", vert[i*3], vert[i*3+1], vert[i*3+2]);
 1282   gamgi_io_file_fprintf(fp, string, error);
 1283   }
 1284 sprintf (string, "%f %f %f", vert[i*3], vert[i*3+1], vert[i*3+2]);
 1285 gamgi_io_file_fprintf (fp, string, error);
 1286 
 1287 gamgi_io_file_fprintf(fp, "'/>\n</IndexedFaceSet>\n", error);
 1288 
 1289 gamgi_engine_darray_remove (tessdata.vert);
 1290 gamgi_engine_iarray_remove (tessdata.order);
 1291 }