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

TachyonDisplayDevice.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: TachyonDisplayDevice.C,v $
00013 *      $Author: johns $        $Locker:  $               $State: Exp $
00014 *      $Revision: 1.119 $        $Date: 2012/03/13 19:46:02 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 *
00019 * FileRenderer type for the Tachyon Parallel / Multiprocessor Ray Tracer 
00020 *
00021 ***************************************************************************/
00022 
00023 #include <string.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include "TachyonDisplayDevice.h"
00028 #include "Matrix4.h"
00029 #include "DispCmds.h"
00030 #include "Inform.h"
00031 #include "utilities.h"
00032 #include "config.h"    // for VMDVERSION string
00033 #include "Hershey.h"   // needed for Hershey font rendering fctns
00034 
00035 #define DEFAULT_RADIUS 0.002f
00036 #define DASH_LENGTH 0.02f
00037 
00038 #if defined(_MSC_VER) || defined(WIN32)
00039 #define TACHYON_RUN_STRING " -aasamples 12 %s -format BMP -o %s.bmp"
00040 #else
00041 #define TACHYON_RUN_STRING " -aasamples 12 %s -format TARGA -o %s.tga"
00042 #endif
00043 
00044 static char tachyon_run_string[2048];
00045 
00046 static char * get_tachyon_run_string() {
00047   char *tbin;
00048   strcpy(tachyon_run_string, "tachyon");
00049   
00050   if ((tbin=getenv("TACHYON_BIN")) != NULL) {
00051     sprintf(tachyon_run_string, "\"%s\"", tbin);
00052   }
00053   strcat(tachyon_run_string, TACHYON_RUN_STRING);
00054  
00055   return tachyon_run_string;
00056 }
00057 
00058 void TachyonDisplayDevice::update_exec_cmd() {
00059   const char *tbin;
00060   if ((tbin = getenv("TACHYON_BIN")) == NULL)
00061     tbin = "tachyon";
00062 
00063   switch(curformat) {
00064     case 0:  // BMP
00065       sprintf(tachyon_run_string, 
00066         "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "BMP", "bmp");
00067       break;
00068 
00069     case 1: // PPM
00070       sprintf(tachyon_run_string, 
00071         "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "PPM", "ppm");
00072       break;
00073 
00074     case 2: // PPM48
00075       sprintf(tachyon_run_string, 
00076         "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "PPM48", "ppm");
00077       break;
00078 
00079     case 3: // PSD
00080       sprintf(tachyon_run_string, 
00081         "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "PSD48", "psd");
00082       break;
00083 
00084     case 4: // SGI RGB
00085       sprintf(tachyon_run_string, 
00086         "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "RGB", "rgb");
00087       break;
00088 
00089     case 5: // TARGA
00090     default:
00091       sprintf(tachyon_run_string, 
00092         "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "TARGA", "tga");
00093       break;
00094   }
00095   delete [] execCmd;
00096   execCmd = stringdup(tachyon_run_string);
00097 }
00098 
00100 
00101 // constructor ... initialize some variables
00102 
00103 TachyonDisplayDevice::TachyonDisplayDevice() : FileRenderer ("Tachyon", "Tachyon", "vmdscene.dat", get_tachyon_run_string()) { 
00104   // Add supported file formats
00105   formats.add_name("BMP", 0);
00106   formats.add_name("PPM", 0);
00107   formats.add_name("PPM48", 0);
00108   formats.add_name("PSD48", 0);
00109   formats.add_name("RGB", 0);
00110   formats.add_name("TGA", 0);
00111 
00112   // Set default aa level
00113   has_aa = TRUE;
00114   aasamples = 12;
00115   aosamples = 12;
00116 
00117   reset_vars();
00118 
00119   // Default image format depends on platform
00120 #if defined(_MSC_VER) || defined(WIN32)
00121   curformat = 0; // Windows BMP
00122 #else
00123   curformat = 5; // Targa
00124 #endif
00125 }
00126         
00127 // destructor
00128 TachyonDisplayDevice::~TachyonDisplayDevice(void) { }
00129 
00131 
00132 void TachyonDisplayDevice::reset_vars(void) {
00133   enablemirrorspecular = (getenv("VMDTACHYONMIRRORSPECULAR") != NULL);
00134   phongspecularthresh = 256.0f;
00135   if (getenv("VMDTACHYONPHONGSPECTHRESH")) {
00136     sscanf(getenv("VMDTACHYONPHONGSPECTHRESH"), "%f", &phongspecularthresh);
00137   }
00138   inclipgroup = 0; // not currently in a clipping group
00139   involtex = 0;    // volume texturing disabled
00140   voltexID = -1;   // invalid texture ID
00141   memset(xplaneeq, 0, sizeof(xplaneeq));
00142   memset(yplaneeq, 0, sizeof(xplaneeq));
00143   memset(zplaneeq, 0, sizeof(xplaneeq));
00144 }  
00145 
00146 
00147 // emit a comment line 
00148 void TachyonDisplayDevice::comment(const char *s) {
00149   fprintf(outfile, "# %s\n", s);
00150 }
00151 
00152 
00153 void TachyonDisplayDevice::text(float *pos, float size, float thickness, 
00154                                 const char *str) {
00155   float textpos[3];
00156   float textsize, textthickness;
00157   hersheyhandle hh;
00158 
00159   // transform the world coordinates
00160   (transMat.top()).multpoint3d(pos, textpos);
00161   textsize = size * 1.5f;
00162   textthickness = thickness*DEFAULT_RADIUS;
00163 
00164   while (*str != '\0') {
00165     float lm, rm, x, y, ox, oy;
00166     int draw, odraw;
00167     ox=oy=x=y=0.0f;
00168     draw=odraw=0;
00169 
00170     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00171     textpos[0] -= lm * textsize;
00172 
00173     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00174       float oldpt[3], newpt[3];
00175       if (draw) {
00176         newpt[0] = textpos[0] + textsize * x;
00177         newpt[1] = textpos[1] + textsize * y;
00178         newpt[2] = textpos[2];
00179 
00180         if (odraw) {
00181           // if we have both previous and next points, connect them...
00182           oldpt[0] = textpos[0] + textsize * ox;
00183           oldpt[1] = textpos[1] + textsize * oy;
00184           oldpt[2] = textpos[2];
00185 
00186           fprintf(outfile, "FCylinder\n"); // flat-ended cylinder
00187           fprintf(outfile, "  Base %g %g %g\n", oldpt[0], oldpt[1], -oldpt[2]); 
00188           fprintf(outfile, "  Apex %g %g %g\n", newpt[0], newpt[1], -newpt[2]);
00189           fprintf(outfile, "  Rad %g \n", textthickness);
00190           write_cindexmaterial(colorIndex, materialIndex);
00191 
00192           fprintf(outfile, "Sphere \n");  // sphere
00193           fprintf(outfile, "  Center %g %g %g \n", newpt[0], newpt[1], -newpt[2]);
00194           fprintf(outfile, "  Rad %g \n", textthickness); 
00195           write_cindexmaterial(colorIndex, materialIndex);
00196         } else {
00197           // ...otherwise, just draw the next point
00198           fprintf(outfile, "Sphere \n");  // sphere
00199           fprintf(outfile, "  Center %g %g %g \n", newpt[0], newpt[1], -newpt[2]);
00200           fprintf(outfile, "  Rad %g \n", textthickness); 
00201           write_cindexmaterial(colorIndex, materialIndex);
00202         }
00203       }
00204 
00205       ox=x;
00206       oy=y;
00207       odraw=draw;
00208     }
00209     textpos[0] += rm * textsize;
00210 
00211     str++;
00212   }
00213 }
00214 
00215 
00216 // draw a point
00217 void TachyonDisplayDevice::point(float * spdata) {
00218   float vec[3];
00219   // transform the world coordinates
00220   (transMat.top()).multpoint3d(spdata, vec);
00221 
00222   // draw a sphere to represent the point, since we can't really draw points
00223   fprintf(outfile, "Sphere \n");  // sphere
00224   fprintf(outfile, "  Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
00225   fprintf(outfile, "  Rad %g \n",     float(lineWidth)*DEFAULT_RADIUS); 
00226   write_cindexmaterial(colorIndex, materialIndex);
00227 }
00228 
00229 
00230 // draw a sphere
00231 void TachyonDisplayDevice::sphere(float * spdata) {
00232   float vec[3];
00233   float radius;
00234     
00235   // transform the world coordinates
00236   (transMat.top()).multpoint3d(spdata, vec);
00237   radius = scale_radius(spdata[3]);
00238    
00239   // draw the sphere
00240   fprintf(outfile, "Sphere \n");  // sphere
00241   fprintf(outfile, "  Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
00242   fprintf(outfile, "  Rad %g \n", radius ); 
00243   write_cindexmaterial(colorIndex, materialIndex);
00244 }
00245 
00246 
00247 // draw a sphere array
00248 void TachyonDisplayDevice::sphere_array(int spnum, int spres, float *centers, float *radii, float *colors) {
00249   float vec[3];
00250   float radius;
00251   int i, ind;
00252 
00253   ind = 0;
00254   for (i=0; i<spnum; i++) {
00255     // transform the world coordinates
00256     (transMat.top()).multpoint3d(&centers[ind], vec);
00257     radius = scale_radius(radii[i]);
00258 
00259     // draw the sphere
00260     fprintf(outfile, "Sphere \n");  // sphere
00261     fprintf(outfile, "  Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
00262     fprintf(outfile, "  Rad %g \n", radius );
00263     write_colormaterial(&colors[ind], materialIndex);
00264     ind += 3; // next sphere
00265   }
00266 
00267   // set final color state after array has been drawn
00268   ind=(spnum-1)*3;
00269   super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00270 }
00271 
00272 
00273 // draw a line (cylinder) from a to b
00274 void TachyonDisplayDevice::line(float *a, float*b) {
00275   int i, j, test;
00276   float dirvec[3], unitdirvec[3];
00277   float from[3], to[3], tmp1[3], tmp2[3];
00278     
00279   if (lineStyle == ::SOLIDLINE) {
00280     // transform the world coordinates
00281     (transMat.top()).multpoint3d(a, from);
00282     (transMat.top()).multpoint3d(b, to);
00283     
00284     // draw the cylinder
00285     fprintf(outfile, "FCylinder\n"); // flat-ended cylinder
00286     fprintf(outfile, "  Base %g %g %g\n", from[0], from[1], -from[2]); 
00287     fprintf(outfile, "  Apex %g %g %g\n", to[0], to[1], -to[2]);
00288     fprintf(outfile, "  Rad %g \n", float(lineWidth)*DEFAULT_RADIUS);
00289     write_cindexmaterial(colorIndex, materialIndex);
00290 
00291   } else if (lineStyle == ::DASHEDLINE) {
00292      // transform the world coordinates
00293     (transMat.top()).multpoint3d(a, tmp1);
00294     (transMat.top()).multpoint3d(b, tmp2);
00295 
00296     // how to create a dashed line
00297     vec_sub(dirvec, tmp2, tmp1);  // vector from a to b
00298     vec_copy(unitdirvec, dirvec);
00299     vec_normalize(unitdirvec);    // unit vector from a to b
00300     test = 1;
00301     i = 0;
00302     while (test == 1) {
00303       for (j=0; j<3; j++) {
00304         from[j] = (float) (tmp1[j] + (2*i    )*DASH_LENGTH*unitdirvec[j]);
00305           to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00306       }
00307       if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00308         vec_copy(to, tmp2);
00309         test = 0;
00310       }
00311     
00312       // draw the cylinder
00313       fprintf(outfile, "FCylinder\n"); // flat-ended cylinder
00314       fprintf(outfile, "  Base %g %g %g\n", from[0], from[1], -from[2]); 
00315       fprintf(outfile, "  Apex %g %g %g\n", to[0], to[1], -to[2]);
00316       fprintf(outfile, "  Rad %g \n", float(lineWidth)*DEFAULT_RADIUS);
00317       write_cindexmaterial(colorIndex, materialIndex);
00318       i++;
00319     }
00320   } else {
00321     msgErr << "TachyonDisplayDevice: Unknown line style " 
00322            << lineStyle << sendmsg;
00323   }
00324 }
00325 
00326 
00327 
00328 
00329 // draw a cylinder
00330 void TachyonDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00331   float from[3], to[3], norm[3];
00332   float radius;
00333   filled = filled;  
00334 
00335   // transform the world coordinates
00336   (transMat.top()).multpoint3d(a, from);
00337   (transMat.top()).multpoint3d(b, to);
00338   radius = scale_radius(r);
00339    
00340  
00341   // draw the cylinder
00342   fprintf(outfile, "FCylinder\n"); // flat-ended cylinder
00343   fprintf(outfile, "  Base %g %g %g\n", from[0], from[1], -from[2]); 
00344   fprintf(outfile, "  Apex %g %g %g\n", to[0], to[1], -to[2]);
00345   fprintf(outfile, "  Rad %g\n", radius);
00346   write_cindexmaterial(colorIndex, materialIndex);
00347 
00348   // Cylinder caps?
00349   if (filled) {
00350     float div;
00351 
00352     norm[0] = to[0] - from[0];
00353     norm[1] = to[1] - from[1];
00354     norm[2] = to[2] - from[2];
00355 
00356     div = 1.0f / sqrtf(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
00357     norm[0] *= div;
00358     norm[1] *= div;
00359     norm[2] *= div;
00360 
00361     if (filled & CYLINDER_TRAILINGCAP) {
00362       fprintf(outfile, "Ring\n");
00363       fprintf(outfile, "Center %g %g %g \n", from[0], from[1], -from[2]);
00364       fprintf(outfile, "Normal %g %g %g \n", norm[0], norm[1], -norm[2]); 
00365       fprintf(outfile, "Inner 0.0  Outer %g \n", radius);
00366       write_cindexmaterial(colorIndex, materialIndex);
00367     }
00368   
00369     if (filled & CYLINDER_LEADINGCAP) {
00370       fprintf(outfile, "Ring\n");
00371       fprintf(outfile, "Center %g %g %g \n", to[0], to[1], -to[2]);
00372       fprintf(outfile, "Normal %g %g %g \n", -norm[0], -norm[1], norm[2]); 
00373       fprintf(outfile, "Inner 0.0  Outer %g \n", radius);
00374       write_cindexmaterial(colorIndex, materialIndex);
00375     }
00376   }
00377 }
00378 
00379 
00380 // draw a triangle
00381 void TachyonDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00382   float vec1[3], vec2[3], vec3[3];
00383   float norm1[3], norm2[3], norm3[3];
00384   
00385   
00386   // transform the world coordinates
00387   (transMat.top()).multpoint3d(a, vec1);
00388   (transMat.top()).multpoint3d(b, vec2);
00389   (transMat.top()).multpoint3d(c, vec3);
00390 
00391   // and the normals
00392   (transMat.top()).multnorm3d(n1, norm1);
00393   (transMat.top()).multnorm3d(n2, norm2);
00394   (transMat.top()).multnorm3d(n3, norm3);
00395 
00396   // draw the triangle
00397   fprintf(outfile, "STri\n"); // triangle
00398   fprintf(outfile, "  V0 %g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00399   fprintf(outfile, "  V1 %g %g %g\n", vec2[0], vec2[1], -vec2[2]); 
00400   fprintf(outfile, "  V2 %g %g %g\n", vec3[0], vec3[1], -vec3[2]);
00401   fprintf(outfile, "  N0 %g %g %g\n", -norm1[0], -norm1[1], norm1[2]);
00402   fprintf(outfile, "  N1 %g %g %g\n", -norm2[0], -norm2[1], norm2[2]); 
00403   fprintf(outfile, "  N2 %g %g %g\n", -norm3[0], -norm3[1], norm3[2]);
00404   write_cindexmaterial(colorIndex, materialIndex);
00405 }
00406 
00407 // draw triangle with per-vertex colors
00408 void TachyonDisplayDevice::tricolor(const float * xyz1, const float * xyz2, const float * xyz3,
00409                                     const float * n1,   const float * n2,   const float * n3,
00410                                     const float *c1, const float *c2, const float *c3) {
00411   float vec1[3], vec2[3], vec3[3];
00412   float norm1[3], norm2[3], norm3[3];
00413 
00414   // transform the world coordinates
00415   (transMat.top()).multpoint3d(xyz1, vec1);
00416   (transMat.top()).multpoint3d(xyz2, vec2);
00417   (transMat.top()).multpoint3d(xyz3, vec3);
00418 
00419   // and the normals
00420   (transMat.top()).multnorm3d(n1, norm1);
00421   (transMat.top()).multnorm3d(n2, norm2);
00422   (transMat.top()).multnorm3d(n3, norm3);
00423 
00424   // draw the triangle
00425   if (!involtex) {
00426     fprintf(outfile, "VCSTri\n"); // triangle
00427   } else {
00428     fprintf(outfile, "STri\n"); // triangle
00429   }
00430   fprintf(outfile, "  V0 %g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00431   fprintf(outfile, "  V1 %g %g %g\n", vec2[0], vec2[1], -vec2[2]);
00432   fprintf(outfile, "  V2 %g %g %g\n", vec3[0], vec3[1], -vec3[2]);
00433 
00434   fprintf(outfile, "  N0 %g %g %g\n", -norm1[0], -norm1[1], norm1[2]);
00435   fprintf(outfile, "  N1 %g %g %g\n", -norm2[0], -norm2[1], norm2[2]);
00436   fprintf(outfile, "  N2 %g %g %g\n", -norm3[0], -norm3[1], norm3[2]);
00437 
00438   if (!involtex) {
00439     fprintf(outfile, "  C0 %g %g %g\n", c1[0], c1[1], c1[2]);
00440     fprintf(outfile, "  C1 %g %g %g\n", c2[0], c2[1], c2[2]);
00441     fprintf(outfile, "  C2 %g %g %g\n", c3[0], c3[1], c3[2]);
00442   }
00443 
00444   if (materials_on) {
00445     float myspecular = 0.0f;
00446     if (enablemirrorspecular && (mat_shininess >= phongspecularthresh))
00447       myspecular=mat_specular;
00448     fprintf(outfile, "  Ambient %g Diffuse %g Specular %g Opacity %g\n",
00449             mat_ambient, mat_diffuse, myspecular, mat_opacity);
00450   } else {
00451     fprintf(outfile, "  Ambient %g Diffuse %g Specular %g Opacity %g\n",
00452             1.0, 0.0, 0.0, mat_opacity);
00453   }
00454 
00455   if (mat_transmode != 0) {
00456     fprintf(outfile, "  TransMode R3D ");
00457   }
00458   if (mat_outline > 0.0) {
00459     fprintf(outfile, "  Outline %g Outline_Width %g ", 
00460             mat_outline, mat_outlinewidth);
00461   }
00462   fprintf(outfile, "  Phong Plastic %g Phong_size %g ", mat_specular,
00463           mat_shininess);
00464   fprintf(outfile, "VCST\n\n");
00465 }
00466 
00467 
00468 // use an efficient mesh primitve rather than individual triangles
00469 // when possible.
00470 void TachyonDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00471                                           int numfacets, int * facets) {
00472   int i;
00473   float vec1[3];
00474   float norm1[3];
00475 
00476   fprintf(outfile, "VertexArray");
00477   fprintf(outfile, "  Numverts %d\n", numverts);
00478 
00479   fprintf(outfile, "\nCoords\n");
00480   for (i=0; i<numverts; i++) {
00481     (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
00482     fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00483   } 
00484 
00485   fprintf(outfile, "\nNormals\n");
00486   for (i=0; i<numverts; i++) {
00487     (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
00488     fprintf(outfile, "%g %g %g\n", -norm1[0], -norm1[1], norm1[2]);
00489   } 
00490 
00491   // don't emit per-vertex colors when volumetric texturing is enabled
00492   if (!involtex) {
00493     fprintf(outfile, "\nColors\n");
00494     for (i=0; i<numverts; i++) {
00495       int idx = i * 10;
00496       fprintf(outfile, "%g %g %g\n", cnv[idx], cnv[idx+1], cnv[idx+2]);
00497     } 
00498   }
00499 
00500   // emit the texture to be used by the geometry that follows
00501   write_cindexmaterial(colorIndex, materialIndex);
00502 
00503   // loop over all of the facets in the mesh
00504   fprintf(outfile, "\nTriMesh %d\n", numfacets);
00505   for (i=0; i<numfacets*3; i+=3) {
00506     fprintf(outfile, "%d %d %d\n", facets[i], facets[i+1], facets[i+2]);
00507   }
00508  
00509   // terminate vertex array 
00510   fprintf(outfile, "\nEnd_VertexArray\n");
00511 }
00512 
00513 
00514 void TachyonDisplayDevice::tristrip(int numverts, const float * cnv,
00515                                    int numstrips, const int *vertsperstrip,
00516                                    const int *facets) {
00517   int i, strip, v=0;
00518   float vec1[3];
00519   float norm1[3];
00520 
00521   fprintf(outfile, "VertexArray");
00522   fprintf(outfile, "  Numverts %d\n", numverts);
00523 
00524   fprintf(outfile, "\nCoords\n");
00525   for (i=0; i<numverts; i++) {
00526     (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
00527     fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00528   } 
00529 
00530   fprintf(outfile, "\nNormals\n");
00531   for (i=0; i<numverts; i++) {
00532     (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
00533     fprintf(outfile, "%g %g %g\n", -norm1[0], -norm1[1], norm1[2]);
00534   } 
00535 
00536   // don't emit per-vertex colors when volumetric texturing is enabled
00537   if (!involtex) {
00538     fprintf(outfile, "\nColors\n");
00539     for (i=0; i<numverts; i++) {
00540       int idx = i * 10;
00541       fprintf(outfile, "%g %g %g\n", cnv[idx], cnv[idx+1], cnv[idx+2]);
00542     } 
00543   }
00544 
00545   // emit the texture to be used by the geometry that follows
00546   write_cindexmaterial(colorIndex, materialIndex);
00547 
00548   // loop over all of the triangle strips
00549   v=0;
00550   for (strip=0; strip < numstrips; strip++) {
00551     fprintf(outfile, "\nTriStrip %d\n", vertsperstrip[strip]);
00552 
00553     // loop over all triangles in this triangle strip
00554     for (i = 0; i < vertsperstrip[strip]; i++) {
00555       fprintf(outfile, "%d ", facets[v]);
00556       v++; // move on to the next triangle
00557     }
00558   }
00559  
00560   // terminate vertex array 
00561   fprintf(outfile, "\nEnd_VertexArray\n");
00562 }
00563 
00564 
00565 // define a volumetric texture map
00566 void TachyonDisplayDevice::define_volume_texture(int ID, 
00567                                                  int xs, int ys, int zs,
00568                                                  const float *xpq,
00569                                                  const float *ypq,
00570                                                  const float *zpq,
00571                                                  unsigned char *texmap) {
00572   voltexID = ID; // remember current texture ID
00573 
00574   memcpy(xplaneeq, xpq, sizeof(xplaneeq));
00575   memcpy(yplaneeq, ypq, sizeof(yplaneeq));
00576   memcpy(zplaneeq, zpq, sizeof(zplaneeq));
00577 
00578   fprintf(outfile, "# VMD volume texture definition: ID %d\n", ID);
00579   fprintf(outfile, "#  Res: %d %d %d\n", xs, ys, zs);
00580   fprintf(outfile, "#  xplaneeq: %g %g %g %g\n",
00581          xplaneeq[0], xplaneeq[1], xplaneeq[2], xplaneeq[3]);
00582   fprintf(outfile, "#  yplaneeq: %g %g %g %g\n",
00583          yplaneeq[0], yplaneeq[1], yplaneeq[2], yplaneeq[3]);
00584   fprintf(outfile, "#  zplaneeq: %g %g %g %g\n",
00585          zplaneeq[0], zplaneeq[1], zplaneeq[2], zplaneeq[3]);
00586 
00587   fprintf(outfile, "ImageDef ::VMDVolTex%d\n", ID);
00588   fprintf(outfile, "  Format RGB24\n");
00589   fprintf(outfile, "  Resolution %d %d %d\n", xs, ys, zs);
00590   fprintf(outfile, "  Encoding Hex\n");
00591  
00592   int x, y, z;
00593   for (z=0; z<zs; z++) {
00594     for (y=0; y<ys; y++) {
00595       int addr = (z * xs * ys) + (y * xs);
00596       for (x=0; x<xs; x++) {
00597         int addr2 = (addr + x) * 3;
00598         fprintf(outfile, "%02x%02x%02x ", 
00599                 texmap[addr2    ],
00600                 texmap[addr2 + 1],
00601                 texmap[addr2 + 2]);
00602       }
00603       fprintf(outfile, "\n");
00604     }
00605     fprintf(outfile, "\n");
00606   }  
00607   fprintf(outfile, "\n");
00608   fprintf(outfile, "# End of volume texture ::VMDVolTex%d\n", ID);
00609   fprintf(outfile, "\n");
00610   fprintf(outfile, "\n");
00611 }
00612 
00613 
00614 // enable volumetric texturing, either in "replace" or "modulate" mode
00615 void TachyonDisplayDevice::volume_texture_on(int texmode) {
00616   involtex = 1;
00617 }
00618 
00619 
00620 // disable volumetric texturing
00621 void TachyonDisplayDevice::volume_texture_off(void) {
00622   involtex = 0;
00623 }
00624 
00625 
00626 void TachyonDisplayDevice::start_clipgroup(void) {
00627   int i;
00628   int planesenabled = 0;
00629 
00630   for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00631     if (clip_mode[i] > 0) {
00632       planesenabled++;  /* count number of active clipping planes */
00633       if (clip_mode[i] > 1)
00634         warningflags |= FILERENDERER_NOCLIP; /* emit warnings */
00635     }
00636   }
00637 
00638   if (planesenabled > 0) {
00639     fprintf(outfile, "Start_ClipGroup\n");
00640     fprintf(outfile, " NumPlanes %d\n", planesenabled);
00641     for (i=0; i<VMD_MAX_CLIP_PLANE; i++) { 
00642       if (clip_mode[i] > 0) {
00643         float tachyon_clip_center[3]; 
00644         float tachyon_clip_normal[3];
00645         float tachyon_clip_distance;
00646 
00647         inclipgroup = 1; // we're in a clipping group presently
00648 
00649         // Transform the plane center and the normal
00650         (transMat.top()).multpoint3d(clip_center[i], tachyon_clip_center);
00651         (transMat.top()).multnorm3d(clip_normal[i], tachyon_clip_normal);
00652         vec_negate(tachyon_clip_normal, tachyon_clip_normal);
00653 
00654         // Tachyon uses the distance from the origin to the plane for its
00655         // representation, instead of the plane center
00656         tachyon_clip_distance = dot_prod(tachyon_clip_normal, tachyon_clip_center);
00657 
00658         fprintf(outfile, "%g %g %g %g\n", tachyon_clip_normal[0], 
00659                 tachyon_clip_normal[1], -tachyon_clip_normal[2], 
00660                 tachyon_clip_distance);
00661       }    
00662     }
00663     fprintf(outfile, "\n");
00664   } else {
00665     inclipgroup = 0; // Not currently in a clipping group
00666   }
00667 }
00668 
00669 
00671 
00672 // initialize the file for output
00673 void TachyonDisplayDevice::write_header() {
00674   fprintf(outfile, "# \n"); 
00675   fprintf(outfile, "# Molecular graphics exported from VMD %s\n", VMDVERSION);
00676   fprintf(outfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00677   fprintf(outfile, "# \n"); 
00678   fprintf(outfile, "# Requires Tachyon version 0.99.0 or newer\n");
00679   fprintf(outfile, "# \n"); 
00680   fprintf(outfile, "# Default tachyon rendering command for this scene:\n"); 
00681   fprintf(outfile, "#   tachyon %s\n", TACHYON_RUN_STRING); 
00682   fprintf(outfile, "# \n"); 
00683   // NOTE: the vmd variable "Aspect" has absolutely *nothing* to do
00684   //       with aspect ratio correction, it is only the ratio of the
00685   //       width of the graphics window to its height, and so it should
00686   //       be used only to cause the ray tracer to generate a similarly
00687   //       proportioned image.
00688 
00689   fprintf(outfile, "Begin_Scene\n");
00690   fprintf(outfile, "Resolution %d %d\n", (int) xSize, (int) ySize);
00691 
00692 
00693   // Emit shading mode information
00694   fprintf(outfile, "Shader_Mode ");
00695 
00696   // change shading mode depending on whether the user wants shadows
00697   // or ambient occlusion lighting.
00698   if (shadows_enabled() || ao_enabled()) {
00699     fprintf(outfile, "Full\n");
00700   } else {
00701     fprintf(outfile, "Medium\n");
00702   }
00703 
00704   // For VMD we always want to enable flags that preserve a more WYSIWYG  
00705   // type of output, although in some cases doing things in Tachyon's
00706   // preferred way might be nicer.  The user can override these with 
00707   // command line flags still if they want radial fog or other options.
00708   fprintf(outfile, "  Trans_VMD\n");
00709   fprintf(outfile, "  Fog_VMD\n");
00710 
00711   // render with ambient occlusion lighting if required
00712   if (ao_enabled()) {
00713     fprintf(outfile, "  Ambient_Occlusion\n");
00714     fprintf(outfile, "    Ambient_Color %g %g %g\n", 
00715             get_ao_ambient(), get_ao_ambient(), get_ao_ambient());
00716     fprintf(outfile, "    Rescale_Direct %g\n", get_ao_direct());
00717     fprintf(outfile, "    Samples %d\n", aosamples);
00718   }
00719   fprintf(outfile, "End_Shader_Mode\n");
00720 
00721   write_camera();    // has to be first thing in the file. 
00722   write_lights();    // could be anywhere.
00723   write_materials(); // has to be before objects that use them.
00724 }
00725 
00726 
00727 void TachyonDisplayDevice::end_clipgroup(void) {
00728   if (inclipgroup) {
00729     fprintf(outfile, "End_ClipGroup\n");
00730     inclipgroup = 0; // we're not in a clipping group anymore
00731   }
00732 }
00733 
00734 
00735 void TachyonDisplayDevice::write_trailer(void){
00736   fprintf(outfile, "End_Scene \n");
00737   if (inclipgroup) {
00738     msgErr << "TachyonDisplayDevice clipping group still active at end of scene\n" << sendmsg;
00739   }
00740   msgInfo << "Tachyon file generation finished" << sendmsg;
00741 
00742   reset_vars();
00743 }
00744 
00745 
00746 
00748 
00749 void TachyonDisplayDevice::write_camera(void) {
00750   int raydepth = 50;
00751  
00752   // Camera position
00753   // Tachyon uses a left-handed coordinate system
00754   // VMD uses right-handed, so z(Tachyon) = -z(VMD).
00755 
00756   switch (projection()) {
00757     // XXX code for new versions of Tachyon that support orthographic views
00758     case DisplayDevice::ORTHOGRAPHIC:
00759       fprintf(outfile, "Camera\n");
00760       fprintf(outfile, "  Projection Orthographic\n");
00761       fprintf(outfile, "  Zoom %g\n", 1.0 / (vSize / 2.0));
00762       fprintf(outfile, "  Aspectratio %g\n", 1.0f);
00763       fprintf(outfile, "  Antialiasing %d\n", aasamples);
00764       fprintf(outfile, "  Raydepth %d\n", raydepth);
00765       fprintf(outfile, "  Center  %g %g %g\n", eyePos[0], eyePos[1], -eyePos[2]);
00766       fprintf(outfile, "  Viewdir %g %g %g\n", eyeDir[0], eyeDir[1], -eyeDir[2]);
00767       fprintf(outfile, "  Updir   %g %g %g\n", upDir[0], upDir[1], -upDir[2]);
00768       fprintf(outfile, "End_Camera\n");
00769       break;
00770 
00771     case DisplayDevice::PERSPECTIVE:
00772     default:
00773       fprintf(outfile, "Camera\n");
00774       fprintf(outfile, "  Zoom %g\n", (eyePos[2] - zDist) / vSize);
00775       fprintf(outfile, "  Aspectratio %g\n", 1.0f);
00776       fprintf(outfile, "  Antialiasing %d\n", aasamples);
00777       fprintf(outfile, "  Raydepth %d\n", raydepth);
00778       fprintf(outfile, "  Center  %g %g %g\n", eyePos[0], eyePos[1], -eyePos[2]);
00779       fprintf(outfile, "  Viewdir %g %g %g\n", eyeDir[0], eyeDir[1], -eyeDir[2]);
00780       fprintf(outfile, "  Updir   %g %g %g\n", upDir[0], upDir[1], -upDir[2]);
00781       fprintf(outfile, "End_Camera\n");
00782       break;
00783 
00784   }
00785 }
00786 
00787   
00788 void TachyonDisplayDevice::write_lights(void) {  
00789   // Lights
00790   int i;  
00791   int lightcount = 0;
00792   for (i=0; i<DISP_LIGHTS; i++) {
00793     if (lightState[i].on) {
00794       /* give negated light position as the direction vector */
00795       fprintf(outfile, "Directional_Light Direction %g %g %g ", 
00796               -lightState[i].pos[0],
00797               -lightState[i].pos[1],
00798                lightState[i].pos[2]);
00799       fprintf(outfile, "Color %g %g %g\n", 
00800               lightState[i].color[0], lightState[i].color[1], lightState[i].color[2]);
00801       lightcount++;
00802     }
00803   }
00804 
00805 #if 1
00806   for (i=0; i<DISP_LIGHTS; i++) {
00807     if (advLightState[i].on) {
00808       float pos[3];
00809 
00810       // always use world coordinates for now
00811       vec_copy(pos, advLightState[i].pos);
00812 
00813       if (advLightState[i].spoton) {
00814         fprintf(outfile, "# SpotLight not implemented yet ...\n");
00815       } else {
00816         /* invert handedness of light position vector */
00817         fprintf(outfile, "Light Center %g %g %g Rad 0.0 ", 
00818                 pos[0], pos[1], -pos[2]);
00819 
00820         /* emit light attentuation parameters if needed */
00821         if (advLightState[i].constfactor != 1.0f ||
00822             advLightState[i].linearfactor != 0.0f ||
00823             advLightState[i].quadfactor != 0.0f) {
00824           fprintf(outfile, "Attenuation Constant %g Linear %g Quadratic %g\n", 
00825                   advLightState[i].constfactor, 
00826                   advLightState[i].linearfactor,
00827                   advLightState[i].quadfactor);
00828         }
00829  
00830         fprintf(outfile, "Color %g %g %g\n", 
00831                 lightState[i].color[0], lightState[i].color[1], lightState[i].color[2]);
00832       }
00833 
00834       lightcount++;
00835     }
00836   }
00837 #endif
00838 
00839   if (lightcount < 1) {
00840     msgInfo << "Warning: no lights defined in exported scene!!" << sendmsg;
00841   }
00842 }
00843 
00844 void TachyonDisplayDevice::write_materials(void) {
00845   // background color
00846   fprintf(outfile, "\nBackground %g %g %g\n", 
00847           backColor[0], backColor[1], backColor[2]);
00848 
00849   // Specify Tachyon background sky sphere if background gradient
00850   // mode is enabled.
00851   if (backgroundmode == 1) {
00852     float bspheremag = 0.5f;
00853 
00854     // compute positive/negative magnitude of sphere gradient
00855     switch (projection()) {
00856       case DisplayDevice::ORTHOGRAPHIC:
00857         // For orthographic views, Tachyon uses the dot product between
00858         // the incident ray origin and the sky sphere gradient "up" vector,
00859         // since all camera rays have the same direction and differ only
00860         // in their origin.
00861         bspheremag = vSize / 4.0f;
00862         break;
00863 
00864       case DisplayDevice::PERSPECTIVE:
00865       default:
00866         // For perspective views, Tachyon uses the dot product between
00867         // the incident ray and the sky sphere gradient "up" vector,
00868         // so for larger values of vSize, we have to clamp the maximum
00869         // magnitude to 1.0.
00870         bspheremag = (vSize / 2.0f) / (eyePos[2] - zDist);
00871         if (bspheremag > 1.0f)
00872           bspheremag = 1.0f;
00873         break;
00874     }
00875 
00876    
00877     fprintf(outfile, "Background_Gradient "); 
00878     if (projection() == DisplayDevice::ORTHOGRAPHIC)
00879       fprintf(outfile, "Sky_Ortho_Plane\n");
00880     else
00881       fprintf(outfile, "Sky_Sphere\n");
00882     fprintf(outfile, "  UpDir %g %g %g\n", 0.0f, 1.0f, 0.0f);
00883     fprintf(outfile, "  TopVal %g\n",     bspheremag);
00884     fprintf(outfile, "  BottomVal %g\n", -bspheremag);
00885     fprintf(outfile, "  TopColor %g %g %g\n", backgradienttopcolor[0], 
00886             backgradienttopcolor[1], backgradienttopcolor[2]);
00887     fprintf(outfile, "  BottomColor %g %g %g\n", backgradientbotcolor[0],
00888             backgradientbotcolor[1], backgradientbotcolor[2]);
00889   }
00890 
00891   // set depth cueing parameters
00892   if (cueingEnabled) {
00893     switch (cueMode) {
00894       case CUE_LINEAR:
00895         fprintf(outfile, 
00896           "Fog Linear Start %g End %g Density %g Color %g %g %g\n", 
00897           get_cue_start(), get_cue_end(), 1.0f, 
00898           backColor[0], backColor[1], backColor[2]);
00899         break;
00900  
00901       case CUE_EXP:
00902         fprintf(outfile,
00903           "Fog Exp Start %g End %g Density %g Color %g %g %g\n", 
00904           0.0, get_cue_end(), get_cue_density(), 
00905           backColor[0], backColor[1], backColor[2]);
00906         break;
00907  
00908       case CUE_EXP2:
00909         fprintf(outfile, 
00910           "Fog Exp2 Start %g End %g Density %g Color %g %g %g\n", 
00911           0.0, get_cue_end(), get_cue_density(), 
00912           backColor[0], backColor[1], backColor[2]);
00913         break;
00914 
00915       case NUM_CUE_MODES:
00916         // this should never happen
00917         break;
00918     }
00919   } 
00920 }
00921 
00922 void TachyonDisplayDevice::write_cindexmaterial(int cindex, int material) {
00923   write_colormaterial((float *) &matData[cindex], material);
00924 }
00925 
00926 // XXX ignores material parameter, may need to improve this..
00927 void TachyonDisplayDevice::write_colormaterial(float *rgb, int /* material */) {
00928   fprintf(outfile, "Texture\n");
00929   if (materials_on) {
00930     float myspecular = 0.0f;
00931     if (enablemirrorspecular && (mat_shininess >= phongspecularthresh))
00932       myspecular=mat_specular;
00933     fprintf(outfile, "  Ambient %g Diffuse %g Specular %g Opacity %g\n",
00934             mat_ambient, mat_diffuse, myspecular, mat_opacity);
00935   } else {
00936     fprintf(outfile, "  Ambient %g Diffuse %g Specular %g Opacity %g\n",
00937             1.0, 0.0, 0.0, mat_opacity);
00938   }
00939   
00940   if (mat_transmode != 0) {
00941     fprintf(outfile, "  TransMode R3D ");
00942   }
00943   if (mat_outline > 0.0) {
00944     fprintf(outfile, "  Outline %g Outline_Width %g ", 
00945             mat_outline, mat_outlinewidth);
00946   }
00947   fprintf(outfile, "  Phong Plastic %g Phong_size %g ", mat_specular, 
00948           mat_shininess);
00949   fprintf(outfile, "Color %g %g %g ", rgb[0], rgb[1], rgb[2]);
00950 
00952   if (!involtex) {
00954     fprintf(outfile, "TexFunc 0\n\n");
00955   } else {
00957     float voluaxs[3];           
00958     float volvaxs[3];           
00959     float volwaxs[3];
00960     float volcent[3];
00961 
00962     // transform the y/v/w texture coordinate axes from molecule
00963     // coordinates into world coordinates
00964     (transMat.top()).multplaneeq3d(xplaneeq, voluaxs);
00965     (transMat.top()).multplaneeq3d(yplaneeq, volvaxs);
00966     (transMat.top()).multplaneeq3d(zplaneeq, volwaxs);
00967 
00968     // undo the scaling operation applied by the transformation
00969     float invscale = 1.0f / scale_radius(1.0f); 
00970     int i;
00971     for (i=0; i<3; i++) {
00972       voluaxs[i] *= invscale;
00973       volvaxs[i] *= invscale;
00974       volwaxs[i] *= invscale;
00975     }
00976 
00977     // compute the volume origin in molecule coordinates by 
00978     // reverting the scaling factor that was previously applied
00979     // to the texture plane equation
00980     float volorgmol[3] = {0,0,0};
00981     volorgmol[0] = -xplaneeq[3] / norm(xplaneeq);
00982     volorgmol[1] = -yplaneeq[3] / norm(yplaneeq);
00983     volorgmol[2] = -zplaneeq[3] / norm(zplaneeq);
00984 
00985     // transform the volume origin into world coordinates
00986     (transMat.top()).multpoint3d(volorgmol, volcent);
00987 
00988     // emit the texture to the scene file
00989     fprintf(outfile, "\n  TexFunc  10  ::VMDVolTex%d\n", voltexID);
00990     fprintf(outfile, "  Center %g %g %g\n", volcent[0], volcent[1], -volcent[2]);
00991     fprintf(outfile, "  Rotate 0 0 0\n");
00992     fprintf(outfile, "  Scale  1 1 1\n");
00993     fprintf(outfile, "  Uaxis %g %g %g\n", voluaxs[0], voluaxs[1], -voluaxs[2]);
00994     fprintf(outfile, "  Vaxis %g %g %g\n", volvaxs[0], volvaxs[1], -volvaxs[2]);
00995     fprintf(outfile, "  Waxis %g %g %g\n", volwaxs[0], volwaxs[1], -volwaxs[2]);
00996     fprintf(outfile, "\n");
00997   }
00998 }
00999 
01000 
01001 
01002 

Generated on Sat May 26 01:48:29 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002