Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

X3DDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: X3DDisplayDevice.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.40 $       $Date: 2012/03/01 16:50:59 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   X3D XML scene export code
00019  *
00020  * X3D XML encoding specification:
00021  *   http://www.web3d.org/x3d/specifications/ISO-IEC-19776-X3DEncodings-All-Edition-1/
00022  *
00023  * Feature compatibility matrix for X3D specification versions 3.0 up to 3.2
00024  *   http://web3d.org/x3d/specifications/ISO-IEC-19775-1.2-X3D-AbstractSpecification/Part01/versionContent.html
00025  *
00026  * General X3D information page:
00027  *   http://www.web3d.org/x3d/content/help.html
00028  *
00029  * List of X3D viewers at NIST:
00030  *   http://cic.nist.gov/vrml/vbdetect.html
00031  *
00032  ***************************************************************************/
00033 
00034 #include <math.h>
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include "X3DDisplayDevice.h"
00039 #include "Matrix4.h"
00040 #include "utilities.h"
00041 #include "DispCmds.h"  // needed for line styles
00042 #include "Hershey.h"   // needed for Hershey font rendering fctns
00043 
00044 // The default radius for points and lines (which are displayed
00045 // as small spheres or cylinders, respectively)
00046 #define DEFAULT_RADIUS 0.002f
00047 #define DASH_LENGTH 0.02f
00048 
00049 //
00050 // The full X3D export subclass currently uses the following node types:
00051 //   Scene, Background, OrthoViewpoint, Viewpoint,
00052 //   Shape, Appearance, Material, Color, Coordinate, Normal, Transform, 
00053 //   LineProperties, IndexedLineSet, LineSet,
00054 //   IndexedFaceSet, IndexedTriangleSet, IndexedTriangleStripSet,
00055 //   Cone, Cylinder, PointSet, Sphere
00056 //   ClipPlane (not quite yet)
00057 //
00058 
00060 
00062 X3DDisplayDevice::X3DDisplayDevice(
00063                const char *public_name,
00064                const char *public_pretty_name,
00065                const char *default_file_name,
00066                const char *default_command_line) :
00067                  FileRenderer(public_name, public_pretty_name,
00068                  default_file_name, default_command_line) {
00069 }
00070 
00071 // constructor ... initialize some variables
00072 X3DDisplayDevice::X3DDisplayDevice(void) : 
00073   FileRenderer("X3D", "X3D (XML) full specification", "vmdscene.x3d", "true") {
00074 }
00075                
00077 void X3DDisplayDevice::set_color(int mycolorIndex) {
00078 #if 0
00079   write_cindexmaterial(mycolorIndex, materialIndex);
00080 #endif
00081 }
00082 
00083 
00084 void X3DDisplayDevice::text(float *pos, float size, float thickness,
00085                             const char *str) {
00086   float textpos[3];
00087   float textsize;
00088   hersheyhandle hh;
00089 
00090   // transform the world coordinates
00091   (transMat.top()).multpoint3d(pos, textpos);
00092   textsize = size * 1.5f;
00093 
00094   ResizeArray<int>   idxs; 
00095   ResizeArray<float> pnts;
00096   idxs.clear();
00097   pnts.clear();
00098 
00099   int idx=0;
00100   while (*str != '\0') {
00101     float lm, rm, x, y;
00102     int draw;
00103     x=y=0.0f;
00104     draw=0;
00105 
00106     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00107     textpos[0] -= lm * textsize;
00108 
00109     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00110       float pt[3];
00111 
00112       if (draw) {
00113         // add another connected point to the line strip
00114         idxs.append(idx);
00115 
00116         pt[0] = textpos[0] + textsize * x;
00117         pt[1] = textpos[1] + textsize * y;
00118         pt[2] = textpos[2];
00119 
00120         pnts.append(pt[0]);
00121         pnts.append(pt[1]);
00122         pnts.append(pt[2]);
00123 
00124         idx++;
00125       } else {
00126         idxs.append(-1); // pen-up, end of the line strip
00127       }
00128     }
00129     idxs.append(-1); // pen-up, end of the line strip
00130     textpos[0] += rm * textsize;
00131     str++;
00132   }
00133 
00134   fprintf(outfile, "<Shape>\n");
00135   fprintf(outfile, "  ");
00136 
00137   // 
00138   // Emit the line properties
00139   // 
00140   fprintf(outfile, "<Appearance><Material ");
00141   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00142   fprintf(outfile, "diffuseColor='0 0 0' "); 
00143 
00144   const float *rgb = matData[colorIndex];
00145   fprintf(outfile, "emissiveColor='%g %g %g' ",
00146           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00147   fprintf(outfile, "/>");
00148 
00149   // emit a line thickness directive, if needed
00150   if (thickness < 0.99f || thickness > 1.01f) {
00151     fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
00152             "containerField=\"lineProperties\"/>\n",
00153             (double) thickness);
00154   }
00155   fprintf(outfile, "</Appearance>\n");
00156 
00157   //
00158   // Emit the line set
00159   // 
00160   fprintf(outfile, "  <IndexedLineSet coordIndex='");
00161   int i, cnt;
00162   cnt = idxs.num();
00163   for (i=0; i<cnt; i++) {
00164     fprintf(outfile, "%d ", idxs[i]);
00165   }
00166   fprintf(outfile, "'>\n");
00167 
00168   fprintf(outfile, "    <Coordinate point='");
00169   cnt = pnts.num();
00170   for (i=0; i<cnt; i+=3) {
00171     fprintf(outfile, "%c%g %g %g", 
00172             (i==0) ? ' ' : ',',
00173             pnts[i], pnts[i+1], pnts[i+2]);
00174   }
00175   fprintf(outfile, "'/>\n");
00176   fprintf(outfile, "  </IndexedLineSet>\n");
00177   fprintf(outfile, "</Shape>\n");
00178 }
00179 
00180 
00181 // draw a sphere
00182 void X3DDisplayDevice::sphere(float *xyzr) {
00183   float cent[3], radius;
00184 
00185   // transform the coordinates
00186   (transMat.top()).multpoint3d(xyzr, cent);
00187   radius = scale_radius(xyzr[3]);
00188 
00189   fprintf(outfile, "<Transform translation='%g %g %g'>\n",
00190           cent[0], cent[1], cent[2]);
00191   fprintf(outfile, "  <Shape>\n");
00192   fprintf(outfile, "  ");
00193   write_cindexmaterial(colorIndex, materialIndex);
00194   fprintf(outfile, "  <Sphere radius='%g'/>\n", radius);
00195   fprintf(outfile, "  </Shape>\n");
00196   fprintf(outfile, "</Transform>\n");
00197 }
00198 
00199 
00200 // draw a point
00201 void X3DDisplayDevice::point(float * xyz) {
00202   float txyz[3];
00203 
00204   // transform the coordinates
00205   (transMat.top()).multpoint3d(xyz, txyz);
00206 
00207   // ugly and wasteful, but it will work
00208   fprintf(outfile, "<Shape>\n");
00209   fprintf(outfile, "  ");
00210 
00211   // Emit the point material properties
00212   fprintf(outfile, "<Appearance><Material ");
00213   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00214   fprintf(outfile, "diffuseColor='0 0 0' ");
00215 
00216   const float *rgb = matData[colorIndex];
00217   fprintf(outfile, "emissiveColor='%g %g %g' ",
00218           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00219   fprintf(outfile, "/>");
00220   fprintf(outfile, "</Appearance>\n");
00221 
00222   fprintf(outfile, "  <PointSet>\n");
00223   fprintf(outfile, "    <Coordinate point='%g %g %g'/>\n",
00224           txyz[0], txyz[1], txyz[2]);
00225   
00226   float col[3];
00227   vec_copy(col, matData[colorIndex]);
00228   fprintf(outfile, "    <Color color='%g %g %g'/>\n", 
00229           col[0], col[1], col[2]);
00230   fprintf(outfile, "  </PointSet>\n");
00231   fprintf(outfile, "</Shape>\n");
00232 }
00233 
00234 
00235 // draw an array of points of the same size
00236 void X3DDisplayDevice::point_array(int num, float size,
00237                                    float *xyz, float *colors) {
00238   float txyz[3];
00239 
00240   // ugly and wasteful, but it will work
00241   fprintf(outfile, "<Shape>\n");
00242   fprintf(outfile, "  ");
00243 
00244   // Emit the point material properties
00245   fprintf(outfile, "<Appearance><Material ");
00246   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00247   fprintf(outfile, "diffuseColor='0 0 0' ");
00248   fprintf(outfile, "emissiveColor='1 1 1' ");
00249   fprintf(outfile, "/>");
00250   fprintf(outfile, "</Appearance>\n");
00251 
00252   fprintf(outfile, "  <PointSet>\n");
00253 
00254   int i;
00255   fprintf(outfile, "    <Coordinate point='");
00256   for (i=0; i<num; i++) {
00257     // transform the coordinates
00258     (transMat.top()).multpoint3d(&xyz[i*3], txyz);
00259     fprintf(outfile, "%c %g %g %g",
00260             (i==0) ? ' ' : ',',
00261             txyz[0], txyz[1], txyz[2]);
00262   } 
00263   fprintf(outfile, "'/>\n");
00264 
00265   fprintf(outfile, "    <Color color='");
00266   for (i=0; i<num; i++) {
00267     int cind = i*3;
00268     fprintf(outfile, "%c %g %g %g", 
00269             (i==0) ? ' ' : ',',
00270             colors[cind], colors[cind+1], colors[cind+2]);
00271   } 
00272   fprintf(outfile, "'/>\n");
00273 
00274   fprintf(outfile, "  </PointSet>\n");
00275   fprintf(outfile, "</Shape>\n");
00276 }
00277 
00278 
00280 void X3DDisplayDevice::line(float *a, float*b) {
00281   float ta[3], tb[3];
00282 
00283   if (lineStyle == ::SOLIDLINE) {
00284     // transform the coordinates
00285     (transMat.top()).multpoint3d(a, ta);
00286     (transMat.top()).multpoint3d(b, tb);
00287 
00288     // ugly and wasteful, but it will work
00289     fprintf(outfile, "<Shape>\n");
00290     fprintf(outfile, "  ");
00291     write_cindexmaterial(colorIndex, materialIndex);
00292 
00293     fprintf(outfile, "  <IndexedLineSet coordIndex='0 1 -1'>\n");
00294     fprintf(outfile, "    <Coordinate point='%g %g %g, %g %g %g'/>\n",
00295             ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]);
00296   
00297     float col[3];
00298     vec_copy(col, matData[colorIndex]);
00299     fprintf(outfile, "    <Color color='%g %g %g, %g %g %g'/>\n", 
00300             col[0], col[1], col[2], col[0], col[1], col[2]);
00301     fprintf(outfile, "  </IndexedLineSet>\n");
00302     fprintf(outfile, "</Shape>\n");
00303   } else if (lineStyle == ::DASHEDLINE) {
00304     float dirvec[3], unitdirvec[3], tmp1[3], tmp2[3];
00305     int i, j, test;
00306 
00307      // transform the world coordinates
00308     (transMat.top()).multpoint3d(a, tmp1);
00309     (transMat.top()).multpoint3d(b, tmp2);
00310 
00311     // how to create a dashed line
00312     vec_sub(dirvec, tmp2, tmp1);  // vector from a to b
00313     vec_copy(unitdirvec, dirvec);
00314     vec_normalize(unitdirvec);    // unit vector from a to b
00315     test = 1;
00316     i = 0;
00317     while (test == 1) {
00318       for (j=0; j<3; j++) {
00319         ta[j] = (float) (tmp1[j] + (2*i    )*DASH_LENGTH*unitdirvec[j]);
00320         tb[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00321       }
00322       if (fabsf(tmp1[0] - tb[0]) >= fabsf(dirvec[0])) {
00323         vec_copy(tb, tmp2);
00324         test = 0;
00325       }
00326 
00327       // ugly and wasteful, but it will work
00328       fprintf(outfile, "<Shape>\n");
00329       fprintf(outfile, "  ");
00330       write_cindexmaterial(colorIndex, materialIndex);
00331 
00332       fprintf(outfile, "  <IndexedLineSet coordIndex='0 1 -1'>\n");
00333       fprintf(outfile, "    <Coordinate point='%g %g %g, %g %g %g'/>\n",
00334               ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]);
00335   
00336       float col[3];
00337       vec_copy(col, matData[colorIndex]);
00338       fprintf(outfile, "    <Color color='%g %g %g, %g %g %g'/>\n", 
00339               col[0], col[1], col[2], col[0], col[1], col[2]);
00340       fprintf(outfile, "  </IndexedLineSet>\n");
00341       fprintf(outfile, "</Shape>\n");
00342       i++;
00343     }
00344   } else {
00345     msgErr << "X3DDisplayDevice: Unknown line style "
00346            << lineStyle << sendmsg;
00347   }
00348 }
00349 
00350 
00351 void X3DDisplayDevice::line_array(int num, float thickness, float *points) {
00352   float *v = points;
00353   float txyz[3];
00354   int i;
00355 
00356   fprintf(outfile, "<Shape>\n");
00357   fprintf(outfile, "  ");
00358 
00359   // Emit the line properties
00360   fprintf(outfile, "<Appearance><Material ");
00361   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00362   fprintf(outfile, "diffuseColor='0 0 0' ");
00363 
00364   const float *rgb = matData[colorIndex];
00365   fprintf(outfile, "emissiveColor='%g %g %g' ",
00366           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00367   fprintf(outfile, "/>");
00368 
00369   // emit a line thickness directive, if needed
00370   if (thickness < 0.99f || thickness > 1.01f) {
00371     fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
00372             "containerField=\"lineProperties\"/>\n",
00373             (double) thickness);
00374   }
00375   fprintf(outfile, "</Appearance>\n");
00376 
00377   // Emit the line set
00378   fprintf(outfile, "  <IndexedLineSet coordIndex='");
00379   for (i=0; i<num; i++) {
00380     fprintf(outfile, "%d %d -1 ", i*2, i*2+1);
00381   }
00382   fprintf(outfile, "'>\n");
00383 
00384   fprintf(outfile, "    <Coordinate point='");
00385   // write two vertices for each line
00386   for (i=0; i<(num*2); i++) {
00387     // transform the coordinates
00388     (transMat.top()).multpoint3d(v, txyz);
00389     fprintf(outfile, "%c%g %g %g",
00390             (i==0) ? ' ' : ',',
00391             txyz[0], txyz[1], txyz[2]);
00392     v += 3;
00393   }
00394   fprintf(outfile, "'/>\n");
00395 
00396   fprintf(outfile, "  </IndexedLineSet>\n");
00397   fprintf(outfile, "</Shape>\n");
00398 }
00399 
00400 
00401 void X3DDisplayDevice::polyline_array(int num, float thickness, float *points) {
00402   float *v = points;
00403   float txyz[3];
00404 
00405   fprintf(outfile, "<Shape>\n");
00406   fprintf(outfile, "  ");
00407 
00408   // Emit the line properties
00409   fprintf(outfile, "<Appearance><Material ");
00410   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00411   fprintf(outfile, "diffuseColor='0 0 0' ");
00412 
00413   const float *rgb = matData[colorIndex];
00414   fprintf(outfile, "emissiveColor='%g %g %g' ",
00415           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00416   fprintf(outfile, "/>");
00417 
00418   // emit a line thickness directive, if needed
00419   if (thickness < 0.99f || thickness > 1.01f) {
00420     fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
00421             "containerField=\"lineProperties\"/>\n",
00422             (double) thickness);
00423   }
00424   fprintf(outfile, "</Appearance>\n");
00425 
00426   // Emit the line set
00427   fprintf(outfile, "  <LineSet vertexCount='%d'>", num);
00428 
00429   fprintf(outfile, "    <Coordinate point='");
00430   for (int i=0; i<num; i++) {
00431     // transform the coordinates
00432     (transMat.top()).multpoint3d(v, txyz);
00433     fprintf(outfile, "%c%g %g %g",
00434             (i==0) ? ' ' : ',',
00435             txyz[0], txyz[1], txyz[2]);
00436     v += 3;
00437   }
00438   fprintf(outfile, "'/>\n");
00439 
00440   fprintf(outfile, "  </LineSet>\n");
00441   fprintf(outfile, "</Shape>\n");
00442 }
00443 
00444 
00445 // draw a cylinder
00446 void X3DDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00447   float ta[3], tb[3], radius;
00448 
00449   // transform the coordinates
00450   (transMat.top()).multpoint3d(a, ta);
00451   (transMat.top()).multpoint3d(b, tb);
00452   radius = scale_radius(r);
00453 
00454   cylinder_noxfrm(ta, tb, radius, filled);
00455 }
00456 
00457 
00458 // draw a cylinder
00459 void X3DDisplayDevice::cylinder_noxfrm(float *ta, float *tb, float radius, int filled) {
00460   if (ta[0] == tb[0] && ta[1] == tb[1] && ta[2] == tb[2]) {
00461     return;  // we don't serve your kind here
00462   }
00463 
00464   float height = distance(ta, tb);
00465 
00466   fprintf(outfile, "<Transform translation='%g %g %g' ",
00467           ta[0], ta[1] + (height / 2.0), ta[2]);
00468 
00469   float rotaxis[3];
00470   float cylaxdir[3];
00471   float yaxis[3] = {0.0, 1.0, 0.0};
00472 
00473   vec_sub(cylaxdir, tb, ta);
00474   vec_normalize(cylaxdir);
00475   float dp = dot_prod(yaxis, cylaxdir);
00476 
00477   cross_prod(rotaxis, cylaxdir, yaxis);
00478   vec_normalize(rotaxis);
00479 
00480   // if we have decent rotation vector, use it
00481   if ((rotaxis[0]*rotaxis[0] + 
00482       rotaxis[1]*rotaxis[1] + 
00483       rotaxis[2]*rotaxis[2]) > 0.5) { 
00484     fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0));
00485     fprintf(outfile, "rotation='%g %g %g  %g'", 
00486             rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp));
00487   } else if (dp < -0.98) {
00488     // if we have denormalized rotation vector, we can assume it is
00489     // caused by a cylinder axis that is nearly coaxial with the Y axis.
00490     // If this is the case, we either perform no rotation in the case of a
00491     // angle cosine near 1.0, or a 180 degree rotation for a cosine near -1.
00492     fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0));
00493     fprintf(outfile, "rotation='0 0 -1 -3.14159'");
00494   }
00495   fprintf(outfile, ">\n");  
00496         
00497   fprintf(outfile, "  <Shape>\n");
00498   fprintf(outfile, "  ");
00499   write_cindexmaterial(colorIndex, materialIndex);
00500 
00501   // draw the cylinder
00502   fprintf(outfile, "    <Cylinder "
00503           "bottom='%s' height='%g' radius='%g' side='%s' top='%s' />\n", 
00504           filled ? "true" : "false",
00505           height,  
00506           radius, 
00507           "true",
00508           filled ? "true" : "false");
00509 
00510   fprintf(outfile, "  </Shape>\n");
00511   fprintf(outfile, "</Transform>\n");
00512 }
00513 
00514 
00515 void X3DDisplayDevice::cone(float *a, float *b, float r) {
00516   float ta[3], tb[3], radius;
00517 
00518   if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) {
00519     return;  // we don't serve your kind here
00520   }
00521 
00522   // transform the coordinates
00523   (transMat.top()).multpoint3d(a, ta);
00524   (transMat.top()).multpoint3d(b, tb);
00525   radius = scale_radius(r);
00526 
00527   float height = distance(a, b);
00528 
00529   fprintf(outfile, "<Transform translation='%g %g %g' ", 
00530           ta[0], ta[1] + (height / 2.0), ta[2]);
00531 
00532   float rotaxis[3];
00533   float cylaxdir[3];
00534   float yaxis[3] = {0.0, 1.0, 0.0};
00535 
00536   vec_sub(cylaxdir, tb, ta);
00537   vec_normalize(cylaxdir);
00538   float dp = dot_prod(yaxis, cylaxdir);
00539 
00540   cross_prod(rotaxis, cylaxdir, yaxis);
00541   vec_normalize(rotaxis);
00542 
00543   if ((rotaxis[0]*rotaxis[0] + 
00544       rotaxis[1]*rotaxis[1] + 
00545       rotaxis[2]*rotaxis[2]) > 0.5) { 
00546     fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0));
00547     fprintf(outfile, "rotation='%g %g %g  %g'", 
00548             rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp));
00549   }
00550   fprintf(outfile, ">\n");  
00551           
00552   fprintf(outfile, "  <Shape>\n");
00553   fprintf(outfile, "  ");
00554   write_cindexmaterial(colorIndex, materialIndex);
00555 
00556   // draw the cone
00557   fprintf(outfile, "  <Cone bottomRadius='%g' height='%g'/>\n", radius, height);
00558 
00559   fprintf(outfile, "  </Shape>\n");
00560   fprintf(outfile, "</Transform>\n");
00561 }
00562 
00563 
00564 // draw a triangle
00565 void X3DDisplayDevice::triangle(const float *a, const float *b, const float *c, 
00566                                 const float *n1, const float *n2, const float *n3) {
00567   float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3];
00568 
00569   // transform the world coordinates
00570   (transMat.top()).multpoint3d(a, ta);
00571   (transMat.top()).multpoint3d(b, tb);
00572   (transMat.top()).multpoint3d(c, tc);
00573 
00574   // and the normals
00575   (transMat.top()).multnorm3d(n1, tn1);
00576   (transMat.top()).multnorm3d(n2, tn2);
00577   (transMat.top()).multnorm3d(n3, tn3);
00578 
00579   fprintf(outfile, "<Shape>\n");
00580   fprintf(outfile, "  ");
00581   write_cindexmaterial(colorIndex, materialIndex);
00582   fprintf(outfile, "  <IndexedFaceSet solid='false' coordIndex='0 1 2 -1'>\n");
00583   fprintf(outfile, "    <Coordinate point='%g %g %g, %g %g %g, %g %g %g'/>\n",
00584           ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]);
00585    
00586   fprintf(outfile, "    <Normal vector='%g %g %g, %g %g %g, %g %g %g'/>\n",
00587           tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]);
00588   fprintf(outfile, "  </IndexedFaceSet>\n");
00589   fprintf(outfile, "</Shape>\n");
00590 }
00591 
00592 
00593 // draw a color-per-vertex triangle
00594 void X3DDisplayDevice::tricolor(const float * a, const float * b, const float * c, 
00595                                 const float * n1, const float * n2, const float * n3,
00596                                 const float *c1, const float *c2, const float *c3) {
00597   float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3];
00598 
00599   // transform the world coordinates
00600   (transMat.top()).multpoint3d(a, ta);
00601   (transMat.top()).multpoint3d(b, tb);
00602   (transMat.top()).multpoint3d(c, tc);
00603 
00604   // and the normals
00605   (transMat.top()).multnorm3d(n1, tn1);
00606   (transMat.top()).multnorm3d(n2, tn2);
00607   (transMat.top()).multnorm3d(n3, tn3);
00608 
00609   // ugly and wasteful, but it will work
00610   fprintf(outfile, "<Shape>\n");
00611   fprintf(outfile, "  ");
00612   write_cindexmaterial(colorIndex, materialIndex);
00613   fprintf(outfile, "  <IndexedFaceSet solid='false' coordIndex='0 1 2 -1'>\n");
00614   fprintf(outfile, "    <Coordinate point='%g %g %g, %g %g %g, %g %g %g'/>\n",
00615           ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]);
00616    
00617   fprintf(outfile, "    <Normal vector='%g %g %g, %g %g %g, %g %g %g'/>\n",
00618           tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]);
00619   fprintf(outfile, "    <Color color='%g %g %g, %g %g %g, %g %g %g'/>\n", 
00620           c1[0], c1[1], c1[2], c2[0], c2[1], c2[2], c3[0], c3[1], c3[2]);
00621   fprintf(outfile, "  </IndexedFaceSet>\n");
00622   fprintf(outfile, "</Shape>\n");
00623 }
00624 
00625 
00626 // use an efficient mesh primitve rather than individual triangles
00627 // when possible.
00628 void X3DDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00629                                       int numfacets, int * facets) {
00630   int i;
00631 
00632   fprintf(outfile, "<Shape>\n");
00633   fprintf(outfile, "  ");
00634   write_cindexmaterial(colorIndex, materialIndex);
00635 
00636   // loop over all of the facets in the mesh
00637   fprintf(outfile, "  <IndexedTriangleSet solid='false' index='");
00638   for (i=0; i<numfacets*3; i+=3) {
00639     fprintf(outfile, "%d %d %d ", facets[i], facets[i+1], facets[i+2]);
00640   }
00641   fprintf(outfile, "'>\n");
00642 
00643   // loop over all of the vertices
00644   fprintf(outfile, "    <Coordinate point='");
00645   for (i=0; i<numverts; i++) {
00646     const float *v = cnv + i*10 + 7;
00647     float tv[3];
00648     (transMat.top()).multpoint3d(v, tv);
00649     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]);
00650   }
00651   fprintf(outfile, "'/>\n");
00652 
00653   // loop over all of the colors
00654   fprintf(outfile, "    <Color color='");
00655   for (i=0; i<numverts; i++) {
00656     const float *c = cnv + i*10;
00657     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]);
00658   }
00659   fprintf(outfile, "'/>\n");
00660    
00661   // loop over all of the normals
00662   fprintf(outfile, "    <Normal vector='");
00663   for (i=0; i<numverts; i++) {
00664     const float *n = cnv + i*10 + 4;
00665     float tn[3];
00666     (transMat.top()).multnorm3d(n, tn);
00667 #if 1
00668     // reduce precision of surface normals to reduce X3D file size
00669     fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00670 #else
00671     // full precision surface normals
00672     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00673 #endif
00674   }
00675   fprintf(outfile, "'/>\n");
00676 
00677   fprintf(outfile, "  </IndexedTriangleSet>\n");
00678   fprintf(outfile, "</Shape>\n");
00679 }
00680 
00681 
00682 
00683 // use an efficient mesh primitve rather than individual triangles
00684 // when possible.
00685 void X3DDisplayDevice::tristrip(int numverts, const float * cnv,
00686                                 int numstrips, const int *vertsperstrip,
00687                                 const int *facets) {
00688   // render directly using the IndexedTriangleStripSet primitive 
00689   int i, strip, v = 0;
00690   fprintf(outfile, "<Shape>\n");
00691   fprintf(outfile, "  ");
00692   write_cindexmaterial(colorIndex, materialIndex);
00693 
00694   // loop over all of the facets in the mesh
00695   // emit vertex indices for each facet
00696   fprintf(outfile, "  <IndexedTriangleStripSet solid='false' index='");
00697   for (strip=0; strip < numstrips; strip++) {
00698     for (i=0; i<vertsperstrip[strip]; i++) {
00699       fprintf(outfile, "%d ", facets[v]);
00700       v++; // move on to next vertex
00701     }
00702     fprintf(outfile, "-1 "); // mark end of strip with a -1 index
00703   }
00704   fprintf(outfile, "'>\n");
00705 
00706   // loop over all of the vertices
00707   fprintf(outfile, "    <Coordinate point='");
00708   for (i=0; i<numverts; i++) {
00709     const float *v = cnv + i*10 + 7;
00710     float tv[3];
00711     (transMat.top()).multpoint3d(v, tv);
00712     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]);
00713   }
00714   fprintf(outfile, "'/>\n");
00715 
00716   // loop over all of the colors
00717   fprintf(outfile, "    <Color color='");
00718   for (i=0; i<numverts; i++) {
00719     const float *c = cnv + i*10;
00720     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]);
00721   }
00722   fprintf(outfile, "'/>\n");
00723   
00724   // loop over all of the normals
00725   fprintf(outfile, "    <Normal vector='");
00726   for (i=0; i<numverts; i++) {
00727     const float *n = cnv + i*10 + 4;
00728     float tn[3];
00729     (transMat.top()).multnorm3d(n, tn);
00730 #if 1
00731     // reduce precision of surface normals to reduce X3D file size
00732     fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00733 #else
00734     // full precision surface normals
00735     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00736 #endif
00737   }
00738   fprintf(outfile, "'/>\n");
00739 
00740   fprintf(outfile, "  </IndexedTriangleStripSet>\n");
00741   fprintf(outfile, "</Shape>\n");
00742 }
00743 
00744 
00745 void X3DDisplayDevice::multmatrix(const Matrix4 &mat) {
00746 }
00747 
00748 
00749 void X3DDisplayDevice::load(const Matrix4 &mat) {
00750 }
00751 
00752 
00753 void X3DDisplayDevice::comment(const char *s) {
00754   fprintf (outfile, "<!-- %s -->\n", s);
00755 }
00756 
00758 
00759 // initialize the file for output
00760 void X3DDisplayDevice::write_header(void) {
00761   fprintf(outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00762   fprintf(outfile, "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\"\n");
00763   fprintf(outfile, "  \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n");
00764   fprintf(outfile, "\n");
00765 
00766   // check for special features that require newer X3D versions
00767   // At present the features that require the latest X3D spec include:
00768   //  - orthographic camera
00769   //  - clipping planes
00770   //  - various special shaders 
00771   if (projection() == PERSPECTIVE) {
00772     // if we use a perspective camera, we are compatible with X3D 3.1 spec
00773     fprintf(outfile, "<X3D version='3.1' profile='Interchange'>\n");
00774   } else {
00775     // if we use an orthographic camera, need the newest X3D 3.2 spec
00776     fprintf(outfile, "<X3D version='3.2' profile='Interchange'>\n");
00777   }
00778 
00779   fprintf(outfile, "<head>\n");
00780   fprintf(outfile, "  <meta name='description' content='VMD Molecular Graphics'/>\n");
00781   fprintf(outfile, "</head>\n");
00782   fprintf(outfile, "<Scene>\n");
00783   fprintf(outfile, "<!-- Created with VMD: -->\n");
00784   fprintf(outfile, "<!-- http://www.ks.uiuc.edu/Research/vmd/ -->\n");
00785 
00786   // export camera definition
00787   if (projection() == PERSPECTIVE) {
00788     float vfov = float(2.0*atan2((double) 0.5*vSize, (double) eyePos[2]-zDist));
00789     if (vfov > VMD_PI)
00790       vfov=float(VMD_PI); // X3D spec disallows FOV over 180 degrees
00791 
00792     fprintf(outfile, "<Viewpoint description=\"VMD Perspective View\" fieldOfView=\"%g\" orientation=\"0 0 -1 0\" position=\"%g %g %g\" centerOfRotation=\"0 0 0\" />\n",
00793             vfov, eyePos[0], eyePos[1], eyePos[2]);
00794   } else {
00795     fprintf(outfile, "<OrthoViewpoint description=\"VMD Orthographic View\" fieldOfView=\"%g %g %g %g\" orientation=\"0 0 -1 0\" position=\"%g %g %g\" centerOfRotation=\"0 0 0\" />\n",
00796             -Aspect*vSize/4, -vSize/4, Aspect*vSize/4, vSize/4,
00797             eyePos[0], eyePos[1], eyePos[2]);
00798   }
00799 
00800   if (backgroundmode == 1) {
00801     // emit background sky color gradient
00802     fprintf(outfile, "<Background skyColor='%g %g %g, %g %g %g, %g %g %g' ", 
00803             backgradienttopcolor[0], // top pole
00804             backgradienttopcolor[1],
00805             backgradienttopcolor[2], 
00806             (backgradienttopcolor[0]+backgradientbotcolor[0])/2.0f, // horizon
00807             (backgradientbotcolor[1]+backgradienttopcolor[1])/2.0f, 
00808             (backgradienttopcolor[2]+backgradientbotcolor[2])/2.0f,
00809             backgradientbotcolor[0], // bottom pole
00810             backgradientbotcolor[1],
00811             backgradientbotcolor[2]);
00812     fprintf(outfile, "skyAngle='1.5, 3.0' />");
00813   } else {
00814     // otherwise emit constant color background sky
00815     fprintf(outfile, "<Background skyColor='%g %g %g'/>",
00816             backColor[0], backColor[1], backColor[2]);
00817   }
00818   fprintf(outfile, "\n");
00819 }
00820 
00821 void X3DDisplayDevice::write_trailer(void) {
00822   fprintf(outfile, "</Scene>\n");
00823   fprintf(outfile, "</X3D>\n");
00824 }
00825 
00826 void X3DDisplayDevice::write_cindexmaterial(int cindex, int material) {
00827   write_colormaterial((float *) &matData[cindex], material);
00828 }
00829 
00830 void X3DDisplayDevice::write_colormaterial(float *rgb, int) {
00831   // use the current material definition
00832   fprintf(outfile, "<Appearance><Material "); 
00833   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00834   fprintf(outfile, "diffuseColor='%g %g %g' ",
00835           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00836   fprintf(outfile, "shininess='%g' ", mat_shininess);
00837   fprintf(outfile, "specularColor='%g %g %g' ",
00838           mat_specular, mat_specular, mat_specular);
00839   fprintf(outfile, "transparency='%g' ", 1.0 - mat_opacity);
00840   fprintf(outfile, "/></Appearance>\n");
00841 }
00842 
00843 
00844 
00845 //
00846 // Export an X3D subset that is compatible with X3DOM v1.1
00847 //
00848 // The X3DOM-compatible X3D subset cannot use a few of the 
00849 // nodes that may be used in the full-feature X3D export subclass:
00850 //   LineSet, LineProperties, IndexedTriangleStripSet, OrthoViewpoint,
00851 //   ClipPlane
00852 //
00853 // The list of nodes implemented in X3DOM v1.1 is available here:
00854 //   http://x3dom.org/x3dom/release/dumpNodeTypeTree-v1.1.html
00855 //
00856 
00858 
00859 // constructor ... initialize some variables
00860 X3DOMDisplayDevice::X3DOMDisplayDevice(void) :
00861   X3DDisplayDevice("X3DOM", "X3D (XML) limited subset for X3DOM v1.1", "vmdscene.x3d", "true") {
00862 }
00863 
00864 
00865 // To write an X3DOM-compatible scene file, we cannot include
00866 // LineProperties nodes.
00867 void X3DOMDisplayDevice::line_array(int num, float thickness, float *points) {
00868   float *v = points;
00869   float txyz[3];
00870   int i;
00871 
00872   fprintf(outfile, "<Shape>\n");
00873   fprintf(outfile, "  ");
00874 
00875   // Emit the line properties
00876   fprintf(outfile, "<Appearance><Material ");
00877   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00878   fprintf(outfile, "diffuseColor='0 0 0' ");
00879 
00880   const float *rgb = matData[colorIndex];
00881   fprintf(outfile, "emissiveColor='%g %g %g' ",
00882           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00883   fprintf(outfile, "/>");
00884 
00885 #if 0
00886   // XXX X3DOM v1.1 doesn't handle LineProperties nodes
00887   // emit a line thickness directive, if needed
00888   if (thickness < 0.99f || thickness > 1.01f) {
00889     fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
00890             "containerField=\"lineProperties\"/>\n",
00891             (double) thickness);
00892   }
00893 #endif
00894   fprintf(outfile, "</Appearance>\n");
00895 
00896   // Emit the line set
00897   fprintf(outfile, "  <IndexedLineSet coordIndex='");
00898   for (i=0; i<num; i++) {
00899     fprintf(outfile, "%d %d -1 ", i*2, i*2+1);
00900   }
00901   fprintf(outfile, "'>\n");
00902 
00903   fprintf(outfile, "    <Coordinate point='");
00904   // write two vertices for each line
00905   for (i=0; i<(num*2); i++) {
00906     // transform the coordinates
00907     (transMat.top()).multpoint3d(v, txyz);
00908     fprintf(outfile, "%c%g %g %g",
00909             (i==0) ? ' ' : ',',
00910             txyz[0], txyz[1], txyz[2]);
00911     v += 3;
00912   }
00913   fprintf(outfile, "'/>\n");
00914 
00915   fprintf(outfile, "  </IndexedLineSet>\n");
00916   fprintf(outfile, "</Shape>\n");
00917 }
00918 
00919 
00920 // To write an X3DOM-compatible scene file, we cannot include
00921 // LineProperties or LineSet nodes, so we use an IndexedLineSet instead.
00922 void X3DOMDisplayDevice::polyline_array(int num, float thickness, float *points) {
00923   float *v = points;
00924   float txyz[3];
00925   int i;
00926 
00927   fprintf(outfile, "<Shape>\n");
00928   fprintf(outfile, "  ");
00929 
00930   // Emit the line properties
00931   fprintf(outfile, "<Appearance><Material ");
00932   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
00933   fprintf(outfile, "diffuseColor='0 0 0' ");
00934 
00935   const float *rgb = matData[colorIndex];
00936   fprintf(outfile, "emissiveColor='%g %g %g' ",
00937           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
00938   fprintf(outfile, "/>");
00939 
00940 #if 0
00941   // XXX X3DOM v1.1 doesn't handle LineProperties nodes
00942   // emit a line thickness directive, if needed
00943   if (thickness < 0.99f || thickness > 1.01f) {
00944     fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
00945             "containerField=\"lineProperties\"/>\n",
00946             (double) thickness);
00947   }
00948 #endif
00949   fprintf(outfile, "</Appearance>\n");
00950 
00951   // Emit the line set
00952   // XXX X3DOM v1.1 doesn't handle LineSet nodes, 
00953   // so we have to use IndexedLineSet instead
00954   fprintf(outfile, "  <IndexedLineSet coordIndex='");
00955   for (i=0; i<num; i++) {
00956     fprintf(outfile, "%d ", i);
00957   }
00958   fprintf(outfile, "'>\n");
00959 
00960   fprintf(outfile, "    <Coordinate point='");
00961   for (i=0; i<num; i++) {
00962     // transform the coordinates
00963     (transMat.top()).multpoint3d(v, txyz);
00964     fprintf(outfile, "%c%g %g %g",
00965             (i==0) ? ' ' : ',',
00966             txyz[0], txyz[1], txyz[2]);
00967     v += 3;
00968   }
00969   fprintf(outfile, "'/>\n");
00970 
00971   fprintf(outfile, "  </IndexedLineSet>\n");
00972   fprintf(outfile, "</Shape>\n");
00973 }
00974 
00975 
00976 // To write an X3DOM-compatible scene file, we cannot include
00977 // LineProperties nodes.
00978 void X3DOMDisplayDevice::text(float *pos, float size, float thickness,
00979                                const char *str) {
00980   float textpos[3];
00981   float textsize;
00982   hersheyhandle hh;
00983 
00984   // transform the world coordinates
00985   (transMat.top()).multpoint3d(pos, textpos);
00986   textsize = size * 1.5f;
00987 
00988   ResizeArray<int>   idxs; 
00989   ResizeArray<float> pnts;
00990   idxs.clear();
00991   pnts.clear();
00992 
00993   int idx=0;
00994   while (*str != '\0') {
00995     float lm, rm, x, y;
00996     int draw;
00997     x=y=0.0f;
00998     draw=0;
00999 
01000     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
01001     textpos[0] -= lm * textsize;
01002 
01003     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
01004       float pt[3];
01005 
01006       if (draw) {
01007         // add another connected point to the line strip
01008         idxs.append(idx);
01009 
01010         pt[0] = textpos[0] + textsize * x;
01011         pt[1] = textpos[1] + textsize * y;
01012         pt[2] = textpos[2];
01013 
01014         pnts.append(pt[0]);
01015         pnts.append(pt[1]);
01016         pnts.append(pt[2]);
01017 
01018         idx++;
01019       } else {
01020         idxs.append(-1); // pen-up, end of the line strip
01021       }
01022     }
01023     idxs.append(-1); // pen-up, end of the line strip
01024     textpos[0] += rm * textsize;
01025     str++;
01026   }
01027 
01028   fprintf(outfile, "<Shape>\n");
01029   fprintf(outfile, "  ");
01030 
01031   // 
01032   // Emit the line properties
01033   // 
01034   fprintf(outfile, "<Appearance><Material ");
01035   fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
01036   fprintf(outfile, "diffuseColor='0 0 0' "); 
01037 
01038   const float *rgb = matData[colorIndex];
01039   fprintf(outfile, "emissiveColor='%g %g %g' ",
01040           mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
01041   fprintf(outfile, "/>");
01042 
01043 #if 0
01044   // XXX X3DOM v1.1 doesn't handle LineProperties nodes
01045   // emit a line thickness directive, if needed
01046   if (thickness < 0.99f || thickness > 1.01f) {
01047     fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
01048             "containerField=\"lineProperties\"/>\n",
01049             (double) thickness);
01050   }
01051 #endif
01052   fprintf(outfile, "</Appearance>\n");
01053 
01054   //
01055   // Emit the line set
01056   // 
01057   fprintf(outfile, "  <IndexedLineSet coordIndex='");
01058   int i, cnt;
01059   cnt = idxs.num();
01060   for (i=0; i<cnt; i++) {
01061     fprintf(outfile, "%d ", idxs[i]);
01062   }
01063   fprintf(outfile, "'>\n");
01064 
01065   fprintf(outfile, "    <Coordinate point='");
01066   cnt = pnts.num();
01067   for (i=0; i<cnt; i+=3) {
01068     fprintf(outfile, "%c%g %g %g", 
01069             (i==0) ? ' ' : ',',
01070             pnts[i], pnts[i+1], pnts[i+2]);
01071   }
01072   fprintf(outfile, "'/>\n");
01073   fprintf(outfile, "  </IndexedLineSet>\n");
01074   fprintf(outfile, "</Shape>\n");
01075 }
01076 
01077 
01078 // Use a less-efficient, but X3DOM-compatible 
01079 // IndexedTriangleSet primitve rather than triangle strips.
01080 void X3DOMDisplayDevice::tristrip(int numverts, const float * cnv,
01081                                   int numstrips, const int *vertsperstrip,
01082                                   const int *facets) {
01083   // render triangle strips one triangle at a time
01084   // triangle winding order is:
01085   //   v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc.
01086   int i, strip, v = 0;
01087   int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
01088 
01089   fprintf(outfile, "<Shape>\n");
01090   fprintf(outfile, "  ");
01091   write_cindexmaterial(colorIndex, materialIndex);
01092 
01093   // loop over all of the facets in the mesh
01094   // emit vertex indices for each facet
01095   fprintf(outfile, "  <IndexedTriangleSet solid='false' index='");
01096   for (strip=0; strip < numstrips; strip++) {
01097     for (i=0; i<(vertsperstrip[strip] - 2); i++) {
01098       // render one triangle, using lookup table to fix winding order
01099       fprintf(outfile, "%d %d %d ",
01100               facets[v + (stripaddr[i & 0x01][0])],
01101               facets[v + (stripaddr[i & 0x01][1])],
01102               facets[v + (stripaddr[i & 0x01][2])]);
01103       v++; // move on to next vertex
01104     }
01105     v+=2; // last two vertices are already used by last triangle
01106   }
01107   fprintf(outfile, "'>\n");
01108 
01109   // loop over all of the vertices
01110   fprintf(outfile, "    <Coordinate point='");
01111   for (i=0; i<numverts; i++) {
01112     const float *v = cnv + i*10 + 7;
01113     float tv[3];
01114     (transMat.top()).multpoint3d(v, tv);
01115     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]);
01116   }
01117   fprintf(outfile, "'/>\n");
01118 
01119   // loop over all of the colors
01120   fprintf(outfile, "    <Color color='");
01121   for (i=0; i<numverts; i++) {
01122     const float *c = cnv + i*10;
01123     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]);
01124   }
01125   fprintf(outfile, "'/>\n");
01126 
01127   // loop over all of the normals
01128   fprintf(outfile, "    <Normal vector='");
01129   for (i=0; i<numverts; i++) {
01130     const float *n = cnv + i*10 + 4;
01131     float tn[3];
01132     (transMat.top()).multnorm3d(n, tn);
01133 #if 1
01134     // reduce precision of surface normals to reduce X3D file size
01135     fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
01136 #else
01137     // full precision surface normals
01138     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
01139 #endif
01140   }
01141   fprintf(outfile, "'/>\n");
01142 
01143   fprintf(outfile, "  </IndexedTriangleSet>\n");
01144   fprintf(outfile, "</Shape>\n");
01145 }
01146 
01148 
01149 
01150 

Generated on Wed May 23 01:50:37 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002