00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <math.h>
00033 #include <time.h>
00034 #include "WavefrontDisplayDevice.h"
00035 #include "Matrix4.h"
00036 #include "DispCmds.h"
00037 #include "Inform.h"
00038 #include "utilities.h"
00039 #include "config.h"
00040
00041 #define DASH_LENGTH 0.02f
00042
00043 #define VMDGENMTLFILE 1
00044
00045 static int replacefileextension(char * s,
00046 const char * oldextension,
00047 const char * newextension) {
00048 int sz, extsz;
00049 sz = strlen(s);
00050 extsz = strlen(oldextension);
00051
00052 if (strlen(newextension) != strlen(oldextension))
00053 return -1;
00054
00055 if (extsz > sz)
00056 return -1;
00057
00058 if (strupncmp(s + (sz - extsz), oldextension, extsz)) {
00059 return -1;
00060 }
00061
00062 strcpy(s + (sz - extsz), newextension);
00063
00064 return 0;
00065 }
00066
00067 static char * stripleadingfilepath(const char *fullpath) {
00068 int i, j;
00069 char *s = NULL;
00070 int len=strlen(fullpath);
00071 s = (char *) calloc(1, len+1);
00072
00073
00074
00075 for (i=0,j=0; i<len; i++) {
00076 if (fullpath[i] == '/' || fullpath[i] == '\\')
00077 j=i;
00078 }
00079
00080
00081 if (j != 0)
00082 strcpy(s, fullpath+j+1);
00083 else
00084 strcpy(s, fullpath);
00085
00086 return s;
00087 }
00088
00089
00090
00091 WavefrontDisplayDevice::WavefrontDisplayDevice(void)
00092 : FileRenderer("Wavefront", "Wavefront (OBJ and MTL)", "vmdscene.obj", "true") { }
00093
00094
00095 WavefrontDisplayDevice::~WavefrontDisplayDevice(void) { }
00096
00097
00098 void WavefrontDisplayDevice::beginrepgeomgroup(const char *s) {
00099 fprintf(outfile, "g %s\n", s);
00100 }
00101
00102
00103 void WavefrontDisplayDevice::comment(const char *s) {
00104 fprintf(outfile, "# %s\n", s);
00105 }
00106
00107
00108 void WavefrontDisplayDevice::point(float * spdata) {
00109 float vec[3];
00110
00111 (transMat.top()).multpoint3d(spdata, vec);
00112
00113
00114 fprintf(outfile, "v %5f %5f %5f\n", vec[0], vec[1], -vec[2]);
00115 fprintf(outfile, "p -1\n");
00116 }
00117
00118
00119 void WavefrontDisplayDevice::line(float *a, float*b) {
00120 int i, j, test;
00121 float dirvec[3], unitdirvec[3];
00122 float from[3], to[3], tmp1[3], tmp2[3];
00123 float len;
00124
00125 if (lineStyle == ::SOLIDLINE) {
00126
00127 (transMat.top()).multpoint3d(a, from);
00128 (transMat.top()).multpoint3d(b, to);
00129
00130
00131 fprintf(outfile, "v %5f %5f %5f\n", from[0], from[1], -from[2]);
00132 fprintf(outfile, "v %5f %5f %5f\n", to[0], to[1], -to[2]);
00133 fprintf(outfile, "l -1 -2\n");
00134 } else if (lineStyle == ::DASHEDLINE) {
00135
00136 (transMat.top()).multpoint3d(a, tmp1);
00137 (transMat.top()).multpoint3d(b, tmp2);
00138
00139
00140 for(i=0; i<3; i++) {
00141 dirvec[i] = tmp2[i] - tmp1[i];
00142 }
00143 len = sqrtf(dirvec[0]*dirvec[0] + dirvec[1]*dirvec[1] + dirvec[2]*dirvec[2])
00144 ;
00145 for(i=0;i<3;i++) {
00146 unitdirvec[i] = dirvec[i] / sqrtf(len);
00147 }
00148
00149 test = 1;
00150 i = 0;
00151 while(test == 1) {
00152 for(j=0;j<3;j++) {
00153 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]);
00154 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00155 }
00156
00157 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00158 for(j=0;j<3;j++)
00159 to[j] = tmp2[j];
00160 test = 0;
00161 }
00162
00163
00164 fprintf(outfile, "v %5f %5f %5f\n", from[0], from[1], -from[2]);
00165 fprintf(outfile, "v %5f %5f %5f\n", to[0], to[1], -to[2]);
00166 fprintf(outfile, "l -1 -2\n");
00167 i++;
00168 }
00169 } else {
00170 msgErr << "WavefrontDisplayDevice: Unknown line style "
00171 << lineStyle << sendmsg;
00172 }
00173 }
00174
00175
00176
00177
00178 void WavefrontDisplayDevice::triangle(const float *v1, const float *v2, const float *v3,
00179 const float *n1, const float *n2, const float *n3) {
00180 float a[3], b[3], c[3];
00181 float norm1[3], norm2[3], norm3[3];
00182
00183
00184 (transMat.top()).multpoint3d(v1, a);
00185 (transMat.top()).multpoint3d(v2, b);
00186 (transMat.top()).multpoint3d(v3, c);
00187
00188
00189 (transMat.top()).multnorm3d(n1, norm1);
00190 (transMat.top()).multnorm3d(n2, norm2);
00191 (transMat.top()).multnorm3d(n3, norm3);
00192
00193 #ifdef VMDGENMTLFILE
00194
00195 write_cindexmaterial(colorIndex, materialIndex);
00196 #endif
00197
00198
00199 fprintf(outfile,"v %f %f %f\n", a[0], a[1], a[2]);
00200 fprintf(outfile,"v %f %f %f\n", b[0], b[1], b[2]);
00201 fprintf(outfile,"v %f %f %f\n", c[0], c[1], c[2]);
00202 fprintf(outfile,"vn %.4f %.4f %.4f\n", norm1[0], norm1[1], norm1[2]);
00203 fprintf(outfile,"vn %.4f %.4f %.4f\n", norm2[0], norm2[1], norm2[2]);
00204 fprintf(outfile,"vn %.4f %.4f %.4f\n", norm3[0], norm3[1], norm3[2]);
00205 fprintf(outfile,"f -3//-3 -2//-2 -1//-1\n");
00206 }
00207
00208
00209
00210
00211 void WavefrontDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00212 int numfacets, int * facets) {
00213 int i;
00214 float vec1[3];
00215 float norm1[3];
00216 const float onethird = (1.0f / 3.0f);
00217
00218
00219 for (i=0; i<numverts; i++) {
00220 int idx = i*10;
00221
00222 (transMat.top()).multpoint3d(cnv + idx + 7, vec1);
00223 fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]);
00224
00225 (transMat.top()).multnorm3d(cnv + idx + 4, norm1);
00226 fprintf(outfile, "vn %.4f %.4f %.4f\n", norm1[0], norm1[1], norm1[2]);
00227 }
00228
00229
00230 for (i=0; i<numfacets*3; i+=3) {
00231 int v0 = facets[i ];
00232 int v1 = facets[i + 1];
00233 int v2 = facets[i + 2];
00234
00235 #ifdef VMDGENMTLFILE
00236
00237
00238
00239 const float *c1 = cnv + v0 * 10;
00240 const float *c2 = cnv + v1 * 10;
00241 const float *c3 = cnv + v2 * 10;
00242 float r, g, b;
00243 r = (c1[0] + c2[0] + c3[0]) * onethird;
00244 g = (c1[1] + c2[1] + c3[1]) * onethird;
00245 b = (c1[2] + c2[2] + c3[2]) * onethird;
00246
00247 int cindex = nearest_index(r, g, b);
00248 write_cindexmaterial(cindex, materialIndex);
00249 #endif
00250
00251
00252 v0 -= numverts;
00253 v1 -= numverts;
00254 v2 -= numverts;
00255 fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
00256 }
00257 }
00258
00259
00260
00261
00262 void WavefrontDisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, char *n,
00263 float *v, int numfacets) {
00264 int i;
00265 float vec1[3];
00266 float norm1[3];
00267 int numverts = 3*numfacets;
00268
00269 const float onethird = (1.0f / 3.0f);
00270 const float ci2f = 1.0f / 255.0f;
00271 const float cn2f = 1.0f / 127.5f;
00272
00273
00274 for (i=0; i<numverts; i++) {
00275 float ntmp[3];
00276 int idx = i * 3;
00277
00278 (transMat.top()).multpoint3d(v + idx, vec1);
00279 fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]);
00280
00281
00282
00283 ntmp[0] = n[idx ] * cn2f + ci2f;
00284 ntmp[1] = n[idx+1] * cn2f + ci2f;
00285 ntmp[2] = n[idx+2] * cn2f + ci2f;
00286 (transMat.top()).multnorm3d(ntmp, norm1);
00287 fprintf(outfile, "vn %.3f %.3f %.3f\n", norm1[0], norm1[1], norm1[2]);
00288 }
00289
00290
00291 for (i=0; i<numfacets*3; i+=3) {
00292 int idx;
00293
00294 int v0 = i;
00295 int v1 = i+1;
00296 int v2 = i+2;
00297
00298 #ifdef VMDGENMTLFILE
00299
00300
00301
00302
00303
00304
00305 float c0[3], c1[3], c2[3];
00306 idx = v0 * 4;
00307 c0[0] = c[idx ] * ci2f;
00308 c0[1] = c[idx + 1] * ci2f;
00309 c0[2] = c[idx + 2] * ci2f;
00310
00311 idx = v1 * 4;
00312 c1[0] = c[idx ] * ci2f;
00313 c1[1] = c[idx + 1] * ci2f;
00314 c1[2] = c[idx + 2] * ci2f;
00315
00316 idx = v2 * 4;
00317 c2[0] = c[idx ] * ci2f;
00318 c2[1] = c[idx + 1] * ci2f;
00319 c2[2] = c[idx + 2] * ci2f;
00320
00321 float r, g, b;
00322 r = (c0[0] + c1[0] + c2[0]) * onethird;
00323 g = (c0[1] + c1[1] + c2[1]) * onethird;
00324 b = (c0[2] + c1[2] + c2[2]) * onethird;
00325
00326 int cindex = nearest_index(r, g, b);
00327 write_cindexmaterial(cindex, materialIndex);
00328 #endif
00329
00330
00331 v0 -= numverts;
00332 v1 -= numverts;
00333 v2 -= numverts;
00334 fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
00335 }
00336 }
00337
00338
00339 void WavefrontDisplayDevice::tristrip(int numverts, const float * cnv,
00340 int numstrips, const int *vertsperstrip,
00341 const int *facets) {
00342 int i, strip, t, v = 0;
00343 int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
00344 float vec1[3];
00345 float norm1[3];
00346 const float onethird = (1.0f / 3.0f);
00347
00348
00349 for (i=0; i<numverts; i++) {
00350 int idx = i*10;
00351
00352 (transMat.top()).multpoint3d(cnv + idx + 7, vec1);
00353 fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]);
00354
00355 (transMat.top()).multnorm3d(cnv + idx + 4, norm1);
00356 fprintf(outfile, "vn %f %f %f\n", norm1[0], norm1[1], norm1[2]);
00357 }
00358
00359
00360
00361
00362
00363 for (strip=0; strip < numstrips; strip++) {
00364
00365 for (t = 0; t < (vertsperstrip[strip] - 2); t++) {
00366
00367 int v0 = facets[v + (stripaddr[t & 0x01][0])];
00368 int v1 = facets[v + (stripaddr[t & 0x01][1])];
00369 int v2 = facets[v + (stripaddr[t & 0x01][2])];
00370
00371 #ifdef VMDGENMTLFILE
00372
00373
00374
00375 const float *c1 = cnv + v0 * 10;
00376 const float *c2 = cnv + v1 * 10;
00377 const float *c3 = cnv + v2 * 10;
00378 float r, g, b;
00379 r = (c1[0] + c2[0] + c3[0]) * onethird;
00380 g = (c1[1] + c2[1] + c3[1]) * onethird;
00381 b = (c1[2] + c2[2] + c3[2]) * onethird;
00382
00383 int cindex = nearest_index(r, g, b);
00384 write_cindexmaterial(cindex, materialIndex);
00385 #endif
00386
00387
00388 v0 -= numverts;
00389 v1 -= numverts;
00390 v2 -= numverts;
00391 fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
00392 v++;
00393 }
00394 v+=2;
00395 }
00396 }
00397
00398
00399 int WavefrontDisplayDevice::open_file(const char *filename) {
00400 if (isOpened) {
00401 close_file();
00402 }
00403 if ((outfile = fopen(filename, "w")) == NULL) {
00404 msgErr << "Could not open file " << filename
00405 << " in current directory for writing!" << sendmsg;
00406 return FALSE;
00407 }
00408 my_filename = stringdup(filename);
00409
00410 #ifdef VMDGENMTLFILE
00411 mtlfilename = stringdup(filename);
00412 if (replacefileextension(mtlfilename, ".obj", ".mtl")) {
00413 msgErr << "Could not generate material filename" << sendmsg;
00414 return FALSE;
00415 }
00416 if ((mtlfile = fopen(mtlfilename, "w")) == NULL) {
00417 msgErr << "Could not open file " << mtlfilename
00418 << " in current directory for writing!" << sendmsg;
00419 return FALSE;
00420 }
00421 #endif
00422
00423 isOpened = TRUE;
00424 reset_state();
00425 oldColorIndex = -1;
00426 oldMaterialIndex = -1;
00427 oldMaterialState = -1;
00428 return TRUE;
00429 }
00430
00431 void WavefrontDisplayDevice::close_file(void) {
00432 if (outfile) {
00433 fclose(outfile);
00434 outfile = NULL;
00435 }
00436 delete [] my_filename;
00437 my_filename = NULL;
00438
00439 #ifdef VMDGENMTLFILE
00440 if (mtlfile) {
00441 fclose(mtlfile);
00442 mtlfile = NULL;
00443 }
00444 delete [] mtlfilename;
00445 mtlfilename = NULL;
00446 #endif
00447
00448 isOpened = FALSE;
00449 }
00450
00451 void WavefrontDisplayDevice::write_header(void) {
00452 fprintf(outfile, "# Wavefront OBJ file export by VMD\n");
00453 fprintf(outfile, "# \n");
00454 fprintf(outfile, "# Molecular graphics exported from VMD %s\n", VMDVERSION);
00455 fprintf(outfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00456 fprintf(outfile, "# \n");
00457
00458 #ifdef VMDGENMTLFILE
00459 fprintf(mtlfile, "# Wavefront OBJ MTL file export by VMD\n");
00460 fprintf(mtlfile, "# \n");
00461 fprintf(mtlfile, "# Molecular graphics exported from VMD %s\n", VMDVERSION);
00462 fprintf(mtlfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00463 fprintf(mtlfile, "# \n");
00464
00465 if (mtlfilename) {
00466 char *shortmtlfilename = NULL;
00467 shortmtlfilename = stripleadingfilepath(mtlfilename);
00468 fprintf(outfile, "# Load Material Library paired with this scene:\n");
00469 fprintf(outfile, "mtllib %s\n", shortmtlfilename);
00470 free(shortmtlfilename);
00471 }
00472
00473 write_material_block();
00474 #endif
00475 }
00476
00477 void WavefrontDisplayDevice::write_material_block(void) {
00478 #ifdef VMDGENMTLFILE
00479 int n;
00480
00481
00482 for (n=BEGREGCLRS; n < (BEGREGCLRS + REGCLRS + MAPCLRS); n++) {
00483 float rgb[3];
00484 fprintf(mtlfile, "newmtl vmd_mat_cindex_%d\n", n);
00485 vec_scale(rgb, 0.0f, matData[n]);
00486 fprintf(mtlfile, "Ka %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00487 vec_scale(rgb, 0.65f, matData[n]);
00488 fprintf(mtlfile, "Kd %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00489 vec_scale(rgb, 0.50f, matData[n]);
00490 fprintf(mtlfile, "Ks %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00491 vec_scale(rgb, 0.0f, matData[n]);
00492 fprintf(mtlfile, "Tf %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00493 fprintf(mtlfile, "d 1.0\n");
00494 fprintf(mtlfile, "Ns 40.0\n");
00495 fprintf(mtlfile, "illum_4\n");
00496 fprintf(mtlfile, "\n");
00497 }
00498
00499
00500 for (n=BEGREGCLRS; n < (BEGREGCLRS + REGCLRS + MAPCLRS); n++) {
00501 float rgb[3];
00502 fprintf(mtlfile, "newmtl vmd_nomat_cindex_%d\n", n);
00503 vec_scale(rgb, 0.0f, matData[n]);
00504 fprintf(mtlfile, "Ka %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00505 vec_scale(rgb, 0.65f, matData[n]);
00506 fprintf(mtlfile, "Kd %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00507 fprintf(mtlfile, "illum_0\n");
00508 fprintf(mtlfile, "\n");
00509 }
00510 #endif
00511 }
00512
00513 void WavefrontDisplayDevice::write_cindexmaterial(int cindex, int material) {
00514 #ifdef VMDGENMTLFILE
00515 if ((oldColorIndex != cindex) ||
00516 (oldMaterialIndex != material) ||
00517 (oldMaterialState != materials_on)) {
00518 if (materials_on) {
00519 fprintf(outfile, "usemtl vmd_mat_cindex_%d\n", cindex);
00520 } else {
00521 fprintf(outfile, "usemtl vmd_nomat_cindex_%d\n", cindex);
00522 }
00523 }
00524 #endif
00525 oldMaterialIndex = material;
00526 oldColorIndex = cindex;
00527 oldMaterialState = materials_on;
00528 }
00529
00530 void WavefrontDisplayDevice::write_colormaterial(float *rgb, int material) {
00531 #ifdef VMDGENMTLFILE
00532 int cindex = nearest_index(rgb[0], rgb[1], rgb[2]);
00533 write_cindexmaterial(cindex, material);
00534 #endif
00535 }
00536
00537 void WavefrontDisplayDevice::write_trailer (void) {
00538 msgWarn << "Materials are not exported to Wavefront files.\n";
00539 }
00540