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

RenderManDisplayDevice.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: RenderManDisplayDevice.C
00013 *      $Author: johns $      $Locker:  $               $State: Exp $
00014 *      $Revision: 1.55 $         $Date: 2011/11/10 17:05:34 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 *
00019 * FileRenderer type for the RenderMan interface.
00020 *
00021 ***************************************************************************/
00022 
00023 #include <math.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include "RenderManDisplayDevice.h"
00028 #include "DispCmds.h"  // needed for line styles
00029 #include "config.h"    // for VMDVERSION string
00030 #include "Hershey.h"   // needed for Hershey font rendering fctns
00031 
00032 
00033 // The default radius for points and lines (which are displayed
00034 // as small spheres or cylinders, respectively)
00035 #define DEFAULT_RADIUS  0.0025f
00036 #define DASH_LENGTH 0.02f
00037 
00039 RenderManDisplayDevice::RenderManDisplayDevice() 
00040 : FileRenderer("RenderMan", "PIXAR RenderMan", "vmdscene.rib", "prman %s") {
00041   reset_vars(); // initialize material cache
00042 }
00043         
00045 RenderManDisplayDevice::~RenderManDisplayDevice(void) { }
00046 
00047 
00049 void RenderManDisplayDevice::reset_vars(void) {
00050   old_color[0] = -1;
00051   old_color[1] = -1;
00052   old_color[2] = -1;
00053   old_ambient = -1;
00054   old_specular = -1;
00055   old_opacity = -1;
00056   old_diffuse = -1;
00057 }
00058 
00059 
00060 void RenderManDisplayDevice::text(float *pos, float size, float thickness,
00061                                   const char *str) {
00062   float textpos[3];
00063   float textsize, textthickness;
00064   hersheyhandle hh;
00065 
00066   // transform the world coordinates
00067   (transMat.top()).multpoint3d(pos, textpos);
00068   textsize = size * 1.5f;
00069   textthickness = thickness*DEFAULT_RADIUS;
00070 
00071   while (*str != '\0') {
00072     float lm, rm, x, y, ox, oy;
00073     int draw, odraw;
00074     ox=oy=x=y=0.0f;
00075     draw=odraw=0;
00076 
00077     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00078     textpos[0] -= lm * textsize;
00079 
00080     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00081       float oldpt[3], newpt[3];
00082       if (draw) {
00083         newpt[0] = textpos[0] + textsize * x;
00084         newpt[1] = textpos[1] + textsize * y;
00085         newpt[2] = textpos[2];
00086 
00087         if (odraw) {
00088           // if we have both previous and next points, connect them...
00089           oldpt[0] = textpos[0] + textsize * ox;
00090           oldpt[1] = textpos[1] + textsize * oy;
00091           oldpt[2] = textpos[2];
00092 
00093           cylinder_noxfrm(oldpt, newpt, textthickness, 0);
00094 
00095           fprintf(outfile, "TransformBegin\n");
00096           write_materials(1);
00097           fprintf(outfile, "  Translate %g %g %g\n",
00098                   newpt[0], newpt[1], newpt[2]);
00099           fprintf(outfile, "  Sphere %g %g %g 360\n",
00100                   textthickness, -textthickness, textthickness);
00101           fprintf(outfile, "TransformEnd\n");
00102         } else {
00103           // ...otherwise, just draw the next point
00104           fprintf(outfile, "TransformBegin\n");
00105           write_materials(1);
00106           fprintf(outfile, "  Translate %g %g %g\n",
00107                   newpt[0], newpt[1], newpt[2]);
00108           fprintf(outfile, "  Sphere %g %g %g 360\n",
00109                   textthickness, -textthickness, textthickness);
00110           fprintf(outfile, "TransformEnd\n");
00111         }
00112       }
00113 
00114       ox=x;
00115       oy=y;
00116       odraw=draw;
00117     }
00118     textpos[0] += rm * textsize;
00119 
00120     str++;
00121   }
00122 }
00123 
00124 
00126 void RenderManDisplayDevice::point(float * spdata) {
00127   float vec[3];
00128   // Transform the world coordinates
00129   (transMat.top()).multpoint3d(spdata, vec);
00130 
00131   fprintf(outfile, "TransformBegin\n");
00132   write_materials(1);
00133   fprintf(outfile, "  Translate %g %g %g\n", vec[0], vec[1], vec[2]);
00134   fprintf(outfile, "  Sphere %g %g %g 360\n",
00135     (float)  lineWidth * DEFAULT_RADIUS,
00136     (float) -lineWidth * DEFAULT_RADIUS,
00137     (float)  lineWidth * DEFAULT_RADIUS);
00138   fprintf(outfile, "TransformEnd\n");
00139 }
00140 
00141 
00143 void RenderManDisplayDevice::sphere(float * spdata) {
00144   float vec[3];
00145   float radius;
00146 
00147   // Transform the world coordinates
00148   (transMat.top()).multpoint3d(spdata, vec);
00149   radius = scale_radius(spdata[3]);
00150   if (radius < DEFAULT_RADIUS) {
00151     radius = (float) DEFAULT_RADIUS;
00152   }
00153 
00154   // Draw the sphere
00155   fprintf(outfile, "TransformBegin\n");
00156   write_materials(1);
00157   fprintf(outfile, "  Translate %g %g %g\n", vec[0], vec[1], vec[2]);
00158   fprintf(outfile, "  Sphere %g %g %g 360\n", radius, -radius, radius);
00159   fprintf(outfile, "TransformEnd\n");
00160 }
00161 
00162 
00164 void RenderManDisplayDevice::line(float *a, float *b) {
00165   int i, j, test;
00166   float dirvec[3], unitdirvec[3];
00167   float from[3], to[3], tmp1[3], tmp2[3];
00168 
00169   if (lineStyle == ::SOLIDLINE) {
00170     // transform the world coordinates
00171     (transMat.top()).multpoint3d(a, from);
00172     (transMat.top()).multpoint3d(b, to);
00173 
00174     cylinder_noxfrm(from, to, (float) (lineWidth * DEFAULT_RADIUS), 0);
00175   } else if (lineStyle == ::DASHEDLINE) {
00176      // transform the world coordinates
00177     (transMat.top()).multpoint3d(a, tmp1);
00178     (transMat.top()).multpoint3d(b, tmp2);
00179 
00180     // how to create a dashed line
00181     vec_sub(dirvec, tmp2, tmp1);  // vector from a to b
00182     vec_copy(unitdirvec, dirvec);
00183     vec_normalize(unitdirvec);    // unit vector from a to b
00184     test = 1;
00185     i = 0;
00186     while (test == 1) {
00187       for (j=0; j<3; j++) {
00188         from[j] = (float) (tmp1[j] + (2*i    )*DASH_LENGTH*unitdirvec[j]);
00189           to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00190       }
00191       if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00192         vec_copy(to, tmp2);
00193         test = 0;
00194       }
00195 
00196       cylinder_noxfrm(from, to, (float) (lineWidth * DEFAULT_RADIUS), 0);
00197       i++;
00198     }
00199   } else {
00200     msgErr << "RenderManDisplayDevice: Unknown line style "
00201            << lineStyle << sendmsg;
00202   }
00203 }
00204 
00205 
00207 void RenderManDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00208   float vec1[3], vec2[3], radius;
00209 
00210   if (filled) {
00211     FileRenderer::cylinder(a, b, r, filled);
00212     return;
00213   }
00214 
00215   // Transform the world coordinates
00216   (transMat.top()).multpoint3d(a, vec1);
00217   (transMat.top()).multpoint3d(b, vec2);
00218   radius = scale_radius(r);
00219 
00220   cylinder_noxfrm(vec1, vec2, radius, filled);
00221 }
00222 
00223 
00225 void RenderManDisplayDevice::cylinder_noxfrm(float *vec1, float *vec2, 
00226                                              float radius, int filled) {
00227   float axis[3];
00228   float R, phi, rxy, theta;
00229 
00230   // safety check to prevent overly-tiny cylinders
00231   if (radius < DEFAULT_RADIUS) {
00232     radius = (float) DEFAULT_RADIUS;
00233   }
00234 
00235   // RenderMan's cylinders always run along the z axis, and must
00236   // be transformed to the proper position and rotation. This
00237   // code is taken from OpenGLRenderer.C.
00238   axis[0] = vec2[0] - vec1[0];
00239   axis[1] = vec2[1] - vec1[1];
00240   axis[2] = vec2[2] - vec1[2];
00241 
00242   R = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2];
00243   if (R <= 0) return;
00244 
00245   R = sqrtf(R); // evaluation of sqrt() _after_ early exit
00246 
00247   // determine phi rotation angle, amount to rotate about y
00248   phi = acosf(axis[2] / R);
00249 
00250   // determine theta rotation, amount to rotate about z
00251   rxy = sqrtf(axis[0] * axis[0] + axis[1] * axis[1]);
00252   if (rxy <= 0) {
00253     theta = 0;
00254   } else {
00255     theta = acosf(axis[0] / rxy);
00256     if (axis[1] < 0) theta = (float) (2.0 * VMD_PI) - theta;
00257   }
00258 
00259   // Write the cylinder
00260   fprintf(outfile, "TransformBegin\n");
00261   write_materials(1);
00262   fprintf(outfile, "  Translate %g %g %g\n", vec1[0], vec1[1], vec1[2]);
00263   if (theta) 
00264     fprintf(outfile, "  Rotate %g 0 0 1\n", (theta / VMD_PI) * 180);
00265   if (phi) 
00266     fprintf(outfile, "  Rotate %g 0 1 0\n", (phi / VMD_PI) * 180);
00267   fprintf(outfile, "  Cylinder %g 0 %g 360\n", radius, R);
00268   fprintf(outfile, "TransformEnd\n");
00269 }
00270 
00271 
00273 void RenderManDisplayDevice::cone(float *a, float *b, float r) {
00274   float axis[3], vec1[3], vec2[3];
00275   float R, phi, rxy, theta;
00276   float radius;
00277 
00278   // Transform the world coordinates
00279   (transMat.top()).multpoint3d(a, vec1);
00280   (transMat.top()).multpoint3d(b, vec2);
00281   radius = scale_radius(r);
00282   if (radius < DEFAULT_RADIUS) {
00283     radius = (float) DEFAULT_RADIUS;
00284   }
00285 
00286   // RenderMan's cylinders always run along the z axis, and must
00287   // be transformed to the proper position and rotation. This
00288   // code is taken from OpenGLRenderer.C.
00289   axis[0] = vec2[0] - vec1[0];
00290   axis[1] = vec2[1] - vec1[1];
00291   axis[2] = vec2[2] - vec1[2];
00292 
00293   R = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2];
00294   if (R <= 0) return;
00295 
00296   R = sqrtf(R); // evaluation of sqrt() _after_ early exit
00297 
00298   // determine phi rotation angle, amount to rotate about y
00299   phi = acosf(axis[2] / R);
00300 
00301   // determine theta rotation, amount to rotate about z
00302   rxy = sqrtf(axis[0] * axis[0] + axis[1] * axis[1]);
00303   if (rxy <= 0) {
00304     theta = 0;
00305   } else {
00306     theta = acosf(axis[0] / rxy);
00307     if (axis[1] < 0) theta = (float) (2.0 * VMD_PI) - theta;
00308   }
00309 
00310   // Write the cone
00311   fprintf(outfile, "TransformBegin\n");
00312   write_materials(1);
00313   fprintf(outfile, "  Translate %g %g %g\n", vec1[0], vec1[1], vec1[2]);
00314   if (theta) 
00315     fprintf(outfile, "  Rotate %g 0 0 1\n", (theta / VMD_PI) * 180);
00316   if (phi) 
00317     fprintf(outfile, "  Rotate %g 0 1 0\n", (phi / VMD_PI) * 180);
00318   fprintf(outfile, "  Cone %g %g 360\n", R, radius);
00319   fprintf(outfile, "TransformEnd\n");
00320 }
00321 
00322 
00323 // draw a triangle
00324 void RenderManDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00325   float vec1[3], vec2[3], vec3[3];
00326   float norm1[3], norm2[3], norm3[3];
00327 
00328   // Transform the world coordinates
00329   (transMat.top()).multpoint3d(a, vec1);
00330   (transMat.top()).multpoint3d(b, vec2);
00331   (transMat.top()).multpoint3d(c, vec3);
00332   (transMat.top()).multnorm3d(n1, norm1);
00333   (transMat.top()).multnorm3d(n2, norm2);
00334   (transMat.top()).multnorm3d(n3, norm3);
00335 
00336   // Write the triangle
00337   write_materials(1);
00338   fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g ] ",
00339           vec1[0], vec1[1], vec1[2],
00340           vec2[0], vec2[1], vec2[2],
00341           vec3[0], vec3[1], vec3[2]);
00342   fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g ]\n",
00343           norm1[0], norm1[1], norm1[2],
00344           norm2[0], norm2[1], norm2[2],
00345           norm3[0], norm3[1], norm3[2]);
00346 }
00347 
00348 
00349 // draw a tricolor
00350 void RenderManDisplayDevice::tricolor(const float *a, const float *b, const float *c,
00351                       const float *n1, const float *n2, const float *n3,
00352                       const float *c1, const float *c2, const float *c3) {
00353   float vec1[3], vec2[3], vec3[3];
00354   float norm1[3], norm2[3], norm3[3];
00355 
00356   // Transform the world coordinates
00357   (transMat.top()).multpoint3d(a, vec1);
00358   (transMat.top()).multpoint3d(b, vec2);
00359   (transMat.top()).multpoint3d(c, vec3);
00360   (transMat.top()).multnorm3d(n1, norm1);
00361   (transMat.top()).multnorm3d(n2, norm2);
00362   (transMat.top()).multnorm3d(n3, norm3);
00363 
00364   // Write the triangle
00365   write_materials(0);
00366   fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g ] ",
00367           vec1[0], vec1[1], vec1[2],
00368           vec2[0], vec2[1], vec2[2],
00369           vec3[0], vec3[1], vec3[2]);
00370   fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g ] ",
00371           norm1[0], norm1[1], norm1[2],
00372           norm2[0], norm2[1], norm2[2],
00373           norm3[0], norm3[1], norm3[2]);
00374   fprintf(outfile, "\"Cs\" [ %g %g %g %g %g %g %g %g %g ]\n",
00375           c1[0], c1[1], c1[2],
00376           c2[0], c2[1], c2[2],
00377           c3[0], c3[1], c3[2]);
00378 }
00379 
00380 
00381 // use an efficient mesh primitve rather than individual triangles
00382 // when possible.
00383 void RenderManDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00384                                             int numfacets, int * facets) {
00385   int i;
00386   float vec1[3];
00387   float norm1[3];
00388 
00389   write_materials(0);
00390 
00391   fprintf(outfile, "PointsPolygons");
00392 
00393   // emit vertex counts for each face
00394   fprintf(outfile, "  [ ");
00395   for (i=0; i<numfacets; i++) {
00396     fprintf(outfile, "3 ");
00397   }
00398   fprintf(outfile, "]\n");
00399 
00400   // emit vertex indices for each facet
00401   fprintf(outfile, "  [ ");
00402   for (i=0; i<numfacets*3; i+=3) {
00403     fprintf(outfile, "%d %d %d ", facets[i], facets[i+1], facets[i+2]);
00404   }
00405   fprintf(outfile, "]\n");
00406 
00407   // emit vertex coordinates
00408   fprintf(outfile, "  \"P\" [ ");
00409   for (i=0; i<numverts; i++) {
00410     (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
00411     fprintf(outfile, "%g %g %g ", vec1[0], vec1[1], vec1[2]);
00412   }
00413   fprintf(outfile, "]\n");
00414 
00415   // emit surface normals
00416   fprintf(outfile, "  \"N\" [ ");
00417   for (i=0; i<numverts; i++) {
00418     (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
00419     fprintf(outfile, "%g %g %g ", norm1[0], norm1[1], norm1[2]);
00420   }
00421   fprintf(outfile, "]\n");
00422 
00423   // don't emit per-vertex colors when volumetric texturing is enabled
00424   fprintf(outfile, "  \"Cs\" [ ");
00425   for (i=0; i<numverts; i++) {
00426     int idx = i * 10;
00427     fprintf(outfile, "%g %g %g ", cnv[idx], cnv[idx+1], cnv[idx+2]);
00428   }
00429   fprintf(outfile, "]\n");
00430 
00431   fprintf(outfile, "\n");
00432 }
00433 
00434 
00435 void RenderManDisplayDevice::tristrip(int numverts, const float * cnv,
00436                                       int numstrips, const int *vertsperstrip,
00437                                       const int *facets) {
00438   float vec1[3];
00439   float norm1[3];
00440   int i;
00441   // render triangle strips one triangle at a time
00442   // triangle winding order is:
00443   //   v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc.
00444   int strip, v = 0;
00445   int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
00446 
00447   write_materials(0);
00448 
00449   fprintf(outfile, "PointsPolygons");
00450 
00451   // emit vertex counts for each face
00452   fprintf(outfile, "  [ ");
00453   // loop over all of the triangle strips
00454   for (strip=0; strip < numstrips; strip++) {
00455     for (i=0; i<(vertsperstrip[strip] - 2); i++) {
00456       fprintf(outfile, "3 ");
00457     }
00458   }
00459   fprintf(outfile, "]\n");
00460 
00461   // emit vertex indices for each facet
00462   fprintf(outfile, "  [ ");
00463   for (strip=0; strip < numstrips; strip++) {
00464     for (i=0; i<(vertsperstrip[strip] - 2); i++) {
00465       // render one triangle, using lookup table to fix winding order
00466       fprintf(outfile, "%d %d %d ",
00467               facets[v + (stripaddr[i & 0x01][0])],
00468               facets[v + (stripaddr[i & 0x01][1])],
00469               facets[v + (stripaddr[i & 0x01][2])]);
00470       v++; // move on to next vertex
00471     }
00472     v+=2; // last two vertices are already used by last triangle
00473   }
00474   fprintf(outfile, "]\n");
00475 
00476   // emit vertex coordinates
00477   fprintf(outfile, "  \"P\" [ ");
00478   for (i=0; i<numverts; i++) {
00479     (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
00480     fprintf(outfile, "%g %g %g ", vec1[0], vec1[1], vec1[2]);
00481   }
00482   fprintf(outfile, "]\n");
00483 
00484   // emit surface normals
00485   fprintf(outfile, "  \"N\" [ ");
00486   for (i=0; i<numverts; i++) {
00487     (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
00488     fprintf(outfile, "%g %g %g ", norm1[0], norm1[1], norm1[2]);
00489   }
00490   fprintf(outfile, "]\n");
00491 
00492   // don't emit per-vertex colors when volumetric texturing is enabled
00493   fprintf(outfile, "  \"Cs\" [ ");
00494   for (i=0; i<numverts; i++) {
00495     int idx = i * 10;
00496     fprintf(outfile, "%g %g %g ", cnv[idx], cnv[idx+1], cnv[idx+2]);
00497   }
00498   fprintf(outfile, "]\n");
00499 
00500   fprintf(outfile, "\n");
00501 }
00502 
00503 
00504 // draw a square
00505 void RenderManDisplayDevice::square(float *n, float *a, float *b, float *c, float *d) {
00506   float vec1[3], vec2[3], vec3[3], vec4[3];
00507   float norm[3];
00508 
00509   // Transform the world coordinates
00510   (transMat.top()).multpoint3d(a, vec1);
00511   (transMat.top()).multpoint3d(b, vec2);
00512   (transMat.top()).multpoint3d(c, vec3);
00513   (transMat.top()).multpoint3d(d, vec4);
00514   (transMat.top()).multnorm3d(n, norm);
00515 
00516   // Write the square
00517   write_materials(1);
00518   fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g %g %g %g ] ",
00519           vec1[0], vec1[1], vec1[2],
00520           vec2[0], vec2[1], vec2[2],
00521           vec3[0], vec3[1], vec3[2],
00522           vec4[0], vec4[1], vec4[2]);
00523   fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g %g %g %g ]\n",
00524           norm[0], norm[1], norm[2],
00525           norm[0], norm[1], norm[2],
00526           norm[0], norm[1], norm[2],
00527           norm[0], norm[1], norm[2]);
00528 }
00529 
00530 
00531 // display a comment
00532 void RenderManDisplayDevice::comment(const char *s) {
00533   fprintf(outfile, "# %s\n", s);
00534 }
00535 
00537 
00538 void RenderManDisplayDevice::write_header() {
00539   int i, n;
00540 
00541   // Initialize the RenderMan interface
00542   fprintf(outfile, "##RenderMan RIB-Structure 1.1\n");
00543   fprintf(outfile, "version 3.03\n");
00544   fprintf(outfile, "##Creator VMD %s\n", VMDVERSION);
00545   fprintf(outfile, "#\n");
00546   fprintf(outfile, "# Molecular graphics export from VMD %s\n", VMDVERSION);
00547   fprintf(outfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00548   fprintf(outfile, "#\n");
00549   fprintf(outfile, "# Requires PhotoRealistic RenderMan version 13\n");
00550   fprintf(outfile, "# Older versions may work, but have not been tested...\n");
00551   fprintf(outfile, "#\n");
00552 
00553   fprintf(outfile, "# VMD output image resolution and aspect ratio\n");
00554   fprintf(outfile, "Display \"plot.tif\" \"file\" \"rgba\"\n");
00555   fprintf(outfile, "Format %ld %ld 1\n", xSize, ySize);
00556   fprintf(outfile, "FrameAspectRatio %g\n", Aspect);
00557 
00558   // background color rendering takes longer, but is expected behavior
00559   fprintf(outfile, "# VMD background color\n");
00560   fprintf(outfile, "# Background colors may slow down rendering, \n");
00561   fprintf(outfile, "# but this is what VMD users expect by default\n");
00562   fprintf(outfile, "# Comment these lines for a transparent background:\n");
00563   fprintf(outfile, "Declare \"bgcolor\" \"uniform color\"\n");
00564   fprintf(outfile, "Imager \"background\" \"bgcolor\" [%g %g %g]\n",
00565           backColor[0], backColor[1], backColor[2]);
00566 
00567   fprintf(outfile, "# VMD camera definition\n");
00568   if (projection() == PERSPECTIVE) {
00569     // XXX after changing the RIB file to move the inversion of the 
00570     //     Z directions for left-to-right handedness conversion from
00571     //     the camera parameter block into the world transformations, 
00572     //     I somehow picked up an extra unit of translation (not sure how)
00573     //     so I compensate for that here by adjusting the FOV calculation.
00574     fprintf(outfile, "Projection \"perspective\" \"fov\" %g\n",
00575             360.0*atan2((double) 0.5*vSize, (double) 1.0+eyePos[2]-zDist)*VMD_1_PI);
00576   } else {
00577     // scaling necessary to equalize sizes of vmd screen and image 
00578     fprintf(outfile, "ScreenWindow %g %g %g %g\n",
00579             -Aspect*vSize/4, Aspect*vSize/4, -vSize/4, vSize/4);
00580     fprintf(outfile, "Projection \"orthographic\"\n");
00581   }
00582 
00583   // Set up the camera position, negate Z for right-handed coordinate system
00584   fprintf(outfile, "Translate %g %g %g\n", -eyePos[0], -eyePos[1], eyePos[2]);
00585 
00586   // shadows on, comment out for no shadows
00587   fprintf(outfile, "# Comment out shadow lines below to disable shadows:\n");
00588   fprintf(outfile, "Declare \"shadows\" \"string\"\n");
00589   fprintf(outfile, "Attribute \"light\" \"shadows\" \"on\"\n" );
00590 
00591   // ambient light source (for ambient shading values)
00592   fprintf(outfile, "# VMD ambient light color\n");
00593   fprintf(outfile, "LightSource \"ambientlight\" 0 \"intensity\" [1.0] \"lightcolor\" [1 1 1]\n" );
00594   
00595   fprintf(outfile, "# VMD directional light sources:\n");
00596   n = 1;
00597   // Write out all the light sources as point lights
00598   for (i = 0; i < DISP_LIGHTS; i++) {
00599     if (lightState[i].on) {
00600 //      fprintf(outfile, "LightSource \"pointlight\" %d \"intensity\" [1.0] \"lightcolor\" [%g %g %g] \"from\" [%g %g %g]\n",
00601       fprintf(outfile, "LightSource \"distantlight\" %d \"intensity\" [1.0] \"lightcolor\" [%g %g %g] \"from\" [%g %g %g] \"to\" [0 0 0]\n",
00602       n++,
00603       lightState[i].color[0], lightState[i].color[1], lightState[i].color[2],
00604       lightState[i].pos[0], lightState[i].pos[1], -lightState[i].pos[2]);
00605     }
00606   }
00607 
00608 
00609   fprintf(outfile, "WorldBegin\n");
00610 
00611   // Make coordinate system right-handed
00612   fprintf(outfile, "# Make coordinate system right handed by applying a top\n");
00613   fprintf(outfile, "# level transformation to all subsequent geometry...\n");
00614   fprintf(outfile, "TransformBegin\n");
00615   fprintf(outfile, "  Scale 1 1 -1\n");
00616   fprintf(outfile, "# VMD scene begins here...\n");
00617 }
00618 
00619 
00620 void RenderManDisplayDevice::write_trailer(void){
00621   // Make coordinate system right-handed
00622   fprintf(outfile, "# VMD scene ends here...\n");
00623   fprintf(outfile, "# \n");
00624   fprintf(outfile, "# End right-handed coordinate system transformation...\n");
00625   fprintf(outfile, "TransformEnd\n");
00626 
00627   fprintf(outfile, "WorldEnd\n");
00628   reset_vars(); // reinitialize material cache
00629 }
00630 
00631 
00632 void RenderManDisplayDevice::write_materials(int write_color) {
00633   // keep track of what the last written material properties
00634   // are, that way we can avoid writing redundant def's
00635   if (write_color) {
00636     // the color has changed since last write, emit an update 
00637     if ((matData[colorIndex][0] != old_color[0]) ||
00638         (matData[colorIndex][1] != old_color[1]) ||
00639         (matData[colorIndex][2] != old_color[2])) {
00640       fprintf(outfile, "  Color %g %g %g\n",
00641               matData[colorIndex][0], 
00642               matData[colorIndex][1],
00643               matData[colorIndex][2]);
00644       // save the last color
00645       memcpy(old_color, matData[colorIndex], sizeof(float) * 3);
00646     }
00647   }
00648 
00649   // now check opacity
00650   if (mat_opacity != old_opacity) {
00651     fprintf(outfile, "  Opacity %g %g %g\n", 
00652             mat_opacity, mat_opacity, mat_opacity);
00653     old_opacity = mat_opacity;
00654   }
00655 
00656   // and the lighting and roughness coefficients
00657   if ((mat_ambient != old_ambient) || 
00658       (mat_diffuse != old_diffuse) ||
00659       (mat_specular != old_specular)) {
00660     float roughness=10000.0;
00661     if (mat_shininess > 0.00001f) {
00662       roughness = 1.0f / mat_shininess;
00663     }
00664     fprintf(outfile, "  Surface \"plastic\"" 
00665             "\"Ka\" %g \"Kd\" %g \"Ks\" %g \"roughness\" %g\n",
00666             mat_ambient, mat_diffuse, mat_specular, roughness);
00667     old_ambient = mat_ambient;
00668     old_specular = mat_specular;
00669     old_diffuse = mat_diffuse;
00670   }
00671 }
00672 
00673 
00674 

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