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

RenderManDisplayDevice.C

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

Generated on Fri Nov 8 02:45:30 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002