"Fossies" - the Fresh Open Source Software Archive

Member "gamgi0.17.5x/src/io/gamgi_io_x3d.c" (23 Feb 2022, 58955 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. For more information about "gamgi_io_x3d.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.17.4x_vs_0.17.5x.

    1 /*******************************************
    2  *
    3  * $GAMGI/src/io/gamgi_io_x3d.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_mesa_atom.h"
   23 #include "gamgi_mesa_bond.h"
   24 #include "gamgi_math_vector.h"
   25 #include "gamgi_math_quaternion.h"
   26 #include "gamgi_io_file.h"
   27 #include "gamgi_io_error.h"
   28 #include "gamgi_io_x3d_render.h"
   29 
   30 /************* internal function ***********
   31  *                                         *
   32  *                STATIC_SCALE             *
   33  *                                         *
   34  *     open the scale node of an object    *
   35  *******************************************/
   36 
   37 static void static_scale (FILE *fp, double scale, double *center, 
   38 gamgi_bool *error)
   39 {
   40 char string[GAMGI_ENGINE_LINE];
   41 
   42 /*******************
   43  * Transform start *
   44  *******************/
   45 
   46 /*********************************************************
   47  * move the object center to the origin, scale the       *
   48  * object, move the object back to its original position *
   49  *********************************************************/
   50 
   51 if (fabs (scale - 1.0) > GAMGI_MATH_TOLERANCE)
   52   {
   53   sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
   54   gamgi->gamgi->length, center[0], 
   55   gamgi->gamgi->length, center[1], 
   56   gamgi->gamgi->length, center[2]);
   57   gamgi_io_file_fprintf (fp, string, error);
   58 
   59   sprintf (string, "<Transform scale=\"%.*f %.*f %.*f\">\n", 
   60   GAMGI_MATH_DECIMAL_SCALE, scale,
   61   GAMGI_MATH_DECIMAL_SCALE, scale,
   62   GAMGI_MATH_DECIMAL_SCALE, scale);
   63   gamgi_io_file_fprintf (fp, string, error);
   64 
   65   sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
   66   gamgi->gamgi->length, -center[0],
   67   gamgi->gamgi->length, -center[1],
   68   gamgi->gamgi->length, -center[2]);
   69   gamgi_io_file_fprintf (fp, string, error);
   70   }
   71 }
   72 
   73 /************* internal function ***********
   74  *                                         *
   75  *               STATIC_UNSCALE            *
   76  *                                         *
   77  *     close the scale node of an object   *
   78  *******************************************/
   79 
   80 static void static_unscale (FILE *fp, double scale, gamgi_bool *error)
   81 {
   82 /*****************
   83  * Transform end *
   84  *****************/
   85 
   86 if (fabs (scale - 1.0) > GAMGI_MATH_TOLERANCE)
   87   gamgi_io_file_fprintf(fp, "</Transform>\n</Transform>\n</Transform>\n", error);
   88 }
   89 
   90 static void static_line (FILE *fp, gamgi_bool lights, float *color, 
   91 double *start, double *end, int width, gamgi_bool *error)
   92 {
   93 char string[GAMGI_ENGINE_LINE];
   94 
   95 /***************
   96  * Shape start *
   97  ***************/
   98 
   99 gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  100 
  101 /************************
  102  * Appearance start+end *
  103  ************************/
  104 
  105 gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  106 
  107 if (lights == TRUE)
  108   sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
  109   GAMGI_MATH_DECIMAL_COLOR, color[0],
  110   GAMGI_MATH_DECIMAL_COLOR, color[1],
  111   GAMGI_MATH_DECIMAL_COLOR, color[2]);
  112 else
  113   sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  114   GAMGI_MATH_DECIMAL_COLOR, color[0],
  115   GAMGI_MATH_DECIMAL_COLOR, color[1],
  116   GAMGI_MATH_DECIMAL_COLOR, color[2]);
  117 gamgi_io_file_fprintf (fp, string, error);
  118 
  119 sprintf (string, "<LineProperties linewidthScaleFactor=\"%d\"/>\n", width);
  120 gamgi_io_file_fprintf (fp, string, error);
  121 
  122 gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  123 
  124 /******************
  125  * Line start+end *
  126  ******************/
  127 
  128 gamgi_io_file_fprintf (fp, "<IndexedLineSet coordIndex=\"0 1 -1\">\n", error);
  129 sprintf (string, "<Coordinate point=\"%.*f %.*f %.*f %.*f %.*f %.*f\"/>\n",
  130 gamgi->gamgi->length, start[0],
  131 gamgi->gamgi->length, start[1],
  132 gamgi->gamgi->length, start[2],
  133 gamgi->gamgi->length, end[0],
  134 gamgi->gamgi->length, end[1],
  135 gamgi->gamgi->length, end[2]);
  136 gamgi_io_file_fprintf (fp, string, error);
  137 gamgi_io_file_fprintf (fp, "</IndexedLineSet>\n", error);
  138 
  139 /*************
  140  * Shape end *
  141  *************/
  142 
  143 gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  144 }
  145 
  146 static void static_cylinder (FILE *fp, gamgi_bool lights, float *color,
  147 double length, double radius, gamgi_bool *error)
  148 {
  149 char string[GAMGI_ENGINE_LINE];
  150 
  151 /***************
  152  * Shape start *
  153  ***************/
  154 
  155 gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  156 
  157 /************************
  158  * Appearance start+end *
  159  ************************/
  160 
  161 gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  162 if (lights == TRUE)
  163   sprintf (string, "<Material shininess=\"%.*f\" diffuseColor=\"%.*f %.*f %.*f\"/>\n",
  164   GAMGI_MATH_DECIMAL_SHININESS, gamgi->light->shininess,
  165   GAMGI_MATH_DECIMAL_COLOR, color[0],
  166   GAMGI_MATH_DECIMAL_COLOR, color[1],
  167   GAMGI_MATH_DECIMAL_COLOR, color[2]);
  168 else
  169   sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  170   GAMGI_MATH_DECIMAL_COLOR, color[0],
  171   GAMGI_MATH_DECIMAL_COLOR, color[1],
  172   GAMGI_MATH_DECIMAL_COLOR, color[2]);
  173 gamgi_io_file_fprintf (fp, string, error);
  174 gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  175 
  176 /**********************
  177  * Cylinder start+end *
  178  **********************/
  179 
  180 sprintf (string, "<Cylinder height=\"%.*f\" radius=\"%.*f\" top=\"false\" bottom=\"false\"/>\n",
  181 gamgi->gamgi->length, length, gamgi->gamgi->length, radius);
  182 gamgi_io_file_fprintf (fp, string, error);
  183 
  184 /*************
  185  * Shape end *
  186  *************/
  187 
  188 gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  189 }
  190 
  191 static void static_text (FILE *fp, gamgi_text *text, 
  192 gamgi_bool lights, gamgi_bool *error)
  193 {
  194 gamgi_dlist *dlist;
  195 char string[GAMGI_ENGINE_LINE];
  196 double axis[3];
  197 double phi;
  198 
  199 /*************************
  200  * scale Transform start *
  201  *************************/
  202 
  203 static_scale (fp, text->object.scale, text->center, error);
  204 
  205 /*******************************
  206  * rotate+move Transform start *
  207  *******************************/
  208 
  209 gamgi_math_quaternion_to_axis (text->quaternion, &phi, axis);
  210 sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\" rotation=\"%.*f %.*f %.*f %.*f\">\n",
  211 gamgi->gamgi->length, text->origin[0], 
  212 gamgi->gamgi->length, text->origin[1], 
  213 gamgi->gamgi->length, text->origin[2],
  214 gamgi->gamgi->length, axis[0], 
  215 gamgi->gamgi->length, axis[1], 
  216 gamgi->gamgi->length, axis[2], 
  217 gamgi->gamgi->angle, phi);
  218 gamgi_io_file_fprintf (fp, string, error);
  219 
  220 /***************
  221  * Shape start *
  222  ***************/
  223 
  224 gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  225 
  226 /************************
  227  * Appearance start+end *
  228  ************************/
  229 
  230 gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  231 if (lights == TRUE)
  232   sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n", 
  233   GAMGI_MATH_DECIMAL_COLOR, text->red, 
  234   GAMGI_MATH_DECIMAL_COLOR, text->green, 
  235   GAMGI_MATH_DECIMAL_COLOR, text->blue);
  236 else
  237   sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
  238   GAMGI_MATH_DECIMAL_COLOR, text->red, 
  239   GAMGI_MATH_DECIMAL_COLOR, text->green, 
  240   GAMGI_MATH_DECIMAL_COLOR, text->blue);
  241 gamgi_io_file_fprintf(fp, string, error);
  242 gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  243 
  244 /*************************
  245  * export geometric data *
  246  *************************/
  247 
  248 if (text->font > GAMGI_IO_FONTS_WIRED)
  249   gamgi_io_x3d_render_solid (fp, text, error);
  250 else
  251   gamgi_io_x3d_render_wired (fp, text, error);
  252     
  253 /************************************
  254  * Shape, rotate+move Transform end *
  255  ************************************/
  256 
  257 gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  258 gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  259 
  260 /***********************
  261  * child objects: text *
  262  ***********************/
  263     
  264 for (dlist = text->text_start; dlist != NULL; dlist = dlist->next)
  265   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
  266 
  267 /***********************
  268  * scale Transform end *
  269  ***********************/
  270 
  271 static_unscale (fp, text->object.scale, error);
  272 }
  273 
  274 static void static_orbital (FILE *fp, gamgi_orbital *orbital, 
  275 gamgi_bool lights, gamgi_bool *error)
  276 {
  277 gamgi_dlist *dlist;
  278 int *dots;
  279 char string[GAMGI_ENGINE_LINE];
  280 double axis[3];
  281 double phi;
  282 float background[4];
  283 float color[3];
  284 
  285 /*************************
  286  * scale Transform start *
  287  *************************/
  288 
  289 static_scale (fp, orbital->object.scale, orbital->center, error);
  290 
  291 /*******************************
  292  * rotate+move Transform start *
  293  *******************************/
  294 
  295 gamgi_math_quaternion_to_axis (orbital->quaternion, &phi, axis);
  296 sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\" rotation=\"%.*f %.*f %.*f %.*f\">\n",
  297 gamgi->gamgi->length, orbital->origin[0],
  298 gamgi->gamgi->length, orbital->origin[1],
  299 gamgi->gamgi->length, orbital->origin[2],
  300 gamgi->gamgi->length, axis[0],
  301 gamgi->gamgi->length, axis[1],
  302 gamgi->gamgi->length, axis[2],
  303 gamgi->gamgi->angle, phi);
  304 gamgi_io_file_fprintf (fp, string, error);
  305 
  306 glGetFloatv (GL_COLOR_CLEAR_VALUE, background);
  307 
  308 dots = orbital->dots;
  309 if (orbital->style == GAMGI_MESA_WIRED)
  310   {
  311   /*************************
  312    * export geometric data *
  313    *************************/
  314 
  315   glLineWidth (4.0);
  316   if (dots[1] > 0)
  317     { 
  318     color[0] = orbital->base_r;
  319     color[1] = orbital->base_g;
  320     color[2] = orbital->base_b;
  321     gamgi_io_x3d_render_points (fp, dots[1],
  322     orbital->points + 3 * dots[0], color, error);
  323     }
  324 
  325   if (dots[2] > 0)
  326     {
  327     color[0] = orbital->phase_r;
  328     color[1] = orbital->phase_g;
  329     color[2] = orbital->phase_b;
  330     gamgi_io_x3d_render_points (fp, dots[2],
  331     orbital->points + 3 * dots[0] + 3 * dots[1], color, error);
  332     }
  333   }
  334 
  335 if (orbital->style == GAMGI_MESA_SOLID)
  336   {
  337   if (dots[1] > 0)
  338     {
  339     /***************
  340      * Shape start *
  341      ***************/
  342 
  343     /************************
  344      * Appearance start+end *
  345      ************************/
  346 
  347     gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  348     gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  349     if (lights == TRUE)
  350       sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
  351       GAMGI_MATH_DECIMAL_COLOR, orbital->base_r,
  352       GAMGI_MATH_DECIMAL_COLOR, orbital->base_g,
  353       GAMGI_MATH_DECIMAL_COLOR, orbital->base_b);
  354     else
  355       sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  356       GAMGI_MATH_DECIMAL_COLOR, orbital->base_r,
  357       GAMGI_MATH_DECIMAL_COLOR, orbital->base_g,
  358       GAMGI_MATH_DECIMAL_COLOR, orbital->base_b);
  359     gamgi_io_file_fprintf (fp, string, error);
  360     gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  361 
  362     /*************************
  363      * export geometric data *
  364      *************************/
  365 
  366     gamgi_io_x3d_render_triangles (fp, dots[1] / 3,
  367     orbital->points + 3 * dots[0], error);
  368     gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  369 
  370     /*************
  371      * Shape end *
  372      *************/
  373     }
  374 
  375   if (dots[2] > 0)
  376     {
  377     /***************
  378      * Shape start *
  379      ***************/
  380 
  381     /************************
  382      * Appearance start+end *
  383      ************************/
  384 
  385     gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  386     gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  387     if (lights == TRUE)
  388       sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
  389       GAMGI_MATH_DECIMAL_COLOR, orbital->phase_r,
  390       GAMGI_MATH_DECIMAL_COLOR, orbital->phase_g,
  391       GAMGI_MATH_DECIMAL_COLOR, orbital->phase_b);
  392     else
  393       sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  394       GAMGI_MATH_DECIMAL_COLOR, orbital->phase_r,
  395       GAMGI_MATH_DECIMAL_COLOR, orbital->phase_g,
  396       GAMGI_MATH_DECIMAL_COLOR, orbital->phase_b);
  397     gamgi_io_file_fprintf (fp, string, error);
  398     gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  399 
  400     /*************************
  401      * export geometric data *
  402      *************************/
  403 
  404     gamgi_io_x3d_render_triangles (fp, dots[2] / 3,
  405     orbital->points + 3 * dots[0] + 3 * dots[1], error);
  406     gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  407 
  408     /*************
  409      * Shape end *
  410      *************/
  411     }
  412   }
  413 
  414 /*****************************
  415  * rotate+move Transform end *
  416  *****************************/
  417 
  418 gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  419 
  420 /***********************
  421  * child objects: text *
  422  ***********************/
  423 
  424 for (dlist = orbital->text_start; dlist!=NULL; dlist = dlist->next)
  425   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
  426 
  427 /***********************
  428  * scale Transform end *
  429  ***********************/
  430 
  431 static_unscale (fp, orbital->object.scale, error);
  432 }
  433 
  434 static void static_bond (FILE *fp, gamgi_bond *bond, gamgi_atom *atom, 
  435 gamgi_bool lights, gamgi_bool *error)
  436 {
  437 gamgi_dlist *dlist;
  438 char string[GAMGI_ENGINE_LINE];
  439 double endpoint[3];
  440 double center[3], sub[3], axis[3];
  441 double length, radius;
  442 double angle = 0.0;
  443 float background[4];
  444 float color[3];
  445 
  446 glGetFloatv (GL_COLOR_CLEAR_VALUE, background);
  447     
  448 if (bond->atom2 == NULL) return;
  449 
  450 /***************************************
  451  * when color is a bond property, this *
  452  * function is executed only for atom1 *
  453  ***************************************/
  454 
  455 if (bond->color == TRUE && bond->atom2 == atom) return;
  456 
  457 if (bond->color == FALSE)
  458   {
  459   color[0] = atom->red;
  460   color[1] = atom->green;
  461   color[2] = atom->blue;
  462 
  463   /*****************************************************
  464    * the point where color changes from atom1 to atom2 *
  465    *****************************************************/
  466 
  467   endpoint[0] = (bond->atom1->position[0] + bond->atom2->position[0]) / 2.0;
  468   endpoint[1] = (bond->atom1->position[1] + bond->atom2->position[1]) / 2.0;
  469   endpoint[2] = (bond->atom1->position[2] + bond->atom2->position[2]) / 2.0;
  470   }
  471 else
  472   {     
  473   color[0] = bond->red;
  474   color[1] = bond->green;
  475   color[2] = bond->blue;
  476         
  477   /*********************************** 
  478    * this code runs for atom1 only,  *
  479    * so the endpoint is always atom2 *
  480    ***********************************/
  481 
  482   endpoint[0] = bond->atom2->position[0];
  483   endpoint[1] = bond->atom2->position[1];
  484   endpoint[2] = bond->atom2->position[2];
  485   }
  486     
  487 if (bond->draw == gamgi_mesa_bond_draw_cylinder)
  488   {
  489   /******************
  490    * draw cylinders *
  491    ******************/
  492 
  493   radius = bond->object.scale * bond->size * gamgi->atom->min;
  494 
  495   center[0] = (atom->position[0] + endpoint[0]) / 2.0;
  496   center[1] = (atom->position[1] + endpoint[1]) / 2.0;
  497   center[2] = (atom->position[2] + endpoint[2]) / 2.0;
  498 
  499   if (atom == bond->atom1)
  500     gamgi_math_vector_sub (atom->position, endpoint, sub);
  501   else
  502      gamgi_math_vector_sub (endpoint, atom->position, sub);
  503   length = gamgi_math_vector_length (sub);
  504   angle = acos (sub[1] / length);
  505   gamgi_math_vector_absolute (axis, sub[2], 0.0, -sub[0]);
  506   gamgi_math_vector_normal (axis);
  507         
  508   sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\" rotation=\"%.*f %.*f %.*f %.*f\">\n", 
  509   gamgi->gamgi->length, center[0], 
  510   gamgi->gamgi->length, center[1], 
  511   gamgi->gamgi->length, center[2],
  512   gamgi->gamgi->length, axis[0], 
  513   gamgi->gamgi->length, axis[1], 
  514   gamgi->gamgi->length, axis[2], 
  515   gamgi->gamgi->angle, angle);
  516   gamgi_io_file_fprintf (fp, string, error);
  517         
  518   if (bond->order <= 1.5)
  519     {
  520     /**********************************************
  521      * single bond: rendered as a single cylinder *
  522      **********************************************/
  523 
  524     static_cylinder (fp, lights, color, length, radius, error);
  525     }
  526   else if (bond->order <= 2.5)
  527     {
  528     /********************************************************************
  529      * double bond: render a central cylinder and two lateral cylinders *
  530      ********************************************************************/
  531 
  532     static_cylinder (fp, lights, color, length, radius, error);
  533 
  534     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n", 
  535     gamgi->gamgi->length, 0.0, gamgi->gamgi->length, 0.0, 
  536     gamgi->gamgi->length, -radius);
  537     gamgi_io_file_fprintf (fp, string, error);
  538     static_cylinder (fp, lights, color, length, radius / 2.0, error);
  539     gamgi_io_file_fprintf(fp, "</Transform>\n", error);
  540 
  541     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n", 
  542     gamgi->gamgi->length, 0.0, gamgi->gamgi->length, 0.0, 
  543     gamgi->gamgi->length, radius);
  544     gamgi_io_file_fprintf(fp, string, error);
  545     static_cylinder (fp, lights, color, length, radius / 2.0, error);
  546     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  547     }
  548   else
  549     {
  550     /*********************************************************************
  551      * triple bond: render a central cylinder and four lateral cylinders *
  552      *********************************************************************/
  553 
  554     static_cylinder (fp, lights, color, length, radius, error);
  555 
  556     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
  557     gamgi->gamgi->length, -radius,
  558     gamgi->gamgi->length, 0.0, gamgi->gamgi->length, 0.0);
  559     gamgi_io_file_fprintf (fp, string, error);
  560     static_cylinder (fp, lights, color, length, radius / 3.0, error);
  561     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  562 
  563     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
  564     gamgi->gamgi->length, radius,
  565     gamgi->gamgi->length, 0.0, gamgi->gamgi->length, 0.0);
  566     gamgi_io_file_fprintf (fp, string, error);
  567     static_cylinder (fp, lights, color, length, radius / 3.0, error);
  568     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  569 
  570     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
  571     gamgi->gamgi->length, 0.0, gamgi->gamgi->length, 0.0,
  572     gamgi->gamgi->length, -radius);
  573     gamgi_io_file_fprintf (fp, string, error);
  574     static_cylinder (fp, lights, color, length, radius / 3.0, error);
  575     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  576 
  577     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
  578     gamgi->gamgi->length, 0.0, gamgi->gamgi->length, 0.0,
  579     gamgi->gamgi->length, radius);
  580     gamgi_io_file_fprintf (fp, string, error);
  581     static_cylinder (fp, lights, color, length, radius / 3.0, error);
  582     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  583     }
  584   gamgi_io_file_fprintf(fp, "</Transform>\n", error);
  585   }
  586 else
  587   {
  588   /**************
  589    * draw lines *
  590    **************/
  591 
  592   if (bond->order <= 1.5)
  593     {
  594     /******************************************************************
  595      * bonds rendered as a single line: render the whole bond segment *
  596      ******************************************************************/
  597 
  598     static_line (fp, lights, color, atom->position, endpoint, 2, error);
  599     }
  600   else if (bond->order <= 2.5)
  601     {
  602     /*********************************************************************
  603      * bonds rendered as a double line: 1) render the whole bond segment *
  604      * with bond color; 2) render a inner segment with background color  *
  605      *********************************************************************/
  606 
  607     static_line (fp, lights, background, atom->position, endpoint, 2, error);
  608     static_line (fp, lights, color, atom->position, endpoint, 6, error);
  609     }
  610   else
  611     {
  612     /***************************************************************
  613      * bonds rendered as a triple line: 1) render the whole bond   *
  614      * segment with bond color; 2) render inner segment with       *
  615      * background color; 3) render central segment with bond color *
  616      ***************************************************************/
  617 
  618     static_line (fp, lights, color, atom->position, endpoint, 2, error);
  619     static_line (fp, lights, background, atom->position, endpoint, 6, error);
  620     static_line (fp, lights, color, atom->position, endpoint, 10, error);
  621     }
  622   }
  623 
  624 /**************************************************
  625  * when color is inherited from the parent atoms, *
  626  * this function is run for each atom, but the    *
  627  * section below is executed only for atom 1      *
  628  **************************************************/
  629 
  630 if (bond->color == FALSE && atom == bond->atom2) return;
  631 
  632 /********************************
  633  * child objects: orbital, text *
  634  ********************************/
  635 
  636 center[0] = (bond->atom1->position[0] + bond->atom2->position[0]) / 2.0;
  637 center[1] = (bond->atom1->position[1] + bond->atom2->position[1]) / 2.0;
  638 center[2] = (bond->atom1->position[2] + bond->atom2->position[2]) / 2.0;
  639 
  640 static_scale (fp, bond->object.scale, center, error);
  641 
  642 for (dlist = bond->orbital_start; dlist != NULL; dlist = dlist->next)
  643   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
  644     
  645 for (dlist = bond->text_start; dlist != NULL; dlist = dlist->next)
  646   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
  647 
  648 static_unscale (fp, bond->object.scale, error);
  649 }
  650 
  651 static void static_atom (FILE *fp, gamgi_atom *atom, 
  652 gamgi_bool lights, gamgi_bool *error)
  653 {
  654 gamgi_dlist *dlist;
  655 char string[GAMGI_ENGINE_LINE];
  656 double radius;
  657 float size;
  658     
  659 static_scale (fp, atom->object.scale, atom->position, error);
  660     
  661 if (atom->draw == gamgi_mesa_atom_draw_sphere || atom->bond_start == NULL)
  662   { 
  663   sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n", 
  664   gamgi->gamgi->length, atom->position[0],
  665   gamgi->gamgi->length, atom->position[1],
  666   gamgi->gamgi->length, atom->position[2]);
  667   gamgi_io_file_fprintf(fp, string, error);
  668             
  669   gamgi_io_file_fprintf (fp, "<Shape>\n<Appearance>\n", error);
  670   if (lights == TRUE)
  671     sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
  672     GAMGI_MATH_DECIMAL_COLOR, atom->red,
  673     GAMGI_MATH_DECIMAL_COLOR, atom->green,
  674     GAMGI_MATH_DECIMAL_COLOR, atom->blue);
  675   else
  676     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  677     GAMGI_MATH_DECIMAL_COLOR, atom->red,
  678     GAMGI_MATH_DECIMAL_COLOR, atom->green,
  679     GAMGI_MATH_DECIMAL_COLOR, atom->blue);
  680   gamgi_io_file_fprintf (fp, string, error);
  681 
  682   if (atom->draw != gamgi_mesa_atom_draw_sphere)
  683     {
  684     sprintf (string, "<LineProperties linewidthScaleFactor=\"%d\"/>\n",
  685     gamgi->atom->width);
  686     gamgi_io_file_fprintf (fp, string, error);
  687     }
  688   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  689 
  690   if (atom->draw == gamgi_mesa_atom_draw_sphere)
  691     {
  692     radius = atom->size * (atom->variancy * atom->radius +
  693     (1 - atom->variancy) * gamgi->atom->min);
  694     sprintf (string, "<Sphere radius=\"%.*f\"/>\n", 
  695     gamgi->gamgi->length, radius);
  696     gamgi_io_file_fprintf (fp, string, error);
  697     }
  698 
  699   if (atom->draw == gamgi_mesa_atom_draw_cross)
  700     {
  701     size = 0.5 * gamgi->atom->size * gamgi->atom->min;
  702     gamgi_io_file_fprintf (fp, "<IndexedLineSet coordIndex=\""
  703     "0 1 -1 2 3 -1 4 5 -1\">\n", error);
  704     sprintf (string, "<Coordinate point=\""
  705     "%.*f 0 0 %.*f 0 0 0 %.*f 0 0 %.*f 0 0 0 %.*f 0 0 %.*f\"/>\n", 
  706     GAMGI_MATH_DECIMAL_SIZE, -size, GAMGI_MATH_DECIMAL_SIZE, size, 
  707     GAMGI_MATH_DECIMAL_SIZE, -size, GAMGI_MATH_DECIMAL_SIZE, size, 
  708     GAMGI_MATH_DECIMAL_SIZE, -size, GAMGI_MATH_DECIMAL_SIZE, size);
  709     gamgi_io_file_fprintf(fp, string, error);
  710     gamgi_io_file_fprintf(fp, "</IndexedLineSet>\n", error);
  711     }
  712             
  713   gamgi_io_file_fprintf(fp, "</Shape>\n</Transform>\n", error); 
  714   }
  715     
  716 /**************************************
  717  * child objects: bond, orbital, text *
  718  **************************************/
  719 
  720 for (dlist = atom->bond_start; dlist != NULL; dlist = dlist->next)
  721   static_bond (fp, GAMGI_CAST_BOND dlist->data, atom, lights, error);
  722 
  723 for (dlist = atom->orbital_start; dlist != NULL; dlist = dlist->next)
  724   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
  725     
  726 for (dlist = atom->text_start; dlist != NULL; dlist = dlist->next)
  727   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
  728     
  729 static_unscale (fp, atom->object.scale, error);
  730 }
  731 
  732 static void static_direction (FILE *fp, gamgi_direction *direction, 
  733 gamgi_bool lights, gamgi_bool *error)
  734 {
  735 gamgi_dlist * dlist;
  736 char string[GAMGI_ENGINE_LINE];
  737 double axis[3];
  738 double phi;
  739 float color[3];
  740 
  741 static_scale (fp, direction->object.scale, direction->center, error);
  742     
  743 if (direction->loops[0] != 0)
  744   {
  745   sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n",
  746   gamgi->gamgi->length, direction->origin[0], 
  747   gamgi->gamgi->length, direction->origin[1],
  748   gamgi->gamgi->length, direction->origin[2]);
  749   gamgi_io_file_fprintf (fp, string, error);
  750         
  751   if (direction->model == GAMGI_PHYS_LINE)
  752     {
  753     /******************************
  754      * render direction as a line *
  755      ******************************/
  756 
  757     gamgi_math_quaternion_to_axis (direction->quaternion, &phi, axis);
  758     sprintf (string, "<Transform rotation=\"%.*f %.*f %.*f %.*f\">\n", 
  759     gamgi->gamgi->length, axis[0],
  760     gamgi->gamgi->length, axis[1],
  761     gamgi->gamgi->length, axis[2],
  762     gamgi->gamgi->angle, phi);
  763     gamgi_io_file_fprintf(fp, string, error);
  764             
  765     gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  766 
  767     gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  768     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  769     GAMGI_MATH_DECIMAL_COLOR, direction->red,
  770     GAMGI_MATH_DECIMAL_COLOR, direction->green,
  771     GAMGI_MATH_DECIMAL_COLOR, direction->blue);
  772     gamgi_io_file_fprintf (fp, string, error);
  773     sprintf (string, "<LineProperties linewidthScaleFactor=\"%.*f\"/>\n", 
  774     GAMGI_MATH_DECIMAL_SCALE, GAMGI_IO_X3D_DIRECTION_WIDTH);
  775     gamgi_io_file_fprintf (fp, string, error);
  776     gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  777             
  778     gamgi_io_x3d_render_lines (fp, direction->loops, direction->points, error);
  779 
  780     gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  781     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  782     }
  783   else if (direction->model == GAMGI_PHYS_POLE)
  784     {
  785     /*****************************************************************
  786      * stereographic projection: render direction as a chess bitmask *
  787      *****************************************************************/
  788 
  789     color[0] = direction->red;
  790     color[1] = direction->green;
  791     color[2] = direction->blue;
  792     gamgi_io_x3d_render_chess (fp, direction->loops[0], direction->points, color, error);
  793     }
  794   else if (direction->model == GAMGI_PHYS_TRACE)
  795     {
  796     /*********************************************************
  797      * stereographic projection: render direction as an arch *
  798      *********************************************************/
  799 
  800     gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  801 
  802     gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  803     if (lights)
  804       sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n", 
  805       GAMGI_MATH_DECIMAL_COLOR, direction->red,
  806       GAMGI_MATH_DECIMAL_COLOR, direction->green,
  807       GAMGI_MATH_DECIMAL_COLOR, direction->blue);
  808     else
  809       sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
  810       GAMGI_MATH_DECIMAL_COLOR, direction->red,
  811       GAMGI_MATH_DECIMAL_COLOR, direction->green,
  812       GAMGI_MATH_DECIMAL_COLOR, direction->blue);
  813     gamgi_io_file_fprintf (fp, string, error);
  814     gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  815 
  816     gamgi_io_x3d_render_line_strip (fp, direction->loops[0], direction->points, error);
  817     gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  818     }
  819         
  820   gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  821   }
  822     
  823 /**************************************
  824  * child objects: atom, orbital, text *
  825  **************************************/
  826 
  827 for (dlist = direction->atom_start; dlist != NULL; dlist = dlist->next)
  828   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
  829 
  830 for (dlist = direction->orbital_start; dlist != NULL; dlist = dlist->next)
  831   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
  832 
  833 for (dlist = direction->text_start; dlist != NULL; dlist = dlist->next)
  834   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
  835     
  836 if (direction->loops[0] != 0)
  837   static_unscale (fp, direction->object.scale, error);
  838 }
  839 
  840 static void static_plane (FILE *fp, gamgi_plane *plane, 
  841 gamgi_bool lights, gamgi_bool *error)
  842 {
  843 gamgi_dlist *dlist;
  844 char string[GAMGI_ENGINE_LINE];
  845 double axis[3];
  846 double phi;
  847 float color[3];
  848 
  849 static_scale (fp, plane->object.scale, plane->center, error);
  850 
  851 if (plane->loops[0] != 0)
  852   {
  853   if (plane->model == GAMGI_PHYS_VECTOR)
  854     {
  855     /*******************************************************
  856      * reciprocal lattice: render plane as a cross bitmask *
  857      *******************************************************/
  858 
  859     color[0] = plane->red;
  860     color[1] = plane->green;
  861     color[2] = plane->blue;
  862     gamgi_io_x3d_render_cross (fp, plane->loops[0], plane->points, color, error);
  863     }
  864   else
  865     {
  866     sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n", 
  867     gamgi->gamgi->length, plane->origin[0],
  868     gamgi->gamgi->length, plane->origin[1],
  869     gamgi->gamgi->length, plane->origin[2]);
  870     gamgi_io_file_fprintf (fp, string, error);
  871             
  872     if (plane->model == GAMGI_PHYS_POLYGON)
  873       {
  874       /*****************************
  875        * render plane as a polygon *
  876        *****************************/
  877 
  878       gamgi_math_quaternion_to_axis (plane->quaternion, &phi, axis);
  879       sprintf (string, "<Transform rotation=\"%.*f %.*f %.*f %.*f\">\n", 
  880       gamgi->gamgi->length, axis[0],
  881       gamgi->gamgi->length, axis[1],
  882       gamgi->gamgi->length, axis[2],
  883       gamgi->gamgi->angle, phi);
  884       gamgi_io_file_fprintf (fp, string, error);
  885                 
  886       gamgi_io_file_fprintf (fp, "<Shape>\n", error);
  887 
  888       gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
  889       if (lights == TRUE)
  890         sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
  891         GAMGI_MATH_DECIMAL_COLOR, plane->red,
  892         GAMGI_MATH_DECIMAL_COLOR, plane->green,
  893         GAMGI_MATH_DECIMAL_COLOR, plane->blue);
  894       else
  895         sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
  896         GAMGI_MATH_DECIMAL_COLOR, plane->red,
  897         GAMGI_MATH_DECIMAL_COLOR, plane->green,
  898         GAMGI_MATH_DECIMAL_COLOR, plane->blue);
  899       gamgi_io_file_fprintf (fp, string, error);
  900       gamgi_io_file_fprintf(fp, "</Appearance>\n", error);
  901                 
  902       gamgi_io_x3d_render_polygons (fp, plane->loops, plane->points, error);
  903                 
  904       gamgi_io_file_fprintf(fp, "</Shape>\n", error);
  905       gamgi_io_file_fprintf(fp, "</Transform>\n", error);
  906       }
  907     else if (plane->model == GAMGI_PHYS_POLE)
  908       {
  909       /*************************************************************
  910        * stereographic projection: render plane as a cross bitmask *
  911        *************************************************************/
  912 
  913       color[0] = plane->red;
  914       color[1] = plane->green;
  915       color[2] = plane->blue;
  916       gamgi_io_x3d_render_cross (fp, plane->loops[0], plane->points, color, error);
  917       }
  918     else if (plane->model == GAMGI_PHYS_TRACE)
  919       {
  920       /*****************************************************
  921        * stereographic projection: render plane as an arch *
  922        *****************************************************/
  923 
  924       gamgi_io_file_fprintf(fp, "<Shape>\n", error);
  925 
  926       gamgi_io_file_fprintf(fp, "<Appearance>\n", error);
  927       if (lights == TRUE)
  928         sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n", 
  929         GAMGI_MATH_DECIMAL_COLOR, plane->red,
  930         GAMGI_MATH_DECIMAL_COLOR, plane->green,
  931         GAMGI_MATH_DECIMAL_COLOR, plane->blue);
  932       else
  933         sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
  934         GAMGI_MATH_DECIMAL_COLOR, plane->red,
  935         GAMGI_MATH_DECIMAL_COLOR, plane->green,
  936         GAMGI_MATH_DECIMAL_COLOR, plane->blue);
  937       gamgi_io_file_fprintf (fp, string, error);
  938       gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
  939                 
  940       gamgi_io_x3d_render_line_strip (fp, plane->loops[0], plane->points, error);
  941       gamgi_io_file_fprintf (fp, "</Shape>\n", error);
  942       }
  943             
  944     gamgi_io_file_fprintf (fp, "</Transform>\n", error);
  945     }
  946   }
  947     
  948 /*************************************************
  949  * child objects: direction, atom, orbital, text *
  950  *************************************************/
  951     
  952 for (dlist = plane->direction_start; dlist != NULL; dlist = dlist->next)
  953   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
  954 
  955 for (dlist = plane->atom_start; dlist != NULL; dlist = dlist->next)
  956   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
  957 
  958 for (dlist = plane->orbital_start; dlist != NULL; dlist = dlist->next)
  959   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
  960 
  961 for (dlist = plane->text_start; dlist != NULL; dlist = dlist->next)
  962   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
  963 
  964 if (plane->loops[0] != 0)
  965   static_unscale (fp, plane->object.scale, error);
  966 }
  967 
  968 static void static_group (FILE *fp, gamgi_group *group, 
  969 gamgi_bool lights, gamgi_bool *error)
  970 {
  971 gamgi_dlist * dlist;
  972 char string[GAMGI_ENGINE_LINE];
  973 double axis[4];
  974 double phi;
  975 float background[4];
  976 
  977 glGetFloatv (GL_COLOR_CLEAR_VALUE, background);
  978 
  979 static_scale (fp, group->object.scale, group->center, error);
  980 
  981 gamgi_math_quaternion_to_axis (group->quaternion, &phi, axis);
  982 
  983 if (group->loops != NULL)
  984   {
  985   sprintf (string, 
  986   "<Transform translation=\"%.*f %.*f %.*f\" rotation=\"%.*f %.*f %.*f %.*f\">\n",
  987   gamgi->gamgi->length, group->origin[0],
  988   gamgi->gamgi->length, group->origin[1],
  989   gamgi->gamgi->length, group->origin[2],
  990   gamgi->gamgi->length, axis[0],
  991   gamgi->gamgi->length, axis[1],
  992   gamgi->gamgi->length, axis[2],
  993   gamgi->gamgi->angle, phi);
  994   gamgi_io_file_fprintf (fp, string, error);
  995 
  996   gamgi_io_file_fprintf (fp, "<Shape>\n<Appearance>\n", error);
  997   sprintf (string, "<LineProperties linewidthScaleFactor=\"%.*f\"/>",
  998   GAMGI_MATH_DECIMAL_SCALE, GAMGI_MESA_POLYHEDRON_WIDTH);
  999   gamgi_io_file_fprintf (fp, string, error);
 1000 
 1001   if (group->faces == FALSE)
 1002     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
 1003     GAMGI_MATH_DECIMAL_COLOR, group->red,
 1004     GAMGI_MATH_DECIMAL_COLOR, group->green,
 1005     GAMGI_MATH_DECIMAL_COLOR, group->blue);
 1006   else if (lights == TRUE)
 1007     sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
 1008     GAMGI_MATH_DECIMAL_COLOR, background[0],
 1009     GAMGI_MATH_DECIMAL_COLOR, background[1],
 1010     GAMGI_MATH_DECIMAL_COLOR, background[2]);
 1011   else
 1012     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
 1013     GAMGI_MATH_DECIMAL_COLOR, background[0],
 1014     GAMGI_MATH_DECIMAL_COLOR, background[1],
 1015     GAMGI_MATH_DECIMAL_COLOR, background[2]);
 1016   gamgi_io_file_fprintf (fp, string, error);
 1017   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
 1018 
 1019   gamgi_io_x3d_render_loops (fp, group->loops, group->points, error);
 1020 
 1021   if (group->faces == TRUE)
 1022     {
 1023     gamgi_io_file_fprintf (fp, "</Shape>\n<Shape>\n", error);
 1024 
 1025     gamgi_io_file_fprintf (fp, "<Appearance>\n", error);
 1026     if (lights == TRUE)
 1027       sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n",
 1028       GAMGI_MATH_DECIMAL_COLOR, group->red,
 1029       GAMGI_MATH_DECIMAL_COLOR, group->green,
 1030       GAMGI_MATH_DECIMAL_COLOR, group->blue);
 1031     else
 1032       sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n",
 1033       GAMGI_MATH_DECIMAL_COLOR, group->red,
 1034       GAMGI_MATH_DECIMAL_COLOR, group->green,
 1035       GAMGI_MATH_DECIMAL_COLOR, group->blue);
 1036     gamgi_io_file_fprintf (fp, string, error);
 1037     gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
 1038 
 1039     gamgi_io_x3d_render_polygons (fp, group->loops, group->points, error);
 1040     }
 1041 
 1042   gamgi_io_file_fprintf (fp, "</Shape>\n", error);
 1043   gamgi_io_file_fprintf(fp, "</Transform>\n", error);
 1044   }
 1045 
 1046 /**********************************
 1047  * child objects: group, plane,   *
 1048  * direction, atom, orbital, text * 
 1049  **********************************/
 1050 
 1051 for (dlist = group->group_start; dlist!=NULL; dlist = dlist->next)
 1052   static_group (fp, GAMGI_CAST_GROUP dlist->data, lights, error);
 1053 
 1054 for (dlist = group->plane_start; dlist!=NULL; dlist = dlist->next)
 1055   static_plane (fp, GAMGI_CAST_PLANE dlist->data, lights, error);
 1056 
 1057 for (dlist = group->direction_start; dlist!=NULL; dlist = dlist->next)
 1058   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
 1059 
 1060 for (dlist = group->atom_start; dlist!=NULL; dlist = dlist->next)
 1061   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
 1062 
 1063 for (dlist = group->orbital_start; dlist!=NULL; dlist = dlist->next)
 1064   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
 1065 
 1066 for (dlist = group->text_start; dlist!=NULL; dlist = dlist->next)
 1067   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1068 
 1069 static_unscale (fp, group->object.scale, error);
 1070 }
 1071 
 1072 static void static_molecule (FILE *fp, gamgi_molecule *molecule, 
 1073 gamgi_bool lights, gamgi_bool *error)
 1074 {
 1075 gamgi_dlist *dlist;
 1076 double center[3];
 1077     
 1078 gamgi_math_vector_zero (center);
 1079 static_scale (fp, molecule->object.scale, center, error);
 1080 
 1081 /**********************************
 1082  * child objects: group, plane,   *
 1083  * direction, atom, orbital, text * 
 1084  **********************************/
 1085     
 1086 for (dlist = molecule->group_start; dlist != NULL; dlist = dlist->next)
 1087   static_group (fp, GAMGI_CAST_GROUP dlist->data, lights, error);
 1088     
 1089 for (dlist = molecule->plane_start; dlist != NULL; dlist = dlist->next)
 1090   static_plane (fp, GAMGI_CAST_PLANE dlist->data, lights, error);
 1091     
 1092 for (dlist = molecule->direction_start; dlist != NULL; dlist = dlist->next)
 1093   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
 1094 
 1095 for (dlist = molecule->atom_start; dlist != NULL; dlist = dlist->next)
 1096   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
 1097     
 1098 for (dlist = molecule->orbital_start; dlist != NULL; dlist = dlist->next)
 1099   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
 1100 
 1101 for (dlist = molecule->text_start; dlist != NULL; dlist = dlist->next)
 1102   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1103     
 1104 static_unscale (fp, molecule->object.scale, error);
 1105 }
 1106 
 1107 static void static_cluster (FILE *fp, gamgi_cluster *cluster, 
 1108 gamgi_bool lights, gamgi_bool *error)
 1109 {
 1110 gamgi_dlist * dlist;
 1111 char string[GAMGI_ENGINE_LINE];
 1112 double axis[4];
 1113 double phi;
 1114 float background[4];
 1115     
 1116 glGetFloatv (GL_COLOR_CLEAR_VALUE, background);
 1117 
 1118 static_scale (fp, cluster->object.scale, cluster->center, error);
 1119 
 1120 gamgi_math_quaternion_to_axis (cluster->quaternion, &phi, axis);
 1121 
 1122 if (cluster->loops != NULL)
 1123   {
 1124   sprintf (string, 
 1125   "<Transform translation=\"%.*f %.*f %.*f\" rotation=\"%.*f %.*f %.*f %.*f\">\n",
 1126   gamgi->gamgi->length, cluster->origin[0], 
 1127   gamgi->gamgi->length, cluster->origin[1], 
 1128   gamgi->gamgi->length, cluster->origin[2],
 1129   gamgi->gamgi->length, axis[0], 
 1130   gamgi->gamgi->length, axis[1],
 1131   gamgi->gamgi->length, axis[2], 
 1132   gamgi->gamgi->angle, phi);
 1133   gamgi_io_file_fprintf (fp, string, error);
 1134 
 1135   gamgi_io_file_fprintf (fp, "<Shape>\n<Appearance>\n", error);
 1136   sprintf (string, "<LineProperties linewidthScaleFactor=\"%.*f\"/>", 
 1137   GAMGI_MATH_DECIMAL_SCALE, GAMGI_MESA_POLYHEDRON_WIDTH);
 1138   gamgi_io_file_fprintf (fp, string, error);
 1139 
 1140   if (cluster->faces == FALSE)
 1141     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
 1142     GAMGI_MATH_DECIMAL_COLOR, cluster->colors[0],
 1143     GAMGI_MATH_DECIMAL_COLOR, cluster->colors[1],
 1144     GAMGI_MATH_DECIMAL_COLOR, cluster->colors[2]);
 1145   else if (lights == TRUE)
 1146     sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n", 
 1147     GAMGI_MATH_DECIMAL_COLOR, background[0],
 1148     GAMGI_MATH_DECIMAL_COLOR, background[1],
 1149     GAMGI_MATH_DECIMAL_COLOR, background[2]);
 1150   else
 1151     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
 1152     GAMGI_MATH_DECIMAL_COLOR, background[0],
 1153     GAMGI_MATH_DECIMAL_COLOR, background[1],
 1154     GAMGI_MATH_DECIMAL_COLOR, background[2]);
 1155   gamgi_io_file_fprintf (fp, string, error);
 1156   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
 1157 
 1158   gamgi_io_x3d_render_loops (fp, cluster->loops, cluster->points, error);
 1159 
 1160   if (cluster->faces == TRUE)
 1161     {
 1162     gamgi_io_file_fprintf (fp, "</Shape>\n<Shape>\n", error);
 1163     gamgi_io_x3d_render_polygons_color (fp, cluster->loops, 
 1164     cluster->points, cluster->paints, cluster->colors, error);
 1165     }
 1166 
 1167   gamgi_io_file_fprintf (fp, "</Shape>\n", error);
 1168 
 1169   if (cluster->atoms > 0)
 1170     gamgi_io_x3d_render_points (fp, cluster->atoms, 
 1171     cluster->points, cluster->colors, error);
 1172 
 1173   gamgi_io_file_fprintf(fp, "</Transform>\n", error);
 1174   }
 1175 
 1176 /********************************************
 1177  * child objects: cluster, molecule, group, *
 1178  * plane, direction, atom, orbital, text    *
 1179  ********************************************/
 1180 
 1181 for (dlist = cluster->cluster_start; dlist!=NULL; dlist = dlist->next)
 1182   static_cluster (fp, GAMGI_CAST_CLUSTER dlist->data, lights, error);
 1183 
 1184 for (dlist = cluster->molecule_start; dlist!=NULL; dlist = dlist->next)
 1185   static_molecule (fp, GAMGI_CAST_MOLECULE dlist->data, lights, error);
 1186 
 1187 for (dlist = cluster->group_start; dlist!=NULL; dlist = dlist->next)
 1188   static_group (fp, GAMGI_CAST_GROUP dlist->data, lights, error);
 1189 
 1190 for (dlist = cluster->plane_start; dlist!=NULL; dlist = dlist->next)
 1191   static_plane (fp, GAMGI_CAST_PLANE dlist->data, lights, error);
 1192 
 1193 for (dlist = cluster->direction_start; dlist!=NULL; dlist = dlist->next)
 1194   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
 1195 
 1196 for (dlist = cluster->atom_start; dlist!=NULL; dlist = dlist->next)
 1197   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
 1198 
 1199 for (dlist = cluster->orbital_start; dlist!=NULL; dlist = dlist->next)
 1200   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
 1201 
 1202 for (dlist = cluster->text_start; dlist!=NULL; dlist = dlist->next)
 1203   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1204 
 1205 static_unscale (fp, cluster->object.scale, error);
 1206 }
 1207 
 1208 static void static_cell (FILE *fp, gamgi_cell *cell, 
 1209 gamgi_bool lights, gamgi_bool *error)
 1210 {
 1211 gamgi_dlist * dlist;
 1212 char string[GAMGI_ENGINE_LINE];
 1213 double axis[3];
 1214 double phi;
 1215 float background[4];
 1216 float color[3];
 1217 
 1218 /****************************
 1219  * scale, translate, rotate *
 1220  ****************************/
 1221 
 1222 static_scale (fp, cell->object.scale, cell->center, error);
 1223 
 1224 sprintf (string, "<Transform translation=\"%.*f %.*f %.*f\">\n", 
 1225 gamgi->gamgi->length, cell->origin[0], 
 1226 gamgi->gamgi->length, cell->origin[1], 
 1227 gamgi->gamgi->length, cell->origin[2]);
 1228 gamgi_io_file_fprintf (fp, string, error);
 1229     
 1230 if (cell->model != GAMGI_PHYS_PROJECTION)
 1231   {
 1232   gamgi_math_quaternion_to_axis (cell->quaternion, &phi, axis);
 1233   sprintf (string, "<Transform rotation=\"%.*f %.*f %.*f %.*f\">\n", 
 1234   gamgi->gamgi->length, axis[0],
 1235   gamgi->gamgi->length, axis[1],
 1236   gamgi->gamgi->length, axis[2],
 1237   gamgi->gamgi->angle, phi);
 1238   gamgi_io_file_fprintf (fp, string, error);
 1239   }
 1240     
 1241 glGetFloatv (GL_COLOR_CLEAR_VALUE, background);
 1242 
 1243 /*********
 1244  * Shape *
 1245  *********/
 1246 
 1247 if (cell->loops != NULL && cell->borders != FALSE && 
 1248 (cell->lattice != GAMGI_PHYS_HEXAGONAL_P || 
 1249 (cell->model != GAMGI_PHYS_WIGNER && cell->model != GAMGI_PHYS_CONVENTIONAL)) &&
 1250 (cell->lattice != GAMGI_PHYS_ORTHORHOMBIC_C || cell->model != GAMGI_PHYS_WIGNER))
 1251   {
 1252   gamgi_io_file_fprintf (fp, "<Shape>\n<Appearance>\n", error);
 1253 
 1254   if (cell->faces == TRUE)
 1255     {
 1256     color[0] = background[0];
 1257     color[1] = background[1];
 1258     color[2] = background[2];
 1259     }
 1260   else
 1261     {
 1262     color[0] = cell->red;
 1263     color[1] = cell->green;
 1264     color[2] = cell->blue;
 1265     }
 1266 
 1267   sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
 1268   GAMGI_MATH_DECIMAL_COLOR, color[0], 
 1269   GAMGI_MATH_DECIMAL_COLOR, color[1], 
 1270   GAMGI_MATH_DECIMAL_COLOR, color[2]);
 1271   gamgi_io_file_fprintf (fp, string, error);
 1272         
 1273   sprintf (string, "<LineProperties linewidthScaleFactor=\"%.*f\"/>\n", 
 1274   GAMGI_MATH_DECIMAL_SCALE, GAMGI_MESA_CELL_LINE);
 1275   gamgi_io_file_fprintf (fp, string, error);
 1276   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
 1277         
 1278   gamgi_io_x3d_render_loops (fp, cell->loops, cell->points, error);
 1279   gamgi_io_file_fprintf (fp, "</Shape>\n", error);
 1280   }
 1281     
 1282 if (cell->lines != NULL)
 1283   {
 1284   gamgi_io_file_fprintf (fp, "<Shape>\n<Appearance>\n", error);
 1285 
 1286   if (cell->faces == TRUE)
 1287     {
 1288     color[0] = background[0];
 1289     color[1] = background[1];
 1290     color[2] = background[2];
 1291     }
 1292   else
 1293     {
 1294     color[0] = cell->red;
 1295     color[1] = cell->green;
 1296     color[2] = cell->blue;
 1297     }
 1298 
 1299   sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
 1300   GAMGI_MATH_DECIMAL_COLOR, color[0], 
 1301   GAMGI_MATH_DECIMAL_COLOR, color[1], 
 1302   GAMGI_MATH_DECIMAL_COLOR, color[2]);
 1303   gamgi_io_file_fprintf (fp, string, error);
 1304 
 1305   sprintf (string, "<LineProperties linewidthScaleFactor=\"%.*f\"/>\n", 
 1306   GAMGI_MATH_DECIMAL_SCALE, GAMGI_MESA_CELL_LINE);
 1307   gamgi_io_file_fprintf (fp, string, error);
 1308   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
 1309 
 1310   gamgi_io_x3d_render_lines (fp, cell->lines, cell->points, error);
 1311   gamgi_io_file_fprintf (fp, "</Shape>\n", error);
 1312   }
 1313     
 1314 if (cell->faces == TRUE)
 1315   {
 1316   gamgi_io_file_fprintf (fp, "<Shape>\n<Appearance>\n", error);
 1317 
 1318   if (lights == TRUE)
 1319     sprintf (string, "<Material diffuseColor=\"%.*f %.*f %.*f\"/>\n", 
 1320     GAMGI_MATH_DECIMAL_COLOR, cell->red, 
 1321     GAMGI_MATH_DECIMAL_COLOR, cell->green, 
 1322     GAMGI_MATH_DECIMAL_COLOR, cell->blue);
 1323   else
 1324     sprintf (string, "<Material emissiveColor=\"%.*f %.*f %.*f\"/>\n", 
 1325     GAMGI_MATH_DECIMAL_COLOR, cell->red, 
 1326     GAMGI_MATH_DECIMAL_COLOR, cell->green, 
 1327     GAMGI_MATH_DECIMAL_COLOR, cell->blue);
 1328   gamgi_io_file_fprintf (fp, string, error);
 1329   gamgi_io_file_fprintf (fp, "</Appearance>\n", error);
 1330 
 1331   gamgi_io_x3d_render_polygons (fp, cell->loops, cell->points, error);
 1332   gamgi_io_file_fprintf(fp, "</Shape>\n", error);
 1333   }
 1334 
 1335 if (cell->nodes == TRUE)
 1336   gamgi_io_x3d_render_points (fp, cell->n_nodes, cell->points, color,error);
 1337 
 1338 if (cell->model != GAMGI_PHYS_PROJECTION)
 1339   gamgi_io_file_fprintf (fp, "</Transform>\n", error);
 1340     
 1341 gamgi_io_file_fprintf (fp, "</Transform>\n", error);
 1342     
 1343 /********************************************
 1344  * child objects: cluster, molecule, group, *
 1345  * plane, direction, atom, orbital, text    * 
 1346  ********************************************/
 1347     
 1348 for (dlist = cell->cluster_start; dlist != NULL; dlist = dlist->next)
 1349   static_cluster (fp, GAMGI_CAST_CLUSTER dlist->data, lights, error);
 1350 
 1351 for (dlist = cell->molecule_start; dlist != NULL; dlist = dlist->next)
 1352   static_molecule (fp, GAMGI_CAST_MOLECULE dlist->data, lights, error);
 1353 
 1354 for (dlist = cell->group_start; dlist != NULL; dlist = dlist->next)
 1355   static_group (fp, GAMGI_CAST_GROUP dlist->data, lights, error);
 1356 
 1357 for (dlist = cell->plane_start; dlist != NULL; dlist = dlist->next)
 1358   static_plane (fp, GAMGI_CAST_PLANE dlist->data, lights, error);
 1359 
 1360 for (dlist = cell->direction_start; dlist != NULL; dlist = dlist->next)
 1361   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
 1362 
 1363 for (dlist = cell->atom_start; dlist != NULL; dlist = dlist->next)
 1364   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
 1365 
 1366 for (dlist = cell->orbital_start; dlist != NULL; dlist = dlist->next)
 1367   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
 1368 
 1369 for (dlist = cell->text_start; dlist != NULL; dlist = dlist->next)
 1370   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1371 
 1372 static_unscale (fp, cell->object.scale, error);
 1373 }
 1374 
 1375 static void static_arrow (FILE *fp, gamgi_arrow *arrow, 
 1376 gamgi_bool lights, gamgi_bool *error)
 1377 {
 1378 gamgi_dlist * dlist;
 1379 
 1380 /***********************
 1381  * child objects: text *
 1382  ***********************/
 1383 
 1384 for (dlist = arrow->text_start; dlist != NULL; dlist = dlist->next)
 1385   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1386 }
 1387 
 1388 static void static_shape (FILE * fp, gamgi_shape *shape, 
 1389 gamgi_bool lights, gamgi_bool *error)
 1390 {
 1391 gamgi_dlist * dlist;
 1392 
 1393 /***********************
 1394  * child objects: text *
 1395  ***********************/
 1396 
 1397 for (dlist = shape->text_start; dlist != NULL; dlist = dlist->next)
 1398   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1399 }
 1400 
 1401 static void static_graph (FILE *fp, gamgi_graph *graph, 
 1402 gamgi_bool lights, gamgi_bool *error)
 1403 {
 1404 gamgi_dlist * dlist;
 1405     
 1406 /***********************
 1407  * child objects: text * 
 1408  ***********************/
 1409  
 1410 for (dlist = graph->text_start; dlist != NULL; dlist = dlist->next)
 1411   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1412 }
 1413 
 1414 static void static_assembly (FILE *fp, gamgi_assembly *assembly, 
 1415 gamgi_bool lights, gamgi_bool *error)
 1416 {
 1417 gamgi_dlist * dlist;
 1418 double center[3];
 1419     
 1420 gamgi_math_vector_zero (center);
 1421 static_scale (fp, assembly->object.scale, center, error);
 1422     
 1423 /******************************************
 1424  * child objects: assembly, graph, arrow, *
 1425  * shape, cell, cluster, molecule, group, *
 1426  * plane, direction, atom, orbital, text  *
 1427  ******************************************/
 1428     
 1429 for (dlist = assembly->assembly_start; dlist != NULL; dlist = dlist->next)
 1430   static_assembly (fp, GAMGI_CAST_ASSEMBLY dlist->data, lights, error);
 1431 
 1432 for (dlist = assembly->graph_start; dlist != NULL; dlist = dlist->next)
 1433   static_graph (fp, GAMGI_CAST_GRAPH dlist->data, lights, error);
 1434 
 1435 for (dlist = assembly->arrow_start; dlist != NULL; dlist = dlist->next)
 1436   static_arrow (fp, GAMGI_CAST_ARROW dlist->data, lights, error);
 1437 
 1438 for (dlist = assembly->shape_start; dlist != NULL; dlist = dlist->next)
 1439   static_shape (fp, GAMGI_CAST_SHAPE dlist->data, lights, error);
 1440 
 1441 for (dlist = assembly->cell_start; dlist != NULL; dlist = dlist->next)
 1442   static_cell (fp, GAMGI_CAST_CELL dlist->data, lights, error);
 1443 
 1444 for (dlist = assembly->cluster_start; dlist != NULL; dlist = dlist->next)
 1445   static_cluster (fp, GAMGI_CAST_CLUSTER dlist->data, lights, error);
 1446 
 1447 for (dlist = assembly->molecule_start; dlist != NULL; dlist = dlist->next)
 1448   static_molecule (fp, GAMGI_CAST_MOLECULE dlist->data, lights, error);
 1449 
 1450 for (dlist = assembly->group_start; dlist != NULL; dlist = dlist->next)
 1451   static_group (fp, GAMGI_CAST_GROUP dlist->data, lights, error);
 1452 
 1453 for (dlist = assembly->plane_start; dlist != NULL; dlist = dlist->next)
 1454   static_plane (fp, GAMGI_CAST_PLANE dlist->data, lights, error);
 1455 
 1456 for (dlist = assembly->direction_start; dlist != NULL; dlist = dlist->next)
 1457   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
 1458 
 1459 for (dlist = assembly->atom_start; dlist != NULL; dlist = dlist->next)
 1460   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
 1461 
 1462 for (dlist = assembly->orbital_start; dlist != NULL; dlist = dlist->next)
 1463   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
 1464 
 1465 for (dlist = assembly->text_start; dlist != NULL; dlist = dlist->next)
 1466   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1467 
 1468 static_unscale (fp, assembly->object.scale, error);
 1469 }
 1470 
 1471 static void static_light (FILE *fp, gamgi_light *light, gamgi_bool *error)
 1472 {
 1473 char string[GAMGI_ENGINE_LINE];
 1474 double direction[3], position[3];
 1475 float color[3];
 1476 float ambient;
 1477     
 1478 direction[0] = light->direction[0];
 1479 direction[1] = light->direction[1];
 1480 direction[2] = light->direction[2];
 1481 
 1482 position[0] = light->position[0];
 1483 position[1] = light->position[1];
 1484 position[2] = light->position[2];
 1485 
 1486 /***********************************************************************
 1487  *      set ambient as the average of the three ambient components     *
 1488  *                                                                     *
 1489  * set color as the sum (limited to 1.0) of diffuse and specular color *
 1490  ***********************************************************************/
 1491 
 1492 ambient = (light->ambient[0] + light->ambient[1] + light->ambient[2]) / 3;
 1493 
 1494 color[0] = light->diffuse[0] + light->specular[0];
 1495 if (color[0] > 1.0) color[0] = 1.0;
 1496 color[1] = light->diffuse[1] + light->specular[1];
 1497 if (color[1] > 1.0) color[1] = 1.0;
 1498 color[2] = light->diffuse[2] + light->specular[2];
 1499 if (color[2] > 1.0) color[2] = 1.0;
 1500 
 1501 if (light->position[3] == 0.0)
 1502   {
 1503   /*********************
 1504    * directional light *
 1505    *********************/
 1506 
 1507   sprintf (string, "<DirectionalLight ambientIntensity=\"%.*f\""
 1508   " color=\"%.*f %.*f %.*f\" direction=\"%.*f %.*f %.*f\"/>\n", 
 1509   GAMGI_MATH_DECIMAL_COLOR, ambient, 
 1510   GAMGI_MATH_DECIMAL_COLOR, color[0], 
 1511   GAMGI_MATH_DECIMAL_COLOR, color[1], 
 1512   GAMGI_MATH_DECIMAL_COLOR, color[2], 
 1513   gamgi->gamgi->length, direction[0], 
 1514   gamgi->gamgi->length, direction[1],
 1515   gamgi->gamgi->length, direction[2]);
 1516   }
 1517 else if (light->angle == 180.0)
 1518   {
 1519   /********************
 1520    * positional light *
 1521    ********************/
 1522 
 1523   sprintf (string, "<PointLight ambientIntensity=\"%.*f\""
 1524   " color=\"%.*f %.*f %.*f\" location=\"%.*f %.*f %.*f\"/>\n", 
 1525   GAMGI_MATH_DECIMAL_COLOR, ambient,
 1526   GAMGI_MATH_DECIMAL_COLOR, color[0], 
 1527   GAMGI_MATH_DECIMAL_COLOR, color[1],
 1528   GAMGI_MATH_DECIMAL_COLOR, color[2], 
 1529   gamgi->gamgi->length, position[0],
 1530   gamgi->gamgi->length, position[1],
 1531   gamgi->gamgi->length, position[2]);
 1532   }
 1533 else
 1534   {
 1535   /**************
 1536    * spot light *
 1537    **************/
 1538 
 1539   sprintf (string, "<SpotLight ambientIntensity=\"%.*f\""
 1540   " color=\"%.*f %.*f %.*f\" cutOffAngle=\"%.*f\""
 1541   " direction=\"%.*f %.*f %.*f\" location=\"%.*f %.*f %.*f\"/>\n",
 1542   GAMGI_MATH_DECIMAL_COLOR, ambient,
 1543   GAMGI_MATH_DECIMAL_COLOR, color[0],
 1544   GAMGI_MATH_DECIMAL_COLOR, color[1],
 1545   GAMGI_MATH_DECIMAL_COLOR, color[2],
 1546   gamgi->gamgi->angle, light->angle * GAMGI_MATH_DEG_RAD,
 1547   gamgi->gamgi->length, direction[0], 
 1548   gamgi->gamgi->length, direction[1], 
 1549   gamgi->gamgi->length, direction[2], 
 1550   gamgi->gamgi->length, position[0],
 1551   gamgi->gamgi->length, position[1],
 1552   gamgi->gamgi->length, position[2]);
 1553   }
 1554 
 1555 gamgi_io_file_fprintf (fp, string, error);
 1556 }
 1557 
 1558 static void static_layer (FILE *fp, gamgi_layer *layer, gamgi_bool *error)
 1559 {
 1560 gamgi_dlist *dlist;
 1561 char string[GAMGI_ENGINE_LINE];
 1562 double normal[3];
 1563 double scale;
 1564 float color[4];
 1565 gamgi_bool lights;
 1566 
 1567 /********************************************************
 1568  * The exported scene describes only the current layer! *
 1569  ********************************************************/
 1570 
 1571 gamgi_io_file_fprintf (fp, "<Scene>\n", error);
 1572 
 1573 /***************************************************************
 1574  * Apparently, the GAMGI OpenGL lightning seems to be slightly *
 1575  * better simulated in X3D when headLight is set to false.     *
 1576  *                                                             *
 1577  * Possible values are: WALK, FLY, EXAMINE, LOOKAT, ANY, NONE  *
 1578  * values can be combined, for example: type='"EXAMINE" "ANY"' *
 1579  *                                                             *
 1580  * Apparently, the GAMGI OpenGL lightning seems to be slightly *
 1581  * better simulated in X3D when global is set to false, which  *
 1582  * means that lights apply only to the local node.             *
 1583  ***************************************************************/
 1584 
 1585 gamgi_io_file_fprintf (fp, "<NavigationInfo headlight=\"false\"", error);
 1586 gamgi_io_file_fprintf (fp, " type='\"ANY\"'/>\n", error);
 1587 
 1588 gamgi_io_file_fprintf (fp, "<DirectionalLight global=\"false\"/>\n", error);
 1589 
 1590 /**************
 1591  * projection *
 1592  **************/
 1593 
 1594 if (layer->perspective == TRUE)
 1595   {
 1596   gamgi_io_file_fprintf (fp, "<Viewpoint description=\"perspective\"", error);
 1597   sprintf (string, " fieldOfView=\"%.*f\"\n", 
 1598   gamgi->gamgi->length, 2.0 * atan ((2.0 * layer->top) * 0.5 / layer->near));
 1599   }
 1600 else
 1601   {
 1602   gamgi_io_file_fprintf (fp, "<OrthoViewpoint description=\"orthographic\"", error);
 1603   sprintf (string, " fieldOfView=\"%.*f %.*f %.*f %.*f\"", 
 1604   gamgi->gamgi->length, -layer->top, 
 1605   gamgi->gamgi->length, -layer->top, 
 1606   gamgi->gamgi->length, layer->top, 
 1607   gamgi->gamgi->length, layer->top);
 1608   }
 1609 gamgi_io_file_fprintf (fp, string, error);
 1610 
 1611 /*************
 1612  * modelview *
 1613  *************/
 1614 
 1615 gamgi_math_vector_sub (layer->eye, layer->center, normal);
 1616 gamgi_math_vector_normal (normal);
 1617 sprintf (string, "orientation=\"%.*f %.*f %.*f %.*f\"", 
 1618 gamgi->gamgi->length, normal[0], 
 1619 gamgi->gamgi->length, normal[1], 
 1620 gamgi->gamgi->length, normal[2],
 1621 gamgi->gamgi->length, 0.0);
 1622 gamgi_io_file_fprintf (fp, string, error);
 1623 
 1624 sprintf (string, " position=\"%.*f %.*f %.*f\"/>\n", 
 1625 gamgi->gamgi->length, layer->eye[0], 
 1626 gamgi->gamgi->length, layer->eye[1], 
 1627 gamgi->gamgi->length, layer->eye[2]);
 1628 gamgi_io_file_fprintf (fp, string, error);
 1629 
 1630 glGetFloatv (GL_COLOR_CLEAR_VALUE, color);
 1631 sprintf (string, "<Background skyColor=\"%.*f %.*f %.*f\"/>\n", 
 1632 GAMGI_MATH_DECIMAL_COLOR, color[0], 
 1633 GAMGI_MATH_DECIMAL_COLOR, color[1], 
 1634 GAMGI_MATH_DECIMAL_COLOR, color[2]);
 1635 gamgi_io_file_fprintf (fp, string, error);
 1636 
 1637 scale = layer->object.scale;
 1638 if (fabs (scale - 1.0) > GAMGI_MATH_TOLERANCE)
 1639   {
 1640   sprintf (string, "<Transform scale=\"%.*f %.*f %.*f\">\n", 
 1641   GAMGI_MATH_DECIMAL_SCALE, scale,
 1642   GAMGI_MATH_DECIMAL_SCALE, scale, 
 1643   GAMGI_MATH_DECIMAL_SCALE, scale);
 1644   gamgi_io_file_fprintf (fp, string, error);
 1645   }
 1646 
 1647 if (layer->light_start == NULL) lights = FALSE;
 1648 else lights = TRUE;
 1649 
 1650 /*************************************************
 1651  * child objects: light, assembly, graph, shape, *
 1652  * arrow, cell, cluster, molecule, group, plane, *
 1653  * direction, atom, orbital, text                *
 1654  *************************************************/
 1655 
 1656 for (dlist = layer->light_start; dlist != NULL; dlist = dlist->next)
 1657   static_light (fp, GAMGI_CAST_LIGHT dlist->data, error);
 1658 
 1659 for (dlist = layer->assembly_start; dlist != NULL; dlist = dlist->next)
 1660   static_assembly (fp, GAMGI_CAST_ASSEMBLY dlist->data, lights, error);
 1661 
 1662 for (dlist = layer->graph_start; dlist != NULL; dlist = dlist->next)
 1663   static_graph (fp, GAMGI_CAST_GRAPH dlist->data, lights, error);
 1664     
 1665 for (dlist = layer->shape_start; dlist != NULL; dlist = dlist->next)
 1666   static_shape (fp, GAMGI_CAST_SHAPE dlist->data, lights, error);
 1667     
 1668 for (dlist = layer->arrow_start; dlist != NULL; dlist = dlist->next)
 1669   static_arrow (fp, GAMGI_CAST_ARROW dlist->data, lights, error);
 1670     
 1671 for (dlist = layer->cell_start; dlist != NULL; dlist = dlist->next)
 1672   static_cell(fp, GAMGI_CAST_CELL dlist->data, lights, error);
 1673 
 1674 for (dlist = layer->cluster_start; dlist != NULL; dlist = dlist->next)
 1675   static_cluster(fp, GAMGI_CAST_CLUSTER dlist->data, lights, error);
 1676 
 1677 for (dlist = layer->molecule_start; dlist != NULL; dlist = dlist->next)
 1678   static_molecule(fp, GAMGI_CAST_MOLECULE dlist->data, lights, error);
 1679     
 1680 for (dlist = layer->group_start; dlist != NULL; dlist = dlist->next)
 1681   static_group (fp, GAMGI_CAST_GROUP dlist->data, lights, error);
 1682     
 1683 for (dlist = layer->plane_start; dlist != NULL; dlist = dlist->next)
 1684   static_plane (fp, GAMGI_CAST_PLANE dlist->data, lights, error);
 1685 
 1686 for (dlist = layer->direction_start; dlist != NULL; dlist = dlist->next)
 1687   static_direction (fp, GAMGI_CAST_DIRECTION dlist->data, lights, error);
 1688 
 1689 for (dlist = layer->atom_start; dlist != NULL; dlist = dlist->next)
 1690   static_atom (fp, GAMGI_CAST_ATOM dlist->data, lights, error);
 1691     
 1692 for (dlist = layer->orbital_start; dlist != NULL; dlist = dlist->next)
 1693   static_orbital (fp, GAMGI_CAST_ORBITAL dlist->data, lights, error);
 1694     
 1695 for (dlist = layer->text_start; dlist != NULL; dlist = dlist->next)
 1696   static_text (fp, GAMGI_CAST_TEXT dlist->data, lights, error);
 1697 
 1698 if (fabs (scale - 1.0) > GAMGI_MATH_TOLERANCE)
 1699   gamgi_io_file_fprintf (fp, "</Transform>\n", error);
 1700 
 1701 gamgi_io_file_fprintf (fp, "</Scene>", error);
 1702 }
 1703 
 1704 /************ external function **********
 1705  *                                       *
 1706  *               GAMGI_IO_X3D            *
 1707  *                                       *
 1708  *      Main x3d writing function call   *
 1709  *****************************************/
 1710 
 1711 gamgi_bool gamgi_io_x3d (FILE *fp, gamgi_window *window, gamgi_bool *error)
 1712 {
 1713 /*********************************
 1714  * export only the current layer *
 1715  *********************************/
 1716 
 1717 static_layer (fp, window->layer, error);
 1718 
 1719 return TRUE;
 1720 }