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

FileRenderer.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: FileRenderer.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.172 $      $Date: 2013/03/07 19:39:28 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  * 
00019  * The FileRenderer class implements the data and functions needed to 
00020  * render a scene to a file in some format (postscript, raster3d, etc.)
00021  *
00022  ***************************************************************************/
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include "utilities.h"
00027 #include "DispCmds.h"
00028 #include "FileRenderer.h"
00029 #include "VMDDisplayList.h"
00030 #include "Inform.h"
00031 #include "Scene.h"
00032 #include "Hershey.h"
00033 
00034 // constructor
00035 FileRenderer::FileRenderer(const char *public_name, 
00036                            const char *public_pretty_name,
00037                            const char *default_file_name,
00038                            const char *default_command_line) : 
00039   DisplayDevice(public_name), transMat(10)
00040 {
00041   // save the various names
00042   publicName = stringdup(public_name);
00043   publicPrettyName = stringdup(public_pretty_name);
00044   defaultFilename = stringdup(default_file_name);
00045   defaultCommandLine = stringdup(default_command_line);
00046   execCmd = stringdup(defaultCommandLine);
00047   has_aa = 0;
00048   aasamples = -1;
00049   has_imgsize = 0;
00050   imgwidth = imgheight = 0;
00051   aspectratio = 0.0f;
00052   curformat = -1;
00053   textoffset_x = 0; 
00054   textoffset_y = 0;
00055   warningflags = FILERENDERER_NOWARNINGS;
00056 
00057   // init some state variables
00058   outfile = NULL;
00059   isOpened = FALSE;
00060   my_filename = NULL;
00061 
00062   // initialize sphere tesselation variables
00063   sph_nverts = 0;
00064   sph_verts = NULL;
00065 }
00066 
00067 // close (to be on the safe side) and delete
00068 FileRenderer::~FileRenderer(void) {
00069   // free sphere tessellation data
00070   if (sph_verts && sph_nverts) 
00071     free(sph_verts);
00072 
00073   close_file();
00074   delete [] my_filename;
00075   delete [] publicName;
00076   delete [] publicPrettyName;
00077   delete [] defaultFilename;
00078   delete [] defaultCommandLine;
00079   delete [] execCmd;
00080 }
00081 
00082 int FileRenderer::do_define_light(int n, float *color, float *position) {
00083   if (n < 0 || n >= DISP_LIGHTS)
00084     return FALSE;
00085 
00086   for (int i=0; i<3; i++) {
00087     lightState[n].color[i] = color[i];
00088     lightState[n].pos[i] = position[i];
00089   }
00090   return TRUE;
00091 }
00092 
00093 int FileRenderer::do_activate_light(int n, int turnon) {
00094   if (n < 0 || n >= DISP_LIGHTS)
00095     return FALSE;
00096 
00097   lightState[n].on = turnon;
00098   return TRUE;
00099 }
00100 
00101 int FileRenderer::do_define_adv_light(int n, float *color,
00102                                       float *position,
00103                                       float constant, float linear, float quad,
00104                                       float *spotdir, float fallstart, 
00105                                       float fallend, int spoton) {
00106   if(n < 0 || n >= DISP_LIGHTS)
00107     return FALSE;
00108 
00109   for (int i=0; i < 3; i++) {
00110     advLightState[n].color[i] = color[i];
00111     advLightState[n].pos[i] = position[i];
00112     advLightState[n].spotdir[i] = spotdir[i];
00113   }
00114   advLightState[n].constfactor = constant;
00115   advLightState[n].linearfactor = linear;
00116   advLightState[n].quadfactor = quad;
00117   advLightState[n].fallstart = fallstart;
00118   advLightState[n].fallend = fallend;
00119   advLightState[n].spoton = spoton;
00120   return TRUE;
00121 }
00122 
00123 int FileRenderer::do_activate_adv_light(int n, int turnon) {
00124   if (n < 0 || n >= DISP_LIGHTS)
00125     return FALSE;
00126 
00127   advLightState[n].on = turnon;
00128   return TRUE;
00129 }
00130 
00131 
00132 
00133 void FileRenderer::do_use_colors() {
00134   for (int i=0; i<MAXCOLORS; i++) {
00135     matData[i][0] = colorData[3*i  ];
00136     matData[i][1] = colorData[3*i+1];
00137     matData[i][2] = colorData[3*i+2];
00138   }
00139 }
00140 
00141 int FileRenderer::set_imagesize(int *w, int *h) {
00142   if (*w < 0 || *h < 0) return FALSE;
00143   if (*w == imgwidth && *h == imgheight) return TRUE;
00144   if (!aspectratio) {
00145     if (*w) imgwidth = *w; 
00146     if (*h) imgheight = *h;
00147   } else {
00148     if (*w) {
00149       imgwidth = *w;
00150       imgheight = (int)(*w / aspectratio);
00151     } else if (*h) {
00152       imgwidth = (int)(*h * aspectratio);
00153       imgheight = *h;
00154     } else {
00155       if (imgwidth || imgheight) {
00156         int wtmp = imgwidth, htmp = imgheight;
00157         set_imagesize(&wtmp, &htmp);
00158       }
00159     }
00160   }
00161   update_exec_cmd();
00162   *w = imgwidth;
00163   *h = imgheight;
00164   return TRUE;
00165 }
00166 
00167 float FileRenderer::set_aspectratio(float aspect) {
00168   if (aspect >= 0) aspectratio = aspect;
00169   int w=0, h=0;
00170   set_imagesize(&w, &h);  // update_exec_cmd() called from set_imagesize() 
00171   return aspectratio;
00172 }
00173 
00174 int FileRenderer::nearest_index(float r, float g, float b) const {
00175    const float *rcol = matData[BEGREGCLRS];  // get the solid colors
00176    float lsq = r - rcol[0]; lsq *= lsq;
00177    float tmp = g - rcol[1]; lsq += tmp * tmp;
00178          tmp = b - rcol[2]; lsq += tmp * tmp;
00179    float best = lsq;
00180    int bestidx = BEGREGCLRS;
00181    for (int n=BEGREGCLRS+1; n < (BEGREGCLRS + REGCLRS + MAPCLRS); n++) {
00182      rcol = matData[n];
00183      lsq = r - rcol[0]; lsq *= lsq;
00184      tmp = g - rcol[1]; lsq += tmp * tmp;
00185      tmp = b - rcol[2]; lsq += tmp * tmp;
00186      if (lsq < best) {
00187        best = lsq;
00188        bestidx = n;
00189      }
00190    }
00191    return bestidx;
00192 }
00193 
00194 void FileRenderer::set_background(const float * bg) {
00195   backColor[0] = bg[0];
00196   backColor[1] = bg[1];
00197   backColor[2] = bg[2];
00198 }
00199 
00200 void FileRenderer::set_backgradient(const float *top, const float *bot) {
00201   vec_copy(backgradienttopcolor, top);
00202   vec_copy(backgradientbotcolor, bot);
00203 }
00204 
00205 
00206 // open file, closing the previous file if it was still open
00207 int FileRenderer::open_file(const char *filename) {
00208   if (isOpened) {
00209     close_file();
00210   }
00211   if ((outfile = fopen(filename, "w")) == NULL) {
00212     msgErr << "Could not open file " << filename
00213            << " in current directory for writing!" << sendmsg;
00214     return FALSE;
00215   }
00216   my_filename = stringdup(filename);
00217   isOpened = TRUE;
00218   reset_state();
00219   return TRUE;
00220 }
00221 
00222 void FileRenderer::reset_state(void) {
00223   // empty out the viewing stack
00224   while (transMat.num()) {
00225     transMat.pop();
00226   }
00227   // reset everything else
00228   colorIndex = -1;
00229   materialIndex = -1;
00230   lineWidth = 1;
00231   lineStyle = ::SOLIDLINE;
00232   pointSize = 1;
00233   sphereResolution = 4;
00234   sphereStyle = 1;
00235   materials_on = 0;
00236 }
00237 
00238 // close the file.  This could be called by open_file if the previous
00239 // file wasn't closed, so don't put too much here
00240 void FileRenderer::close_file(void) {
00241   if (outfile) {
00242     fclose(outfile);
00243     outfile = NULL;
00244   }
00245   delete [] my_filename;
00246   my_filename = NULL;
00247   isOpened = FALSE;
00248 }
00249 
00250 
00251 int FileRenderer::prepare3D(int) {
00252   // set the eye position, based on the value of whichEye, which was
00253   // obtained when we copied the current visible display device to the
00254   // file renderer.  
00255   int i;
00256   float lookat[3];
00257   for (i=0; i<3; i++) 
00258     lookat[i] = eyePos[i] + eyeDir[i];
00259 
00260   switch (whichEye) {
00261     case LEFTEYE:
00262       for (i=0; i<3; i++) 
00263         eyePos[i] -= eyeSepDir[i];
00264   
00265       for (i=0; i<3; i++) 
00266         eyeDir[i] = lookat[i] - eyePos[i];
00267       break; 
00268 
00269     case RIGHTEYE:
00270       for (i=0; i<3; i++) 
00271         eyePos[i] += eyeSepDir[i]; 
00272 
00273       for (i=0; i<3; i++) 
00274         eyeDir[i] = lookat[i] - eyePos[i];
00275       break;
00276 
00277     case NOSTEREO: 
00278       break;
00279   }
00280 
00281   if (isOpened) {
00282     write_header();
00283   }
00284 
00285   return TRUE;
00286 }
00287 
00289 
00290 void FileRenderer::render(const VMDDisplayList *cmdList) {
00291   if (!cmdList) return;
00292   int tok, i;
00293   char *cmdptr; 
00294 
00295   // scan through the list and do the action based on the token type
00296   // if the command relates to the viewing state, keep track of it
00297   // for those renderers that don't store state
00298   while (transMat.num()) {    // clear the stack
00299     transMat.pop();
00300   }
00301   Matrix4 m;
00302   transMat.push(m);           // push on the identity matrix
00303   super_multmatrix(cmdList->mat.mat);
00304 
00305   colorIndex = 0;
00306   materialIndex = 0;
00307   float textsize = 1;
00308   pointSize = 1;
00309   lineWidth = 1;
00310   lineStyle = ::SOLIDLINE;
00311   sphereResolution = 4;
00312   sphereStyle = 1;
00313  
00314   // set the material properties
00315   super_set_material(cmdList->materialtag);
00316   mat_ambient   = cmdList->ambient;
00317   mat_specular  = cmdList->specular;
00318   mat_diffuse   = cmdList->diffuse;
00319   mat_shininess = cmdList->shininess;
00320   mat_opacity   = cmdList->opacity;
00321   mat_outline   = cmdList->outline;
00322   mat_outlinewidth = cmdList->outlinewidth;
00323   mat_transmode = cmdList->transmode;
00324 
00325   for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00326     clip_mode[i] = cmdList->clipplanes[i].mode;
00327     memcpy(&clip_center[i][0], &cmdList->clipplanes[i].center, 3*sizeof(float));
00328     memcpy(&clip_normal[i][0], &cmdList->clipplanes[i].normal, 3*sizeof(float));
00329     memcpy(&clip_color[i][0],  &cmdList->clipplanes[i].color,  3*sizeof(float));
00330   }
00331   start_clipgroup();
00332 
00333   // Compute periodic images
00334   ResizeArray<Matrix4> pbcImages;
00335   find_pbc_images(cmdList, pbcImages);
00336 
00337   // initialize text offset variables.  These values should never be
00338   // set in one display list and applied in another, so we reset the
00339   // variables to zero here at the start of each display list.
00340   textoffset_x = 0;
00341   textoffset_y = 0;
00342 
00343 int nimages = pbcImages.num();
00344 for (int pbcimage = 0; pbcimage < nimages; pbcimage++) {
00345  transMat.dup();
00346  super_multmatrix(pbcImages[pbcimage].mat);
00347 
00348   VMDDisplayList::VMDLinkIter cmditer;
00349   cmdList->first(&cmditer);
00350   while ((tok = cmdList->next(&cmditer, cmdptr))  != DLASTCOMMAND) {
00351     switch (tok) {   // plot a point
00352     case DPOINT:
00353       point(((DispCmdPoint *)cmdptr)->pos);  
00354       break;
00355 
00356     case DPOINTARRAY:
00357       {
00358       DispCmdPointArray *pa = (DispCmdPointArray *)cmdptr;
00359       float *centers, *colors;
00360       pa->getpointers(centers, colors);
00361       point_array(pa->numpoints, pa->size, centers, colors);
00362       }
00363       break;
00364 
00365     case DLITPOINTARRAY:
00366       {
00367       DispCmdLitPointArray *pa = (DispCmdLitPointArray *)cmdptr;
00368       float *centers, *normals, *colors;
00369       pa->getpointers(centers, normals, colors);
00370       point_array_lit(pa->numpoints, pa->size, centers, normals, colors);
00371       }
00372       break;
00373 
00374     case DSPHERE:    // draw a sphere
00375       sphere((float *)cmdptr);  
00376       break;
00377 
00378     case DSPHEREARRAY:     
00379       {
00380       DispCmdSphereArray *sa = (DispCmdSphereArray *)cmdptr;
00381       float *centers, *radii, *colors;
00382       sa->getpointers(centers, radii, colors);
00383       sphere_array(sa->numspheres, sa->sphereres, centers, radii, colors);
00384       }
00385       break;
00386 
00387     case DLINE:    // plot a line
00388       // don't draw degenerate lines of zero length
00389       if (memcmp(cmdptr, cmdptr+3*sizeof(float), 3*sizeof(float))) {
00390         line((float *)cmdptr, ((float *)cmdptr) + 3);
00391       }
00392       break;
00393    
00394     case DLINEARRAY: // array of lines
00395       {
00396       float *v = (float *) cmdptr;
00397       int nlines = (int)v[0];
00398       v++; // vertex array begins on next floating point word
00399       line_array(nlines, (float) lineWidth, v);
00400       }
00401       break; 
00402 
00403     case DPOLYLINEARRAY: // array of lines
00404       {
00405       float *v = (float *) cmdptr;
00406       int nlines = (int)v[0];
00407       v++; // vertex array begins on next floating point word
00408       polyline_array(nlines, (float) lineWidth, v);
00409       }
00410       break; 
00411 
00412     case DCYLINDER: // plot a cylinder
00413       if (memcmp(cmdptr, cmdptr+3*sizeof(float), 3*sizeof(float))) {
00414         cylinder((float *)cmdptr, ((float *)cmdptr) + 3, ((float *)cmdptr)[6],
00415                  ((int) ((float *) cmdptr)[8]));
00416       }
00417       break;
00418 
00419     case DCONE:      // plot a cone  
00420       {
00421       DispCmdCone *cmd = (DispCmdCone *)cmdptr;
00422       if (memcmp(cmd->pos1, cmd->pos2, 3*sizeof(float))) 
00423         cone_trunc(cmd->pos1, cmd->pos2, cmd->radius, cmd->radius2, cmd->res);
00424       }
00425       break;
00426    
00427     case DTRIANGLE:    // plot a triangle
00428       {
00429       DispCmdTriangle *cmd = (DispCmdTriangle *)cmdptr;
00430       triangle(cmd->pos1,cmd->pos2,cmd->pos3,
00431                cmd->norm1, cmd->norm2, cmd->norm3);
00432       }
00433       break;
00434 
00435     case DTRIMESH_C3F_N3F_V3F: // draw a triangle mesh
00436       {
00437       DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00438       float *c=NULL, *n=NULL, *v=NULL;
00439 
00440       if (cmd->pervertexcolors) {
00441         cmd->getpointers(c, n, v);
00442         trimesh_c3f_n3f_v3f(c, n, v, cmd->numfacets); 
00443       } else {
00444         cmd->getpointers(n, v);
00445         trimesh_n3f_v3f(n, v, cmd->numfacets); 
00446       }
00447       }
00448       break;
00449 
00450     case DTRIMESH_C4F_N3F_V3F: // draw a triangle mesh
00451       {
00452       DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00453       float *cnv=NULL;
00454       int *f=NULL;
00455       cmd->getpointers(cnv, f);
00456       trimesh_c4n3v3(cmd->numverts, cnv, cmd->numfacets, f); 
00457       }
00458       break;
00459 
00460     case DTRIMESH_C4U_N3F_V3F: // draw a triangle mesh
00461       {
00462       DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00463       unsigned char *c=NULL; 
00464       float *n=NULL, *v=NULL;
00465 
00466       if (cmd->pervertexcolors) {
00467         cmd->getpointers(c, n, v);
00468         trimesh_c4u_n3f_v3f(c, n, v, cmd->numfacets); 
00469       } else {
00470         cmd->getpointers(n, v);
00471         trimesh_n3f_v3f(n, v, cmd->numfacets); 
00472       }
00473       }
00474       break;
00475 
00476     case DTRIMESH_C4U_N3B_V3F: // draw a triangle mesh
00477       {
00478       DispCmdTriMesh *cmd = (DispCmdTriMesh *) cmdptr;
00479       unsigned char *c=NULL; 
00480       char *n=NULL;
00481       float *v=NULL;
00482 
00483       if (cmd->pervertexcolors) {
00484         cmd->getpointers(c, n, v);
00485         trimesh_c4u_n3b_v3f(c, n, v, cmd->numfacets); 
00486       } else {
00487         cmd->getpointers(n, v);
00488         trimesh_n3b_v3f(n, v, cmd->numfacets); 
00489       }
00490       }
00491       break;
00492 
00493     case DTRISTRIP:     // draw a triangle strip
00494       {
00495       DispCmdTriStrips *cmd = (DispCmdTriStrips *) cmdptr;
00496       float *cnv=NULL;
00497       int *f=NULL;
00498       int *vertsperstrip;
00499       cmd->getpointers(cnv, f, vertsperstrip);
00500       tristrip(cmd->numverts, cnv, cmd->numstrips, vertsperstrip, f); 
00501       }
00502       break;
00503 
00504     case DWIREMESH:     // draw a triangle mesh in wireframe
00505       {
00506       DispCmdWireMesh *cmd = (DispCmdWireMesh *) cmdptr;
00507       float *cnv=NULL;
00508       int *l=NULL;
00509       cmd->getpointers(cnv, l);
00510       wiremesh(cmd->numverts, cnv, cmd->numlines, l); 
00511       }
00512       break;
00513 
00514     case DSQUARE:      // plot a square (norm, 4 verticies
00515       {
00516       DispCmdSquare *cmd = (DispCmdSquare *)cmdptr;
00517       square(cmd->norml, cmd->pos1, cmd->pos2, cmd->pos3, cmd->pos4);
00518       }
00519       break;
00520 
00521 
00523     case DLINEWIDTH:   //  set the line width (and in superclass)
00524       lineWidth = ((DispCmdLineWidth *)cmdptr)->width;
00525       set_line_width(lineWidth);
00526       break;
00527 
00528     case DLINESTYLE:   // set the line style (and in superclass)
00529       lineStyle = ((DispCmdLineType *)cmdptr)->type;
00530       set_line_style(lineStyle);
00531       break;
00532 
00533     case DSPHERERES:   // sphere resolution (and in superclass)
00534       sphereResolution = ((DispCmdSphereRes *)cmdptr)->res;
00535       set_sphere_res(sphereResolution);
00536       break;
00537 
00538     case DSPHERETYPE:   // sphere resolution (and in superclass)
00539       sphereStyle = ((DispCmdSphereType *)cmdptr)->type;
00540       set_sphere_style(sphereStyle);
00541       break;
00542 
00543     case DMATERIALON:
00544       super_materials(1); 
00545       break;
00546 
00547     case DMATERIALOFF:
00548       super_materials(0); 
00549       break;
00550 
00551     case DCOLORINDEX:  // change the color
00552       super_set_color(((DispCmdColorIndex *)cmdptr)->color);
00553       break; 
00554 
00555     case DTEXTSIZE:
00556       textsize = ((DispCmdTextSize *)cmdptr)->size;
00557       break;
00558 
00559     case DTEXTOFFSET:
00560       textoffset_x = ((DispCmdTextOffset *)cmdptr)->x;
00561       textoffset_y = ((DispCmdTextOffset *)cmdptr)->y;
00562       break;
00563 
00564     case DTEXT: 
00565       {
00566       float *pos = (float *)cmdptr;
00567       text(pos, textsize, pos[3], (char *) (pos+4));
00568       }
00569       break;
00570 
00571     case DBEGINREPGEOMGROUP:
00572       beginrepgeomgroup((char *)cmdptr);
00573       break;
00574 
00575     case DCOMMENT:
00576       comment((char *)cmdptr);
00577       break;
00578 
00579     // pick selections (only one implemented)
00580     case DPICKPOINT:
00581       pick_point(((DispCmdPickPoint *)cmdptr)->postag,
00582                  ((DispCmdPickPoint *)cmdptr)->tag); 
00583       break;
00584 
00585     case DPICKPOINT_ARRAY:
00586       { 
00587         int i;
00588         DispCmdPickPointArray *cmd =  ((DispCmdPickPointArray *)cmdptr);
00589         float *crds=NULL;
00590         int *indices=NULL;
00591         cmd->getpointers(crds, indices);
00592         if (cmd->allselected) {
00593           for (i=0; i<cmd->numpicks; i++) {
00594             pick_point(crds + i*3, i);
00595           }
00596         } else {
00597           for (i=0; i<cmd->numpicks; i++) {
00598             pick_point(crds + i*3, indices[i]); 
00599           }
00600         }
00601       }
00602       break;
00603 
00604     // generate warnings if any geometry token is unimplemented the renderer
00605 #if 0
00606     case DSTRIPETEXON:
00607     case DSTRIPETEXOFF:
00608 #endif
00609     case DVOLUMETEXTURE:
00610       {
00611       DispCmdVolumeTexture *cmd = (DispCmdVolumeTexture *)cmdptr;
00612       float xplaneeq[4];
00613       float yplaneeq[4];
00614       float zplaneeq[4];
00615       int i;
00616 
00617       // automatically generate texture coordinates by translating from
00618       // model coordinate space to volume coordinates.
00619       for (i=0; i<3; i++) {
00620         xplaneeq[i] = cmd->v1[i];
00621         yplaneeq[i] = cmd->v2[i];
00622         zplaneeq[i] = cmd->v3[i];
00623       }
00624       xplaneeq[3] = cmd->v0[0];
00625       yplaneeq[3] = cmd->v0[1];
00626       zplaneeq[3] = cmd->v0[2];
00627 
00628       // define a volumetric texture map
00629       define_volume_texture(cmd->ID, cmd->xsize, cmd->ysize, cmd->zsize,
00630                             xplaneeq, yplaneeq, zplaneeq,
00631                             cmd->texmap);
00632       volume_texture_on(1);
00633       }
00634       break;
00635 
00636     case DVOLSLICE:
00637       {
00638       // Since OpenGL is using texture-replace here, we emulate that
00639       // by disabling lighting altogether
00640       super_materials(0); 
00641       DispCmdVolSlice *cmd = (DispCmdVolSlice *)cmdptr;
00642       volume_texture_on(1);
00643       square(cmd->normal, cmd->v, cmd->v + 3, cmd->v + 6, cmd->v + 9); 
00644       volume_texture_off();
00645       super_materials(1); 
00646       }
00647       break;
00648 
00649     case DVOLTEXON:
00650       volume_texture_on(0);
00651       break;
00652 
00653     case DVOLTEXOFF:
00654       volume_texture_off();
00655       break;
00656 
00657 #if 0
00658     // generate warnings if any geometry token is unimplemented the renderer
00659     default:
00660       warningflags |= FILERENDERER_NOMISCFEATURE;
00661       break;
00662 #endif
00663     } // end of switch statement
00664   } // while (tok != DLASTCOMMAND)
00665  transMat.pop();
00666 } // end of loop over periodic images
00667   end_clipgroup();
00668 }
00669 
00671 
00672 
00673 // change the active color
00674 void FileRenderer::super_set_color(int color_index) {
00675   if (colorIndex != color_index) {
00676     colorIndex = color_index;
00677     set_color(color_index);
00678   }
00679 }
00680 
00681 // change the active material
00682 void FileRenderer::super_set_material(int material_index) {
00683   if (materialIndex != material_index) {
00684     materialIndex = material_index;
00685     set_material(material_index);
00686   }
00687 }
00688 
00689 // turn materials on or off
00690 void FileRenderer::super_materials(int on_or_off) {
00691   if (on_or_off) {
00692     materials_on = 1;
00693     activate_materials();
00694   } else {
00695     materials_on = 0;
00696     deactivate_materials();
00697   }
00698 }
00699 
00700 
00702 
00703 void FileRenderer::super_load(float *cmdptr) {
00704   Matrix4 tmp(cmdptr);
00705   (transMat.top()).loadmatrix(tmp);
00706   load(tmp);
00707 }
00708 void FileRenderer::super_multmatrix(const float *cmdptr) {
00709   Matrix4 tmp(cmdptr);
00710   (transMat.top()).multmatrix(tmp);
00711   multmatrix(tmp);
00712 }
00713 
00714 void FileRenderer::super_translate(float *cmdptr) {
00715   (transMat.top()).translate( cmdptr[0], cmdptr[1], cmdptr[2]);
00716   translate( cmdptr[0], cmdptr[1], cmdptr[2]);
00717 }
00718 
00719 void FileRenderer::super_rot(float * cmdptr) {
00720   (transMat.top()).rot( cmdptr[0], 'x' + (int) (cmdptr[1]) );
00721   rot( cmdptr[0], 'x' + (int) (cmdptr[1]) );
00722 }
00723 
00724 void FileRenderer::super_scale(float *cmdptr) {
00725   (transMat.top()).scale( cmdptr[0], cmdptr[1], cmdptr[2] );
00726   scale( cmdptr[0], cmdptr[1], cmdptr[2] );
00727 }
00728 
00729 void FileRenderer::super_scale(float s) {
00730   transMat.top().scale(s,s,s);
00731   scale(s,s,s);
00732 }
00733 
00734 // return global scaling factor (used for sphere radii, similar)
00735 float FileRenderer::scale_factor(void) {
00736   // of course, VMD does not have a direction-independent scaling
00737   // factor, so I'll fake it using an average of the scaling
00738   // factors in each direction.
00739   float scaleFactor;
00740 
00741   float *mat =  &transMat.top().mat[0];
00742   scaleFactor = (sqrtf(mat[0]*mat[0] + mat[4]*mat[4] + mat[ 8]*mat[ 8]) +
00743                  sqrtf(mat[1]*mat[1] + mat[5]*mat[5] + mat[ 9]*mat[ 9]) +
00744                  sqrtf(mat[2]*mat[2] + mat[6]*mat[6] + mat[10]*mat[10])) / 3.0f;
00745 
00746   return scaleFactor;
00747 }
00748 
00749 // scale the radius a by the global scaling factor, return as b.
00750 float FileRenderer::scale_radius(float r) {
00751   float scaleFactor = scale_factor();
00752   if (r < 0.0) {
00753     msgErr << "FileRenderer: Error, Negative radius" << sendmsg;
00754     r = -r;
00755   } 
00756   r = r * scaleFactor;
00757   return r;
00758 }
00759 
00760 
00762 void FileRenderer::set_exec_string(const char *extstr) {
00763   delete [] execCmd;
00764   execCmd = stringdup(extstr);
00765 }
00766 
00767 
00768 // default triangulated implementation of two-radius cones
00769 void FileRenderer::cone_trunc(float *base, float *apex, float radius, float radius2, int numsides) {
00770   int h;
00771   float theta, incTheta, cosTheta, sinTheta;
00772   float axis[3], temp[3], perp[3], perp2[3];
00773   float vert0[3], vert1[3], vert2[3], edge0[3], edge1[3], face0[3], face1[3], norm0[3], norm1[3];
00774 
00775   axis[0] = base[0] - apex[0];
00776   axis[1] = base[1] - apex[1];
00777   axis[2] = base[2] - apex[2];
00778   vec_normalize(axis);
00779 
00780   // Find an arbitrary vector that is not the axis and has non-zero length
00781   temp[0] = axis[0] - 1.0f;
00782   temp[1] = 1.0f;
00783   temp[2] = 1.0f;
00784 
00785   // use the cross product to find orthogonal vectors
00786   cross_prod(perp, axis, temp);
00787   vec_normalize(perp);
00788   cross_prod(perp2, axis, perp); // shouldn't need normalization
00789 
00790   // Draw the triangles
00791   incTheta = (float) VMD_TWOPI / numsides;
00792   theta = 0.0;
00793 
00794   // if radius2 is larger than zero, we will draw quadrilateral
00795   // panels rather than triangular panels
00796   if (radius2 > 0) {
00797     float negaxis[3], offsetL[3], offsetT[3], vert3[3];
00798     int filled=1;
00799     vec_negate(negaxis, axis);
00800     memset(vert0, 0, sizeof(vert0));
00801     memset(vert1, 0, sizeof(vert1));
00802     memset(norm0, 0, sizeof(norm0));
00803 
00804     for (h=0; h <= numsides+3; h++) {
00805       // project 2-D unit circles onto perp/perp2 3-D basis vectors
00806       // and scale to desired radii
00807       cosTheta = (float) cosf(theta);
00808       sinTheta = (float) sinf(theta);
00809       offsetL[0] = radius2 * (cosTheta*perp[0] + sinTheta*perp2[0]);
00810       offsetL[1] = radius2 * (cosTheta*perp[1] + sinTheta*perp2[1]);
00811       offsetL[2] = radius2 * (cosTheta*perp[2] + sinTheta*perp2[2]);
00812       offsetT[0] = radius  * (cosTheta*perp[0] + sinTheta*perp2[0]);
00813       offsetT[1] = radius  * (cosTheta*perp[1] + sinTheta*perp2[1]);
00814       offsetT[2] = radius  * (cosTheta*perp[2] + sinTheta*perp2[2]);
00815 
00816       // copy old vertices
00817       vec_copy(vert2, vert0); 
00818       vec_copy(vert3, vert1); 
00819       vec_copy(norm1, norm0); 
00820 
00821       // calculate new vertices
00822       vec_add(vert0, base, offsetT);
00823       vec_add(vert1, apex, offsetL);
00824 
00825       // Use the new vertex to find new edges
00826       edge0[0] = vert0[0] - vert1[0];
00827       edge0[1] = vert0[1] - vert1[1];
00828       edge0[2] = vert0[2] - vert1[2];
00829       edge1[0] = vert0[0] - vert2[0];
00830       edge1[1] = vert0[1] - vert2[1];
00831       edge1[2] = vert0[2] - vert2[2];
00832 
00833       // Use the new edge to find a new facet normal
00834       cross_prod(norm0, edge1, edge0);
00835       vec_normalize(norm0);
00836 
00837       if (h > 2) {
00838         // Use the new normal to draw the previous side
00839         triangle(vert0, vert3, vert1, norm0, norm1, norm0);
00840         triangle(vert3, vert0, vert2, norm1, norm0, norm1);
00841 
00842         // Draw cylinder caps
00843         if (filled & CYLINDER_LEADINGCAP) {
00844           triangle(vert1, vert3, apex, axis, axis, axis);
00845         }
00846         if (filled & CYLINDER_TRAILINGCAP) {
00847           triangle(vert0, vert2, base, negaxis, negaxis, negaxis);
00848         }
00849       }
00850 
00851       theta += incTheta;
00852     }
00853   } else {
00854     // radius2 is zero, so we draw triangular panels joined at the apex
00855     for (h=0; h < numsides+3; h++) {
00856       // project 2-D unit circle onto perp/perp2 3-D basis vectors
00857       // and scale to desired radius
00858       cosTheta = (float) cosf(theta);
00859       sinTheta = (float) sinf(theta);
00860       vert0[0] = base[0] + radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00861       vert0[1] = base[1] + radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00862       vert0[2] = base[2] + radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00863 
00864       // Use the new vertex to find a new edge
00865       edge0[0] = vert0[0] - apex[0];
00866       edge0[1] = vert0[1] - apex[1];
00867       edge0[2] = vert0[2] - apex[2];
00868 
00869       if (h > 0) {
00870         // Use the new edge to find a new face
00871         cross_prod(face0, edge1, edge0);
00872         vec_normalize(face0);
00873 
00874         if (h > 1) {
00875           // Use the new face to find the normal of the previous triangle
00876           norm0[0] = (face1[0] + face0[0]) * 0.5f;
00877           norm0[1] = (face1[1] + face0[1]) * 0.5f;
00878           norm0[2] = (face1[2] + face0[2]) * 0.5f;
00879           vec_normalize(norm0);
00880 
00881           if (h > 2) {
00882             // Use the new normal to draw the previous side and base of the cone
00883             triangle(vert2, vert1, apex, norm1, norm0, face1);
00884             triangle(vert2, vert1, base, axis, axis, axis);
00885           }
00886 
00887         }
00888 
00889         // Copy the old values
00890         memcpy(norm1, norm0, 3*sizeof(float));
00891         memcpy(vert2, vert1, 3*sizeof(float));
00892         memcpy(face1, face0, 3*sizeof(float));
00893       }
00894       memcpy(vert1, vert0, 3*sizeof(float));
00895       memcpy(edge1, edge0, 3*sizeof(float));
00896   
00897       theta += incTheta;
00898     }
00899   }
00900 }
00901 
00902 
00903 // default trianglulated cylinder implementation, with optional end caps
00904 void FileRenderer::cylinder(float *base, float *apex, float radius, int filled) {
00905   const int numsides = 20;
00906   int h;
00907   float theta, incTheta, cosTheta, sinTheta;
00908   float axis[3], negaxis[3], temp[3], perp[3], perp2[3], offset[3];
00909 
00910   axis[0] = base[0] - apex[0];
00911   axis[1] = base[1] - apex[1];
00912   axis[2] = base[2] - apex[2];
00913   vec_normalize(axis);
00914   vec_negate(negaxis, axis);
00915 
00916   // Find an arbitrary vector that is not the axis and has non-zero length
00917   temp[0] = axis[0] - 1.0f;
00918   temp[1] = 1.0f;
00919   temp[2] = 1.0f;
00920 
00921   // use the cross product to find orthogonal vectors
00922   cross_prod(perp, axis, temp);
00923   vec_normalize(perp);
00924   cross_prod(perp2, axis, perp); // shouldn't need normalization
00925 
00926   // Draw the triangles
00927   incTheta = (float) VMD_TWOPI / numsides;
00928   theta = 0.0;
00929 
00930   const int stripsz = (2*numsides) * 6;
00931   float *stripnv = new float[stripsz];
00932   memset(stripnv, 0, sizeof(float) * stripsz);
00933 
00934   const int capsz = numsides+1;
00935   float *lcapnv = new float[capsz*6];
00936   memset(lcapnv, 0, sizeof(float)*capsz*6);
00937   vec_copy(&lcapnv[0], negaxis);
00938   vec_copy(&lcapnv[3], apex);
00939 
00940   float *tcapnv = new float[capsz*6];
00941   memset(tcapnv, 0, sizeof(float)*capsz*6);
00942   vec_copy(&tcapnv[0], axis);
00943   vec_copy(&tcapnv[3], base);
00944 
00945   for (h=0; h < numsides; h++) {
00946     // project 2-D unit circle onto perp/perp2 3-D basis vectors
00947     // and scale to desired radius
00948     cosTheta = (float) cosf(theta);
00949     sinTheta = (float) sinf(theta);
00950     offset[0] = radius * (cosTheta*perp[0] + sinTheta*perp2[0]);
00951     offset[1] = radius * (cosTheta*perp[1] + sinTheta*perp2[1]);
00952     offset[2] = radius * (cosTheta*perp[2] + sinTheta*perp2[2]);
00953 
00954     // calculate new vertices
00955     float lvert[3], tvert[3];
00956     vec_add(lvert, apex, offset);
00957     vec_add(tvert, base, offset);
00958     vec_copy(&stripnv[((2*h)*6)+9], lvert); 
00959     vec_copy(&stripnv[((2*h)*6)+3], tvert); 
00960     vec_copy(&lcapnv[((1+h)*6)+3], lvert); 
00961     vec_copy(&tcapnv[((1+h)*6)+3], tvert); 
00962 
00963     // new normals
00964     vec_normalize(offset);
00965     vec_copy(&stripnv[((2*h)*6)  ], offset);
00966     vec_copy(&stripnv[((2*h)*6)+6], offset);
00967     vec_copy(&lcapnv[((1+h)*6)], negaxis);
00968     vec_copy(&tcapnv[((1+h)*6)], axis);
00969 
00970     theta += incTheta;
00971   }
00972 
00973   const int vertsperstrip = (numsides + 1)*2;
00974   int *stripfaces = new int[vertsperstrip];
00975   memset(stripfaces, 0, sizeof(float) * vertsperstrip);
00976   for (h=0; h < vertsperstrip-2; h++) {
00977     stripfaces[h] = h;
00978   }
00979   stripfaces[h  ] = 0; // wraparound to start
00980   stripfaces[h+1] = 1; // wraparound to start
00981 
00982   tristrip_singlecolor(2*numsides, &stripnv[0],
00983                        1, &colorIndex, &vertsperstrip, &stripfaces[0]);
00984   delete [] stripfaces;
00985 
00986   // Draw cylinder caps
00987   if (filled & CYLINDER_LEADINGCAP) {
00988     const int vertsperfan = capsz+1;
00989     int *fanfaces = new int[vertsperfan];
00990     memset(fanfaces, 0, sizeof(float) * vertsperfan);
00991     fanfaces[0] = 0;
00992     for (h=1; h < capsz; h++) {
00993       fanfaces[h] = capsz-h;
00994     }
00995     fanfaces[h] = capsz-1; // wraparound to start
00996     trifan_singlecolor(capsz-1, &lcapnv[0],
00997                        1, &colorIndex, &vertsperfan, &fanfaces[0]);
00998     delete [] fanfaces;
00999   }
01000   if (filled & CYLINDER_TRAILINGCAP) {
01001     const int vertsperfan = capsz+1;
01002     int *fanfaces = new int[vertsperfan];
01003     memset(fanfaces, 0, sizeof(float) * vertsperfan);
01004     fanfaces[0] = 0;
01005     for (h=1; h < capsz; h++) {
01006       fanfaces[h] = h;
01007     }
01008     fanfaces[h] = 1; // wraparound to start
01009     trifan_singlecolor(capsz-1, &tcapnv[0],
01010                        1, &colorIndex, &vertsperfan, &fanfaces[0]);
01011     delete [] fanfaces;
01012   }
01013 
01014   delete [] stripnv;
01015   delete [] lcapnv;
01016   delete [] tcapnv;
01017 }
01018 
01019 
01020 // default cylinder-based implementation of lines used
01021 // for ray tracing packages that can't draw real lines
01022 void FileRenderer::line(float * a, float * b) {
01023   // draw a line (cylinder) from a to b
01024   int i, j, test;
01025   float dirvec[3], unitdirvec[3];
01026   float from[3], to[3]; 
01027 
01028   if (lineStyle == ::SOLIDLINE) {
01029     cylinder(a, b, lineWidth * 0.002f, 0);
01030   } else if (lineStyle == ::DASHEDLINE) {
01031     vec_sub(dirvec, b, a);        // vector from a to b
01032     vec_copy(unitdirvec, dirvec);
01033     vec_normalize(unitdirvec);    // unit vector from a to b
01034     test = 1;
01035     i = 0;
01036     while (test == 1) {
01037       for (j=0; j<3; j++) {
01038         from[j] = (float) (a[j] + (2*i    )* 0.05 * unitdirvec[j]);
01039           to[j] = (float) (a[j] + (2*i + 1)* 0.05 * unitdirvec[j]);
01040       }
01041       if (fabsf(a[0] - to[0]) >= fabsf(dirvec[0])) {
01042         vec_copy(to, b);
01043         test = 0;
01044       }
01045       cylinder(from, to, lineWidth * 0.002f, 0);
01046       i++;
01047     }
01048   } 
01049 }
01050 
01051 
01052 void FileRenderer::line_array(int num, float thickness, float *points) {
01053   float *v = points;
01054   for (int i=0; i<num; i++) {
01055     // don't draw degenerate lines of zero length
01056     if (memcmp(v, v+3, 3*sizeof(float))) {
01057       line(v, v+3);
01058     }
01059     v += 6;
01060   }
01061 }
01062 
01063 
01064 void FileRenderer::polyline_array(int num, float thickness, float *points) {
01065   float *v = points;
01066   for (int i=0; i<num-1; i++) {
01067     // don't draw degenerate lines of zero length
01068     if (memcmp(v, v+3, 3*sizeof(float))) {
01069       line(v, v+3);
01070     }
01071     v += 3;
01072   }
01073 }
01074 
01075 
01076 // default triangulated sphere implementation
01077 void FileRenderer::sphere(float * xyzr) {
01078   float c[3], r;
01079   int pi, ni;
01080   int i;
01081   int sph_iter = -1;
01082   int sph_desired_iter = 0;
01083 
01084   // copy params
01085   vec_copy(c, xyzr);
01086   r = xyzr[3];
01087 
01088   // the sphere resolution has changed. if sphereRes is less than 32, we
01089   // will use a lookup table to achieve equal or better resolution than
01090   // OpenGL. otherwise we use the following equation:
01091   //    iterations = .9 *
01092   //    (sphereRes)^(1/2)
01093   // This is used as a lookup table to determine the proper
01094   // number of iterations used in the sphere approximation
01095   // algorithm.
01096   const int sph_iter_table[] = {
01097       0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
01098       3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
01099 
01100   if (sphereResolution < 0) 
01101     return;
01102   else if (sphereResolution < 32) 
01103     sph_desired_iter = sph_iter_table[sphereResolution];
01104   else 
01105     sph_desired_iter = (int) (0.8f * sqrtf((float) sphereResolution));
01106  
01107   // first we need to determine if a recalculation of the cached
01108   // unit sphere is necessary. this is necessary if the number
01109   // of desired iterations has changed.
01110   if (!sph_verts || !sph_nverts || sph_iter != sph_desired_iter) {
01111     float a[3], b[3], c[3];
01112     float *newverts;
01113     float *oldverts;
01114     int nverts, ntris;
01115     int level;
01116 
01117     // remove old cached copy
01118     if (sph_verts && sph_nverts) free(sph_verts);
01119 
01120     newverts = (float *) malloc(sizeof(float) * 36);
01121     nverts = 12;
01122     ntris = 4;
01123 
01124     // start with half of a unit octahedron (front, convex half)
01125 
01126     // top left triangle
01127     newverts[0] = -1;    newverts[1] = 0;     newverts[2] = 0;
01128     newverts[3] = 0;     newverts[4] = 1;     newverts[5] = 0;
01129     newverts[6] = 0;     newverts[7] = 0;     newverts[8] = 1;
01130 
01131     // top right triangle
01132     newverts[9] = 0;     newverts[10] = 0;    newverts[11] = 1;
01133     newverts[12] = 0;    newverts[13] = 1;    newverts[14] = 0;
01134     newverts[15] = 1;    newverts[16] = 0;    newverts[17] = 0;
01135 
01136     // bottom right triangle
01137     newverts[18] = 0;    newverts[19] = 0;    newverts[20] = 1;
01138     newverts[21] = 1;    newverts[22] = 0;    newverts[23] = 0;
01139     newverts[24] = 0;    newverts[25] = -1;   newverts[26] = 0;
01140 
01141     // bottom left triangle
01142     newverts[27] = 0;    newverts[28] = 0;    newverts[29] = 1;
01143     newverts[30] = 0;    newverts[31] = -1;   newverts[32] = 0;
01144     newverts[33] = -1;   newverts[34] = 0;    newverts[35] = 0;
01145 
01146     for (level = 1; level < sph_desired_iter; level++) {
01147       oldverts = newverts;
01148 
01149       // allocate memory for the next iteration: we will need
01150       // four times the current number of vertices
01151       newverts = (float *) malloc(sizeof(float) * 12 * nverts);
01152       if (!newverts) {
01153         // memory error
01154         sph_iter = -1;
01155         sph_nverts = 0;
01156         sph_verts = NULL;
01157         free(oldverts);
01158         msgErr << "FileRenderer::sphere(): Out of memory. Some "
01159                << "objects were not drawn." << sendmsg;
01160         return;
01161       }
01162 
01163       pi = 0;
01164       ni = 0;
01165       for (i = 0; i < ntris; i++) {
01166         // compute intermediate vertices
01167         a[0] = (oldverts[pi    ] + oldverts[pi + 6]) / 2;
01168         a[1] = (oldverts[pi + 1] + oldverts[pi + 7]) / 2;
01169         a[2] = (oldverts[pi + 2] + oldverts[pi + 8]) / 2;
01170         vec_normalize(a);
01171         b[0] = (oldverts[pi    ] + oldverts[pi + 3]) / 2;
01172         b[1] = (oldverts[pi + 1] + oldverts[pi + 4]) / 2;
01173         b[2] = (oldverts[pi + 2] + oldverts[pi + 5]) / 2;
01174         vec_normalize(b);
01175         c[0] = (oldverts[pi + 3] + oldverts[pi + 6]) / 2;
01176         c[1] = (oldverts[pi + 4] + oldverts[pi + 7]) / 2;
01177         c[2] = (oldverts[pi + 5] + oldverts[pi + 8]) / 2;
01178         vec_normalize(c);
01179 
01180         // build triangles
01181         memcpy(&newverts[ni     ], &oldverts[pi], sizeof(float) * 3);
01182         memcpy(&newverts[ni + 3 ], b, sizeof(float) * 3);
01183         memcpy(&newverts[ni + 6 ], a, sizeof(float) * 3);
01184 
01185         memcpy(&newverts[ni + 9 ], b, sizeof(float) * 3);
01186         memcpy(&newverts[ni + 12], &oldverts[pi + 3], sizeof(float) * 3);
01187         memcpy(&newverts[ni + 15], c, sizeof(float) * 3);
01188 
01189         memcpy(&newverts[ni + 18], a, sizeof(float) * 3);
01190         memcpy(&newverts[ni + 21], b, sizeof(float) * 3);
01191         memcpy(&newverts[ni + 24], c, sizeof(float) * 3);
01192 
01193         memcpy(&newverts[ni + 27], a, sizeof(float) * 3);
01194         memcpy(&newverts[ni + 30], c, sizeof(float) * 3);
01195         memcpy(&newverts[ni + 33], &oldverts[pi + 6], sizeof(float) * 3);
01196 
01197         pi += 9;
01198         ni += 36;
01199       }
01200 
01201       free(oldverts);
01202       nverts *= 4;
01203       ntris *= 4;
01204     }
01205 
01206     sph_iter = sph_desired_iter;
01207     sph_nverts = nverts;
01208     sph_verts = newverts;
01209   }
01210 
01211   // now we're guaranteed to have a valid cached unit sphere, so
01212   // all we need to do is translate each coordinate based on the
01213   // desired position and radius, and add the triangles
01214   pi = 0;
01215   for (i = 0; i < sph_nverts / 3; i++) {
01216     float v0[3], v1[3], v2[3];
01217     float n0[3], n1[3], n2[3];
01218 
01219     // calculate upper hemisphere translation and scaling
01220     v0[0] = r * sph_verts[pi    ] + c[0];
01221     v0[1] = r * sph_verts[pi + 1] + c[1];
01222     v0[2] = r * sph_verts[pi + 2] + c[2];
01223     v1[0] = r * sph_verts[pi + 3] + c[0];
01224     v1[1] = r * sph_verts[pi + 4] + c[1];
01225     v1[2] = r * sph_verts[pi + 5] + c[2];
01226     v2[0] = r * sph_verts[pi + 6] + c[0];
01227     v2[1] = r * sph_verts[pi + 7] + c[1];
01228     v2[2] = r * sph_verts[pi + 8] + c[2];
01229 
01230     // calculate upper hemisphere normals
01231     vec_copy(n0, &sph_verts[pi    ]);
01232     vec_copy(n1, &sph_verts[pi + 3]);
01233     vec_copy(n2, &sph_verts[pi + 6]);
01234 
01235     // draw upper hemisphere
01236     triangle(v0, v2, v1, n0, n2, n1);
01237 
01238     // calculate lower hemisphere translation and scaling
01239     v0[2] = (-r * sph_verts[pi + 2]) + c[2];
01240     v1[2] = (-r * sph_verts[pi + 5]) + c[2];
01241     v2[2] = (-r * sph_verts[pi + 8]) + c[2];
01242 
01243     // calculate lower hemisphere normals
01244     n0[2] = -n0[2];
01245     n1[2] = -n1[2];
01246     n2[2] = -n2[2];
01247 
01248     // draw lower hemisphere
01249     triangle(v0, v1, v2, n0, n1, n2);
01250 
01251     pi += 9;
01252   }
01253 }
01254 
01255 
01256 // render a bunch of spheres that share the same material properties,
01257 // and resolution parameters, differing only in their individual
01258 // positions, radii, and colors.
01259 void FileRenderer::sphere_array(int spnum, int spres, 
01260                                 float *centers, float *radii, float *colors) {
01261   int i, ind;
01262   set_sphere_res(spres); // set the current sphere resolution
01263   ind = 0;
01264   for (i=0; i<spnum; i++) {
01265     float xyzr[4];
01266     xyzr[0]=centers[ind    ];
01267     xyzr[1]=centers[ind + 1];
01268     xyzr[2]=centers[ind + 2];
01269     xyzr[3]=radii[i];
01270 
01271     super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
01272     sphere(xyzr);
01273     ind += 3; // next sphere
01274   }
01275 }
01276 
01277 
01278 // render a bunch of points that share the same size differing only
01279 // in their positions and colors
01280 void FileRenderer::point_array(int num, float size, float *xyz, float *colors) {
01281   int i, ind;
01282 
01283   pointSize = (int) size;     // set the point size
01284 
01285   // draw all of the points
01286   for (ind=0,i=0; i<num; i++) {
01287     super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
01288     point(&xyz[ind]);
01289     ind += 3;
01290   }
01291 
01292   pointSize = 1;        // reset the point size
01293 }
01294 
01295 
01296 // render a bunch of lighted points that share the same size differing only
01297 // in their positions and colors
01298 void FileRenderer::point_array_lit(int num, float size, 
01299                                    float *xyz, float *norms, float *colors) {
01300   // XXX none of the existing scene formats are able to describe
01301   //     shaded point sets, so we just draw unlit points
01302   point_array(num, size, xyz, colors);
01303 }
01304 
01305 
01306 // start rendering geometry for which user-defined
01307 // clipping planes have been applied.
01308 void FileRenderer::start_clipgroup() {
01309   int i;
01310 
01311   for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
01312     if (clip_mode[i]) {
01313       warningflags |= FILERENDERER_NOCLIP;
01314       break;
01315     }
01316   }
01317 }
01318 
01319 
01320 void FileRenderer::text(float *pos, float size, float thickness, const char *str) {
01321 #if 1
01322   // each subclass has to provide its own text() method, otherwise no text
01323   // will be emitted, and we need to warn the user
01324   warningflags |= FILERENDERER_NOTEXT;
01325 #else
01326   hersheyhandle hh;
01327   float lm, rm, x, y, ox, oy;
01328   int draw, odraw;
01329 
01330   Matrix4 m;
01331   transMat.push(m);           // push on the identity matrix
01332 
01333   while (*str != '\0') {
01334     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
01335     (transMat.top()).translate(-lm, 0, 0);
01336     ox=0;
01337     oy=0;
01338     odraw=0;
01339     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
01340       if (draw && odraw) {
01341         float a[3], b[3];
01342         a[0] = ox; 
01343         a[1] = oy;
01344         a[2] = 0;
01345         b[0] = x;
01346         b[1] = y;
01347         b[2] = 0;
01348 
01349   //      printf("line: %g %g -> %g %g\n", ox, oy, x, y);
01350         line(a, b);        
01351       }
01352 
01353       ox=x;
01354       oy=y;
01355       odraw=draw;
01356     }
01357     (transMat.top()).translate(rm, 0, 0);
01358 
01359     str++;
01360   }
01361 
01362   transMat.pop();
01363 #endif
01364 }
01365 
01366 

Generated on Mon May 20 01:45:41 2013 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002