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

X3DDisplayDevice.C

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

Generated on Thu Mar 28 02:44:30 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002