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

POV3DisplayDevice.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: POV3DisplayDevice.C,v $
00013 *      $Author: johns $        $Locker:  $               $State: Exp $
00014 *      $Revision: 1.115 $        $Date: 2011/12/04 22:19:00 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 *
00019 * FileRenderer type for the Persistence of Vision raytracer, v 3.5+
00020 *
00021 ***************************************************************************/
00022 
00023 #include <string.h>
00024 #include <stdio.h>
00025 #include <math.h>
00026 #include "POV3DisplayDevice.h"
00027 #include "Matrix4.h"
00028 #include "Inform.h"
00029 #include "utilities.h"
00030 #include "DispCmds.h"  // need for line styles
00031 #include "config.h"    // for VMDVERSION string
00032 #include "Hershey.h"   // needed for Hershey font rendering fctns
00033 
00034 #define DEFAULT_RADIUS  0.002f
00035 #define DASH_LENGTH     0.02f
00036 #define PHONG_DIVISOR  64.0f
00037 
00038 // Enable triangle coordinate scaling hacks to prevent POV-Ray 3.x
00039 // from emitting millions of "all determinants too small" warnings
00040 // when rendering finely tessellated geometry. #$@!#@$@ POV-Ray....
00041 // If/when POV-Ray gets fixed, this hack should gladly be removed.
00042 #define POVRAY_BRAIN_DAMAGE_WORKAROUND   1 
00043 #define POVRAY_SCALEHACK                 1000.0f
00044 
00046 
00047 // constructor ... initialize some variables
00048 
00049 POV3DisplayDevice::POV3DisplayDevice() : FileRenderer("POV3", "POV-Ray 3.6", "vmdscene.pov", "povray +W%w +H%h -I%s -O%s.tga +D +X +A +FT") {
00050   reset_vars(); // initialize state variables
00051 }
00052         
00053 // destructor
00054 POV3DisplayDevice::~POV3DisplayDevice(void) { }
00055 
00056 
00057 void POV3DisplayDevice::reset_vars(void) {
00058   degenerate_triangles = 0;
00059   degenerate_cylinders = 0;
00060   degenerate_cones = 0;
00061   memset(&clip_on, 0, sizeof(clip_on));
00062   old_materialIndex = -1;
00063 }
00064 
00065 
00067 
00068 void POV3DisplayDevice::text(float *pos, float size, float thickness,
00069                                    const char *str) {
00070   float textpos[3];
00071   float textsize, textthickness;
00072   hersheyhandle hh;
00073 
00074   // transform the world coordinates
00075   (transMat.top()).multpoint3d(pos, textpos);
00076   textsize = size * 1.5f;
00077   textthickness = thickness*DEFAULT_RADIUS;
00078 
00079   while (*str != '\0') {
00080     float lm, rm, x, y, ox, oy;
00081     int draw, odraw;
00082     ox=oy=x=y=0.0f;
00083     draw=odraw=0;
00084 
00085     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00086     textpos[0] -= lm * textsize;
00087 
00088     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00089       float oldpt[3], newpt[3];
00090       if (draw) {
00091         newpt[0] = textpos[0] + textsize * x;
00092         newpt[1] = textpos[1] + textsize * y;
00093         newpt[2] = textpos[2];
00094 
00095         if (odraw) {
00096           // if we have both previous and next points, connect them...
00097           oldpt[0] = textpos[0] + textsize * ox;
00098           oldpt[1] = textpos[1] + textsize * oy;
00099           oldpt[2] = textpos[2];
00100 
00101           fprintf(outfile, "VMD_cylinder(<%.8f,%.8f,%.8f>,<%.8f,%.8f,%.8f>",
00102                   oldpt[0], oldpt[1], -oldpt[2], newpt[0], newpt[1], -newpt[2]);
00103           fprintf(outfile, "%.4f,rgbt<%.3f,%.3f,%.3f,%.3f>,%d)\n",
00104                   textthickness, matData[colorIndex][0], matData[colorIndex][1],
00105                   matData[colorIndex][2], 1 - mat_opacity, 1);
00106 
00107           fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
00108                   newpt[0], newpt[1], -newpt[2], textthickness);
00109           fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00110                   matData[colorIndex][0], matData[colorIndex][1], 
00111                   matData[colorIndex][2], 1 - mat_opacity);
00112         } else {
00113           // ...otherwise, just draw the next point
00114           fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
00115                   newpt[0], newpt[1], -newpt[2], textthickness);
00116           fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00117                   matData[colorIndex][0], matData[colorIndex][1], 
00118                   matData[colorIndex][2], 1 - mat_opacity);
00119         }
00120       }
00121 
00122       ox=x;
00123       oy=y;
00124       odraw=draw;
00125     }
00126     textpos[0] += rm * textsize;
00127 
00128     str++;
00129   }
00130 }
00131 
00132 
00133 // draw a point
00134 void POV3DisplayDevice::point(float * spdata) {
00135   float vec[3];
00136   // transform the world coordinates
00137   (transMat.top()).multpoint3d(spdata, vec);
00138 
00139 //  write_materials();
00140 
00141   // Draw the point
00142   fprintf(outfile, "VMD_point(<%.4f,%.4f,%.4f>,%.4f,rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00143           vec[0], vec[1], -vec[2], ((float)pointSize)*DEFAULT_RADIUS, 
00144           matData[colorIndex][0], matData[colorIndex][1], 
00145           matData[colorIndex][2], 1 - mat_opacity);
00146 }
00147 
00148 // draw a sphere
00149 void POV3DisplayDevice::sphere(float * spdata) {
00150   float vec[3];
00151   float radius;
00152     
00153   // transform the world coordinates
00154   (transMat.top()).multpoint3d(spdata, vec);
00155   radius = scale_radius(spdata[3]);
00156 
00157 //  write_materials();
00158 
00159   // Draw the sphere
00160   fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
00161     vec[0], vec[1], -vec[2], radius);
00162   fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00163     matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00164     1 - mat_opacity);
00165 }
00166 
00167 // draw a line from a to b
00168 void POV3DisplayDevice::line(float *a, float*b) {
00169   int i, j, test;
00170   float dirvec[3], unitdirvec[3];
00171   float from[3], to[3], tmp1[3], tmp2[3];
00172 
00173   if (lineStyle == ::SOLIDLINE) {
00174     // transform the world coordinates
00175     (transMat.top()).multpoint3d(a, from);
00176     (transMat.top()).multpoint3d(b, to);
00177 
00178 //    write_materials();
00179 
00180     // Draw the line
00181     fprintf(outfile, "VMD_line(<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>,",
00182             from[0], from[1], -from[2], to[0], to[1], -to[2]);
00183     fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00184       matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00185       1 - mat_opacity);
00186 
00187   } 
00188   else if (lineStyle == ::DASHEDLINE) {
00189     // transform the world coordinates
00190     (transMat.top()).multpoint3d(a, tmp1);
00191     (transMat.top()).multpoint3d(b, tmp2);
00192 
00193     // how to create a dashed line
00194     vec_sub(dirvec, tmp2, tmp1);  // vector from a to b
00195     vec_copy(unitdirvec, dirvec);
00196     vec_normalize(unitdirvec);    // unit vector from a to b
00197     test = 1;
00198     i = 0;
00199     while (test == 1) {
00200       for (j=0; j<3; j++) {
00201         from[j] = (float) (tmp1[j] + (2*i)*DASH_LENGTH*unitdirvec[j]);
00202         to[j] =   (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00203       }
00204       if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00205         vec_copy(to, tmp2);
00206         test = 0;
00207       }
00208 
00209 //      write_materials();
00210 
00211       // Draw the line
00212       fprintf(outfile, "VMD_line(<%.4f,%.4f,%.4f>,<%.4f,%.4f,%.4f>,",
00213               from[0], from[1], -from[2], to[0], to[1], -to[2]);
00214       fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00215         matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00216         1 - mat_opacity);
00217 
00218       i++;
00219     }
00220   } 
00221   else {
00222     msgErr << "POV3DisplayDevice: Unknown line style " << lineStyle << sendmsg;
00223   }
00224 }
00225 
00226 
00227 // draw a cylinder
00228 void POV3DisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00229   float from[3], to[3];
00230   float radius;
00231 
00232   // transform the world coordinates
00233   (transMat.top()).multpoint3d(a, from);
00234   (transMat.top()).multpoint3d(b, to);
00235   radius = scale_radius(r);
00236 
00237   // check for degenerate cylinders
00238   if ( ((from[0]-to[0])*(from[0]-to[0]) +
00239         (from[1]-to[1])*(from[1]-to[1]) +
00240         (from[2]-to[2])*(from[2]-to[2])) < 1e-20 ) {
00241     degenerate_cylinders++;
00242     return;
00243   }
00244 
00245 //  write_materials();
00246    
00247   fprintf(outfile, "VMD_cylinder(<%g,%g,%g>,<%g,%g,%g>",
00248           from[0], from[1], -from[2], to[0], to[1], -to[2]);
00249   fprintf(outfile, "%.4f,rgbt<%.3f,%.3f,%.3f,%.3f>,%d)\n",
00250           radius, matData[colorIndex][0], matData[colorIndex][1],
00251           matData[colorIndex][2], 1 - mat_opacity, !filled);
00252 }
00253 
00254 // draw a cone
00255 void POV3DisplayDevice::cone(float *a, float *b, float r) {
00256   float from[3], to[3];
00257   float radius;
00258   
00259   // transform the world coordinates
00260   (transMat.top()).multpoint3d(a, from);
00261   (transMat.top()).multpoint3d(b, to);
00262   radius = scale_radius(r);
00263 
00264   // check for degenerate cylinders
00265   if ( ((from[0]-to[0])*(from[0]-to[0]) +
00266         (from[1]-to[1])*(from[1]-to[1]) +
00267         (from[2]-to[2])*(from[2]-to[2])) < 1e-20 ) {
00268     degenerate_cones++;
00269     return;
00270   }
00271 
00272 //  write_materials();
00273 
00274   // Draw the cone
00275   fprintf(outfile, "VMD_cone (<%g,%g,%g>,<%g,%g,%g>,%.4f,",
00276           from[0], from[1], -from[2], to[0], to[1], -to[2], radius);
00277   fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00278           matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
00279           1 - mat_opacity);
00280 }
00281 
00282 // draw a triangle using the current color
00283 // XXX - POV-Ray doesn't support indexed color for triangles -- we need to
00284 // use an RGB triple. Here we just use the same RGB triple for each vertex
00285 // and call tricolor.
00286 void POV3DisplayDevice::triangle(const float *a, const float *b, const float *c, 
00287                                  const float *n1, const float *n2, const float *n3) {
00288   float c1[3], c2[3], c3[3];
00289 
00290   memcpy(c1, matData[colorIndex], 3 * sizeof(float));
00291   memcpy(c2, matData[colorIndex], 3 * sizeof(float));
00292   memcpy(c3, matData[colorIndex], 3 * sizeof(float));
00293 
00294   tricolor(a, b, c, n1, n2, n3, c1, c2, c3);
00295   return;
00296 }
00297 
00298 // draw triangle with per-vertex colors
00299 void POV3DisplayDevice::tricolor(const float * xyz1, const float * xyz2, const float * xyz3,
00300                                  const float * n1,   const float * n2,   const float * n3,
00301                                  const float *c1, const float *c2, const float *c3) {
00302   float vec1[3], vec2[3], vec3[3], norm1[3], norm2[3], norm3[3];
00303   float leg1[3], leg2[3], trinorm[3], ang1, ang2, ang3;
00304 
00305   // transform the world coordinates
00306   (transMat.top()).multpoint3d(xyz1, vec1);
00307   (transMat.top()).multpoint3d(xyz2, vec2);
00308   (transMat.top()).multpoint3d(xyz3, vec3);
00309 
00310   // and the normals
00311   (transMat.top()).multnorm3d(n1, norm1);
00312   (transMat.top()).multnorm3d(n2, norm2);
00313   (transMat.top()).multnorm3d(n3, norm3);
00314 
00315 //  write_materials();
00316 
00317   // Don't write degenerate triangles -- those with all normals more than 90
00318   // degrees from triangle normal or its inverse.
00319   vec_sub(leg1, vec2, vec1);
00320   vec_sub(leg2, vec3, vec1);
00321   cross_prod(trinorm, leg1, leg2);
00322   ang1 = dot_prod(trinorm, norm1);
00323   ang2 = dot_prod(trinorm, norm2);
00324   ang3 = dot_prod(trinorm, norm3);
00325   if ( ((ang1 >= 0.0) || (ang2 >= 0.0) || (ang3 >= 0.0)) &&
00326        ((ang1 <= 0.0) || (ang2 <= 0.0) || (ang3 <= 0.0)) ) {
00327     degenerate_triangles++;
00328     return;
00329   }
00330 
00331   // If all verticies have the same color, don't bother with per-vertex
00332   // coloring
00333   if ( (c1[0] == c2[0]) && (c1[0] == c3[0]) &&
00334        (c1[1] == c2[1]) && (c1[1] == c3[1]) &&
00335        (c1[2] == c2[2]) && (c1[2] == c3[2]) ) {
00336     fprintf(outfile, "VMD_triangle(");
00337     fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00338         vec1[0], vec1[1], -vec1[2], vec2[0], vec2[1], -vec2[2], 
00339         vec3[0], vec3[1], -vec3[2]);
00340     fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00341         norm1[0], norm1[1], -norm1[2], norm2[0], norm2[1], -norm2[2], 
00342         norm3[0], norm3[1], -norm3[2]);
00343     fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00344         c1[0], c1[1], c1[2], 1 - mat_opacity);
00345   }
00346   else {
00347     fprintf(outfile, "VMD_tricolor(");
00348     fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00349         vec1[0], vec1[1], -vec1[2], vec2[0], vec2[1], -vec2[2], 
00350         vec3[0], vec3[1], -vec3[2]);
00351     fprintf(outfile, "<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,<%.8g,%.8g,%.8g>,",
00352         norm1[0], norm1[1], -norm1[2], norm2[0], norm2[1], -norm2[2], 
00353         norm3[0], norm3[1], -norm3[2]);
00354     fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>,rgbt<%.3f,%.3f,%.3f,%.3f>,rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
00355         c1[0], c1[1], c1[2], 1 - mat_opacity, c2[0], c2[1], c2[2], 
00356         1 - mat_opacity, c3[0], c3[1], c3[2], 1 - mat_opacity);
00357   }
00358 }
00359 
00360 // Draw a triangle mesh as a mesh2 POV-Ray object
00361 void POV3DisplayDevice::trimesh_c4n3v3(int numverts, float *cnv, 
00362                                        int numfacets, int *facets) {
00363   float (*vert)[3], (*norm)[3], (*color)[3], prev_color[3];
00364   int i, ind, v0, v1, v2, *c_index, curr_index;
00365  
00366 //  write_materials();
00367 
00368   if (clip_on[2]) {
00369     fprintf(outfile, "intersection {\n");
00370   }
00371   fprintf(outfile, "mesh2 {\n");
00372 
00373   // Read the mesh, storing vertex coordinates, normals, and (unique) colors
00374   // XXX - this can use a *lot* of memory, but not as much as POV will when
00375   // parsing the resulting scene file.
00376   vert = new float[numfacets * 3][3];
00377   norm = new float[numfacets * 3][3];
00378   color = new float[numfacets * 3][3];
00379   c_index = new int[numfacets * 3];
00380   curr_index = -1;
00381   prev_color[0] = -1;
00382   prev_color[1] = -1;
00383   prev_color[2] = -1;
00384 
00385   for (i = 0; i < numfacets; i++) {
00386     ind = i * 3;
00387     v0 = facets[ind    ] * 10;
00388     v1 = facets[ind + 1] * 10;
00389     v2 = facets[ind + 2] * 10;
00390 
00391     // transform the verticies and store them in the array
00392     transMat.top().multpoint3d(cnv + v0 + 7, vert[ind    ]);
00393     transMat.top().multpoint3d(cnv + v1 + 7, vert[ind + 1]);
00394     transMat.top().multpoint3d(cnv + v2 + 7, vert[ind + 2]);
00395 
00396     // transform the normals and store them in the array
00397     transMat.top().multnorm3d(cnv + v0 + 4, norm[ind    ]);
00398     transMat.top().multnorm3d(cnv + v1 + 4, norm[ind + 1]);
00399     transMat.top().multnorm3d(cnv + v2 + 4, norm[ind + 2]);
00400 
00401 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00402     vert[ind    ][0] *= POVRAY_SCALEHACK;
00403     vert[ind    ][1] *= POVRAY_SCALEHACK;
00404     vert[ind    ][2] *= POVRAY_SCALEHACK;
00405     vert[ind + 1][0] *= POVRAY_SCALEHACK;
00406     vert[ind + 1][1] *= POVRAY_SCALEHACK;
00407     vert[ind + 1][2] *= POVRAY_SCALEHACK;
00408     vert[ind + 2][0] *= POVRAY_SCALEHACK;
00409     vert[ind + 2][1] *= POVRAY_SCALEHACK;
00410     vert[ind + 2][2] *= POVRAY_SCALEHACK;
00411 #endif
00412 
00413     // XXX - Only store a color if it's different than the previous color.
00414     // While this is pretty lame in theory, it will save a lot of space for
00415     // the surf and isosurface reps, which are currently the only reps that
00416     // use triangle meshes
00417     if (memcmp(prev_color, (cnv + v0), 3*sizeof(float)) != 0) {
00418       curr_index++;
00419       memcpy(color[curr_index], (cnv + v0), 3*sizeof(float));
00420       memcpy(prev_color, (cnv + v0), 3*sizeof(float));
00421     }
00422     c_index[ind] = curr_index;
00423 
00424     if (memcmp(prev_color, (cnv + v1), 3*sizeof(float)) != 0) {
00425       curr_index++;
00426       memcpy(color[curr_index], (cnv + v1), 3*sizeof(float));
00427       memcpy(prev_color, (cnv + v1), 3*sizeof(float));
00428     }
00429     c_index[ind+1] = curr_index;
00430 
00431     if (memcmp(prev_color, (cnv + v2), 3*sizeof(float)) != 0) {
00432       curr_index++;
00433       memcpy(color[curr_index], (cnv + v2), 3*sizeof(float));
00434       memcpy(prev_color, (cnv + v2), 3*sizeof(float));
00435     }
00436     c_index[ind+2] = curr_index;
00437   }
00438 
00439   // Print the Vertex Vectors
00440   fprintf(outfile, "  vertex_vectors {\n");
00441   fprintf(outfile, "  %d,\n", numfacets * 3);
00442   for (i = 0; i < (numfacets * 3); i++) {
00443     fprintf(outfile, "  <%.4f,%.4f,%.4f>,\n", 
00444             vert[i][0], vert[i][1], -vert[i][2]);
00445   }
00446   fprintf(outfile, "  }\n");
00447 
00448   // Print the Normal Vectors
00449   fprintf(outfile, "  normal_vectors {\n");
00450   fprintf(outfile, "  %d,\n", numfacets * 3);
00451   for (i = 0; i < (numfacets * 3); i++) {
00452     fprintf(outfile, "  <%.4f,%.4f,%.4f>,\n", 
00453             norm[i][0], norm[i][1], -norm[i][2]);
00454   }
00455   fprintf(outfile, "  }\n");
00456 
00457   // Print the Texture List
00458   fprintf(outfile, "  texture_list {\n");
00459   fprintf(outfile, "  %d,\n", curr_index+1);
00460   for (i = 0; i <= curr_index; i++) {
00461     fprintf(outfile, "  VMDC(<%.3f,%.3f,%.3f,%.3f>)\n", 
00462             color[i][0], color[i][1], color[i][2], 1 - mat_opacity);
00463   }
00464   fprintf(outfile, "  }\n");
00465 
00466   // Face Indices
00467   fprintf(outfile, "  face_indices {\n");
00468   fprintf(outfile, "  %d\n", numfacets);
00469   for (i = 0; i < numfacets; i++) {
00470     ind = i * 3;
00471 
00472     // Print three vertex/normal and color indicies.
00473     if ((c_index[ind] == c_index[ind+1]) && (c_index[ind] == c_index[ind+2])) {
00474       // Only one color index is required if the triangle doesn't use
00475       // per-vertex shading
00476       fprintf(outfile, "  <%d,%d,%d>,%d\n",
00477               ind, ind + 1, ind + 2, c_index[ind]);
00478     }
00479     else {
00480       fprintf(outfile, "  <%d,%d,%d>,%d,%d,%d\n",
00481               ind, ind + 1, ind + 2, 
00482               c_index[ind], c_index[ind+1], c_index[ind+2]);
00483     }
00484   }
00485   fprintf(outfile, "  }\n");
00486 
00487   // Object Modifiers
00488   fprintf(outfile, "  inside_vector <0, 0, 1>\n");
00489   if (clip_on[1]) {
00490 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00491     fprintf(outfile, "  clipped_by { VMD_scaledclip[1] }\n");
00492 #else
00493     fprintf(outfile, "  clipped_by { VMD_clip[1] }\n");
00494 #endif
00495   }
00496   if (!shadows_enabled())
00497     fprintf(outfile, "  no_shadow\n");
00498 
00499 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00500   Matrix4 hackmatrix;
00501   hackmatrix.identity();
00502   hackmatrix.scale(1.0f / POVRAY_SCALEHACK);
00503   const float *trans = hackmatrix.mat;
00504   fprintf(outfile, "matrix < \n");
00505   fprintf(outfile, "  %f, %f, %f,\n", trans[ 0], trans[ 1], trans[ 2]);
00506   fprintf(outfile, "  %f, %f, %f,\n", trans[ 4], trans[ 5], trans[ 6]);
00507   fprintf(outfile, "  %f, %f, %f,\n", trans[ 8], trans[ 9], trans[10]);
00508   fprintf(outfile, "  %f, %f, %f \n", trans[12], trans[13], trans[14]);
00509   fprintf(outfile, "> ");
00510 #endif
00511 
00512   fprintf(outfile, "}\n");
00513 
00514   if (clip_on[2]) {
00515     fprintf(outfile, "  VMD_clip[2]\n");
00516     if (!shadows_enabled())
00517       fprintf(outfile, "  no_shadow\n");
00518     fprintf(outfile, "}\n");
00519   }
00520 
00521   delete [] vert;
00522   delete [] norm;
00523   delete [] color;
00524   delete [] c_index;
00525 }
00526 
00527 // Draw a collection of triangle strips as a mesh2 POV-Ray object
00528 void POV3DisplayDevice::tristrip(int numverts, const float *cnv, 
00529                         int numstrips, const int *vertsperstrip, 
00530                         const int *facets) {
00531   int strip, v, i, numfacets;
00532   float (*vert)[3], (*norm)[3], (*color)[3];
00533 
00534   // POV-Ray does use triangle winding-order to determine the orientation of
00535   // a triangle. Although the default triangle macro doesn't make use of
00536   // this, the interior_texture property can be specified to give
00537   // back-facing triangles a different texture.
00538   int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
00539 
00540 //  write_materials();
00541 
00542   if (clip_on[2]) {
00543     fprintf(outfile, "intersection {\n");
00544   }
00545   fprintf(outfile, "mesh2 {\n");
00546 
00547   // Read the mesh, storing vertex coordinates, normals, and colors
00548   // XXX - this can use a *lot* of memory, but not as much as POV will when
00549   // parsing the resulting scene file.
00550   vert = new float[numverts][3];
00551   norm = new float[numverts][3];
00552   color = new float[numverts][3];
00553 
00554   for (i = 0; i < numverts; i++) {
00555     transMat.top().multpoint3d(cnv + i*10 + 7, vert[i]);
00556     transMat.top().multnorm3d(cnv + i*10 + 4, norm[i]);
00557 
00558 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00559     vert[i][0] *= POVRAY_SCALEHACK;
00560     vert[i][1] *= POVRAY_SCALEHACK;
00561     vert[i][2] *= POVRAY_SCALEHACK;
00562 #endif
00563 
00564     memcpy(color[i], cnv + i*10, 3*sizeof(float));
00565   }
00566 
00567   // Print the Vertex Vectors
00568   fprintf(outfile, "  vertex_vectors {\n");
00569   fprintf(outfile, "  %d,\n", numverts);
00570   for (i = 0; i < numverts; i++) {
00571     fprintf(outfile, "  <%.4f,%.4f,%.4f>,\n", 
00572             vert[i][0], vert[i][1], -vert[i][2]);
00573   }
00574   fprintf(outfile, "  }\n");
00575 
00576   // Print the Normal Vectors
00577   fprintf(outfile, "  normal_vectors {\n");
00578   fprintf(outfile, "  %d,\n", numverts);
00579   for (i = 0; i < numverts; i++) {
00580     fprintf(outfile, "  <%.4f,%.4f,%.4f>,\n", 
00581             norm[i][0], norm[i][1], -norm[i][2]);
00582   }
00583   fprintf(outfile, "  }\n");
00584 
00585   // Print the Texture List
00586   fprintf(outfile, "  texture_list {\n");
00587   fprintf(outfile, "  %d,\n", numverts);
00588   for (i = 0; i < numverts; i++) {
00589     fprintf(outfile, "  VMDC(<%.3f,%.3f,%.3f,%.3f>)\n", 
00590             color[i][0], color[i][1], color[i][2], 1 - mat_opacity);
00591   }
00592   fprintf(outfile, "  }\n");
00593 
00594   // Find the number of facets
00595   numfacets = 0;
00596   for (strip = 0; strip < numstrips; strip++) {
00597     numfacets += (vertsperstrip[strip] - 2);
00598   }
00599 
00600   // Print the Face Indices
00601   v = 0;
00602   fprintf(outfile, "  face_indices {\n");
00603   fprintf(outfile, "  %d\n", numfacets);
00604   for (strip = 0; strip < numstrips; strip++) {
00605     for (i = 0; i < (vertsperstrip[strip] - 2); i++) {
00606       fprintf(outfile, "  <%d,%d,%d>,%d,%d,%d\n",
00607               facets[v + (stripaddr[i & 0x01][0])],
00608               facets[v + (stripaddr[i & 0x01][1])],
00609               facets[v + (stripaddr[i & 0x01][2])],
00610               facets[v + (stripaddr[i & 0x01][0])],
00611               facets[v + (stripaddr[i & 0x01][1])],
00612               facets[v + (stripaddr[i & 0x01][2])] );
00613       v++;
00614     }
00615     v += 2;
00616   }
00617   fprintf(outfile, "  }\n");
00618 
00619   // Object Modifiers
00620   fprintf(outfile, "  inside_vector <0, 0, 1>\n");
00621   if (clip_on[1]) {
00622 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00623     fprintf(outfile, "  clipped_by { VMD_scaledclip[1] }\n");
00624 #else
00625     fprintf(outfile, "  clipped_by { VMD_clip[1] }\n");
00626 #endif
00627   }
00628 
00629 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
00630   Matrix4 hackmatrix;
00631   hackmatrix.identity();
00632   hackmatrix.scale(1.0f / POVRAY_SCALEHACK);
00633   const float *trans = hackmatrix.mat;
00634   fprintf(outfile, "matrix < \n");
00635   fprintf(outfile, "  %f, %f, %f,\n", trans[ 0], trans[ 1], trans[ 2]);
00636   fprintf(outfile, "  %f, %f, %f,\n", trans[ 4], trans[ 5], trans[ 6]);
00637   fprintf(outfile, "  %f, %f, %f,\n", trans[ 8], trans[ 9], trans[10]);
00638   fprintf(outfile, "  %f, %f, %f \n", trans[12], trans[13], trans[14]);
00639   fprintf(outfile, "> ");
00640 #endif
00641 
00642   if (!shadows_enabled())
00643     fprintf(outfile, "  no_shadow\n");
00644   fprintf(outfile, "}\n");
00645 
00646   if (clip_on[2]) {
00647     fprintf(outfile, "  VMD_clip[2]\n");
00648     if (!shadows_enabled())
00649       fprintf(outfile, "  no_shadow\n");
00650     fprintf(outfile, "}\n");
00651   }
00652 
00653   delete [] vert;
00654   delete [] norm;
00655   delete [] color;
00656 }
00657 
00658 // display a comment
00659 void POV3DisplayDevice::comment(const char *s) {
00660   fprintf (outfile, "// %s\n", s);
00661 }
00662 
00664 
00665 void POV3DisplayDevice::write_header() {
00666   long myXsize;
00667   float zDirection;
00668 
00669   // cross-eyes and side-by-side stereo split the screen; so we need
00670   // to cut xSize in half in this case
00671   myXsize = xSize;
00672   //if (inStereo == OPENGL_STEREO_SIDE)
00673   //   myXsize /= 2;
00674   // if (inStereo == OPENGL_STEREO_ABOVEBELOW) 
00675   //   myXsize *= 2;
00676   fprintf(outfile, "// \n");
00677   fprintf(outfile, "// Molecular graphics export from VMD %s\n", VMDVERSION);
00678   fprintf(outfile, "// http://www.ks.uiuc.edu/Research/vmd/\n");
00679   fprintf(outfile, "// Requires POV-Ray 3.5 or later\n");
00680   fprintf(outfile, "// \n");
00681 
00682   fprintf(outfile, "// POV 3.x input script : %s \n", my_filename);
00683   fprintf(outfile, "// try povray +W%ld +H%ld -I%s ", myXsize, ySize, my_filename);
00684   fprintf(outfile, "-O%s.tga +P +X +A +FT +C", my_filename);
00685 
00686   // need to disable the vista buffer when stereo rendering
00687   if (whichEye != DisplayDevice::NOSTEREO) fprintf(outfile, " -UV");
00688   fprintf(outfile, "\n");
00689 
00690 #if 0
00691   msgInfo << "Default povray command line should be:" << sendmsg;
00692 
00693   msgInfo << "  povray +W" << myXsize << " +H" << ySize << " -I" << my_filename
00694           << " -O" << my_filename << ".tga +P +X +A +FT +C";
00695   if (whichEye != DisplayDevice::NOSTEREO) msgInfo << " -UV";
00696   msgInfo << sendmsg;
00697 #endif
00698 
00699   // Warn the user if the plugin was compiled for a different version of POV
00700   // than they're using
00701   fprintf(outfile, "#if (version < 3.5) \n");
00702   fprintf(outfile, "#error \"VMD POV3DisplayDevice has been compiled for POV-Ray 3.5 or above.\\nPlease upgrade POV-Ray or recompile VMD.\"\n");
00703   fprintf(outfile, "#end \n");
00704 
00705   // Initialize POV-Ray state variables
00706   fprintf(outfile, "#declare VMD_clip_on=array[3] {0, 0, 0};\n");
00707   fprintf(outfile, "#declare VMD_clip=array[3];\n");
00708   fprintf(outfile, "#declare VMD_scaledclip=array[3];\n");
00709   fprintf(outfile, "#declare VMD_line_width=%.4f;\n", 
00710           ((float)lineWidth)*DEFAULT_RADIUS);
00711 
00712   //
00713   // Macros for VMD-like graphic primitives in POV.
00714   //
00715  
00716   // Color/Texture: save space when emitting texture lines for mesh2 primitives
00717   fprintf(outfile, "#macro VMDC ( C1 )\n");
00718   fprintf(outfile, "  texture { pigment { rgbt C1 }}\n");
00719   fprintf(outfile, "#end\n");
00720 
00721   // Point: can be quickly approximated as spheres with no shading.
00722   fprintf(outfile, "#macro VMD_point (P1, R1, C1)\n");
00723   fprintf(outfile, "  #local T = texture { finish { ambient 1.0 diffuse 0.0 phong 0.0 specular 0.0 } pigment { C1 } }\n");
00724   fprintf(outfile, "  #if(VMD_clip_on[2])\n");
00725   fprintf(outfile, "  intersection {\n");
00726   fprintf(outfile, "    sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00727   fprintf(outfile, "    VMD_clip[2]\n");
00728   fprintf(outfile, "  }\n  #else\n");
00729   fprintf(outfile, "  sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00730   fprintf(outfile, "  #end\n");
00731   fprintf(outfile, "#end\n");
00732 
00733   // Line: can be quickly approximated as cylinders with no shading
00734   fprintf(outfile, "#macro VMD_line (P1, P2, C1)\n");
00735   fprintf(outfile, "  #local T = texture { finish { ambient 1.0 diffuse 0.0 phong 0.0 specular 0.0 } pigment { C1 } }\n");
00736   fprintf(outfile, "  #if(VMD_clip_on[2])\n");
00737   fprintf(outfile, "  intersection {\n");
00738   fprintf(outfile, "    cylinder {P1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00739   fprintf(outfile, "    VMD_clip[2]\n");
00740   fprintf(outfile, "  }\n  #else\n");
00741   fprintf(outfile, "  cylinder {P1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00742   fprintf(outfile, "  #end\n");
00743   fprintf(outfile, "#end\n");
00744 
00745   // Sphere
00746   fprintf(outfile, "#macro VMD_sphere (P1, R1, C1)\n");
00747   fprintf(outfile, "  #local T = texture { pigment { C1 } }\n");
00748   fprintf(outfile, "  #if(VMD_clip_on[2])\n");
00749   fprintf(outfile, "  intersection {\n");
00750   fprintf(outfile, "    sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00751   fprintf(outfile, "    VMD_clip[2]\n");
00752   fprintf(outfile, "  }\n  #else\n");
00753   fprintf(outfile, "  sphere {P1, R1 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00754   fprintf(outfile, "  #end\n");
00755   fprintf(outfile, "#end\n");
00756 
00757   // Cylinder: open iff O1 == 1
00758   fprintf(outfile, "#macro VMD_cylinder (P1, P2, R1, C1, O1)\n");
00759   fprintf(outfile, "  #local T = texture { pigment { C1 } }\n");
00760   fprintf(outfile, "  #if(VMD_clip_on[2])\n");
00761   fprintf(outfile, "  intersection {\n");
00762   fprintf(outfile, "    cylinder {P1, P2, R1 #if(O1) open #end texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00763   fprintf(outfile, "    VMD_clip[2]\n");
00764   fprintf(outfile, "  }\n  #else\n");
00765   fprintf(outfile, "  cylinder {P1, P2, R1 #if(O1) open #end texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00766   fprintf(outfile, "  #end\n");
00767   fprintf(outfile, "#end\n");
00768 
00769   // Cone: use the current lineWidth for the cap radius
00770   fprintf(outfile, "#macro VMD_cone (P1, P2, R1, C1)\n");
00771   fprintf(outfile, "  #local T = texture { pigment { C1 } }\n");
00772   fprintf(outfile, "  #if(VMD_clip_on[2])\n");
00773   fprintf(outfile, "  intersection {\n");
00774   fprintf(outfile, "    cone {P1, R1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00775   fprintf(outfile, "    VMD_clip[2]\n");
00776   fprintf(outfile, "  }\n  #else\n");
00777   fprintf(outfile, "  cone {P1, R1, P2, VMD_line_width texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00778   fprintf(outfile, "  #end\n");
00779   fprintf(outfile, "#end\n");
00780 
00781   // Triangle: single color, vertex normals
00782   // XXX - don't CSG clip triangles, behavior is undefined
00783   fprintf(outfile, "#macro VMD_triangle (P1, P2, P3, N1, N2, N3, C1)\n");
00784   fprintf(outfile, "  #local T = texture { pigment { C1 } }\n");
00785   fprintf(outfile, "  smooth_triangle {P1, N1, P2, N2, P3, N3 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00786   fprintf(outfile, "#end\n");
00787 
00788   // Tricolor: vertex colors and normals
00789   // XXX - don't CSG clip triangles, behavior is undefined
00790   fprintf(outfile, "#macro VMD_tricolor (P1, P2, P3, N1, N2, N3, C1, C2, C3)\n");
00791   fprintf(outfile, "  #local NX = P2-P1;\n");
00792   fprintf(outfile, "  #local NY = P3-P1;\n");
00793   fprintf(outfile, "  #local NZ = vcross(NX, NY);\n");
00794   fprintf(outfile, "  #local T = texture { pigment {\n");
00795 
00796   // Create a color cube with the vertex colors at three corners
00797   fprintf(outfile, "    average pigment_map {\n");
00798   fprintf(outfile, "      [1 gradient x color_map {[0 rgb 0] [1 C2*3]}]\n");
00799   fprintf(outfile, "      [1 gradient y color_map {[0 rgb 0] [1 C3*3]}]\n");
00800   fprintf(outfile, "      [1 gradient z color_map {[0 rgb 0] [1 C1*3]}]\n");
00801   fprintf(outfile, "    }\n");
00802 
00803   // Transform the cube so those corners match the triangle vertices
00804   fprintf(outfile, "    matrix <1.01,0,1,0,1.01,1,0,0,1,-.002,-.002,-1>\n");
00805   fprintf(outfile, "    matrix <NX.x,NX.y,NX.z,NY.x,NY.y,NY.z,NZ.x,NZ.y,NZ.z,P1.x,P1.y,P1.z>\n");
00806   fprintf(outfile, "  } }\n");
00807 
00808   fprintf(outfile, "  smooth_triangle {P1, N1, P2, N2, P3, N3 texture {T} #if(VMD_clip_on[1]) clipped_by {VMD_clip[1]} #end %s}\n", (shadows_enabled()) ? "" : "no_shadow");
00809   fprintf(outfile, "#end\n");
00810 
00811 
00812   // Camera position
00813   // POV uses a left-handed coordinate system 
00814   // VMD uses right-handed, so z(pov) = -z(vmd).
00815 
00816   switch (projection()) {
00817 
00818     case DisplayDevice::ORTHOGRAPHIC:
00819 
00820       fprintf(outfile, "camera {\n");
00821       fprintf(outfile, "  orthographic\n");
00822       fprintf(outfile, "  location <%.4f, %.4f, %.4f>\n",
00823               eyePos[0], eyePos[1], -eyePos[2]);
00824       fprintf(outfile, "  look_at <%.4f, %.4f, %.4f>\n",
00825               eyeDir[0], eyeDir[1], -eyeDir[2]);
00826       fprintf(outfile, "  up <0.0000, %.4f, 0.0000>\n", vSize / 2.0f);
00827       fprintf(outfile, "  right <%.4f, 0.0000, 0.0000>\n", Aspect * vSize / 2.0f);
00828       fprintf(outfile, "}\n");
00829 
00830       break;
00831 
00832     case DisplayDevice::PERSPECTIVE:
00833     default:
00834 
00835       if (whichEye != DisplayDevice::NOSTEREO) {
00836          if (whichEye == DisplayDevice::LEFTEYE)
00837             fprintf(outfile, "// Stereo rendering enabled. Now rendering left eye.\n");
00838          else
00839             fprintf(outfile, "// Stereo rendering enabled. Now rendering right eye.\n");
00840 
00841          fprintf(outfile, "// POV-Ray may give you a warning about non-perpendicular\n");
00842          fprintf(outfile, "// camera vectors; this is a result of the stereo rendering.\n");
00843          fprintf(outfile, "#warning \"You may ignore the following warning about "
00844                           "nonperpendicular camera vectors.\"\n");
00845       }
00846 
00847       fprintf(outfile, "camera {\n");
00848       fprintf(outfile, "  up <0, %.4f, 0>\n", vSize);
00849       fprintf(outfile, "  right <%.4f, 0, 0>\n", Aspect * vSize);
00850       fprintf(outfile, "  location <%.4f, %.4f, %.4f>\n",
00851               eyePos[0], eyePos[1], -eyePos[2]);
00852       fprintf(outfile, "  look_at <%.4f, %.4f, %.4f>\n",
00853               eyePos[0] + eyeDir[0],
00854               eyePos[1] + eyeDir[1],
00855               -(eyePos[2] + eyeDir[2]));
00856 
00857       // POV-Ray doesn't handle negative directions (i.e. when the image
00858       // plane is behind the viewpoint) well: the image should be mirrored
00859       // about both the x and y axes. We simulate this case by using a sky
00860       // vector.
00861       zDirection = eyePos[2] - zDist;
00862       if (zDirection < 0) {
00863         fprintf(outfile, "  direction <%.4f, %.4f, %.4f>\n",
00864                 -eyePos[0], -eyePos[1], -zDirection);
00865         fprintf(outfile, "  sky <0, -1, 0>\n");
00866       }
00867       else {
00868         fprintf(outfile, "  direction <%.4f, %.4f, %.4f>\n",
00869                 -eyePos[0], -eyePos[1], zDirection);
00870       }
00871 
00872       fprintf(outfile, "}\n");
00873 
00874       break;
00875 
00876   } // switch (projection())
00877         
00878   // Lights
00879   int i;
00880   for (i=0;i<DISP_LIGHTS;i++) {
00881     if (lightState[i].on) {
00882       // directional light source, as implemented in povray 3.5
00883       fprintf(outfile, "light_source { \n  <%.4f, %.4f, %.4f> \n",
00884               lightState[i].pos[0], lightState[i].pos[1],
00885               -lightState[i].pos[2]);
00886       fprintf(outfile, "  color rgb<%.3f, %.3f, %.3f> \n",
00887               lightState[i].color[0], lightState[i].color[1],
00888               lightState[i].color[2]);
00889       fprintf(outfile, "  parallel \n  point_at <0.0, 0.0, 0.0> \n}\n");
00890     }
00891   }
00892        
00893 
00894   // background color
00895   fprintf(outfile, "background {\n  color rgb<%.3f, %.3f, %.3f>\n}\n", 
00896           backColor[0], backColor[1], backColor[2]);
00897 
00898   // Specify background sky sphere if background gradient mode is enabled.
00899   if (backgroundmode == 1) {
00900     fprintf(outfile, "\n");
00901     fprintf(outfile, "sky_sphere {\n");
00902     fprintf(outfile, "  pigment {\n");
00903     fprintf(outfile, "    gradient y\n");
00904     fprintf(outfile, "    color_map {\n");
00905     fprintf(outfile, "      [ 0.0  color rgb<%.3f, %.3f, %.3f> ]\n",
00906             backgradientbotcolor[0], backgradientbotcolor[1], backgradientbotcolor[2]);
00907     fprintf(outfile, "      [ 1.0  color rgb<%.3f, %.3f, %.3f> ]\n",
00908             backgradienttopcolor[0], backgradienttopcolor[1], backgradienttopcolor[2]);
00909     fprintf(outfile, "    }\n");
00910     fprintf(outfile, "    scale 2\n");
00911     fprintf(outfile, "    translate -1\n");
00912     fprintf(outfile, "  }\n");
00913     fprintf(outfile, "}\n");
00914     fprintf(outfile, "\n");
00915   }
00916 
00917   // depth-cueing (fog)
00918   if (cueingEnabled && (get_cue_density() >= 1e-4)) {
00919     fprintf(outfile, "fog {\n");
00920 
00921     switch (cueMode) {
00922       case CUE_EXP2:
00923       case CUE_LINEAR:
00924       case CUE_EXP:
00925         // XXX We use povray's exponential fog for all cases 
00926         // since it doesn't currently support any other fog types yet.
00927         fprintf(outfile, "  distance %.4f \n", 
00928                 (get_cue_density() >= 1e4) ? 1e-4 : 1.0/get_cue_density() );
00929         fprintf(outfile, "  fog_type 1 \n");
00930       break;
00931 
00932       case NUM_CUE_MODES:
00933         // this should never happen
00934         break;
00935     }
00936 
00937     // for depth-cueing, the fog color is the background color
00938     fprintf(outfile, "  color rgb<%.3f, %.3f, %.3f> \n",
00939             backColor[0], backColor[1], backColor[2] );
00940     fprintf(outfile, "} \n");
00941   }
00942 }
00943 
00944 void POV3DisplayDevice::write_trailer(void){
00945   fprintf(outfile, "// End of POV-Ray 3.x generation \n");
00946 
00947   if (degenerate_cones != 0) {
00948     msgWarn << "Skipped " << degenerate_cones 
00949             << " degenerate cones" << sendmsg;
00950   }
00951   if (degenerate_cylinders != 0) {
00952     msgWarn << "Skipped " << degenerate_cylinders 
00953             << " degenerate cylinders" << sendmsg;
00954   }
00955   if (degenerate_triangles != 0) {
00956     msgWarn << "Skipped " << degenerate_triangles 
00957             << " degenerate triangles" << sendmsg;
00958   }
00959 
00960   reset_vars(); // Reset variables before the next rendering.
00961 }
00962     
00963 
00964 void POV3DisplayDevice::write_materials(void) {
00965   if (old_materialIndex != materialIndex) {
00966 
00967     old_materialIndex = materialIndex;
00968 
00969     fprintf(outfile, "#default { texture {\n");
00970     fprintf(outfile, " finish { ambient %.3f diffuse %.3f",
00971       mat_ambient, mat_diffuse);
00972     fprintf(outfile, " phong 0.1 phong_size %.3f specular %.3f }\n",
00973       mat_shininess, mat_specular);
00974     fprintf(outfile, "} }\n");
00975   }
00976 }
00977 
00978 
00979 void POV3DisplayDevice::start_clipgroup(void) {
00980   int i, num_clipplanes[3], mode;
00981   float pov_clip_center[3], pov_clip_distance[VMD_MAX_CLIP_PLANE];
00982   float pov_clip_normal[VMD_MAX_CLIP_PLANE][3];
00983 
00984   write_materials();
00985 
00986   memset(num_clipplanes, 0, 3*sizeof(int));
00987   for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
00988     if (clip_mode[i] != 0) {
00989       // Count the number of clipping planes for each clip mode
00990       num_clipplanes[clip_mode[i]]++;
00991 
00992       // Translate the plane center
00993       (transMat.top()).multpoint3d(clip_center[i], pov_clip_center);
00994 
00995       // and the normal
00996       (transMat.top()).multnorm3d(clip_normal[i], pov_clip_normal[i]);
00997       vec_negate(pov_clip_normal[i], pov_clip_normal[i]);
00998 
00999       // POV-Ray uses the distance from the origin to the plane for its
01000       // representation, instead of the plane center
01001       pov_clip_distance[i] = dot_prod(pov_clip_normal[i], pov_clip_center);
01002     }
01003   }
01004 
01005   // Define the clip object for each clip mode
01006   for (mode = 1; mode < 3; mode++) {
01007     if (num_clipplanes[mode] > 0) {
01008       // This flag is used within VMD to determine if clipping information
01009       // should be written to the scene file
01010       clip_on[mode] = 1;
01011 
01012       // This flag is used within POV to determine if clipping should be done
01013       // within macros
01014       fprintf(outfile, "#declare VMD_clip_on[%d]=1;\n", mode);
01015 
01016       if (num_clipplanes[mode] == 1) {
01017         for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01018           if (clip_mode[i] == mode) {
01019             if (mode == 2) {
01020               // Textured plane for CSG clipping
01021               fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
01022                       mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
01023                       -pov_clip_normal[i][2], pov_clip_distance[i],
01024                       clip_color[i][0], clip_color[i][1], clip_color[i][2],
01025                       1 - mat_opacity);
01026             } else {
01027               // Non-textured plane for non-CSG clipping
01028               fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01029                       mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
01030                       -pov_clip_normal[i][2], pov_clip_distance[i]);
01031 
01032 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
01033               // Non-textured plane for non-CSG clipping, but scaled for use
01034               // when emitting meshes with the scaling hack.
01035               fprintf(outfile, "#declare VMD_scaledclip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01036                       mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], 
01037                       pov_clip_distance[i] * POVRAY_SCALEHACK);
01038 #endif
01039             }
01040           }
01041         }
01042       }
01043 
01044       // Declare the clipping object to be an intersection of planes
01045       else {
01046         fprintf(outfile, "#declare VMD_clip[%d] = intersection {\n", mode);
01047         for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01048           if (clip_mode[i] == mode) {
01049             if (mode == 2) {
01050               // Textured plane for CSG clipping
01051               fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
01052                       pov_clip_normal[i][0], pov_clip_normal[i][1], 
01053                       -pov_clip_normal[i][2], pov_clip_distance[i],
01054                       clip_color[i][0], clip_color[i][1], clip_color[i][2],
01055                       1 - mat_opacity);
01056             } else {
01057               // Non-textured plane for non-CSG clipping
01058               fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01059                     pov_clip_normal[i][0], pov_clip_normal[i][1], 
01060                     -pov_clip_normal[i][2], pov_clip_distance[i]);
01061             }
01062           }
01063         }
01064         fprintf(outfile, "}\n");
01065 
01066 #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
01067         fprintf(outfile, "#declare VMD_scaledclip[%d] = intersection {\n", mode);
01068         for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
01069           if (clip_mode[i] == mode) {
01070             if (mode == 2) {
01071               // Textured plane for CSG clipping
01072               fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
01073                       pov_clip_normal[i][0], pov_clip_normal[i][1], 
01074                       -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK,
01075                       clip_color[i][0], clip_color[i][1], clip_color[i][2],
01076                       1 - mat_opacity);
01077             } else {
01078               // Non-textured plane for non-CSG clipping
01079               fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f }\n",
01080                     pov_clip_normal[i][0], pov_clip_normal[i][1], 
01081                     -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK);
01082             }
01083           }
01084         }
01085         fprintf(outfile, "}\n");
01086 #endif
01087 
01088 
01089       }
01090 
01091     }
01092   }
01093 }
01094 
01095 void POV3DisplayDevice::end_clipgroup(void) {
01096   int i;
01097   for (i = 0; i < 3; i++) {
01098     if (clip_on[i]) {
01099       fprintf(outfile, "#declare VMD_clip_on[%d]=0;\n", i);
01100       clip_on[i] = 0;
01101     }
01102   }
01103 }
01104 
01105 void POV3DisplayDevice::set_line_width(int new_width) {
01106   // XXX - find out why lineWidth is getting set outside this function!
01107 //  if (lineWidth != new_width) {
01108   {
01109     lineWidth = new_width;
01110     fprintf(outfile, "#declare VMD_line_width=%.4f;\n", 
01111             ((float)new_width)*DEFAULT_RADIUS);
01112   }
01113 }
01114 

Generated on Mon May 21 01:51:13 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002