00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include "DepthSortObj.h"
00024 #include "Matrix4.h"
00025 #include "PSDisplayDevice.h"
00026 #include "VMDDisplayList.h"
00027 #include "Inform.h"
00028 
00029 
00030 PSDisplayDevice::PSDisplayDevice(void)
00031 : FileRenderer ("PostScript", "PostScript (vector graphics)", "vmdscene.ps","ghostview %s &") {
00032    memerror = 0;
00033    x_offset = 306;
00034    y_offset = 396;
00035 
00036    
00037    
00038    sph_iter = -1;
00039    sph_desired_iter = 0;
00040    sph_nverts = 0;
00041    sph_verts = NULL;
00042 
00043    memusage = 0;
00044    points = 0;
00045    objects = 0;
00046 }
00047 
00048 
00049 PSDisplayDevice::~PSDisplayDevice(void) {
00050    
00051    
00052    if (sph_nverts && sph_verts) free(sph_verts);
00053 }
00054 
00055 
00056 void PSDisplayDevice::render(const VMDDisplayList *cmdList) {
00057    if (!cmdList) return;
00058    DepthSortObject depth_obj;
00059    char *cmd_ptr;
00060    int draw;
00061    int tok;
00062    int nc;
00063    float a[3], b[3], c[3], d[3];
00064    float cent[3];
00065    float r;
00066    Matrix4 ident;
00067 
00068    
00069    while (transMat.num())
00070       transMat.pop();
00071 
00072    
00073    transMat.push(ident);
00074 
00075    
00076    super_multmatrix(cmdList->mat.mat);
00077 
00078    
00079    
00080    norm_light[0] = lightState[0].pos[0];
00081    norm_light[1] = lightState[0].pos[1];
00082    norm_light[2] = lightState[0].pos[2];
00083    if (norm_light[0] || norm_light[1] || norm_light[2])
00084       vec_normalize(norm_light);
00085 
00086    
00087    ResizeArray<Matrix4> pbcImages;
00088    find_pbc_images(cmdList, pbcImages);
00089    int npbcimages = pbcImages.num();
00090 
00091    
00092    ResizeArray<Matrix4> instanceImages;
00093    find_instance_images(cmdList, instanceImages);
00094    int ninstances = instanceImages.num();
00095 
00096    for (int pbcimage = 0; pbcimage < npbcimages; pbcimage++) {
00097      transMat.dup();
00098      super_multmatrix(pbcImages[pbcimage].mat);
00099 
00100    for (int instanceimage = 0; instanceimage < ninstances; instanceimage++) {
00101      transMat.dup();
00102      super_multmatrix(instanceImages[instanceimage].mat);
00103 
00104    
00105    
00106    VMDDisplayList::VMDLinkIter cmditer;
00107    cmdList->first(&cmditer);
00108    while ((tok = cmdList->next(&cmditer, cmd_ptr)) != DLASTCOMMAND) {
00109       draw = 0;
00110       nc = -1;
00111 
00112       switch (tok) {
00113          case DPOINT:
00114             
00115             depth_obj.points = (float *) malloc(sizeof(float) * 2);
00116             if (!depth_obj.points) {
00117                
00118                if (!memerror) {
00119                   memerror = 1;
00120                   msgErr << "PSDisplayDevice: Out of memory. Some " <<
00121                      "objects were not drawn." << sendmsg;
00122                }
00123                break;
00124             }
00125 
00126             
00127             depth_obj.npoints = 1;
00128             depth_obj.color = colorIndex;
00129             (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
00130             memcpy(depth_obj.points, a, sizeof(float) * 2);
00131 
00132             
00133             depth_obj.dist = compute_dist(a);
00134 
00135             
00136             draw = 1;
00137             break;
00138 
00139          case DSPHERE:
00140          {
00141             (transMat.top()).multpoint3d(((DispCmdSphere *) cmd_ptr)->pos_r, c);
00142             r = scale_radius(((DispCmdSphere *) cmd_ptr)->pos_r[3]);
00143 
00144             sphere_approx(c, r);
00145             break;
00146          }
00147 
00148          case DSPHEREARRAY:
00149          {
00150             DispCmdSphereArray *sa = (DispCmdSphereArray *) cmd_ptr;
00151             int cIndex, rIndex; 
00152                                 
00153             float * centers;
00154             float * radii;
00155             float * colors;
00156             sa->getpointers(centers, radii, colors);
00157 
00158             set_sphere_res(sa->sphereres);
00159 
00160             for (cIndex = 0, rIndex=0; rIndex < sa->numspheres; 
00161                  cIndex+=3, rIndex++)
00162             {
00163                 colorIndex = nearest_index(colors[cIndex],
00164                                            colors[cIndex+1],
00165                                            colors[cIndex+2]);
00166                 (transMat.top()).multpoint3d(¢ers[cIndex] , c);
00167                 r = scale_radius(radii[rIndex]);
00168 
00169                 sphere_approx(c, r);
00170             }
00171 
00172             break;
00173          }   
00174 
00175          case DLINE:
00176             
00177             if (!memcmp(((DispCmdLine *) cmd_ptr)->pos1,
00178                         ((DispCmdLine *) cmd_ptr)->pos2,
00179                         sizeof(float) * 3)) {
00180                
00181                break;
00182             }
00183 
00184             
00185             depth_obj.points = (float *) malloc(sizeof(float) * 4);
00186             if (!depth_obj.points) {
00187                
00188                if (!memerror) {
00189                   memerror = 1;
00190                   msgErr << "PSDisplayDevice: Out of memory. Some " <<
00191                      "objects were not drawn." << sendmsg;
00192                }
00193                break;
00194             }
00195 
00196             
00197             depth_obj.npoints = 2;
00198             depth_obj.color = colorIndex;
00199             (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos1, a);
00200             (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos2, b);
00201             memcpy(depth_obj.points, a, sizeof(float) * 2);
00202             memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
00203 
00204             
00205             cent[0] = (a[0] + b[0]) / 2;
00206             cent[1] = (a[1] + b[1]) / 2;
00207             cent[2] = (a[2] + b[2]) / 2;
00208 
00209             
00210             depth_obj.dist = compute_dist(cent);
00211 
00212             
00213             draw = 1;
00214             break;
00215 
00216          case DLINEARRAY:
00217            {
00218             
00219             float *v = (float *)cmd_ptr;
00220             int nlines = (int)v[0];
00221             v++;
00222             for (int i=0; i<nlines; i++) {
00223               
00224               if (!memcmp(v,v+3,3*sizeof(float)))
00225                 break;
00226 
00227               
00228               depth_obj.points = (float *) malloc(sizeof(float) * 4);
00229               if (!depth_obj.points) {
00230                  
00231                  if (!memerror) {
00232                     memerror = 1;
00233                     msgErr << "PSDisplayDevice: Out of memory. Some " <<
00234                        "objects were not drawn." << sendmsg;
00235                  }
00236                  break;
00237               }
00238 
00239               
00240               depth_obj.npoints = 2;
00241               depth_obj.color = colorIndex;
00242               (transMat.top()).multpoint3d(v, a);
00243               (transMat.top()).multpoint3d(v+3, b);
00244               memcpy(depth_obj.points, a, sizeof(float) * 2);
00245               memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
00246   
00247               
00248               cent[0] = (a[0] + b[0]) / 2;
00249               cent[1] = (a[1] + b[1]) / 2;
00250               cent[2] = (a[2] + b[2]) / 2;
00251   
00252               
00253               depth_obj.dist = compute_dist(cent);
00254  
00255               
00256               draw = 0;
00257               memusage += sizeof(float) * 2 * depth_obj.npoints;
00258               points += depth_obj.npoints;
00259               objects++;
00260               depth_list.append(depth_obj);
00261 
00262               v += 6;
00263             } 
00264            }
00265            break;           
00266 
00267          case DPOLYLINEARRAY:
00268            {
00269             
00270             float *v = (float *)cmd_ptr;
00271             int nverts = (int)v[0];
00272             v++;
00273             for (int i=0; i<nverts-1; i++) {
00274               
00275               if (!memcmp(v,v+3,3*sizeof(float)))
00276                 break;
00277 
00278               
00279               depth_obj.points = (float *) malloc(sizeof(float) * 4);
00280               if (!depth_obj.points) {
00281                  
00282                  if (!memerror) {
00283                     memerror = 1;
00284                     msgErr << "PSDisplayDevice: Out of memory. Some " <<
00285                        "objects were not drawn." << sendmsg;
00286                  }
00287                  break;
00288               }
00289 
00290               
00291               depth_obj.npoints = 2;
00292               depth_obj.color = colorIndex;
00293               (transMat.top()).multpoint3d(v, a);
00294               (transMat.top()).multpoint3d(v+3, b);
00295               memcpy(depth_obj.points, a, sizeof(float) * 2);
00296               memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
00297   
00298               
00299               cent[0] = (a[0] + b[0]) / 2;
00300               cent[1] = (a[1] + b[1]) / 2;
00301               cent[2] = (a[2] + b[2]) / 2;
00302   
00303               
00304               depth_obj.dist = compute_dist(cent);
00305  
00306               
00307               draw = 0;
00308               memusage += sizeof(float) * 2 * depth_obj.npoints;
00309               points += depth_obj.npoints;
00310               objects++;
00311               depth_list.append(depth_obj);
00312 
00313               v += 3;
00314             } 
00315            }
00316            break;           
00317  
00318          case DCYLINDER:
00319          {
00320             int res;
00321 
00322             (transMat.top()).multpoint3d((float *) cmd_ptr, a);
00323             (transMat.top()).multpoint3d(&((float *) cmd_ptr)[3], b);
00324             r = scale_radius(((float *) cmd_ptr)[6]);
00325             res = (int) ((float *) cmd_ptr)[7];
00326 
00327             cylinder_approx(a, b, r, res, (int) ((float *) cmd_ptr)[8]);
00328             break;
00329          }
00330 
00331          case DCONE:
00332          {
00333             (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos1, a);
00334             (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos2, b);
00335             float r1 = scale_radius(((DispCmdCone *) cmd_ptr)->radius);
00336             float r2 = scale_radius(((DispCmdCone *) cmd_ptr)->radius2);
00337 
00338             
00339             if (r2 > 0.0f) {
00340               msgWarn << "PSDisplayDevice) can't draw truncated cones" 
00341                       << sendmsg;
00342             }
00343             cone_approx(a, b, r1);
00344             break;
00345          }
00346 
00347         case DTEXT:
00348         {
00349             float* pos = (float *)cmd_ptr;
00350             float textsize = pos[4];
00351 #if 0
00352             
00353             float thickness = pos[3];    
00354 #endif
00355             char* txt = (char *)(pos+7);
00356             int   txtlen = strlen(txt);
00357             
00358             depth_obj.points = (float *) malloc(sizeof(float) * 2);
00359             depth_obj.text   = (char  *) malloc(sizeof(char) * (txtlen+1));
00360             if ( !(depth_obj.points || depth_obj.text) ) {
00361               
00362               if (!memerror) {
00363                  memerror = 1;
00364                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
00365                     "objects were not drawn." << sendmsg;
00366               }
00367               break;
00368            }
00369 
00370             
00371             depth_obj.npoints = 1;
00372             depth_obj.color = colorIndex;
00373             (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
00374             memcpy(depth_obj.points, a, sizeof(float) * 2);
00375             strcpy(depth_obj.text , txt);
00376 
00377             
00378             
00379             depth_obj.light_scale = textsize * 15;
00380 
00381             
00382             depth_obj.dist = compute_dist(a);
00383 
00384             
00385             draw = 1;
00386             break;
00387          }
00388 
00389          case DTRIANGLE:
00390             
00391             if (!memcmp(((DispCmdTriangle *) cmd_ptr)->pos1,
00392                         ((DispCmdTriangle *) cmd_ptr)->pos2,
00393                         sizeof(float) * 3) ||
00394                 !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
00395                         ((DispCmdTriangle *) cmd_ptr)->pos3,
00396                         sizeof(float) * 3) ||
00397                 !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
00398                         ((DispCmdTriangle *) cmd_ptr)->pos3,
00399                         sizeof(float) * 3)) {
00400                
00401                break;
00402             }
00403 
00404             
00405             depth_obj.points = (float *) malloc(sizeof(float) * 6);
00406             if (!depth_obj.points) {
00407                
00408                if (!memerror) {
00409                   memerror = 1;
00410                   msgErr << "PSDisplayDevice: Out of memory. Some " <<
00411                      "objects were not drawn." << sendmsg;
00412                }
00413                break;
00414             }
00415 
00416             
00417             depth_obj.npoints = 3;
00418             depth_obj.color = (nc >= 0) ? nc : colorIndex;
00419             (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos1, a);
00420             (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos2, b);
00421             (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos3, c);
00422             memcpy(depth_obj.points, a, sizeof(float) * 2);
00423             memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
00424             memcpy(&depth_obj.points[4], c, sizeof(float) * 2);
00425 
00426             
00427             cent[0] = (a[0] + b[0] + c[0]) / 3;
00428             cent[1] = (a[1] + b[1] + c[1]) / 3;
00429             cent[2] = (a[2] + b[2] + c[2]) / 3;
00430 
00431             
00432             depth_obj.dist = compute_dist(cent);
00433 
00434             
00435             depth_obj.light_scale = compute_light(a, b, c);
00436 
00437             
00438             draw = 1;
00439             break;
00440 
00441          case DTRIMESH_C4F_N3F_V3F:
00442             
00443             
00444             decompose_mesh((DispCmdTriMesh *) cmd_ptr);
00445             break;
00446 
00447          case DTRISTRIP:
00448             
00449             
00450             decompose_tristrip((DispCmdTriStrips *) cmd_ptr);
00451             break;
00452 
00453          case DSQUARE:
00454             
00455             if (!memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
00456                         ((DispCmdSquare *) cmd_ptr)->pos2,
00457                         sizeof(float) * 3) ||
00458                 !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
00459                         ((DispCmdSquare *) cmd_ptr)->pos3,
00460                         sizeof(float) * 3) ||
00461                 !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
00462                         ((DispCmdSquare *) cmd_ptr)->pos4,
00463                         sizeof(float) * 3) ||
00464                 !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
00465                         ((DispCmdSquare *) cmd_ptr)->pos3,
00466                         sizeof(float) * 3) ||
00467                 !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
00468                         ((DispCmdSquare *) cmd_ptr)->pos4,
00469                         sizeof(float) * 3) ||
00470                 !memcmp(((DispCmdSquare *) cmd_ptr)->pos3,
00471                         ((DispCmdSquare *) cmd_ptr)->pos4,
00472                         sizeof(float) * 3)) {
00473                
00474                break;
00475             }
00476 
00477             
00478             depth_obj.points = (float *) malloc(sizeof(float) * 8);
00479             if (!depth_obj.points) {
00480                
00481                if (!memerror) {
00482                   memerror = 1;
00483                   msgErr << "PSDisplayDevice: Out of memory. Some " <<
00484                      "objects were not drawn." << sendmsg;
00485                }
00486                break;
00487             }
00488 
00489             
00490             depth_obj.npoints = 4;
00491             depth_obj.color = colorIndex;
00492             (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos1, a);
00493             (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos2, b);
00494             (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos3, c);
00495             (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos4, d);
00496             memcpy(depth_obj.points, a, sizeof(float) * 2);
00497             memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
00498             memcpy(&depth_obj.points[4], c, sizeof(float) * 2);
00499             memcpy(&depth_obj.points[6], d, sizeof(float) * 2);
00500 
00501             
00502             cent[0] = (a[0] + b[0] + c[0] + d[0]) / 4;
00503             cent[1] = (a[1] + b[1] + c[1] + d[1]) / 4;
00504             cent[2] = (a[2] + b[2] + c[2] + d[2]) / 4;
00505 
00506             
00507             depth_obj.dist = compute_dist(cent);
00508 
00509             
00510             depth_obj.light_scale = compute_light(a, b, c);
00511 
00512             
00513             draw = 1;
00514             break;
00515 
00516          case DCOLORINDEX:
00517             colorIndex = ((DispCmdColorIndex *) cmd_ptr)->color;
00518             break;
00519 
00520          case DSPHERERES:
00521             set_sphere_res(((int *) cmd_ptr)[0]);
00522             break;
00523 
00524          default:
00525             
00526             break;
00527       }
00528 
00529       
00530       if (draw && depth_obj.npoints) {
00531          memusage += sizeof(float) * 2 * depth_obj.npoints;
00532          if ( depth_obj.text )
00533            memusage += sizeof(char) * (1+strlen(depth_obj.text));
00534          points += depth_obj.npoints;
00535          objects++;
00536          depth_list.append(depth_obj);
00537       }
00538 
00539       depth_obj.npoints = 0;
00540       depth_obj.points = NULL;
00541 
00542    } 
00543 
00544      transMat.pop();
00545    } 
00546 
00547      transMat.pop();
00548    } 
00549 }
00550 
00551 
00552 
00553 
00554 
00555 
00556 void PSDisplayDevice::render_done() {
00557    x_scale = 1.33f * 792 / Aspect / vSize;
00558    y_scale = x_scale;
00559 
00560    msgInfo << "PSDisplayDevice: peak memory totals: " << sendmsg;
00561    msgInfo << "    total dynamic memory used: " <<
00562       (long) (memusage + sizeof(DepthSortObject) * objects) << sendmsg;
00563    msgInfo << "    total dynamic points: " << points << sendmsg;
00564    msgInfo << "    total depthsorted object: " << objects << sendmsg;
00565 
00566    if (depth_list.num()) {
00567       depth_list.qsort(0, depth_list.num() - 1);
00568       process_depth_list();
00569    }
00570 }
00571 
00572 
00573 void PSDisplayDevice::process_depth_list(void) {
00574    DepthSortObject obj;
00575    int i, nobjs;
00576 
00577    nobjs = depth_list.num();
00578    float textsize = -20;
00579    for (i = 0; i < nobjs; i++) {
00580       obj = depth_list.item(i);
00581 
00582       if (obj.text) {
00583         
00584         
00585         
00586         if (obj.light_scale != textsize) {
00587           textsize = obj.light_scale;
00588           fprintf(outfile, "%f ts\n", textsize);
00589         }
00590         fprintf(outfile, "%d 1 c (%s) %d %d text\n",
00591                 obj.color,
00592                 obj.text,
00593                 (int) (obj.points[0] * x_scale + x_offset),
00594                 (int) (obj.points[1] * y_scale + y_offset));
00595       } else {
00596         switch (obj.npoints) {
00597           case 1: 
00598             fprintf(outfile, "%d 1 c %d %d p\n",
00599                     obj.color,
00600                     (int) (obj.points[0] * x_scale + x_offset),
00601                     (int) (obj.points[1] * y_scale + y_offset));
00602             break;
00603             
00604           case 2: 
00605             fprintf(outfile, "%d 1 c %d %d %d %d l\n",
00606                     obj.color,
00607                     (int) (obj.points[0] * x_scale + x_offset),
00608                     (int) (obj.points[1] * y_scale + y_offset),
00609                     (int) (obj.points[2] * x_scale + x_offset),
00610                     (int) (obj.points[3] * y_scale + y_offset));
00611             break;
00612             
00613           case 3: 
00614             fprintf(outfile, "%d %.2f c %d %d %d %d %d %d t\n",
00615                     obj.color, obj.light_scale,
00616                     (int) (obj.points[0] * x_scale + x_offset),
00617                     (int) (obj.points[1] * y_scale + y_offset),
00618                     (int) (obj.points[2] * x_scale + x_offset),
00619                     (int) (obj.points[3] * y_scale + y_offset),
00620                     (int) (obj.points[4] * x_scale + x_offset),
00621                     (int) (obj.points[5] * y_scale + y_offset));
00622             break;
00623             
00624          case 4: 
00625            fprintf(outfile, "%d %.2f c %d %d %d %d %d %d %d %d s\n",
00626                    obj.color, obj.light_scale,
00627                    (int) (obj.points[0] * x_scale + x_offset),
00628                    (int) (obj.points[1] * y_scale + y_offset),
00629                    (int) (obj.points[2] * x_scale + x_offset),
00630                    (int) (obj.points[3] * y_scale + y_offset),
00631                    (int) (obj.points[4] * x_scale + x_offset),
00632                    (int) (obj.points[5] * y_scale + y_offset),
00633                    (int) (obj.points[6] * x_scale + x_offset),
00634                    (int) (obj.points[7] * y_scale + y_offset));
00635            break;
00636         }
00637       }
00638 
00639       
00640       memusage -= sizeof(float) * 2 * obj.npoints;
00641       if (obj.npoints) free(obj.points);
00642       if (obj.text) {
00643         memusage -= sizeof(char) * (1+strlen(obj.text));
00644         free(obj.text);
00645       }
00646    }
00647 
00648    
00649    fprintf(outfile, "showpage\n");
00650    close_file();
00651 
00652    
00653    depth_list.remove(-1, -1);
00654 
00655    msgInfo << "PSDisplayDevice: end memory summary:" << sendmsg;
00656    msgInfo << "    total dynamic memory used: " << memusage << sendmsg;
00657    msgInfo << "    total dynamic points: " << points << sendmsg;
00658    msgInfo << "    total depthsorted object: " << objects << sendmsg;
00659 
00660    
00661    memusage = 0;
00662    objects = 0;
00663    points = 0;
00664 
00665    
00666 }
00667 
00668 
00669 void PSDisplayDevice::set_sphere_res(int res)
00670 {
00671     
00672     
00673     
00674     
00675     
00676 
00677     
00678     
00679     
00680     const int sph_iter_table[] = {
00681         0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
00682         3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
00683 
00684     if (res < 0) return;
00685     else if (res < 32) sph_desired_iter = sph_iter_table[res];
00686     else sph_desired_iter = (int) (0.8f * sqrtf((float) res));
00687 }
00688 
00689 
00690 void PSDisplayDevice::sphere_approx(float *c, float r) {
00691    DepthSortObject depth_obj;
00692    float x[3], y[3], z[3];
00693    float cent[3];
00694    int pi, ni;
00695    int i;
00696 
00697    
00698    
00699    
00700    if (!sph_verts || !sph_nverts || sph_iter != sph_desired_iter) {
00701       float a[3], b[3], c[3];
00702       float *newverts;
00703       float *oldverts;
00704       int nverts, ntris;
00705       int level;
00706 
00707       
00708       if (sph_verts && sph_nverts) free(sph_verts);
00709 
00710       
00711       
00712       
00713       
00714 
00715       newverts = (float *) malloc(sizeof(float) * 36);
00716       nverts = 12;
00717       ntris = 4;
00718 
00719       
00720 
00721       
00722       newverts[0] = -1;    newverts[1] = 0;     newverts[2] = 0;
00723       newverts[3] = 0;     newverts[4] = 1;     newverts[5] = 0;
00724       newverts[6] = 0;     newverts[7] = 0;     newverts[8] = 1;
00725 
00726       
00727       newverts[9] = 0;     newverts[10] = 0;    newverts[11] = 1;
00728       newverts[12] = 0;    newverts[13] = 1;    newverts[14] = 0;
00729       newverts[15] = 1;    newverts[16] = 0;    newverts[17] = 0;
00730 
00731       
00732       newverts[18] = 0;    newverts[19] = 0;    newverts[20] = 1;
00733       newverts[21] = 1;    newverts[22] = 0;    newverts[23] = 0;
00734       newverts[24] = 0;    newverts[25] = -1;   newverts[26] = 0;
00735 
00736       
00737       newverts[27] = 0;    newverts[28] = 0;    newverts[29] = 1;
00738       newverts[30] = 0;    newverts[31] = -1;   newverts[32] = 0;
00739       newverts[33] = -1;   newverts[34] = 0;    newverts[35] = 0;
00740 
00741       for (level = 1; level < sph_desired_iter; level++) {
00742          oldverts = newverts;
00743 
00744          
00745          
00746          newverts = (float *) malloc(sizeof(float) * 12 * nverts);
00747          if (!newverts) {
00748             
00749             sph_iter = -1;
00750             sph_nverts = 0;
00751             sph_verts = NULL;
00752             free(oldverts);
00753 
00754             if (!memerror) {
00755                memerror = 1;
00756                msgErr << "PSDisplayDevice: Out of memory. Some " 
00757                       << "objects were not drawn." << sendmsg;
00758             }
00759 
00760             return;
00761          }
00762 
00763          pi = 0;
00764          ni = 0;
00765          for (i = 0; i < ntris; i++) {
00766             
00767             a[0] = (oldverts[pi    ] + oldverts[pi + 6]) / 2;
00768             a[1] = (oldverts[pi + 1] + oldverts[pi + 7]) / 2;
00769             a[2] = (oldverts[pi + 2] + oldverts[pi + 8]) / 2;
00770             vec_normalize(a);
00771             b[0] = (oldverts[pi    ] + oldverts[pi + 3]) / 2;
00772             b[1] = (oldverts[pi + 1] + oldverts[pi + 4]) / 2;
00773             b[2] = (oldverts[pi + 2] + oldverts[pi + 5]) / 2;
00774             vec_normalize(b);
00775             c[0] = (oldverts[pi + 3] + oldverts[pi + 6]) / 2;
00776             c[1] = (oldverts[pi + 4] + oldverts[pi + 7]) / 2;
00777             c[2] = (oldverts[pi + 5] + oldverts[pi + 8]) / 2;
00778             vec_normalize(c);
00779 
00780             
00781             memcpy(&newverts[ni     ], &oldverts[pi], sizeof(float) * 3);
00782             memcpy(&newverts[ni + 3 ], b, sizeof(float) * 3);
00783             memcpy(&newverts[ni + 6 ], a, sizeof(float) * 3);
00784 
00785             memcpy(&newverts[ni + 9 ], b, sizeof(float) * 3);
00786             memcpy(&newverts[ni + 12], &oldverts[pi + 3], sizeof(float) * 3);
00787             memcpy(&newverts[ni + 15], c, sizeof(float) * 3);
00788 
00789             memcpy(&newverts[ni + 18], a, sizeof(float) * 3);
00790             memcpy(&newverts[ni + 21], b, sizeof(float) * 3);
00791             memcpy(&newverts[ni + 24], c, sizeof(float) * 3);
00792 
00793             memcpy(&newverts[ni + 27], a, sizeof(float) * 3);
00794             memcpy(&newverts[ni + 30], c, sizeof(float) * 3);
00795             memcpy(&newverts[ni + 33], &oldverts[pi + 6], sizeof(float) * 3);
00796 
00797             pi += 9;
00798             ni += 36;
00799          }
00800 
00801          free(oldverts);
00802 
00803          nverts *= 4;
00804          ntris *= 4;
00805       }
00806 
00807       sph_iter = sph_desired_iter;
00808       sph_nverts = nverts;
00809       sph_verts = newverts;
00810    }
00811 
00812    
00813    
00814    
00815    
00816 #if 0
00817    if (!points) {
00818       
00819       if (!memerror) {
00820          memerror = 1;
00821          msgErr << "PSDisplayDevice: Out of memory. Some " <<
00822             "objects were not drawn." << sendmsg;
00823       }
00824       return;
00825    }
00826 #endif
00827 
00828    
00829    
00830    depth_obj.npoints = 3;
00831    depth_obj.color = colorIndex;
00832 
00833    pi = 0;
00834    for (i = 0; i < sph_nverts / 3; i++) {
00835       
00836       depth_obj.points = (float *) malloc(sizeof(float) * 6);
00837       if (!depth_obj.points) {
00838          
00839          if (!memerror) {
00840             memerror = 1;
00841             msgErr << "PSDisplayDevice: Out of memory. Some " 
00842                    << "objects were not drawn." << sendmsg;
00843          }
00844          return;
00845       }
00846 
00847       
00848       x[0] = r * sph_verts[pi] + c[0];
00849       x[1] = r * sph_verts[pi + 1] + c[1];
00850       x[2] = r * sph_verts[pi + 2] + c[2];
00851       y[0] = r * sph_verts[pi + 3] + c[0];
00852       y[1] = r * sph_verts[pi + 4] + c[1];
00853       y[2] = r * sph_verts[pi + 5] + c[2];
00854       z[0] = r * sph_verts[pi + 6] + c[0];
00855       z[1] = r * sph_verts[pi + 7] + c[1];
00856       z[2] = r * sph_verts[pi + 8] + c[2];
00857 
00858       memcpy(depth_obj.points, x, sizeof(float) * 2);
00859       memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
00860       memcpy(&depth_obj.points[4], z, sizeof(float) * 2);
00861 
00862       
00863       cent[0] = (x[0] + y[0] + z[0]) / 3;
00864       cent[1] = (x[1] + y[1] + z[1]) / 3;
00865       cent[2] = (x[2] + y[2] + z[2]) / 3;
00866       depth_obj.dist = compute_dist(cent);
00867       depth_obj.light_scale = compute_light(x, y, z);
00868 
00869       
00870       memusage += sizeof(float) * 2 * depth_obj.npoints;
00871       points += depth_obj.npoints;
00872       objects++;
00873       depth_list.append(depth_obj);
00874 
00875       pi += 9;
00876    }
00877 }
00878 
00879 
00880 void PSDisplayDevice::cylinder_approx(float *a, float *b, float r, int res, 
00881                                       int filled) {
00882 
00883    float axis[3];
00884    float perp1[3], perp2[3];
00885    float pt1[3], pt2[3];
00886    float cent[3];
00887    float theta, theta_inc;
00888    float my_sin, my_cos;
00889    float w[3], x[3], y[3], z[3];
00890    int n;
00891 
00892    DepthSortObject cyl_body, cyl_trailcap, cyl_leadcap;
00893 
00894    
00895    if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) return;
00896    if (r <= 0) return;
00897 
00898    
00899    axis[0] = b[0] - a[0];
00900    axis[1] = b[1] - a[1];
00901    axis[2] = b[2] - a[2];
00902    vec_normalize(axis);
00903 
00904    
00905    if ((ABS(axis[0]) < ABS(axis[1])) &&
00906        (ABS(axis[0]) < ABS(axis[2]))) {
00907       perp1[0] = 0;
00908       perp1[1] = axis[2];
00909       perp1[2] = -axis[1];
00910    }
00911    else if ((ABS(axis[1]) < ABS(axis[2]))) {
00912       perp1[0] = -axis[2];
00913       perp1[1] = 0;
00914       perp1[2] = axis[0];
00915    }
00916    else {
00917       perp1[0] = axis[1];
00918       perp1[1] = -axis[0];
00919       perp1[2] = 0;
00920    }
00921    vec_normalize(perp1);
00922 
00923    
00924    
00925    cross_prod(perp2, axis, perp1);
00926 
00927    
00928    cyl_body.npoints = 4;
00929    cyl_body.color = colorIndex;
00930 
00931    if (filled & CYLINDER_TRAILINGCAP) {
00932       cyl_trailcap.npoints = 3;
00933       cyl_trailcap.color = colorIndex;
00934    }
00935 
00936    if (filled & CYLINDER_LEADINGCAP) {
00937       cyl_leadcap.npoints = 3;
00938       cyl_leadcap.color = colorIndex;
00939    }
00940 
00941    
00942    pt1[0] = r * perp2[0];
00943    pt1[1] = r * perp2[1];
00944    pt1[2] = r * perp2[2];
00945    theta = 0;
00946    theta_inc = (float) (VMD_TWOPI / res);
00947    for (n = 1; n <= res; n++) {
00948       
00949       memcpy(pt2, pt1, sizeof(float) * 3);
00950 
00951       
00952       theta += theta_inc;
00953       sincosf(theta, &my_sin, &my_cos);
00954 
00955       
00956       pt1[0] = r * (perp2[0] * my_cos + perp1[0] * my_sin);
00957       pt1[1] = r * (perp2[1] * my_cos + perp1[1] * my_sin);
00958       pt1[2] = r * (perp2[2] * my_cos + perp1[2] * my_sin);
00959 
00960       cyl_body.points = (float *) malloc(sizeof(float) * 8);
00961       cyl_trailcap.points = (float *) malloc(sizeof(float) * 6);
00962       cyl_leadcap.points = (float *) malloc(sizeof(float) * 6);
00963       if (!(cyl_body.points && cyl_trailcap.points && cyl_leadcap.points)) {
00964          
00965          if (!memerror) {
00966             memerror = 1;
00967             msgErr << "PSDisplayDevice: Out of memory. Some " <<
00968                "objects were not drawn." << sendmsg;
00969          }
00970          continue;
00971       }
00972 
00973       
00974       w[0] = pt1[0] + a[0];
00975       w[1] = pt1[1] + a[1];
00976       w[2] = pt1[2] + a[2];
00977       x[0] = pt2[0] + a[0];
00978       x[1] = pt2[1] + a[1];
00979       x[2] = pt2[2] + a[2];
00980       y[0] = pt2[0] + b[0];
00981       y[1] = pt2[1] + b[1];
00982       y[2] = pt2[2] + b[2];
00983       z[0] = pt1[0] + b[0];
00984       z[1] = pt1[1] + b[1];
00985       z[2] = pt1[2] + b[2];
00986 
00987       memcpy(cyl_body.points, w, sizeof(float) * 2);
00988       memcpy(&cyl_body.points[2], x, sizeof(float) * 2);
00989       memcpy(&cyl_body.points[4], y, sizeof(float) * 2);
00990       memcpy(&cyl_body.points[6], z, sizeof(float) * 2);
00991 
00992       
00993       
00994       
00995       
00996       cent[0] = (w[0] + y[0]) / 2;
00997       cent[1] = (w[1] + y[1]) / 2;
00998       cent[2] = (w[2] + y[2]) / 2;
00999       cyl_body.dist = compute_dist(cent);
01000 
01001       
01002       cyl_body.light_scale = compute_light(w, x, y);
01003 
01004       
01005       memusage += sizeof(float) * 2 * cyl_body.npoints;
01006       points += cyl_body.npoints;
01007       objects++;
01008       depth_list.append(cyl_body);
01009 
01010       
01011       if (filled & CYLINDER_TRAILINGCAP) {
01012         memcpy(&cyl_trailcap.points[0], x, sizeof(float) * 2);
01013         memcpy(&cyl_trailcap.points[2], w, sizeof(float) * 2);
01014         memcpy(&cyl_trailcap.points[4], a, sizeof(float) * 2);
01015       
01016         
01017         cent[0] = (x[0] + w[0] + a[0]) / 3;
01018         cent[1] = (x[1] + w[1] + a[1]) / 3;
01019         cent[2] = (x[2] + w[2] + a[2]) / 3;
01020         cyl_trailcap.dist = compute_dist(cent);
01021 
01022         
01023         cyl_trailcap.light_scale = compute_light(x, w, a);
01024 
01025         memusage += sizeof(float) * 2 * cyl_trailcap.npoints;
01026         points += cyl_trailcap.npoints;
01027         objects++;
01028         depth_list.append(cyl_trailcap);
01029       }
01030 
01031       
01032       if (filled & CYLINDER_LEADINGCAP) {
01033         memcpy(cyl_leadcap.points, z, sizeof(float) * 2);
01034         memcpy(&cyl_leadcap.points[2], y, sizeof(float) * 2);
01035         memcpy(&cyl_leadcap.points[4], b, sizeof(float) * 2);
01036 
01037         
01038         cent[0] = (z[0] + y[0] + b[0]) / 3;
01039         cent[1] = (z[1] + y[1] + b[1]) / 3;
01040         cent[2] = (z[2] + y[2] + b[2]) / 3;
01041         cyl_leadcap.dist = compute_dist(cent);
01042 
01043         
01044         cyl_leadcap.light_scale = compute_light(z, y, b);
01045 
01046         memusage += sizeof(float) * 2 * cyl_leadcap.npoints;
01047         points += cyl_leadcap.npoints;
01048         objects++;
01049         depth_list.append(cyl_leadcap);
01050       }
01051    }
01052 }
01053 
01054 
01055 void PSDisplayDevice::cone_approx(float *a, float *b, float r) {
01056    
01057    const int tris = 20;
01058 
01059    float axis[3];
01060    float perp1[3], perp2[3];
01061    float pt1[3], pt2[3];
01062    float cent[3];
01063    float x[3], y[3], z[3];
01064    float theta, theta_inc;
01065    float my_sin, my_cos;
01066    int n;
01067 
01068    DepthSortObject depth_obj;
01069 
01070    
01071    if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) return;
01072    if (r <= 0) return;
01073 
01074    
01075    axis[0] = b[0] - a[0];
01076    axis[1] = b[1] - a[1];
01077    axis[2] = b[2] - a[2];
01078    vec_normalize(axis);
01079 
01080    
01081    if ((ABS(axis[0]) < ABS(axis[1])) &&
01082        (ABS(axis[0]) < ABS(axis[2]))) {
01083       perp1[0] = 0;
01084       perp1[1] = axis[2];
01085       perp1[2] = -axis[1];
01086    }
01087    else if ((ABS(axis[1]) < ABS(axis[2]))) {
01088       perp1[0] = -axis[2];
01089       perp1[1] = 0;
01090       perp1[2] = axis[0];
01091    }
01092    else {
01093       perp1[0] = axis[1];
01094       perp1[1] = -axis[0];
01095       perp1[2] = 0;
01096    }
01097    vec_normalize(perp1);
01098 
01099    
01100    
01101    cross_prod(perp2, axis, perp1);
01102 
01103    
01104    depth_obj.npoints = 3;
01105    depth_obj.color = colorIndex;
01106 
01107    
01108    pt1[0] = r * perp2[0];
01109    pt1[1] = r * perp2[1];
01110    pt1[2] = r * perp2[2];
01111    theta = 0;
01112    theta_inc = (float) (VMD_TWOPI / tris);
01113    for (n = 1; n <= tris; n++) {
01114       
01115       memcpy(pt2, pt1, sizeof(float) * 3);
01116 
01117       
01118       theta += theta_inc;
01119       sincosf(theta, &my_sin, &my_cos);
01120 
01121       
01122       pt1[0] = r * (perp2[0] * my_cos + perp1[0] * my_sin);
01123       pt1[1] = r * (perp2[1] * my_cos + perp1[1] * my_sin);
01124       pt1[2] = r * (perp2[2] * my_cos + perp1[2] * my_sin);
01125 
01126       depth_obj.points = (float *) malloc(sizeof(float) * 6);
01127       if (!depth_obj.points) {
01128          
01129          if (!memerror) {
01130             memerror = 1;
01131             msgErr << "PSDisplayDevice: Out of memory. Some " <<
01132                "objects were not drawn." << sendmsg;
01133          }
01134          continue;
01135       }
01136 
01137       
01138       x[0] = pt1[0] + a[0];
01139       x[1] = pt1[1] + a[1];
01140       x[2] = pt1[2] + a[2];
01141       y[0] = pt2[0] + a[0];
01142       y[1] = pt2[1] + a[1];
01143       y[2] = pt2[2] + a[2];
01144 
01145       
01146       z[0] = b[0];
01147       z[1] = b[1];
01148       z[2] = b[2];
01149 
01150       memcpy(depth_obj.points, x, sizeof(float) * 2);
01151       memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
01152       memcpy(&depth_obj.points[4], z, sizeof(float) * 2);
01153 
01154       
01155       
01156       cent[0] = (x[0] + y[0] + z[0]) / 3;
01157       cent[1] = (x[1] + y[1] + z[1]) / 3;
01158       cent[2] = (x[2] + y[2] + z[2]) / 3;
01159       depth_obj.dist = compute_dist(cent);
01160 
01161       
01162       depth_obj.light_scale = compute_light(x, y, z);
01163 
01164       
01165       memusage += sizeof(float) * 2 * depth_obj.npoints;
01166       points += depth_obj.npoints;
01167       objects++;
01168       depth_list.append(depth_obj);
01169    }
01170 }
01171 
01172 
01173 void PSDisplayDevice::decompose_mesh(DispCmdTriMesh *mesh) {
01174    int i;
01175    int fi;
01176    int f1, f2, f3;
01177    float r, g, b;
01178    float x[3], y[3], z[3], cent[3];
01179    float *cnv;
01180    int *f;
01181    mesh->getpointers(cnv, f);
01182    DepthSortObject depth_obj;
01183 
01184    depth_obj.npoints = 3;
01185 
01186    fi = -3;
01187    for (i = 0; i < mesh->numfacets; i++) {
01188       fi += 3;
01189       f1 = f[fi    ] * 10;
01190       f2 = f[fi + 1] * 10;
01191       f3 = f[fi + 2] * 10;
01192 
01193       
01194       depth_obj.points = (float *) malloc(6 * sizeof(float));
01195       if (!depth_obj.points) {
01196          if (!memerror) {
01197             memerror = 1;
01198             msgErr << "PSDisplayDevice: Out of memory. Some " <<
01199                "objects were not drawn." << sendmsg;
01200          }
01201          continue;
01202       }
01203 
01204       
01205       
01206       r = (cnv[f1] + cnv[f2] + cnv[f3]) / 3;
01207       g = (cnv[f1 + 1] + cnv[f2 + 1] + cnv[f3 + 1]) / 3;
01208       b = (cnv[f1 + 2] + cnv[f2 + 2] + cnv[f3 + 2]) / 3;
01209       depth_obj.color = nearest_index(r, g, b);
01210 
01211       
01212       
01213       (transMat.top()).multpoint3d(&cnv[f1 + 7], x);
01214       (transMat.top()).multpoint3d(&cnv[f2 + 7], y);
01215       (transMat.top()).multpoint3d(&cnv[f3 + 7], z);
01216       memcpy(depth_obj.points, x, sizeof(float) * 2);
01217       memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
01218       memcpy(&depth_obj.points[4], z, sizeof(float) * 2);
01219 
01220       
01221       cent[0] = (x[0] + y[0] + z[0]) / 3;
01222       cent[1] = (x[1] + y[1] + z[1]) / 3;
01223       cent[2] = (x[2] + y[2] + z[2]) / 3;
01224 
01225       
01226       depth_obj.dist = compute_dist(cent);
01227 
01228       
01229       depth_obj.light_scale = compute_light(x, y, z);
01230 
01231       
01232       memusage += sizeof(float) * 2 * depth_obj.npoints;
01233       points += depth_obj.npoints;
01234       objects++;
01235       depth_list.append(depth_obj);
01236    }
01237 
01238 }
01239 
01240 
01241 void PSDisplayDevice::decompose_tristrip(DispCmdTriStrips *strip)
01242 {
01243     int s, t, v = 0;
01244     int v0, v1, v2;
01245     float r, g, b;
01246     float x[3], y[3], z[3], cent[3];
01247     DepthSortObject depth_obj;
01248 
01249     depth_obj.npoints = 3;
01250 
01251     
01252     const int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
01253 
01254     float *cnv;
01255     int *f;
01256     int *vertsperstrip;
01257     strip->getpointers(cnv, f, vertsperstrip);
01258 
01259     
01260     for (s = 0; s < strip->numstrips; s++)
01261     {
01262         
01263         for (t = 0; t < vertsperstrip[s] - 2; t++)
01264         {
01265             v0 = f[v + (stripaddr[t & 0x01][0])] * 10;
01266             v1 = f[v + (stripaddr[t & 0x01][1])] * 10;
01267             v2 = f[v + (stripaddr[t & 0x01][2])] * 10;
01268 
01269             
01270             depth_obj.points = (float *) malloc(6 * sizeof(float));
01271             if (!depth_obj.points) {
01272                 if (!memerror) {
01273                     memerror = 1;
01274                     msgErr << "PSDisplayDevice: Out of memory. Some "
01275                            << "objects were not drawn." << sendmsg;
01276                 }
01277                 continue;
01278             }
01279 
01280             
01281             
01282             r = (cnv[v0+0] + cnv[v1+0] + cnv[v2+0]) / 3; 
01283             g = (cnv[v0+1] + cnv[v1+1] + cnv[v2+1]) / 3; 
01284             b = (cnv[v0+2] + cnv[v1+2] + cnv[v2+2]) / 3; 
01285             depth_obj.color = nearest_index(r, g, b);
01286 
01287             
01288             
01289             (transMat.top()).multpoint3d(&cnv[v0 + 7], x);
01290             (transMat.top()).multpoint3d(&cnv[v1 + 7], y);
01291             (transMat.top()).multpoint3d(&cnv[v2 + 7], z);
01292             memcpy(depth_obj.points, x, sizeof(float) * 2);
01293             memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
01294             memcpy(&depth_obj.points[4], z, sizeof(float) * 2);
01295 
01296             
01297             cent[0] = (x[0] + y[0] + z[0]) / 3;
01298             cent[1] = (x[1] + y[1] + z[1]) / 3;
01299             cent[2] = (x[2] + y[2] + z[2]) / 3;
01300 
01301             
01302             depth_obj.dist = compute_dist(cent);
01303 
01304             
01305             depth_obj.light_scale = compute_light(x, y, z);
01306 
01307             
01308             memusage += sizeof(float) * 2 * depth_obj.npoints;
01309             points += depth_obj.npoints;
01310             objects++;
01311             depth_list.append(depth_obj);
01312 
01313             v++; 
01314         } 
01315     v+=2; 
01316     } 
01317 }
01318 
01319 
01320 void PSDisplayDevice::write_header(void) {
01321    int i;
01322 
01323    fprintf(outfile, "%%!PS-Adobe-1.0\n");
01324    fprintf(outfile, "%%%%DocumentFonts:Helvetica\n");
01325    fprintf(outfile, "%%%%Title:vmd.ps\n");
01326    fprintf(outfile, "%%%%Creator:VMD -- Visual Molecular Dynamics\n");
01327    fprintf(outfile, "%%%%CreationDate:\n");
01328    fprintf(outfile, "%%%%Pages:1\n");
01329    fprintf(outfile, "%%%%BoundingBox:0 0 612 792\n");
01330    fprintf(outfile, "%%%%EndComments\n");
01331    fprintf(outfile, "%%%%Page:1 1\n");
01332 
01333    fprintf(outfile, "%3.2f %3.2f %3.2f setrgbcolor    %% background color\n",
01334       backColor[0], backColor[1], backColor[2]);
01335    fprintf(outfile, "newpath\n");
01336    fprintf(outfile, "0 0 moveto\n");
01337    fprintf(outfile, "0 792 lineto\n");
01338    fprintf(outfile, "792 792 lineto\n");
01339    fprintf(outfile, "792 0 lineto\n");
01340    fprintf(outfile, "closepath\nfill\nstroke\n");
01341 
01342    
01343    
01344    fprintf(outfile, "/s\n");
01345    fprintf(outfile, "{ newpath moveto lineto lineto lineto closepath fill stroke } def\n");
01346 
01347    
01348    fprintf(outfile, "/sw\n");
01349    fprintf(outfile, "{ newpath moveto lineto lineto lineto closepath stroke } def\n");
01350 
01351    
01352    fprintf(outfile, "/t\n");
01353    fprintf(outfile, "{ newpath moveto lineto lineto closepath fill stroke } def\n");
01354 
01355    
01356    fprintf(outfile, "/tw\n");
01357    fprintf(outfile, "{ newpath moveto lineto lineto closepath stroke } def\n");
01358 
01359    
01360    
01361    
01362    
01363    
01364    fprintf(outfile, "/p\n");
01365    fprintf(outfile, "{ dup dup dup 5 -1 roll dup dup dup 8 -1 roll exch 8 -1\n");
01366    fprintf(outfile, "  roll 4 1 roll 8 -1 roll 6 1 roll newpath -1 add moveto\n");
01367    fprintf(outfile, "  1 add lineto exch -1 add exch moveto exch 1 add exch\n");
01368    fprintf(outfile, "  lineto closepath stroke } def\n");
01369 
01370    
01371    fprintf(outfile, "/l\n");
01372    fprintf(outfile, "{ newpath moveto lineto closepath stroke } def\n");
01373 
01374    
01375    
01376    
01377    fprintf(outfile, "/mc\n");
01378    fprintf(outfile, "{ dup 4 1 roll dup 3 1 roll mul 5 1 roll mul 4 1 roll\n");
01379    fprintf(outfile, "  mul 3 1 roll } def\n");
01380 
01381    
01382    
01383    fprintf(outfile, "/gc\n");
01384    fprintf(outfile, "{ 2 1 roll dup 3 -1 roll get dup dup 0 get 3 1 roll\n");
01385    fprintf(outfile, "  1 get 3 1 roll 2 get 3 -1 roll exch } def\n");
01386 
01387    
01388    fprintf(outfile, "/text\n");
01389    fprintf(outfile,"{ moveto show } def\n");
01390 
01391    
01392    fprintf(outfile, "/ts\n");
01393    fprintf(outfile, "{ /Helvetica findfont exch scalefont setfont } def\n");
01394 
01395    
01396    
01397 
01398    
01399    
01400    fprintf(outfile, "/c\n");
01401    fprintf(outfile, "{ 3 1 roll gc 5 -1 roll mc setrgbcolor } def\n");
01402 
01403    
01404    
01405    
01406    
01407    fprintf(outfile, "\n");
01408    for (i = 0; i < MAXCOLORS; i++) {
01409       fprintf(outfile, "[ %.2f %.2f %.2f ]\n",
01410          matData[i][0],
01411          matData[i][1],
01412          matData[i][2]);
01413    }
01414    fprintf(outfile, "%d array astore\n", MAXCOLORS);
01415 }
01416 
01417 
01418 void PSDisplayDevice::write_trailer(void) {
01419 }
01420 
01421 
01422 void PSDisplayDevice::comment(const char *s) {
01423    fprintf(outfile, "%%%% %s\n", s);
01424 }
01425 
01426 
01427 inline float PSDisplayDevice::compute_dist(float *s) {
01428    return
01429       (s[0] - eyePos[0]) * (s[0] - eyePos[0]) +
01430       (s[1] - eyePos[1]) * (s[1] - eyePos[1]) +
01431       (s[2] - eyePos[2]) * (s[2] - eyePos[2]);
01432 }
01433 
01434 
01435 float PSDisplayDevice::compute_light(float *a, float *b, float *c) {
01436    float norm[3];
01437    float light_scale;
01438 
01439    
01440    norm[0] =
01441       a[1] * (b[2] - c[2]) +
01442       b[1] * (c[2] - a[2]) +
01443       c[1] * (a[2] - b[2]);
01444    norm[1] =
01445       a[2] * (b[0] - c[0]) +
01446       b[2] * (c[0] - a[0]) +
01447       c[2] * (a[0] - b[0]);
01448    norm[2] =
01449       a[0] * (b[1] - c[1]) +
01450       b[0] * (c[1] - a[1]) +
01451       c[0] * (a[1] - b[1]);
01452 
01453    
01454    
01455    if (!norm[0] && !norm[1] && !norm[2]) {
01456       light_scale = 0;
01457    } else {
01458       
01459       
01460       vec_normalize(norm);
01461       light_scale = dot_prod(norm, norm_light);
01462       if (light_scale < 0) light_scale = -light_scale;
01463    }
01464 
01465    return light_scale;
01466 }