00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <ctype.h>
00015 #include <math.h>
00016 #include <string.h>
00017
00018 #if defined(_AIX)
00019 #include <strings.h>
00020 #endif
00021
00022 #if defined(WIN32) || defined(WIN64)
00023 #define strcasecmp stricmp
00024 #endif
00025
00026 #include "molfile_plugin.h"
00027
00028
00029 #define BUFFLEN 1024
00030
00031 static void *open_file_read(const char *filepath, const char *filetype,
00032 int *natoms) {
00033 FILE *f;
00034
00035 f = fopen(filepath, "rb");
00036 if (!f) {
00037 fprintf(stderr, "offplugin) Error opening file.\n");
00038 return NULL;
00039 }
00040 *natoms = 0;
00041 return f;
00042 }
00043
00044
00045 static char *nextNoncommentLine(char *buff, int bufflen, FILE *f) {
00046 while (1) {
00047 char *res = fgets(buff, bufflen, f);
00048 if (!res || (res[0] != '#' && res[0] != '\n' && res[0] != '\r'))
00049 return res;
00050 };
00051 }
00052
00053
00054 static void calcNormals (float vert[9], float norm[9]) {
00055 float x1 = vert[3] - vert[0];
00056 float y1 = vert[4] - vert[1];
00057 float z1 = vert[5] - vert[2];
00058 float x2 = vert[6] - vert[0];
00059 float y2 = vert[7] - vert[1];
00060 float z2 = vert[8] - vert[2];
00061 float nx = y1 * z2 - z1 * y2;
00062 float ny = z1 * x2 - x1 * z2;
00063 float nz = x1 * y2 - y1 * x2;
00064 float n = 1 / sqrtf(nx*nx+ny*ny+nz*nz);
00065 norm[0] = norm[3] = norm[6] = n * nx;
00066 norm[1] = norm[4] = norm[7] = n * ny;
00067 norm[2] = norm[5] = norm[8] = n * nz;
00068 }
00069
00070
00071 static int read_rawgraphics(void *v, int *nelem,
00072 const molfile_graphics_t **data) {
00073 int i, k, n;
00074 int nVert, nFaces, nEdges;
00075 float *vertices = NULL, *vertColors = NULL;
00076 char *vertHasColor = NULL;
00077 molfile_graphics_t *graphics = NULL;
00078 int j=0;
00079
00080 char buff[BUFFLEN+1];
00081 FILE *infile = (FILE *)v;
00082
00083
00084 nextNoncommentLine(buff, BUFFLEN, infile);
00085 if (buff[0] != 'O' || buff[1] != 'F' || buff[2] != 'F') {
00086 fprintf(stderr, "offplugin) error: expected \"OFF\" header.\n");
00087 goto error;
00088 }
00089
00090
00091 nextNoncommentLine(buff, BUFFLEN, infile);
00092 if (sscanf (buff, " %d %d %d", &nVert, &nFaces, &nEdges) < 2 ||
00093 nVert <= 0 || nFaces <= 0) {
00094 fprintf(stderr, "offplugin) error: wrong number of elements.\n");
00095 goto error;
00096 }
00097
00098
00099 vertices = (float *) calloc (3 * nVert, sizeof(float));
00100 vertHasColor = (char *) calloc (nVert, sizeof(char));
00101 vertColors = (float *) calloc (3 * nVert, sizeof(float));
00102 for (i = 0; i < nVert; i++) {
00103 nextNoncommentLine(buff, BUFFLEN, infile);
00104 int n = sscanf (buff, " %g %g %g %g %g %g",
00105 &vertices[3*i], &vertices[3*i+1], &vertices[3*i+2],
00106 &vertColors[3*i], &vertColors[3*i+1], &vertColors[3*i+2]);
00107 if (n != 3 && n != 6) {
00108 fprintf(stderr, "offplugin) error: not enough data.\n");
00109 goto error;
00110 }
00111 vertHasColor[i] = (n == 6);
00112 }
00113
00114
00115
00116
00117
00118 graphics = (molfile_graphics_t *) calloc(6*nFaces, sizeof(molfile_graphics_t));
00119 n = 0;
00120 for (i = 0; i < nFaces; i++) {
00121 int idx[4];
00122 float c[3];
00123 nextNoncommentLine(buff, BUFFLEN, infile);
00124
00125 if (sscanf (buff, "%d", &k) != 1 || k < 3) {
00126 fprintf(stderr, "offplugin) error: not enough data.\n");
00127 goto error;
00128 }
00129
00130 if (k > 4) {
00131
00132
00133
00134 fprintf(stderr, "offplugin) error: TODO -- handling polygons with more than 4 vertices.\n");
00135 goto error;
00136 }
00137
00138 if (k == 3) {
00139 j = sscanf (buff, "%d %d %d %d %g %g %g", &k, &idx[0], &idx[1], &idx[2], &c[0], &c[1], &c[2]);
00140 bool hasColor = ((j == 7) || (vertHasColor[idx[0]] && vertHasColor[idx[1]] && vertHasColor[idx[2]]));
00141
00142 graphics[n].type = (hasColor ? MOLFILE_TRICOLOR : MOLFILE_TRIANGLE);
00143 graphics[n].data[0] = vertices[3*idx[0] ];
00144 graphics[n].data[1] = vertices[3*idx[0]+1];
00145 graphics[n].data[2] = vertices[3*idx[0]+2];
00146 graphics[n].data[3] = vertices[3*idx[1] ];
00147 graphics[n].data[4] = vertices[3*idx[1]+1];
00148 graphics[n].data[5] = vertices[3*idx[1]+2];
00149 graphics[n].data[6] = vertices[3*idx[2] ];
00150 graphics[n].data[7] = vertices[3*idx[2]+1];
00151 graphics[n].data[8] = vertices[3*idx[2]+2];
00152 n++;
00153
00154 if (j == 7) {
00155
00156 graphics[n].type = MOLFILE_NORMS;
00157 calcNormals (graphics[n-1].data, graphics[n].data);
00158 n++;
00159
00160 graphics[n].type = MOLFILE_COLOR;
00161 graphics[n].data[0] = graphics[n].data[3] = graphics[n].data[6] = c[0];
00162 graphics[n].data[1] = graphics[n].data[4] = graphics[n].data[7] = c[1];
00163 graphics[n].data[2] = graphics[n].data[5] = graphics[n].data[8] = c[2];
00164 n++;
00165 } else if (hasColor) {
00166
00167 graphics[n].type = MOLFILE_NORMS;
00168 calcNormals (graphics[n-1].data, graphics[n].data);
00169 n++;
00170
00171 graphics[n].type = MOLFILE_COLOR;
00172 graphics[n].data[0] = vertColors[3*idx[0] ];
00173 graphics[n].data[1] = vertColors[3*idx[0]+1];
00174 graphics[n].data[2] = vertColors[3*idx[0]+2];
00175 graphics[n].data[3] = vertColors[3*idx[1] ];
00176 graphics[n].data[4] = vertColors[3*idx[1]+1];
00177 graphics[n].data[5] = vertColors[3*idx[1]+2];
00178 graphics[n].data[6] = vertColors[3*idx[2] ];
00179 graphics[n].data[7] = vertColors[3*idx[2]+1];
00180 graphics[n].data[8] = vertColors[3*idx[2]+2];
00181 n++;
00182 }
00183 } else if (k == 4) {
00184 j = sscanf (buff, "%d %d %d %d %d %g %g %g", &k, &idx[0], &idx[1], &idx[2], &idx[3], &c[0], &c[1], &c[2]);
00185 bool hasColor = ((j == 8) || (vertHasColor[idx[0]] && vertHasColor[idx[1]] && vertHasColor[idx[2]] && vertHasColor[idx[3]]));
00186
00187
00188 graphics[n].type = (hasColor ? MOLFILE_TRICOLOR : MOLFILE_TRIANGLE);
00189 graphics[n].data[0] = vertices[3*idx[0] ];
00190 graphics[n].data[1] = vertices[3*idx[0]+1];
00191 graphics[n].data[2] = vertices[3*idx[0]+2];
00192 graphics[n].data[3] = vertices[3*idx[1] ];
00193 graphics[n].data[4] = vertices[3*idx[1]+1];
00194 graphics[n].data[5] = vertices[3*idx[1]+2];
00195 graphics[n].data[6] = vertices[3*idx[2] ];
00196 graphics[n].data[7] = vertices[3*idx[2]+1];
00197 graphics[n].data[8] = vertices[3*idx[2]+2];
00198 n++;
00199
00200 if (j == 8) {
00201 graphics[n].type = MOLFILE_NORMS;
00202 calcNormals (graphics[n-1].data, graphics[n].data);
00203 n++;
00204
00205 graphics[n].type = MOLFILE_COLOR;
00206 graphics[n].data[0] = graphics[n].data[3] = graphics[n].data[6] = c[0];
00207 graphics[n].data[1] = graphics[n].data[4] = graphics[n].data[7] = c[1];
00208 graphics[n].data[2] = graphics[n].data[5] = graphics[n].data[8] = c[2];
00209 n++;
00210 } else if (hasColor) {
00211 graphics[n].type = MOLFILE_NORMS;
00212 calcNormals (graphics[n-1].data, graphics[n].data);
00213 n++;
00214
00215 graphics[n].type = MOLFILE_COLOR;
00216 graphics[n].data[0] = vertColors[3*idx[0]];
00217 graphics[n].data[1] = vertColors[3*idx[0]+1];
00218 graphics[n].data[2] = vertColors[3*idx[0]+2];
00219 graphics[n].data[3] = vertColors[3*idx[1]];
00220 graphics[n].data[4] = vertColors[3*idx[1]+1];
00221 graphics[n].data[5] = vertColors[3*idx[1]+2];
00222 graphics[n].data[6] = vertColors[3*idx[2]];
00223 graphics[n].data[7] = vertColors[3*idx[2]+1];
00224 graphics[n].data[8] = vertColors[3*idx[2]+2];
00225 n++;
00226 }
00227
00228 graphics[n].type = (hasColor ? MOLFILE_TRICOLOR : MOLFILE_TRIANGLE);
00229 graphics[n].data[0] = vertices[3*idx[2]];
00230 graphics[n].data[1] = vertices[3*idx[2]+1];
00231 graphics[n].data[2] = vertices[3*idx[2]+2];
00232 graphics[n].data[3] = vertices[3*idx[3]];
00233 graphics[n].data[4] = vertices[3*idx[3]+1];
00234 graphics[n].data[5] = vertices[3*idx[3]+2];
00235 graphics[n].data[6] = vertices[3*idx[0]];
00236 graphics[n].data[7] = vertices[3*idx[0]+1];
00237 graphics[n].data[8] = vertices[3*idx[0]+2];
00238 n++;
00239
00240 if (j == 8) {
00241 graphics[n].type = MOLFILE_NORMS;
00242 calcNormals (graphics[n-1].data, graphics[n].data);
00243 n++;
00244
00245 graphics[n].type = MOLFILE_COLOR;
00246 graphics[n].data[0] = graphics[n].data[3] = graphics[n].data[6] = c[0];
00247 graphics[n].data[1] = graphics[n].data[4] = graphics[n].data[7] = c[1];
00248 graphics[n].data[2] = graphics[n].data[5] = graphics[n].data[8] = c[2];
00249 n++;
00250 } else if (hasColor) {
00251 graphics[n].type = MOLFILE_NORMS;
00252 calcNormals (graphics[n-1].data, graphics[n].data);
00253 n++;
00254
00255 graphics[n].type = MOLFILE_COLOR;
00256 graphics[n].data[0] = vertColors[3*idx[2]];
00257 graphics[n].data[1] = vertColors[3*idx[2]+1];
00258 graphics[n].data[2] = vertColors[3*idx[2]+2];
00259 graphics[n].data[3] = vertColors[3*idx[3]];
00260 graphics[n].data[4] = vertColors[3*idx[3]+1];
00261 graphics[n].data[5] = vertColors[3*idx[3]+2];
00262 graphics[n].data[6] = vertColors[3*idx[0]];
00263 graphics[n].data[7] = vertColors[3*idx[0]+1];
00264 graphics[n].data[8] = vertColors[3*idx[0]+2];
00265 n++;
00266 }
00267 }
00268 }
00269
00270 *nelem = n;
00271 *data = (molfile_graphics_t *) realloc(graphics, n*sizeof(molfile_graphics_t));
00272 return MOLFILE_SUCCESS;
00273
00274
00275 error:
00276 free (graphics);
00277 free (vertices);
00278 return MOLFILE_ERROR;
00279 }
00280
00281
00282 static void close_file_read(void *v) {
00283 fclose((FILE *)v);
00284 }
00285
00286
00287
00288
00289
00290 static molfile_plugin_t plugin;
00291
00292 VMDPLUGIN_API int VMDPLUGIN_init(void) {
00293 memset(&plugin, 0, sizeof(molfile_plugin_t));
00294 plugin.abiversion = vmdplugin_ABIVERSION;
00295 plugin.type = MOLFILE_PLUGIN_TYPE;
00296 plugin.name = "off";
00297 plugin.prettyname = "Object File Format (OFF)";
00298 plugin.author = "Francois-Xavier Coudert";
00299 plugin.majorv = 0;
00300 plugin.minorv = 4;
00301 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00302 plugin.filename_extension = "off";
00303 plugin.open_file_read = open_file_read;
00304 plugin.read_rawgraphics = read_rawgraphics;
00305 plugin.close_file_read = close_file_read;
00306 return VMDPLUGIN_SUCCESS;
00307 }
00308
00309 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00310 (*cb)(v, (vmdplugin_t *)&plugin);
00311 return VMDPLUGIN_SUCCESS;
00312 }
00313
00314 VMDPLUGIN_API int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }
00315