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

raster3dplugin.C

Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003  *cr
00004  *cr            (C) Copyright 1995-2016 The Board of Trustees of the
00005  *cr                        University of Illinois
00006  *cr                         All Rights Reserved
00007  *cr
00008  ***************************************************************************/
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: raster3dplugin.C,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.20 $       $Date: 2020/01/06 20:15:04 $
00015  *
00016  ***************************************************************************/
00017 
00018 
00019 #include <stdio.h>
00020 #include <math.h>
00021 #include <string.h>
00022 #include <stdlib.h>
00023 
00024 #include "molfile_plugin.h"
00025 
00026 typedef struct {
00027   FILE *fd;
00028   molfile_graphics_t *graphics;
00029 } handle_t;
00030 
00031 static void *open_file_read(const char *filepath, const char *filetype,
00032     int *natoms) {
00033   FILE *fd;
00034   handle_t *handle;
00035   
00036   fd = fopen(filepath, "rt");
00037   if (!fd) 
00038     return NULL;
00039   handle = new handle_t;
00040   handle->fd = fd;
00041   handle->graphics = NULL;
00042   *natoms = 0;
00043   return handle;
00044 }
00045 
00046 static void next_elem(int &n, int &max, molfile_graphics_t *& graphics) {
00047   ++n;
00048   if (n == max) {
00049     max *= 2;
00050     graphics = (molfile_graphics_t *)realloc(graphics, max*sizeof(molfile_graphics_t));
00051   }
00052 }
00053 
00054 // gets a line of text from the file, ignoring comments
00055 static int get_line(int &line, char *buf, int len, FILE *f) {
00056    do {
00057       line++;
00058       if (!fgets(buf, len - 1, f)) return 0;
00059    } while (buf[0] == '#');
00060    return 1;
00061 }
00062 
00063 
00064 
00065 
00066 /* 
00067  * Raster3D read_rawgraphics() entrypoint
00068  *
00069  * TODO
00070  *
00071  * 1. doesn't properly render capped cylinders
00072  * 2. needs to handle object types 15, 19, 9 (affects coordinate system);
00073  *    needs to first understand VMD's coordinate system.
00074  * 3. doesn't properly handle object type 8 (material definitions)
00075  * 4. doesn't properly handle object type 14 (quadrics)
00076  * 5. doesn't properly support file indirection (using '@')
00077  * 6. doesn't differentiate between round-ended cylinders (obj 3)
00078  *    and flat-ended cylinders (obj 5)
00079  * 7. doesn't handle planes
00080  * 8. doesn't support text (object types 10-12)
00081  * 9. doesn't handle depth cueing and transformations in global
00082  *    properties (object 16)
00083  */
00084 
00086 // TITLE (80 chars)
00087 // NTX, NTY (number of tiles -- ignored)
00088 // NPX, NPY (number of points per tile -- ignored)
00089 // SCHEME (antialiasing scheme -- ignored)
00090 // BKGND (background color -- ignored)
00091 // SHADOW (T/F -- ignored)
00092 // IPHONG (phong power -- ignored)
00093 // STRAIT (secondary light source -- ignored)
00094 // AMBIEN (ambient illumination -- ignored)
00095 // SPECLR ignored
00096 // EYEPOS ignored
00097 // SOURCE ignored
00098 // TMAT 4x4 matrix used to view the system
00099 // object mode (1 == triangle, 2 == spheres, or 3 ==  mixed)
00100 // INFMTS  --  FORTRAN input field specifications
00101 //   for input format specifiers 1/6, 2, and 3/5
00102 //   triangle(1) or plane(6) (x1,y1,z1)-(x2,y2,z2)-(x3,y3,z3) (r,g,b)
00103 //   sphere(2)      (x,y,z) r (r,g,b)
00104 //   cylinder(3,5)  (x1,y1,z1) R1 - (x2,y2,z2) R2(is ignored) (r,g,b)
00105 //                      except if one radius is 0, a cone is made
00106 //   I ignore these lines and just read them in as "%f"
00107 static int read_rawgraphics(void *v, int *nelem, const molfile_graphics_t **gdata) {
00108   int count, i;
00109   char buffer[200];
00110   float mat[16];
00111   FILE *infile = NULL;
00112   int futureVersion = 0;
00113   int line = 0;
00114 
00115   handle_t *handle = (handle_t *)v;
00116   infile = handle->fd;
00117 
00118   int maxelem = 10;
00119   int n = 0;
00120   molfile_graphics_t *graphics = (molfile_graphics_t *) calloc(1, maxelem*sizeof(molfile_graphics_t));
00121 
00122   // XXX This should probably be in open_file_read
00123   if (!get_line(line, buffer, 199, infile)) {
00124     fprintf(stderr, "raster3dplugin) Error reading file header (line %d)\n", 
00125             line);
00126     return MOLFILE_ERROR;
00127   }
00128 
00129   // tell the user info about the file
00130   for (i = strlen(buffer) - 1; i >= 0 &&
00131        (buffer[i] == 10 || buffer[i] == 13); i--) buffer[i] = 0;
00132   printf("raster3dplugin) scene title: '%s'\n", buffer);
00133 
00134   // The next 11 lines of text contain more header information
00135   // about lighting, anti aliasing, image size, etc. This can be
00136   // ignored.
00137   for (count = 0; count < 11; count++) {
00138     if (!get_line(line, buffer, 199, infile)) {
00139       fprintf(stderr, 
00140               "raster3dplugin) error reading file header (line %d)\n", line);
00141       return MOLFILE_ERROR;
00142     }
00143   }
00144 
00145   // Now I have to get the matrix.  This is made nasty since
00146   // there could be extra text after the first four numbers on a line
00147   // as in: 1 0 0 0 This is an extra comment
00148   for (i=0; i<4; i++) {
00149     get_line(line, buffer, 199, infile);  // read the whole line into a string
00150     if (sscanf(buffer, "%f %f %f %f",
00151                &mat[4*i], &mat[4*i+1], &mat[4*i+2], &mat[4*i+3])<4) {
00152       fprintf(stderr, "raster3dplugin) invalid format in file (line %d)\n",
00153               line);
00154       return MOLFILE_ERROR;
00155     }
00156   }
00157 
00158   get_line(line, buffer, 199, infile);
00159   if (sscanf(buffer, "%d", &i) < 1) {
00160     fprintf(stderr, 
00161             "raster3dplugin) error reading object input mode (line %d)\n", 
00162             line);
00163     return MOLFILE_ERROR;
00164   }
00165 
00166   if (i != 3) {
00167     fprintf(stderr, "raster3dplugin) the specified file is in an unsupported format\n");
00168     fprintf(stderr, "(object input mode %d). Aborting.\n", i);
00169     return MOLFILE_ERROR;
00170   }
00171 
00172   float data[15];
00173   float normals[15];
00174   float tricolors[9];
00175   float color[9];
00176 
00177   // INFMT/INFMTS input specifiers; these can specifiy Fortran formatted
00178   // input formats, but are usually "*" meaning free-format input. We
00179   // give a warning if it's not free-format.
00180   for (count = 0; count < 3; count++) {
00181     get_line(line, buffer, 199, infile);
00182     if (buffer[0] != '*') 
00183       break;
00184   }
00185 
00186   if (count < 3) {  
00187     fprintf(stderr, "raster3dplugin) Warning: this file contains input in a nonstandard\n");
00188     fprintf(stderr, "Fortran format. This is generally not supported, and the read may fail.\n");
00189   }
00190   count = 0;
00191 
00192   while (!feof(infile) && !ferror(infile)) {
00193     int objtype = -1;
00194 
00195     if (!get_line(line, buffer, 199, infile)) 
00196       continue;
00197 
00198     if (sscanf(buffer, "%d", &objtype) != 1) {
00199       fprintf(stderr, "raster3dplugin) bad data in file (line %d)\n", line);
00200       return MOLFILE_ERROR;
00201     }
00202 
00203     switch(objtype) {
00204       case 1: // triangle
00205         char buffer2[200];
00206         int have_normals;
00207         int have_tricolors;
00208         long fpos;
00209 
00210         have_normals = 0;
00211         have_tricolors = 0;
00212 
00213         get_line(line, buffer, 127, infile);
00214         if (feof(infile)) {
00215           //msgErr << "Raster3D input: error reading triangle data (line "
00216           //<< line << ")" << sendmsg;
00217           return MOLFILE_ERROR;
00218         }
00219 
00220         if (sscanf(buffer, "%f %f %f %f %f %f %f %f %f %f %f %f",
00221                    data  , data+1, data+2, data+3, data+4, data+5,
00222                    data+6, data+7, data+8, data+9, data+10, data+11) < 12) { 
00223           //msgErr << "Raster3D input: bad triangle data in file (line "
00224           //<< line << "). Will try to continue." << sendmsg;
00225           continue;
00226         }
00227 
00228         while (!feof(infile) && !ferror(infile)) {
00229           fpos = ftell(infile);
00230           if (!get_line(line, buffer2, 199, infile)) {
00231             fseek(infile, fpos, SEEK_SET);
00232             break;
00233           }
00234 
00235           if (sscanf(buffer2, "%d", &objtype) != 1) {
00236             //msgErr << "Raster3D input: bad data in file (line " << line
00237             //<< "). Aborting." << sendmsg;
00238             return MOLFILE_ERROR;
00239           }
00240 
00241           switch (objtype) {
00242             case 7: // explicit normals
00243               if (!get_line(line, buffer2, 199, infile)) {
00244                 //msgErr << "Raster3D input: read error in file (line " << line
00245                 //<< "). Aborting." << sendmsg;
00246                 return MOLFILE_ERROR;
00247               }
00248 
00249               if (sscanf(buffer2, "%f %f %f %f %f %f %f %f %f",
00250                          normals  , normals+1, normals+2,
00251                          normals+3, normals+4, normals+5,
00252                          normals+6, normals+7, normals+8 ) < 9) { 
00253                 //msgErr << "Raster3D input: error reading triangle normals (line "
00254                 //<< line << "). Will try to continue." << sendmsg;
00255                 continue;
00256               }
00257 
00258               have_normals = 1;
00259               break;
00260 
00261             case 17: // colors at vertices of a tri-color
00262               if (!get_line(line, buffer2, 199, infile)) {
00263                 //msgErr << "Raster3D input: read error in file (line " << line
00264                 //<< "). Aborting." << sendmsg;
00265                 return MOLFILE_ERROR;
00266               }
00267 
00268               if (sscanf(buffer2, "%f %f %f %f %f %f %f %f %f",
00269                          tricolors,  tricolors+ 1, tricolors + 2,
00270                          tricolors + 3, tricolors + 4, tricolors + 5,
00271                          tricolors + 6, tricolors + 7, tricolors + 8) < 9) {
00272                 //msgErr << "Raster3D input: error reading vertex colors (line "
00273                 //<< line << "). Will try to continue." << sendmsg;
00274                 continue;
00275               }
00276 
00277               have_tricolors = 1;
00278               break;
00279 
00280             default:
00281               fseek(infile, fpos, SEEK_SET);
00282               fpos = 0;
00283               break;
00284 
00285           }
00286 
00287           if (!fpos) 
00288             break;
00289         }
00290 
00291         if (ferror(infile)) {
00292           //msgErr << "Raster3D input: read error in file (line "
00293           //<< line << "). Aborting." << sendmsg;
00294           return MOLFILE_ERROR;
00295         }
00296 
00297         graphics[n].type = MOLFILE_COLOR;
00298         graphics[n].data[0] = sqrt(data[9]);
00299         graphics[n].data[1] = sqrt(data[10]);
00300         graphics[n].data[2] = sqrt(data[11]);
00301         next_elem(n, maxelem, graphics);
00302 
00303         if (have_tricolors) {
00304           for (int qq=0; qq<9; qq++) color[qq] = sqrt(tricolors[qq]);
00305         }
00306 
00307         if (!have_normals && !have_tricolors) {
00308           graphics[n].type = MOLFILE_TRIANGLE;
00309           memcpy(graphics[n].data, data, 9*sizeof(float));
00310           next_elem(n, maxelem, graphics);
00311         } else if (have_normals && !have_tricolors) {
00312           graphics[n].type = MOLFILE_TRINORM;
00313           memcpy(graphics[n].data, data, 9*sizeof(float));
00314           next_elem(n, maxelem, graphics);
00315           graphics[n].type = MOLFILE_NORMS;
00316           memcpy(graphics[n].data, normals, 9*sizeof(float));
00317           next_elem(n, maxelem, graphics);
00318         } else if (have_tricolors && !have_normals) {
00319 #if 0
00320           float tmp1[3], tmp2[3], tmp3[3];
00321           int j;
00322           for (j = 0; j < 3; j++) {
00323             tmp1[j] = data[3 + j] - data[j];
00324             tmp2[j] = data[6 + j] - data[3 + j];
00325           }
00326           cross_prod(tmp3, tmp1, tmp2);
00327           vec_normalize(tmp3);
00328           triclr.putdata(data, data+3, data+6,
00329                          tmp3, tmp3, tmp3,
00330                          colorIndices[0], colorIndices[1], colorIndices[2], 
00331                          cmdList);
00332 #else
00333           // XXX Take the average of the color
00334           graphics[n].type = MOLFILE_COLOR;
00335           graphics[n].data[0] = (color[0]+color[3]+color[6])/3.0f;
00336           graphics[n].data[1] = (color[1]+color[4]+color[7])/3.0f;
00337           graphics[n].data[2] = (color[2]+color[5]+color[8])/3.0f;
00338           next_elem(n, maxelem, graphics);
00339           graphics[n].type = MOLFILE_TRIANGLE;
00340           memcpy(graphics[n].data, data, 9*sizeof(float));
00341           next_elem(n, maxelem, graphics);
00342 #endif
00343         } else {
00344 #if 0
00345           triclr.putdata(data, data+3, data+6,
00346                          normals, normals+3, normals+6,
00347                          colorIndices[0], colorIndices[1], colorIndices[2], 
00348                          cmdList);
00349 #else
00350           graphics[n].type = MOLFILE_TRICOLOR;
00351           memcpy(graphics[n].data, data, 9*sizeof(float));
00352           next_elem(n, maxelem, graphics);
00353           graphics[n].type = MOLFILE_NORMS;
00354           memcpy(graphics[n].data, normals, 9*sizeof(float));
00355           next_elem(n, maxelem, graphics);
00356           graphics[n].type = MOLFILE_COLOR;
00357           memcpy(graphics[n].data, color, 9*sizeof(float));
00358           next_elem(n, maxelem, graphics);
00359 #endif
00360        }
00361        break;
00362 
00363      case 2: // sphere
00364        if (!get_line(line, buffer, 199, infile)) {
00365          //msgErr << "Raster3D input: error reading sphere data (line "
00366          //<< line << ")" << sendmsg;
00367          return MOLFILE_ERROR;
00368        }
00369 
00370        if (sscanf(buffer, "%f %f %f %f %f %f %f",
00371                   data, data + 1, data + 2, data + 3,
00372                   data + 4, data + 5, data + 6) != 7) {
00373          //msgErr << "Raster3D input: bad sphere data in file (line "
00374          //<< line << "). Will try to continue." << sendmsg;
00375          continue;
00376        }
00377        graphics[n].type = MOLFILE_COLOR;
00378        color[0] = sqrt(data[4]);
00379        color[1] = sqrt(data[5]);
00380        color[2] = sqrt(data[6]);
00381        memcpy(graphics[n].data, color, 3*sizeof(float));
00382        next_elem(n, maxelem, graphics);
00383        graphics[n].type = MOLFILE_SPHERE;
00384        graphics[n].size = data[3];
00385        graphics[n].style = 12; // XXX hard-coded resolution
00386        memcpy(graphics[n].data, data, 3*sizeof(float));
00387        next_elem(n, maxelem, graphics);
00388        break;
00389 
00390      case 3: // rounded cylinder
00391      case 5: // flat cylinder
00392        if (!get_line(line, buffer, 199, infile)) {
00393          //msgErr << "Raster3D input: error reading cylinder data (line "
00394          //<< line << ")" << sendmsg;
00395          return MOLFILE_ERROR;
00396        }
00397 
00398        if (sscanf(buffer, "%f %f %f %f %f %f %f %f %f %f %f",
00399                   data, data + 1, data + 2, data + 3, data + 4,
00400                   data + 5, data + 6, data + 7, data + 8, data + 9,
00401                   data + 10) != 11) {
00402          //msgErr << "Raster3D input: bad cylinder data (line "
00403          //<< line << "). Will try to continue." << sendmsg;
00404          continue;
00405        }
00406        graphics[n].type = MOLFILE_COLOR;
00407        color[0] = sqrt(data[8]);
00408        color[1] = sqrt(data[9]);
00409        color[2] = sqrt(data[10]);
00410        memcpy(graphics[n].data, color, 3*sizeof(float));
00411        next_elem(n, maxelem, graphics);
00412        graphics[n].type = MOLFILE_CYLINDER;
00413        graphics[n].size = data[3];
00414        graphics[n].style = 12; // XXX hard-coded resolution
00415        memcpy(graphics[n].data, data, 3*sizeof(float));
00416        memcpy(graphics[n].data+3, data+4, 3*sizeof(float));
00417        next_elem(n, maxelem, graphics);
00418 
00419        // cap with spheres for object 3
00420        if (objtype == 3) {
00421          graphics[n].type = MOLFILE_SPHERE;
00422          graphics[n].size = data[3];
00423          graphics[n].style = 12; // XXX hard-coded resolution
00424          memcpy(graphics[n].data, data, 3*sizeof(float));
00425          next_elem(n, maxelem, graphics);
00426          graphics[n].type = MOLFILE_SPHERE;
00427          graphics[n].size = data[3];
00428          graphics[n].style = 12; // XXX hard-coded resolution
00429          memcpy(graphics[n].data, data+4, 3*sizeof(float));
00430          next_elem(n, maxelem, graphics);
00431        }
00432        break;
00433 
00434      case 9:
00435        break;
00436 
00437      case 6: case 8: case 10: case 11: case 12: case 13: case 15: case 19:
00438        // Ignore the next line
00439        get_line(line, buffer, 199, infile);
00440        break;
00441 
00442      case 7:
00443        //msgErr << "Raster3D input: encountered unexpected object 7 (triangle ";
00444        //msgErr << "vertex normals) (line " << line;
00445        //msgErr << "). Will try to continue." << sendmsg;
00446        break;
00447 
00448      case 17:
00449        //msgErr << "Raster3D input: encountered unexpected object 17 (triangle " << sendmsg;
00450        //msgErr << "vertex colors) (line " << line << "). Will try to continue." << sendmsg;
00451        break;
00452 
00453      case 0:  // Raster3D 'force EOF' -- checked later
00454        break;
00455 
00456      // We encountered an object that is not recognized.
00457      // Need to warn the user. Future version of R3d perhaps?
00458      default:
00459        if (!futureVersion) {
00460          //msgErr << "Raster3D input: encountered unknown object type #"
00461          //<< objtype << sendmsg;
00462          //msgErr << " (line " << line << "). Future version of Raster3D maybe?"
00463          //<< " Will try to continue." << sendmsg;
00464          futureVersion = 1;
00465        }
00466        break;
00467 
00468     } // end of switch
00469 
00470     // If this is a Raster3d "force EOF" object, break
00471     if (objtype == 0) 
00472       break;
00473   } // end of while
00474 
00475   if (ferror(infile)) {
00476     //msgErr << "Raster3D input: read error while reading input file (line "
00477     //<< line << "). Aborting." << sendmsg;
00478     return MOLFILE_ERROR;
00479   }
00480 
00481   // normal exit
00482   *nelem = n;
00483   handle->graphics = graphics;
00484   *gdata = graphics;
00485   return MOLFILE_SUCCESS;
00486 }
00487 
00488 
00489 static void close_file_read(void *v) {
00490   handle_t *handle = (handle_t *)v;
00491   fclose(handle->fd);
00492   handle->fd = NULL;
00493   free(handle->graphics);
00494   handle->graphics = NULL;
00495   delete handle;
00496 }
00497 
00498 
00499 /*
00500  * Initialization stuff here
00501  */
00502 static molfile_plugin_t plugin;
00503 
00504 VMDPLUGIN_API int VMDPLUGIN_init(void) {
00505   memset(&plugin, 0, sizeof(molfile_plugin_t));
00506   plugin.abiversion = vmdplugin_ABIVERSION;
00507   plugin.type = MOLFILE_PLUGIN_TYPE;
00508   plugin.name = "raster3d";
00509   plugin.prettyname = "Raster3d Scene File";
00510   plugin.author = "Justin Gullingsrud";
00511   plugin.majorv = 0;
00512   plugin.minorv = 3;
00513   plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00514   plugin.filename_extension = "r3d";
00515   plugin.open_file_read = open_file_read;
00516   plugin.read_rawgraphics = read_rawgraphics;
00517   plugin.close_file_read = close_file_read;
00518   return VMDPLUGIN_SUCCESS;
00519 }
00520 
00521 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00522   (*cb)(v, (vmdplugin_t *)&plugin);
00523   return VMDPLUGIN_SUCCESS;
00524 }
00525 
00526 VMDPLUGIN_API int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }
00527 

Generated on Tue Aug 11 03:06:41 2020 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002