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

Vrml2DisplayDevice.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: Vrml2DisplayDevice.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.47 $       $Date: 2020/07/01 06:09:05 $
00014  *
00015  ***************************************************************************/
00027 #include <math.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include "Vrml2DisplayDevice.h"
00032 #include "Matrix4.h"
00033 #include "utilities.h"
00034 #include "DispCmds.h"  // needed for line styles
00035 #include "Hershey.h"   // needed for Hershey font rendering fctns
00036 
00037 // The default radius for points and lines (which are displayed
00038 // as small spheres or cylinders, respectively)
00039 #define DEFAULT_RADIUS 0.002f
00040 #define DASH_LENGTH 0.02f
00041 
00043 
00044 // constructor ... initialize some variables
00045 Vrml2DisplayDevice::Vrml2DisplayDevice(void) : 
00046   FileRenderer("VRML-2", "VRML 2.0 (VRML97)", "vmdscene.wrl", "true") {
00047 }
00048                
00050 void Vrml2DisplayDevice::set_color(int mycolorIndex) {
00051 #if 0
00052   write_cindexmaterial(mycolorIndex, materialIndex);
00053 #endif
00054 }
00055 
00056 
00057 void Vrml2DisplayDevice::text(float *pos, float size, float thickness,
00058                               const char *str) {
00059   float textpos[3];
00060   hersheyhandle hh;
00061 
00062   // transform the world coordinates
00063   (transMat.top()).multpoint3d(pos, textpos);
00064   float textsize = size * 1.5f;
00065   //  XXX text thickness not usable with VRML2 since we don't have a line
00066   //      thickness parameter when drawing indexed line sets, apparently...
00067   //  float textthickness = thickness*DEFAULT_RADIUS;
00068 
00069   while (*str != '\0') {
00070     float lm, rm, x, y, ox, oy;
00071     int draw, odraw;
00072     ox=oy=x=y=0.0f;
00073     draw=odraw=0;
00074 
00075     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00076     textpos[0] -= lm * textsize;
00077 
00078     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00079       float oldpt[3], newpt[3];
00080       if (draw) {
00081         newpt[0] = textpos[0] + textsize * x;
00082         newpt[1] = textpos[1] + textsize * y;
00083         newpt[2] = textpos[2];
00084 
00085         if (odraw) {
00086           // if we have both previous and next points, connect them...
00087           oldpt[0] = textpos[0] + textsize * ox;
00088           oldpt[1] = textpos[1] + textsize * oy;
00089           oldpt[2] = textpos[2];
00090 
00091           // ugly and wasteful, but it will work
00092           fprintf(outfile, "Shape {\n");
00093           fprintf(outfile, "  ");
00094           write_cindexmaterial(colorIndex, materialIndex);
00095           fprintf(outfile, "  geometry IndexedLineSet { \n");
00096           fprintf(outfile, "    coordIndex [ 0, 1, -1 ]\n");
00097           fprintf(outfile, "    coord Coordinate { point [ %g %g %g,  %g %g %g ] }\n",
00098                   oldpt[0], oldpt[1], oldpt[2], newpt[0], newpt[1], newpt[2]);
00099 
00100           float col[3];
00101           vec_copy(col, matData[colorIndex]);
00102           fprintf(outfile, "    color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n",
00103                   col[0], col[1], col[2], col[0], col[1], col[2]);
00104           fprintf(outfile, "  }\n");
00105           fprintf(outfile, "}\n");
00106         }
00107       }
00108 
00109       ox=x;
00110       oy=y;
00111       odraw=draw;
00112     }
00113     textpos[0] += rm * textsize;
00114 
00115     str++;
00116   }
00117 }
00118 
00119 
00120 // draw a sphere
00121 void Vrml2DisplayDevice::sphere(float *xyzr) {
00122   float cent[3], radius;
00123 
00124   // transform the coordinates
00125   (transMat.top()).multpoint3d(xyzr, cent);
00126   radius = scale_radius(xyzr[3]);
00127 
00128   fprintf(outfile, "Transform {\n");
00129   fprintf(outfile, "  translation %g %g %g\n", cent[0], cent[1], cent[2]);
00130   fprintf(outfile, "  children [ Shape {\n");
00131   fprintf(outfile, "    ");
00132   write_cindexmaterial(colorIndex, materialIndex);
00133   fprintf(outfile, "    geometry Sphere { radius %g }\n", radius);
00134   fprintf(outfile, "  }]\n");
00135   fprintf(outfile, "}\n");
00136 }
00137 
00138 
00139 // draw a point
00140 void Vrml2DisplayDevice::point(float * xyz) {
00141   float txyz[3];
00142 
00143   // transform the coordinates
00144   (transMat.top()).multpoint3d(xyz, txyz);
00145 
00146   // ugly and wasteful, but it will work
00147   fprintf(outfile, "Shape {\n");
00148   fprintf(outfile, "  ");
00149   write_cindexmaterial(colorIndex, materialIndex);
00150 
00151   fprintf(outfile, "  geometry PointSet { \n");
00152   fprintf(outfile, "    coord Coordinate { point [%g %g %g] }\n",
00153           txyz[0], txyz[1], txyz[2]);
00154  
00155   float col[3];
00156   vec_copy(col, matData[colorIndex]);
00157   fprintf(outfile, "    color Color { color [%.3f %.3f %.3f] }\n",
00158           col[0], col[1], col[2]);
00159   fprintf(outfile, "  }\n");
00160   fprintf(outfile, "}\n");
00161 }
00162 
00163 
00166 void Vrml2DisplayDevice::line(float *a, float*b) {
00167   float ta[3], tb[3];
00168 
00169   if (lineStyle == ::SOLIDLINE) {
00170     // transform the coordinates
00171     (transMat.top()).multpoint3d(a, ta);
00172     (transMat.top()).multpoint3d(b, tb);
00173 
00174     // ugly and wasteful, but it will work
00175     fprintf(outfile, "Shape {\n");
00176     fprintf(outfile, "  ");
00177     write_cindexmaterial(colorIndex, materialIndex);
00178     fprintf(outfile, "  geometry IndexedLineSet { \n"); 
00179     fprintf(outfile, "    coordIndex [ 0, 1, -1 ]\n");
00180     fprintf(outfile, "    coord Coordinate { point [ %g %g %g,  %g %g %g ] }\n",
00181             ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]);
00182 
00183     float col[3];
00184     vec_copy(col, matData[colorIndex]);
00185     fprintf(outfile, "    color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 
00186             col[0], col[1], col[2], col[0], col[1], col[2]);
00187 
00188     fprintf(outfile, "  }\n");
00189     fprintf(outfile, "}\n");
00190   } else if (lineStyle == ::DASHEDLINE) {
00191     float dirvec[3], unitdirvec[3], tmp1[3], tmp2[3];
00192     int i, j, test;
00193 
00194      // transform the world coordinates
00195     (transMat.top()).multpoint3d(a, tmp1);
00196     (transMat.top()).multpoint3d(b, tmp2);
00197 
00198     // how to create a dashed line
00199     vec_sub(dirvec, tmp2, tmp1);  // vector from a to b
00200     vec_copy(unitdirvec, dirvec);
00201     vec_normalize(unitdirvec);    // unit vector from a to b
00202     test = 1;
00203     i = 0;
00204     while (test == 1) {
00205       for (j=0; j<3; j++) {
00206         ta[j] = (float) (tmp1[j] + (2*i    )*DASH_LENGTH*unitdirvec[j]);
00207         tb[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00208       }
00209       if (fabsf(tmp1[0] - tb[0]) >= fabsf(dirvec[0])) {
00210         vec_copy(tb, tmp2);
00211         test = 0;
00212       }
00213 
00214       // ugly and wasteful, but it will work
00215       fprintf(outfile, "Shape {\n");
00216       fprintf(outfile, "  ");
00217       write_cindexmaterial(colorIndex, materialIndex);
00218       fprintf(outfile, "  geometry IndexedLineSet { \n"); 
00219       fprintf(outfile, "    coordIndex [ 0, 1, -1 ]\n");
00220       fprintf(outfile, "    coord Coordinate { point [ %g %g %g,  %g %g %g ] }\n",
00221               ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]);
00222 
00223       float col[3];
00224       vec_copy(col, matData[colorIndex]);
00225       fprintf(outfile, "    color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 
00226               col[0], col[1], col[2], col[0], col[1], col[2]);
00227 
00228       fprintf(outfile, "  }\n");
00229       fprintf(outfile, "}\n");
00230       i++;
00231     }
00232   } else {
00233     msgErr << "Vrml2DisplayDevice: Unknown line style "
00234            << lineStyle << sendmsg;
00235   }
00236 }
00237 
00238 
00239 // draw a cylinder
00240 void Vrml2DisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00241   float ta[3], tb[3], radius;
00242 
00243   // transform the coordinates
00244   (transMat.top()).multpoint3d(a, ta);
00245   (transMat.top()).multpoint3d(b, tb);
00246   radius = scale_radius(r);
00247 
00248   cylinder_noxfrm(ta, tb, radius, filled);
00249 }
00250 
00251 
00252 void Vrml2DisplayDevice::cylinder_noxfrm(float *ta, float *tb, float radius, int filled) {
00253   if (ta[0] == tb[0] && ta[1] == tb[1] && ta[2] == tb[2]) {
00254     return;  // we don't serve your kind here
00255   }
00256 
00257   float height = distance(ta, tb);
00258 
00259   fprintf(outfile, "Transform {\n");
00260   fprintf(outfile, "  translation %g %g %g\n", 
00261           ta[0], ta[1] + (height / 2.0), ta[2]);
00262 
00263   float rotaxis[3];
00264   float cylaxdir[3];
00265   float yaxis[3] = {0.0, 1.0, 0.0};
00266 
00267   vec_sub(cylaxdir, tb, ta);
00268   vec_normalize(cylaxdir);
00269   float dp = dot_prod(yaxis, cylaxdir);
00270 
00271   cross_prod(rotaxis, cylaxdir, yaxis);
00272   vec_normalize(rotaxis);
00273 
00274   // if we have decent rotation vector, use it
00275   if ((rotaxis[0]*rotaxis[0] + 
00276       rotaxis[1]*rotaxis[1] + 
00277       rotaxis[2]*rotaxis[2]) > 0.5) { 
00278     fprintf(outfile, "  center 0.0 %g 0.0\n", -(height / 2.0));
00279     fprintf(outfile, "  rotation %g %g %g  %g\n", 
00280             rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp));
00281   } else if (dp < -0.98) {
00282     // if we have denormalized rotation vector, we can assume it is
00283     // caused by a cylinder axis that is nearly coaxial with the Y axis.
00284     // If this is the case, we either perform no rotation in the case of a
00285     // angle cosine near 1.0, or a 180 degree rotation for a cosine near -1.
00286     fprintf(outfile, "  center 0.0 %g 0.0\n", -(height / 2.0));
00287     fprintf(outfile, "  rotation 0 0 -1  -3.14159\n");
00288   }
00289           
00290   fprintf(outfile, "  children [ Shape {\n");
00291   fprintf(outfile, "    ");
00292   write_cindexmaterial(colorIndex, materialIndex);
00293 
00294 #if 0
00295   // draw the cylinder
00296   fprintf(outfile, "    geometry Cylinder { "
00297           "bottom %s height %g radius %g side %s top %s }\n", 
00298           filled ? "TRUE" : "FALSE",
00299           height,  
00300           radius, 
00301           "TRUE",
00302           filled ? "TRUE" : "FALSE");
00303 #else
00304   if (filled) {
00305     fprintf(outfile, "    geometry Cylinder { "
00306             "height %g radius %g }\n", height,  radius);
00307   } else {
00308     fprintf(outfile, "    geometry VMDCyl { "
00309             "h %g r %g }\n", height,  radius);
00310   }
00311 #endif
00312 
00313   fprintf(outfile, "  }]\n");
00314   fprintf(outfile, "}\n");
00315 }
00316 
00317 
00318 void Vrml2DisplayDevice::cone(float *a, float *b, float r, int /* resolution */) {
00319   float ta[3], tb[3], radius;
00320 
00321   if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) {
00322     return;  // we don't serve your kind here
00323   }
00324 
00325   // transform the coordinates
00326   (transMat.top()).multpoint3d(a, ta);
00327   (transMat.top()).multpoint3d(b, tb);
00328   radius = scale_radius(r);
00329 
00330   float height = distance(ta, tb);
00331 
00332   fprintf(outfile, "Transform {\n");
00333   fprintf(outfile, "  translation %g %g %g\n", 
00334           ta[0], ta[1] + (height / 2.0), ta[2]);
00335 
00336   float rotaxis[3];
00337   float cylaxdir[3];
00338   float yaxis[3] = {0.0, 1.0, 0.0};
00339 
00340   vec_sub(cylaxdir, tb, ta);
00341   vec_normalize(cylaxdir);
00342   float dp = dot_prod(yaxis, cylaxdir);
00343 
00344   cross_prod(rotaxis, cylaxdir, yaxis);
00345   vec_normalize(rotaxis);
00346 
00347   if ((rotaxis[0]*rotaxis[0] + 
00348       rotaxis[1]*rotaxis[1] + 
00349       rotaxis[2]*rotaxis[2]) > 0.5) { 
00350     fprintf(outfile, "  center 0.0 %g 0.0\n", -(height / 2.0));
00351     fprintf(outfile, "  rotation %g %g %g  %g\n", 
00352             rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp));
00353   }
00354           
00355   fprintf(outfile, "  children [ Shape {\n");
00356   fprintf(outfile, "    ");
00357   write_cindexmaterial(colorIndex, materialIndex);
00358 
00359   // draw the cone
00360   fprintf(outfile, "    geometry Cone { bottomRadius %g height %g }\n", 
00361           radius, height);
00362 
00363   fprintf(outfile, "  }]\n");
00364   fprintf(outfile, "}\n");
00365 }
00366 
00367 
00368 // draw a triangle
00369 void Vrml2DisplayDevice::triangle(const float *a, const float *b, const float *c, 
00370                                   const float *n1, const float *n2, const float *n3) {
00371   float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3];
00372 
00373   // transform the world coordinates
00374   (transMat.top()).multpoint3d(a, ta);
00375   (transMat.top()).multpoint3d(b, tb);
00376   (transMat.top()).multpoint3d(c, tc);
00377 
00378   // and the normals
00379   (transMat.top()).multnorm3d(n1, tn1);
00380   (transMat.top()).multnorm3d(n2, tn2);
00381   (transMat.top()).multnorm3d(n3, tn3);
00382 
00383   // ugly and wasteful, but it will work
00384   fprintf(outfile, "Shape {\n");
00385   fprintf(outfile, "  ");
00386   write_cindexmaterial(colorIndex, materialIndex);
00387   fprintf(outfile, "  geometry IndexedFaceSet { \n"); 
00388   fprintf(outfile, "    solid FALSE coordIndex [ 0, 1, 2, -1 ]\n");
00389   fprintf(outfile, "    coord Coordinate { point [ %g %g %g,  %g %g %g,  %g %g %g ] }\n",
00390           ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]);
00391    
00392   fprintf(outfile, "    normal Normal { vector [ %g %g %g, %g %g %g, %g %g %g ] }\n",
00393           tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]);
00394 
00395   fprintf(outfile, "  }\n");
00396   fprintf(outfile, "}\n");
00397 }
00398 
00399 
00400 // draw a color-per-vertex triangle
00401 void Vrml2DisplayDevice::tricolor(const float * a, const float * b, const float * c, 
00402                         const float * n1, const float * n2, const float * n3,
00403                         const float *c1, const float *c2, const float *c3) {
00404   float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3];
00405 
00406   // transform the world coordinates
00407   (transMat.top()).multpoint3d(a, ta);
00408   (transMat.top()).multpoint3d(b, tb);
00409   (transMat.top()).multpoint3d(c, tc);
00410 
00411   // and the normals
00412   (transMat.top()).multnorm3d(n1, tn1);
00413   (transMat.top()).multnorm3d(n2, tn2);
00414   (transMat.top()).multnorm3d(n3, tn3);
00415 
00416   // ugly and wasteful, but it will work
00417   fprintf(outfile, "Shape {\n");
00418   fprintf(outfile, "  ");
00419   write_cindexmaterial(colorIndex, materialIndex);
00420   fprintf(outfile, "  geometry IndexedFaceSet { \n"); 
00421   fprintf(outfile, "    solid FALSE coordIndex [ 0, 1, 2, -1 ]\n");
00422   fprintf(outfile, "    coord Coordinate { point [ %g %g %g,  %g %g %g,  %g %g %g ] }\n",
00423           ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]);
00424 
00425   fprintf(outfile, "    color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 
00426           c1[0], c1[1], c1[2], c2[0], c2[1], c2[2], c3[0], c3[1], c3[2]);
00427    
00428   fprintf(outfile, "    normal Normal { vector [ %.3f %.3f %.3f, %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n",
00429           tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]);
00430 
00431   fprintf(outfile, "  }\n");
00432   fprintf(outfile, "}\n");
00433 }
00434 
00435 
00436 // use an efficient mesh primitve rather than individual triangles
00437 // when possible.
00438 void Vrml2DisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00439                                         int numfacets, int * facets) {
00440   int i;
00441 
00442   fprintf(outfile, "Shape {\n");
00443   fprintf(outfile, "  ");
00444   write_cindexmaterial(colorIndex, materialIndex);
00445   fprintf(outfile, "  geometry IndexedFaceSet { \n"); 
00446 
00447   // loop over all of the facets in the mesh
00448   fprintf(outfile, "    coordIndex [ ");
00449   for (i=0; i<numfacets*3; i+=3) {
00450     fprintf(outfile, "%c %d, %d, %d, -1", (i==0) ? ' ' : ',',
00451             facets[i], facets[i+1], facets[i+2]);
00452   }
00453   fprintf(outfile, " ]\n");
00454 
00455   // loop over all of the vertices
00456   fprintf(outfile, "    coord Coordinate { point [ ");
00457   for (i=0; i<numverts; i++) {
00458     const float *v = cnv + i*10 + 7;
00459     float tv[3];
00460     (transMat.top()).multpoint3d(v, tv);
00461     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]);
00462   }
00463   fprintf(outfile, " ] }\n");
00464 
00465   // loop over all of the colors
00466   fprintf(outfile, "    color Color { color [ ");
00467   for (i=0; i<numverts; i++) {
00468     const float *c = cnv + i*10;
00469     fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', c[0], c[1], c[2]);
00470   }
00471   fprintf(outfile, " ] }\n");
00472    
00473   // loop over all of the normals
00474   fprintf(outfile, "    normal Normal { vector [ ");
00475   for (i=0; i<numverts; i++) {
00476     const float *n = cnv + i*10 + 4;
00477     float tn[3];
00478     (transMat.top()).multnorm3d(n, tn);
00479     fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00480   }
00481   fprintf(outfile, " ] }\n");
00482 
00483   // close the IndexedFaceSet node
00484   fprintf(outfile, "  }\n");
00485 
00486   // close the shape node
00487   fprintf(outfile, "}\n");
00488 }
00489 
00490 
00491 // use an efficient mesh primitve rather than individual triangles
00492 // when possible.
00493 void Vrml2DisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, 
00494                                              signed char *n, 
00495                                              float *v, int numfacets) {
00496   int i;
00497   int numverts = 3*numfacets;
00498 
00499   const float ci2f = 1.0f / 255.0f; // used for uchar2float and normal conv
00500   const float cn2f = 1.0f / 127.5f;
00501 
00502   fprintf(outfile, "Shape {\n");
00503   fprintf(outfile, "  ");
00504   write_cindexmaterial(colorIndex, materialIndex);
00505   fprintf(outfile, "  geometry IndexedFaceSet { \n"); 
00506 
00507   // loop over all of the facets in the mesh
00508   fprintf(outfile, "    coordIndex [ ");
00509   for (i=0; i<numfacets*3; i+=3) {
00510     fprintf(outfile, "%c %d, %d, %d, -1", (i==0) ? ' ' : ',', i, i+1, i+2);
00511   }
00512   fprintf(outfile, " ]\n");
00513 
00514   // loop over all of the vertices
00515   fprintf(outfile, "    coord Coordinate { point [ ");
00516   for (i=0; i<numverts; i++) {
00517     float tv[3];
00518     int idx = i * 3;
00519     (transMat.top()).multpoint3d(&v[idx], tv);
00520     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]);
00521   }
00522   fprintf(outfile, " ] }\n");
00523 
00524   // loop over all of the colors
00525   fprintf(outfile, "    color Color { color [ ");
00526   for (i=0; i<numverts; i++) {
00527     int idx = i * 4;
00528 
00529     // conversion from GLubyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
00530     // float = c/(2^8-1)
00531     fprintf(outfile, "%c %.3f %.3f %.3f",
00532             (i==0) ? ' ' : ',',
00533             c[idx  ] * ci2f,
00534             c[idx+1] * ci2f,
00535             c[idx+2] * ci2f);
00536   }
00537   fprintf(outfile, " ] }\n");
00538    
00539   // loop over all of the normals
00540   fprintf(outfile, "    normal Normal { vector [ ");
00541   for (i=0; i<numverts; i++) {
00542     float tn[3], ntmp[3];
00543     int idx = i * 3;
00544 
00545     // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
00546     // float = (2c+1)/(2^8-1)
00547     ntmp[0] = n[idx  ] * cn2f + ci2f;
00548     ntmp[1] = n[idx+1] * cn2f + ci2f;
00549     ntmp[2] = n[idx+2] * cn2f + ci2f;
00550 
00551     (transMat.top()).multnorm3d(ntmp, tn);
00552     fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00553   }
00554   fprintf(outfile, " ] }\n");
00555 
00556   // close the IndexedFaceSet node
00557   fprintf(outfile, "  }\n");
00558 
00559   // close the shape node
00560   fprintf(outfile, "}\n");
00561 }
00562 
00563 
00564 // use an efficient mesh primitve rather than individual triangles
00565 // when possible.
00566 void Vrml2DisplayDevice::tristrip(int numverts, const float * cnv,
00567                                   int numstrips, const int *vertsperstrip,
00568                                   const int *facets) {
00569   int i;
00570   // render triangle strips one triangle at a time
00571   // triangle winding order is:
00572   //   v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc.
00573   int strip, v = 0;
00574   int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
00575 
00576   fprintf(outfile, "Shape {\n");
00577   fprintf(outfile, "  ");
00578   write_cindexmaterial(colorIndex, materialIndex);
00579   fprintf(outfile, "  geometry IndexedFaceSet { \n"); 
00580 
00581   // loop over all of the facets in the mesh
00582   // emit vertex indices for each facet
00583   fprintf(outfile, "    coordIndex [ ");
00584   for (strip=0; strip < numstrips; strip++) {
00585     for (i=0; i<(vertsperstrip[strip] - 2); i++) {
00586       // render one triangle, using lookup table to fix winding order
00587       fprintf(outfile, "%c %d, %d, %d, -1", (i==0) ? ' ' : ',',
00588               facets[v + (stripaddr[i & 0x01][0])],
00589               facets[v + (stripaddr[i & 0x01][1])],
00590               facets[v + (stripaddr[i & 0x01][2])]);
00591       v++; // move on to next vertex
00592     }
00593     v+=2; // last two vertices are already used by last triangle
00594   }
00595   fprintf(outfile, " ]\n");
00596 
00597   // loop over all of the vertices
00598   fprintf(outfile, "    coord Coordinate { point [ ");
00599   for (i=0; i<numverts; i++) {
00600     const float *v = cnv + i*10 + 7;
00601     float tv[3];
00602     (transMat.top()).multpoint3d(v, tv);
00603     fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]);
00604   }
00605   fprintf(outfile, " ] }\n");
00606 
00607   // loop over all of the colors
00608   fprintf(outfile, "    color Color { color [ ");
00609   for (i=0; i<numverts; i++) {
00610     const float *c = cnv + i*10;
00611     fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', c[0], c[1], c[2]);
00612   }
00613   fprintf(outfile, " ] }\n");
00614    
00615   // loop over all of the normals
00616   fprintf(outfile, "    normal Normal { vector [ ");
00617   for (i=0; i<numverts; i++) {
00618     const float *n = cnv + i*10 + 4;
00619     float tn[3];
00620     (transMat.top()).multnorm3d(n, tn);
00621     fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]);
00622   }
00623   fprintf(outfile, " ] }\n");
00624 
00625   // close the IndexedFaceSet node
00626   fprintf(outfile, "  }\n");
00627 
00628   // close the shape node
00629   fprintf(outfile, "}\n");
00630 }
00631 
00632 
00633 void Vrml2DisplayDevice::multmatrix(const Matrix4 &mat) {
00634 }
00635 
00636 
00637 void Vrml2DisplayDevice::load(const Matrix4 &mat) {
00638 }
00639 
00640 
00641 void Vrml2DisplayDevice::comment(const char *s) {
00642   fprintf (outfile, "# %s\n", s);
00643 }
00644 
00646 
00647 // initialize the file for output
00648 void Vrml2DisplayDevice::write_header(void) {
00649   fprintf(outfile, "#VRML V2.0 utf8\n");
00650   fprintf(outfile, "# Created with VMD: "
00651           "http://www.ks.uiuc.edu/Research/vmd/\n");
00652 
00653   // define our special node types
00654   fprintf(outfile, "# Define some custom nodes VMD to decrease file size\n");
00655   fprintf(outfile, "# custom VMD cylinder node\n");
00656   fprintf(outfile, "PROTO VMDCyl [\n");
00657   fprintf(outfile, "  field SFBool  bottom FALSE\n");
00658   fprintf(outfile, "  field SFFloat h      2    \n");
00659   fprintf(outfile, "  field SFFloat r      1    \n");
00660   fprintf(outfile, "  field SFBool  side   TRUE \n");
00661   fprintf(outfile, "  field SFBool  top    FALSE\n");
00662   fprintf(outfile, "  ] {\n");
00663   fprintf(outfile, "  Cylinder {\n"); 
00664   fprintf(outfile, "    bottom IS bottom\n");
00665   fprintf(outfile, "    height IS h     \n");
00666   fprintf(outfile, "    radius IS r     \n");
00667   fprintf(outfile, "    top    IS top   \n");
00668   fprintf(outfile, "  }\n");
00669   fprintf(outfile, "}\n\n");
00670 
00671   fprintf(outfile, "# custom VMD materials node\n");
00672   fprintf(outfile, "PROTO VMDMat [\n");
00673   fprintf(outfile, "  field SFFloat Ka               0.0\n"); 
00674   fprintf(outfile, "  field SFColor Kd               0.8 0.8 0.8\n");
00675   fprintf(outfile, "  field SFColor emissiveColor    0.0 0.0 0.0\n");
00676   fprintf(outfile, "  field SFFloat Ksx              0.0\n"); 
00677   fprintf(outfile, "  field SFColor Ks               0.0 0.0 0.0\n");
00678   fprintf(outfile, "  field SFFloat Kt               0.0\n"); 
00679   fprintf(outfile, "  ] {\n");
00680   fprintf(outfile, "  Appearance {\n");
00681   fprintf(outfile, "    material Material {\n");
00682   fprintf(outfile, "      ambientIntensity IS Ka           \n");
00683   fprintf(outfile, "      diffuseColor     IS Kd           \n");
00684   fprintf(outfile, "      emissiveColor    IS emissiveColor\n");
00685   fprintf(outfile, "      shininess        IS Ksx          \n");
00686   fprintf(outfile, "      specularColor    IS Ks           \n");
00687   fprintf(outfile, "      transparency     IS Kt           \n");
00688   fprintf(outfile, "    }\n");
00689   fprintf(outfile, "  }\n");
00690   fprintf(outfile, "}\n\n");
00691 
00692   fprintf(outfile, "\n");
00693   fprintf(outfile, "# begin the actual scene\n");
00694   fprintf(outfile, "Group {\n");
00695   fprintf(outfile, "  children [\n");
00696 
00697   if (backgroundmode == 1) {
00698     // emit background sky color gradient
00699     fprintf(outfile, "Background { skyColor [%g %g %g, %g %g %g, %g %g %g] ",
00700             backgradienttopcolor[0], // top pole
00701             backgradienttopcolor[1],
00702             backgradienttopcolor[2],
00703             (backgradienttopcolor[0]+backgradientbotcolor[0])/2.0f, // horizon
00704             (backgradientbotcolor[1]+backgradienttopcolor[1])/2.0f,
00705             (backgradienttopcolor[2]+backgradientbotcolor[2])/2.0f,
00706             backgradientbotcolor[0], // bottom pole
00707             backgradientbotcolor[1],
00708             backgradientbotcolor[2]);
00709     fprintf(outfile, "skyAngle [ 1.5, 3.0] }");
00710   } else {
00711     // otherwise emit constant color background sky
00712     fprintf(outfile, "Background { skyColor [ %g %g %g ] }",
00713             backColor[0], backColor[1], backColor[2]);
00714   }
00715   fprintf(outfile, "\n");
00716 }
00717 
00718 void Vrml2DisplayDevice::write_trailer(void) {
00719   fprintf(outfile, "  ]\n");
00720   fprintf(outfile, "}\n");
00721 }
00722 
00723 void Vrml2DisplayDevice::write_cindexmaterial(int cindex, int material) {
00724   write_colormaterial((float *) &matData[cindex], material);
00725 }
00726 
00727 void Vrml2DisplayDevice::write_colormaterial(float *rgb, int) {
00728 
00729 #if 0
00730   // use the current material definition
00731   fprintf(outfile, "        appearance Appearance {\n");
00732   fprintf(outfile, "          material Material {\n"); 
00733   fprintf(outfile, "            ambientIntensity %g\n", mat_ambient);
00734   fprintf(outfile, "            diffuseColor %g %g %g\n",
00735           mat_diffuse * rgb[0],
00736           mat_diffuse * rgb[1],
00737           mat_diffuse * rgb[2]);
00738   fprintf(outfile, "            shininess %g\n", mat_shininess);
00739   fprintf(outfile, "            specularColor %g %g %g\n",
00740           mat_specular,
00741           mat_specular,
00742           mat_specular);
00743   fprintf(outfile, "            transparency %g\n", 1.0 - mat_opacity);
00744   fprintf(outfile, "          }\n");
00745   fprintf(outfile, "        }\n");
00746 #else
00747   // use the current material definition
00748   fprintf(outfile, "appearance VMDMat { ");
00749   if (mat_ambient > 0.0) {
00750     fprintf(outfile, "Ka %g ", mat_ambient);
00751   } 
00752 
00753   fprintf(outfile, "Kd %g %g %g ",
00754           mat_diffuse * rgb[0],
00755           mat_diffuse * rgb[1],
00756           mat_diffuse * rgb[2]);
00757 
00758   if (mat_specular > 0.0) {
00759     fprintf(outfile, "Ksx %g ", mat_shininess);
00760     fprintf(outfile, "Ks %g %g %g ", mat_specular, mat_specular, mat_specular);
00761   }
00762 
00763   if (mat_opacity < 1.0) {
00764     fprintf(outfile, "Kt %g ", 1.0 - mat_opacity);
00765   }
00766   fprintf(outfile, " }\n");
00767 #endif
00768 }
00769 
00770 
00771 

Generated on Fri Apr 26 02:44:33 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002