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 strcpy(s, fullpath+j+1);
00082
00083 return s;
00084 }
00085
00086
00087
00088 WavefrontDisplayDevice::WavefrontDisplayDevice(void)
00089 : FileRenderer("Wavefront", "Wavefront (OBJ and MTL)", "vmdscene.obj", "true") { }
00090
00091
00092 WavefrontDisplayDevice::~WavefrontDisplayDevice(void) { }
00093
00094
00095 void WavefrontDisplayDevice::beginrepgeomgroup(const char *s) {
00096 fprintf(outfile, "g %s\n", s);
00097 }
00098
00099
00100 void WavefrontDisplayDevice::comment(const char *s) {
00101 fprintf(outfile, "# %s\n", s);
00102 }
00103
00104
00105 void WavefrontDisplayDevice::point(float * spdata) {
00106 float vec[3];
00107
00108 (transMat.top()).multpoint3d(spdata, vec);
00109
00110
00111 fprintf(outfile, "v %5f %5f %5f\n", vec[0], vec[1], -vec[2]);
00112 fprintf(outfile, "p -1\n");
00113 }
00114
00115
00116 void WavefrontDisplayDevice::line(float *a, float*b) {
00117 int i, j, test;
00118 float dirvec[3], unitdirvec[3];
00119 float from[3], to[3], tmp1[3], tmp2[3];
00120 float len;
00121
00122 if (lineStyle == ::SOLIDLINE) {
00123
00124 (transMat.top()).multpoint3d(a, from);
00125 (transMat.top()).multpoint3d(b, to);
00126
00127
00128 fprintf(outfile, "v %5f %5f %5f\n", from[0], from[1], -from[2]);
00129 fprintf(outfile, "v %5f %5f %5f\n", to[0], to[1], -to[2]);
00130 fprintf(outfile, "l -1 -2\n");
00131 } else if (lineStyle == ::DASHEDLINE) {
00132
00133 (transMat.top()).multpoint3d(a, tmp1);
00134 (transMat.top()).multpoint3d(b, tmp2);
00135
00136
00137 for(i=0; i<3; i++) {
00138 dirvec[i] = tmp2[i] - tmp1[i];
00139 }
00140 len = sqrtf(dirvec[0]*dirvec[0] + dirvec[1]*dirvec[1] + dirvec[2]*dirvec[2])
00141 ;
00142 for(i=0;i<3;i++) {
00143 unitdirvec[i] = dirvec[i] / sqrtf(len);
00144 }
00145
00146 test = 1;
00147 i = 0;
00148 while(test == 1) {
00149 for(j=0;j<3;j++) {
00150 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]);
00151 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00152 }
00153
00154 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00155 for(j=0;j<3;j++)
00156 to[j] = tmp2[j];
00157 test = 0;
00158 }
00159
00160
00161 fprintf(outfile, "v %5f %5f %5f\n", from[0], from[1], -from[2]);
00162 fprintf(outfile, "v %5f %5f %5f\n", to[0], to[1], -to[2]);
00163 fprintf(outfile, "l -1 -2\n");
00164 i++;
00165 }
00166 } else {
00167 msgErr << "WavefrontDisplayDevice: Unknown line style "
00168 << lineStyle << sendmsg;
00169 }
00170 }
00171
00172
00173
00174
00175 void WavefrontDisplayDevice::triangle(const float *v1, const float *v2, const float *v3,
00176 const float *n1, const float *n2, const float *n3) {
00177 float a[3], b[3], c[3];
00178 float norm1[3], norm2[3], norm3[3];
00179
00180
00181 (transMat.top()).multpoint3d(v1, a);
00182 (transMat.top()).multpoint3d(v2, b);
00183 (transMat.top()).multpoint3d(v3, c);
00184
00185
00186 (transMat.top()).multnorm3d(n1, norm1);
00187 (transMat.top()).multnorm3d(n2, norm2);
00188 (transMat.top()).multnorm3d(n3, norm3);
00189
00190 #ifdef VMDGENMTLFILE
00191
00192 write_cindexmaterial(colorIndex, materialIndex);
00193 #endif
00194
00195
00196 fprintf(outfile,"v %f %f %f\n", a[0], a[1], a[2]);
00197 fprintf(outfile,"v %f %f %f\n", b[0], b[1], b[2]);
00198 fprintf(outfile,"v %f %f %f\n", c[0], c[1], c[2]);
00199 fprintf(outfile,"vn %f %f %f\n", norm1[0], norm1[1], norm1[2]);
00200 fprintf(outfile,"vn %f %f %f\n", norm2[0], norm2[1], norm2[2]);
00201 fprintf(outfile,"vn %f %f %f\n", norm3[0], norm3[1], norm3[2]);
00202 fprintf(outfile,"f -3//-3 -2//-2 -1//-1\n");
00203 }
00204
00205
00206
00207
00208 void WavefrontDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00209 int numfacets, int * facets) {
00210 int i;
00211 float vec1[3];
00212 float norm1[3];
00213 const float onethird = (1.0f / 3.0f);
00214
00215
00216 for (i=0; i<numverts; i++) {
00217 int idx = i*10;
00218
00219 (transMat.top()).multpoint3d(cnv + idx + 7, vec1);
00220 fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]);
00221
00222 (transMat.top()).multnorm3d(cnv + idx + 4, norm1);
00223 fprintf(outfile, "vn %f %f %f\n", norm1[0], norm1[1], norm1[2]);
00224 }
00225
00226
00227 for (i=0; i<numfacets*3; i+=3) {
00228 int v0 = facets[i ];
00229 int v1 = facets[i + 1];
00230 int v2 = facets[i + 2];
00231
00232 #ifdef VMDGENMTLFILE
00233
00234
00235
00236 const float *c1 = cnv + v0 * 10;
00237 const float *c2 = cnv + v1 * 10;
00238 const float *c3 = cnv + v2 * 10;
00239 float r, g, b;
00240 r = (c1[0] + c2[0] + c3[0]) * onethird;
00241 g = (c1[1] + c2[1] + c3[1]) * onethird;
00242 b = (c1[2] + c2[2] + c3[2]) * onethird;
00243
00244 int cindex = nearest_index(r, g, b);
00245 write_cindexmaterial(cindex, materialIndex);
00246 #endif
00247
00248
00249 v0 -= numverts;
00250 v1 -= numverts;
00251 v2 -= numverts;
00252 fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
00253 }
00254 }
00255
00256
00257 void WavefrontDisplayDevice::tristrip(int numverts, const float * cnv,
00258 int numstrips, const int *vertsperstrip,
00259 const int *facets) {
00260 int i, strip, t, v = 0;
00261 int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
00262 float vec1[3];
00263 float norm1[3];
00264 const float onethird = (1.0f / 3.0f);
00265
00266
00267 for (i=0; i<numverts; i++) {
00268 int idx = i*10;
00269
00270 (transMat.top()).multpoint3d(cnv + idx + 7, vec1);
00271 fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]);
00272
00273 (transMat.top()).multnorm3d(cnv + idx + 4, norm1);
00274 fprintf(outfile, "vn %f %f %f\n", norm1[0], norm1[1], norm1[2]);
00275 }
00276
00277
00278
00279
00280
00281 for (strip=0; strip < numstrips; strip++) {
00282
00283 for (t = 0; t < (vertsperstrip[strip] - 2); t++) {
00284
00285 int v0 = facets[v + (stripaddr[t & 0x01][0])];
00286 int v1 = facets[v + (stripaddr[t & 0x01][1])];
00287 int v2 = facets[v + (stripaddr[t & 0x01][2])];
00288
00289 #ifdef VMDGENMTLFILE
00290
00291
00292
00293 const float *c1 = cnv + v0 * 10;
00294 const float *c2 = cnv + v1 * 10;
00295 const float *c3 = cnv + v2 * 10;
00296 float r, g, b;
00297 r = (c1[0] + c2[0] + c3[0]) * onethird;
00298 g = (c1[1] + c2[1] + c3[1]) * onethird;
00299 b = (c1[2] + c2[2] + c3[2]) * onethird;
00300
00301 int cindex = nearest_index(r, g, b);
00302 write_cindexmaterial(cindex, materialIndex);
00303 #endif
00304
00305
00306 v0 -= numverts;
00307 v1 -= numverts;
00308 v2 -= numverts;
00309 fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
00310 v++;
00311 }
00312 v+=2;
00313 }
00314 }
00315
00316
00317 int WavefrontDisplayDevice::open_file(const char *filename) {
00318 if (isOpened) {
00319 close_file();
00320 }
00321 if ((outfile = fopen(filename, "w")) == NULL) {
00322 msgErr << "Could not open file " << filename
00323 << " in current directory for writing!" << sendmsg;
00324 return FALSE;
00325 }
00326 my_filename = stringdup(filename);
00327
00328 #ifdef VMDGENMTLFILE
00329 mtlfilename = stringdup(filename);
00330 if (replacefileextension(mtlfilename, ".obj", ".mtl")) {
00331 msgErr << "Could not generate material filename" << sendmsg;
00332 return FALSE;
00333 }
00334 if ((mtlfile = fopen(mtlfilename, "w")) == NULL) {
00335 msgErr << "Could not open file " << mtlfilename
00336 << " in current directory for writing!" << sendmsg;
00337 return FALSE;
00338 }
00339 #endif
00340
00341 isOpened = TRUE;
00342 reset_state();
00343 oldColorIndex = -1;
00344 oldMaterialIndex = -1;
00345 oldMaterialState = -1;
00346 return TRUE;
00347 }
00348
00349 void WavefrontDisplayDevice::close_file(void) {
00350 if (outfile) {
00351 fclose(outfile);
00352 outfile = NULL;
00353 }
00354 delete [] my_filename;
00355 my_filename = NULL;
00356
00357 #ifdef VMDGENMTLFILE
00358 if (mtlfile) {
00359 fclose(mtlfile);
00360 mtlfile = NULL;
00361 }
00362 delete [] mtlfilename;
00363 mtlfilename = NULL;
00364 #endif
00365
00366 isOpened = FALSE;
00367 }
00368
00369 void WavefrontDisplayDevice::write_header(void) {
00370 fprintf(outfile, "# Wavefront OBJ file export by VMD\n");
00371 fprintf(outfile, "# \n");
00372 fprintf(outfile, "# Molecular graphics exported from VMD %s\n", VMDVERSION);
00373 fprintf(outfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00374 fprintf(outfile, "# \n");
00375
00376 #ifdef VMDGENMTLFILE
00377 fprintf(mtlfile, "# Wavefront OBJ MTL file export by VMD\n");
00378 fprintf(mtlfile, "# \n");
00379 fprintf(mtlfile, "# Molecular graphics exported from VMD %s\n", VMDVERSION);
00380 fprintf(mtlfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00381 fprintf(mtlfile, "# \n");
00382
00383 if (mtlfilename) {
00384 char *shortmtlfilename = NULL;
00385 shortmtlfilename = stripleadingfilepath(mtlfilename);
00386 fprintf(outfile, "# Load Material Library paired with this scene:\n");
00387 fprintf(outfile, "mtllib %s\n", shortmtlfilename);
00388 free(shortmtlfilename);
00389 }
00390
00391 write_material_block();
00392 #endif
00393 }
00394
00395 void WavefrontDisplayDevice::write_material_block(void) {
00396 #ifdef VMDGENMTLFILE
00397 int n;
00398
00399
00400 for (n=BEGREGCLRS; n < (BEGREGCLRS + REGCLRS + MAPCLRS); n++) {
00401 float rgb[3];
00402 fprintf(mtlfile, "newmtl vmd_mat_cindex_%d\n", n);
00403 vec_scale(rgb, 0.0f, matData[n]);
00404 fprintf(mtlfile, "Ka %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00405 vec_scale(rgb, 0.65f, matData[n]);
00406 fprintf(mtlfile, "Kd %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00407 vec_scale(rgb, 0.50f, matData[n]);
00408 fprintf(mtlfile, "Ks %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00409 vec_scale(rgb, 0.0f, matData[n]);
00410 fprintf(mtlfile, "Tf %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00411 fprintf(mtlfile, "d 1.0\n");
00412 fprintf(mtlfile, "Ns 40.0\n");
00413 fprintf(mtlfile, "illum_4\n");
00414 fprintf(mtlfile, "\n");
00415 }
00416
00417
00418 for (n=BEGREGCLRS; n < (BEGREGCLRS + REGCLRS + MAPCLRS); n++) {
00419 float rgb[3];
00420 fprintf(mtlfile, "newmtl vmd_nomat_cindex_%d\n", n);
00421 vec_scale(rgb, 0.0f, matData[n]);
00422 fprintf(mtlfile, "Ka %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00423 vec_scale(rgb, 0.65f, matData[n]);
00424 fprintf(mtlfile, "Kd %.2f %.2f %.2f\n", rgb[0], rgb[1], rgb[2]);
00425 fprintf(mtlfile, "illum_0\n");
00426 fprintf(mtlfile, "\n");
00427 }
00428 #endif
00429 }
00430
00431 void WavefrontDisplayDevice::write_cindexmaterial(int cindex, int material) {
00432 #ifdef VMDGENMTLFILE
00433 if ((oldColorIndex != cindex) ||
00434 (oldMaterialIndex != material) ||
00435 (oldMaterialState != materials_on)) {
00436 if (materials_on) {
00437 fprintf(outfile, "usemtl vmd_mat_cindex_%d\n", cindex);
00438 } else {
00439 fprintf(outfile, "usemtl vmd_nomat_cindex_%d\n", cindex);
00440 }
00441 }
00442 #endif
00443 oldMaterialIndex = material;
00444 oldColorIndex = cindex;
00445 oldMaterialState = materials_on;
00446 }
00447
00448 void WavefrontDisplayDevice::write_colormaterial(float *rgb, int material) {
00449 #ifdef VMDGENMTLFILE
00450 int cindex = nearest_index(rgb[0], rgb[1], rgb[2]);
00451 write_cindexmaterial(cindex, material);
00452 #endif
00453 }
00454
00455 void WavefrontDisplayDevice::write_trailer (void) {
00456 msgWarn << "Materials are not exported to Wavefront files.\n";
00457 }
00458