00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00023 #include <string.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include "TachyonDisplayDevice.h"
00028 #include "Matrix4.h"
00029 #include "DispCmds.h"
00030 #include "Inform.h"
00031 #include "utilities.h"
00032 #include "config.h"
00033 #include "Hershey.h"
00034
00035 #define DEFAULT_RADIUS 0.002f
00036 #define DASH_LENGTH 0.02f
00037
00038 #if defined(_MSC_VER) || defined(WIN32)
00039 #define TACHYON_RUN_STRING " -aasamples 12 %s -format BMP -o %s.bmp"
00040 #else
00041 #define TACHYON_RUN_STRING " -aasamples 12 %s -format TARGA -o %s.tga"
00042 #endif
00043
00044 static char tachyon_run_string[2048];
00045
00046 static char * get_tachyon_run_string() {
00047 char *tbin;
00048 strcpy(tachyon_run_string, "tachyon");
00049
00050 if ((tbin=getenv("TACHYON_BIN")) != NULL) {
00051 sprintf(tachyon_run_string, "\"%s\"", tbin);
00052 }
00053 strcat(tachyon_run_string, TACHYON_RUN_STRING);
00054
00055 return tachyon_run_string;
00056 }
00057
00058 void TachyonDisplayDevice::update_exec_cmd() {
00059 const char *tbin;
00060 if ((tbin = getenv("TACHYON_BIN")) == NULL)
00061 tbin = "tachyon";
00062
00063 switch(curformat) {
00064 case 0:
00065 sprintf(tachyon_run_string,
00066 "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "BMP", "bmp");
00067 break;
00068
00069 case 1:
00070 sprintf(tachyon_run_string,
00071 "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "PPM", "ppm");
00072 break;
00073
00074 case 2:
00075 sprintf(tachyon_run_string,
00076 "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "PPM48", "ppm");
00077 break;
00078
00079 case 3:
00080 sprintf(tachyon_run_string,
00081 "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "PSD48", "psd");
00082 break;
00083
00084 case 4:
00085 sprintf(tachyon_run_string,
00086 "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "RGB", "rgb");
00087 break;
00088
00089 case 5:
00090 default:
00091 sprintf(tachyon_run_string,
00092 "\"%s\" -aasamples %d %%s -format %s -o %%s.%s", tbin, aasamples, "TARGA", "tga");
00093 break;
00094 }
00095 delete [] execCmd;
00096 execCmd = stringdup(tachyon_run_string);
00097 }
00098
00100
00101
00102
00103 TachyonDisplayDevice::TachyonDisplayDevice() : FileRenderer ("Tachyon", "Tachyon", "vmdscene.dat", get_tachyon_run_string()) {
00104
00105 formats.add_name("BMP", 0);
00106 formats.add_name("PPM", 0);
00107 formats.add_name("PPM48", 0);
00108 formats.add_name("PSD48", 0);
00109 formats.add_name("RGB", 0);
00110 formats.add_name("TGA", 0);
00111
00112
00113 has_aa = TRUE;
00114 aasamples = 12;
00115 aosamples = 12;
00116
00117 reset_vars();
00118
00119
00120 #if defined(_MSC_VER) || defined(WIN32)
00121 curformat = 0;
00122 #else
00123 curformat = 5;
00124 #endif
00125 }
00126
00127
00128 TachyonDisplayDevice::~TachyonDisplayDevice(void) { }
00129
00131
00132 void TachyonDisplayDevice::reset_vars(void) {
00133 inclipgroup = 0;
00134 involtex = 0;
00135 voltexID = -1;
00136 memset(xplaneeq, 0, sizeof(xplaneeq));
00137 memset(yplaneeq, 0, sizeof(xplaneeq));
00138 memset(zplaneeq, 0, sizeof(xplaneeq));
00139 }
00140
00141
00142
00143 void TachyonDisplayDevice::comment(const char *s) {
00144 fprintf(outfile, "# %s\n", s);
00145 }
00146
00147
00148 void TachyonDisplayDevice::text(float *pos, float size, float thickness,
00149 const char *str) {
00150 float textpos[3];
00151 float textsize, textthickness;
00152 hersheyhandle hh;
00153
00154
00155 (transMat.top()).multpoint3d(pos, textpos);
00156 textsize = size * 1.5f;
00157 textthickness = thickness*DEFAULT_RADIUS;
00158
00159 while (*str != '\0') {
00160 float lm, rm, x, y, ox, oy;
00161 int draw, odraw;
00162 ox=oy=x=y=0.0f;
00163 draw=odraw=0;
00164
00165 hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00166 textpos[0] -= lm * textsize;
00167
00168 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00169 float oldpt[3], newpt[3];
00170 if (draw) {
00171 newpt[0] = textpos[0] + textsize * x;
00172 newpt[1] = textpos[1] + textsize * y;
00173 newpt[2] = textpos[2];
00174
00175 if (odraw) {
00176
00177 oldpt[0] = textpos[0] + textsize * ox;
00178 oldpt[1] = textpos[1] + textsize * oy;
00179 oldpt[2] = textpos[2];
00180
00181 fprintf(outfile, "FCylinder\n");
00182 fprintf(outfile, " Base %g %g %g\n", oldpt[0], oldpt[1], -oldpt[2]);
00183 fprintf(outfile, " Apex %g %g %g\n", newpt[0], newpt[1], -newpt[2]);
00184 fprintf(outfile, " Rad %g \n", textthickness);
00185 write_cindexmaterial(colorIndex, materialIndex);
00186
00187 fprintf(outfile, "Sphere \n");
00188 fprintf(outfile, " Center %g %g %g \n", newpt[0], newpt[1], -newpt[2]);
00189 fprintf(outfile, " Rad %g \n", textthickness);
00190 write_cindexmaterial(colorIndex, materialIndex);
00191 } else {
00192
00193 fprintf(outfile, "Sphere \n");
00194 fprintf(outfile, " Center %g %g %g \n", newpt[0], newpt[1], -newpt[2]);
00195 fprintf(outfile, " Rad %g \n", textthickness);
00196 write_cindexmaterial(colorIndex, materialIndex);
00197 }
00198 }
00199
00200 ox=x;
00201 oy=y;
00202 odraw=draw;
00203 }
00204 textpos[0] += rm * textsize;
00205
00206 str++;
00207 }
00208 }
00209
00210
00211
00212 void TachyonDisplayDevice::point(float * spdata) {
00213 float vec[3];
00214
00215 (transMat.top()).multpoint3d(spdata, vec);
00216
00217
00218 fprintf(outfile, "Sphere \n");
00219 fprintf(outfile, " Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
00220 fprintf(outfile, " Rad %g \n", float(lineWidth)*DEFAULT_RADIUS);
00221 write_cindexmaterial(colorIndex, materialIndex);
00222 }
00223
00224
00225
00226 void TachyonDisplayDevice::sphere(float * spdata) {
00227 float vec[3];
00228 float radius;
00229
00230
00231 (transMat.top()).multpoint3d(spdata, vec);
00232 radius = scale_radius(spdata[3]);
00233
00234
00235 fprintf(outfile, "Sphere \n");
00236 fprintf(outfile, " Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
00237 fprintf(outfile, " Rad %g \n", radius );
00238 write_cindexmaterial(colorIndex, materialIndex);
00239 }
00240
00241
00242
00243 void TachyonDisplayDevice::sphere_array(int spnum, int spres, float *centers, float *radii, float *colors) {
00244 float vec[3];
00245 float radius;
00246 int i, ind;
00247
00248 ind = 0;
00249 for (i=0; i<spnum; i++) {
00250
00251 (transMat.top()).multpoint3d(¢ers[ind], vec);
00252 radius = scale_radius(radii[i]);
00253
00254
00255 fprintf(outfile, "Sphere \n");
00256 fprintf(outfile, " Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
00257 fprintf(outfile, " Rad %g \n", radius );
00258 write_colormaterial(&colors[ind], materialIndex);
00259 ind += 3;
00260 }
00261
00262
00263 ind=(spnum-1)*3;
00264 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00265 }
00266
00267
00268
00269 void TachyonDisplayDevice::line(float *a, float*b) {
00270 int i, j, test;
00271 float dirvec[3], unitdirvec[3];
00272 float from[3], to[3], tmp1[3], tmp2[3];
00273
00274 if (lineStyle == ::SOLIDLINE) {
00275
00276 (transMat.top()).multpoint3d(a, from);
00277 (transMat.top()).multpoint3d(b, to);
00278
00279
00280 fprintf(outfile, "FCylinder\n");
00281 fprintf(outfile, " Base %g %g %g\n", from[0], from[1], -from[2]);
00282 fprintf(outfile, " Apex %g %g %g\n", to[0], to[1], -to[2]);
00283 fprintf(outfile, " Rad %g \n", float(lineWidth)*DEFAULT_RADIUS);
00284 write_cindexmaterial(colorIndex, materialIndex);
00285
00286 } else if (lineStyle == ::DASHEDLINE) {
00287
00288 (transMat.top()).multpoint3d(a, tmp1);
00289 (transMat.top()).multpoint3d(b, tmp2);
00290
00291
00292 vec_sub(dirvec, tmp2, tmp1);
00293 vec_copy(unitdirvec, dirvec);
00294 vec_normalize(unitdirvec);
00295 test = 1;
00296 i = 0;
00297 while (test == 1) {
00298 for (j=0; j<3; j++) {
00299 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]);
00300 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00301 }
00302 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00303 vec_copy(to, tmp2);
00304 test = 0;
00305 }
00306
00307
00308 fprintf(outfile, "FCylinder\n");
00309 fprintf(outfile, " Base %g %g %g\n", from[0], from[1], -from[2]);
00310 fprintf(outfile, " Apex %g %g %g\n", to[0], to[1], -to[2]);
00311 fprintf(outfile, " Rad %g \n", float(lineWidth)*DEFAULT_RADIUS);
00312 write_cindexmaterial(colorIndex, materialIndex);
00313 i++;
00314 }
00315 } else {
00316 msgErr << "TachyonDisplayDevice: Unknown line style "
00317 << lineStyle << sendmsg;
00318 }
00319 }
00320
00321
00322
00323
00324
00325 void TachyonDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00326 float from[3], to[3], norm[3];
00327 float radius;
00328
00329
00330 (transMat.top()).multpoint3d(a, from);
00331 (transMat.top()).multpoint3d(b, to);
00332 radius = scale_radius(r);
00333
00334
00335 fprintf(outfile, "FCylinder\n");
00336 fprintf(outfile, " Base %g %g %g\n", from[0], from[1], -from[2]);
00337 fprintf(outfile, " Apex %g %g %g\n", to[0], to[1], -to[2]);
00338 fprintf(outfile, " Rad %g\n", radius);
00339 write_cindexmaterial(colorIndex, materialIndex);
00340
00341
00342 if (filled) {
00343 float div;
00344
00345 norm[0] = to[0] - from[0];
00346 norm[1] = to[1] - from[1];
00347 norm[2] = to[2] - from[2];
00348
00349 div = 1.0f / sqrtf(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
00350 norm[0] *= div;
00351 norm[1] *= div;
00352 norm[2] *= div;
00353
00354 if (filled & CYLINDER_TRAILINGCAP) {
00355 fprintf(outfile, "Ring\n");
00356 fprintf(outfile, "Center %g %g %g \n", from[0], from[1], -from[2]);
00357 fprintf(outfile, "Normal %g %g %g \n", norm[0], norm[1], -norm[2]);
00358 fprintf(outfile, "Inner 0.0 Outer %g \n", radius);
00359 write_cindexmaterial(colorIndex, materialIndex);
00360 }
00361
00362 if (filled & CYLINDER_LEADINGCAP) {
00363 fprintf(outfile, "Ring\n");
00364 fprintf(outfile, "Center %g %g %g \n", to[0], to[1], -to[2]);
00365 fprintf(outfile, "Normal %g %g %g \n", -norm[0], -norm[1], norm[2]);
00366 fprintf(outfile, "Inner 0.0 Outer %g \n", radius);
00367 write_cindexmaterial(colorIndex, materialIndex);
00368 }
00369 }
00370 }
00371
00372
00373
00374 void TachyonDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00375 float vec1[3], vec2[3], vec3[3];
00376 float norm1[3], norm2[3], norm3[3];
00377
00378
00379
00380 (transMat.top()).multpoint3d(a, vec1);
00381 (transMat.top()).multpoint3d(b, vec2);
00382 (transMat.top()).multpoint3d(c, vec3);
00383
00384
00385 (transMat.top()).multnorm3d(n1, norm1);
00386 (transMat.top()).multnorm3d(n2, norm2);
00387 (transMat.top()).multnorm3d(n3, norm3);
00388
00389
00390 fprintf(outfile, "STri\n");
00391 fprintf(outfile, " V0 %g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00392 fprintf(outfile, " V1 %g %g %g\n", vec2[0], vec2[1], -vec2[2]);
00393 fprintf(outfile, " V2 %g %g %g\n", vec3[0], vec3[1], -vec3[2]);
00394 fprintf(outfile, " N0 %.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]);
00395 fprintf(outfile, " N1 %.3f %.3f %.3f\n", -norm2[0], -norm2[1], norm2[2]);
00396 fprintf(outfile, " N2 %.3f %.3f %.3f\n", -norm3[0], -norm3[1], norm3[2]);
00397 write_cindexmaterial(colorIndex, materialIndex);
00398 }
00399
00400
00401 void TachyonDisplayDevice::tricolor(const float * xyz1, const float * xyz2, const float * xyz3,
00402 const float * n1, const float * n2, const float * n3,
00403 const float *c1, const float *c2, const float *c3) {
00404 float vec1[3], vec2[3], vec3[3];
00405 float norm1[3], norm2[3], norm3[3];
00406
00407
00408 (transMat.top()).multpoint3d(xyz1, vec1);
00409 (transMat.top()).multpoint3d(xyz2, vec2);
00410 (transMat.top()).multpoint3d(xyz3, vec3);
00411
00412
00413 (transMat.top()).multnorm3d(n1, norm1);
00414 (transMat.top()).multnorm3d(n2, norm2);
00415 (transMat.top()).multnorm3d(n3, norm3);
00416
00417
00418 if (!involtex) {
00419 fprintf(outfile, "VCSTri\n");
00420 } else {
00421 fprintf(outfile, "STri\n");
00422 }
00423 fprintf(outfile, " V0 %g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00424 fprintf(outfile, " V1 %g %g %g\n", vec2[0], vec2[1], -vec2[2]);
00425 fprintf(outfile, " V2 %g %g %g\n", vec3[0], vec3[1], -vec3[2]);
00426
00427 fprintf(outfile, " N0 %.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]);
00428 fprintf(outfile, " N1 %.3f %.3f %.3f\n", -norm2[0], -norm2[1], norm2[2]);
00429 fprintf(outfile, " N2 %.3f %.3f %.3f\n", -norm3[0], -norm3[1], norm3[2]);
00430
00431 if (!involtex) {
00432 fprintf(outfile, " C0 %.3f %.3f %.3f\n", c1[0], c1[1], c1[2]);
00433 fprintf(outfile, " C1 %.3f %.3f %.3f\n", c2[0], c2[1], c2[2]);
00434 fprintf(outfile, " C2 %.3f %.3f %.3f\n", c3[0], c3[1], c3[2]);
00435 }
00436
00437 if (materials_on) {
00438 fprintf(outfile, " Ambient %g Diffuse %g Specular %g Opacity %g\n",
00439 mat_ambient, mat_diffuse, mat_mirror, mat_opacity);
00440 } else {
00441 fprintf(outfile, " Ambient %g Diffuse %g Specular %g Opacity %g\n",
00442 1.0, 0.0, 0.0, mat_opacity);
00443 }
00444
00445 if (mat_transmode != 0) {
00446 fprintf(outfile, " TransMode R3D ");
00447 }
00448 if (mat_outline > 0.0) {
00449 fprintf(outfile, " Outline %g Outline_Width %g ",
00450 mat_outline, mat_outlinewidth);
00451 }
00452 fprintf(outfile, " Phong Plastic %g Phong_size %g ", mat_specular,
00453 mat_shininess);
00454 fprintf(outfile, "VCST\n\n");
00455 }
00456
00457
00458
00459
00460 void TachyonDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00461 int numfacets, int * facets) {
00462 int i;
00463 float vec1[3];
00464 float norm1[3];
00465
00466 fprintf(outfile, "VertexArray");
00467 fprintf(outfile, " Numverts %d\n", numverts);
00468
00469 fprintf(outfile, "\nCoords\n");
00470 for (i=0; i<numverts; i++) {
00471 (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
00472 fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00473 }
00474
00475 fprintf(outfile, "\nNormals\n");
00476 for (i=0; i<numverts; i++) {
00477 (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
00478 fprintf(outfile, "%.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]);
00479 }
00480
00481
00482 if (!involtex) {
00483 fprintf(outfile, "\nColors\n");
00484 for (i=0; i<numverts; i++) {
00485 int idx = i * 10;
00486 fprintf(outfile, "%.3f %.3f %.3f\n", cnv[idx], cnv[idx+1], cnv[idx+2]);
00487 }
00488 }
00489
00490
00491 write_cindexmaterial(colorIndex, materialIndex);
00492
00493
00494 fprintf(outfile, "\nTriMesh %d\n", numfacets);
00495 for (i=0; i<numfacets*3; i+=3) {
00496 fprintf(outfile, "%d %d %d\n", facets[i], facets[i+1], facets[i+2]);
00497 }
00498
00499
00500 fprintf(outfile, "\nEnd_VertexArray\n");
00501 }
00502
00503
00504
00505
00506 void TachyonDisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c,
00507 signed char *n,
00508 float *v, int numfacets) {
00509 int i;
00510 float vec1[3];
00511 float norm1[3];
00512 int numverts = 3*numfacets;
00513
00514 const float ci2f = 1.0f / 255.0f;
00515 const float cn2f = 1.0f / 127.5f;
00516
00517 fprintf(outfile, "VertexArray");
00518 fprintf(outfile, " Numverts %d\n", numverts);
00519
00520 fprintf(outfile, "\nCoords\n");
00521 for (i=0; i<numverts; i++) {
00522 int idx = i * 3;
00523 (transMat.top()).multpoint3d(v + idx, vec1);
00524 fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00525 }
00526
00527 fprintf(outfile, "\nNormals\n");
00528 for (i=0; i<numverts; i++) {
00529 float ntmp[3];
00530 int idx = i * 3;
00531
00532
00533
00534 ntmp[0] = n[idx ] * cn2f + ci2f;
00535 ntmp[1] = n[idx+1] * cn2f + ci2f;
00536 ntmp[2] = n[idx+2] * cn2f + ci2f;
00537 (transMat.top()).multnorm3d(ntmp, norm1);
00538 fprintf(outfile, "%.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]);
00539 }
00540
00541
00542 if (!involtex) {
00543 fprintf(outfile, "\nColors\n");
00544 for (i=0; i<numverts; i++) {
00545 int idx = i * 4;
00546
00547
00548
00549 fprintf(outfile, "%.3f %.3f %.3f\n",
00550 c[idx ] * ci2f,
00551 c[idx+1] * ci2f,
00552 c[idx+2] * ci2f);
00553 }
00554 }
00555
00556
00557 write_cindexmaterial(colorIndex, materialIndex);
00558
00559
00560 fprintf(outfile, "\nTriMesh %d\n", numfacets);
00561 for (i=0; i<numfacets*3; i+=3) {
00562 fprintf(outfile, "%d %d %d\n", i, i+1, i+2);
00563 }
00564
00565
00566 fprintf(outfile, "\nEnd_VertexArray\n");
00567 }
00568
00569
00570 void TachyonDisplayDevice::tristrip(int numverts, const float * cnv,
00571 int numstrips, const int *vertsperstrip,
00572 const int *facets) {
00573 int i, strip, v=0;
00574 float vec1[3];
00575 float norm1[3];
00576
00577 fprintf(outfile, "VertexArray");
00578 fprintf(outfile, " Numverts %d\n", numverts);
00579
00580 fprintf(outfile, "\nCoords\n");
00581 for (i=0; i<numverts; i++) {
00582 (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
00583 fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]);
00584 }
00585
00586 fprintf(outfile, "\nNormals\n");
00587 for (i=0; i<numverts; i++) {
00588 (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
00589 fprintf(outfile, "%.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]);
00590 }
00591
00592
00593 if (!involtex) {
00594 fprintf(outfile, "\nColors\n");
00595 for (i=0; i<numverts; i++) {
00596 int idx = i * 10;
00597 fprintf(outfile, "%.3f %.3f %.3f\n", cnv[idx], cnv[idx+1], cnv[idx+2]);
00598 }
00599 }
00600
00601
00602 write_cindexmaterial(colorIndex, materialIndex);
00603
00604
00605 v=0;
00606 for (strip=0; strip < numstrips; strip++) {
00607 fprintf(outfile, "\nTriStrip %d\n", vertsperstrip[strip]);
00608
00609
00610 for (i = 0; i < vertsperstrip[strip]; i++) {
00611 fprintf(outfile, "%d ", facets[v]);
00612 v++;
00613 }
00614 }
00615
00616
00617 fprintf(outfile, "\nEnd_VertexArray\n");
00618 }
00619
00620
00621
00622 void TachyonDisplayDevice::define_volume_texture(int ID,
00623 int xs, int ys, int zs,
00624 const float *xpq,
00625 const float *ypq,
00626 const float *zpq,
00627 unsigned char *texmap) {
00628 voltexID = ID;
00629
00630 memcpy(xplaneeq, xpq, sizeof(xplaneeq));
00631 memcpy(yplaneeq, ypq, sizeof(yplaneeq));
00632 memcpy(zplaneeq, zpq, sizeof(zplaneeq));
00633
00634 fprintf(outfile, "# VMD volume texture definition: ID %d\n", ID);
00635 fprintf(outfile, "# Res: %d %d %d\n", xs, ys, zs);
00636 fprintf(outfile, "# xplaneeq: %g %g %g %g\n",
00637 xplaneeq[0], xplaneeq[1], xplaneeq[2], xplaneeq[3]);
00638 fprintf(outfile, "# yplaneeq: %g %g %g %g\n",
00639 yplaneeq[0], yplaneeq[1], yplaneeq[2], yplaneeq[3]);
00640 fprintf(outfile, "# zplaneeq: %g %g %g %g\n",
00641 zplaneeq[0], zplaneeq[1], zplaneeq[2], zplaneeq[3]);
00642
00643 fprintf(outfile, "ImageDef ::VMDVolTex%d\n", ID);
00644 fprintf(outfile, " Format RGB24\n");
00645 fprintf(outfile, " Resolution %d %d %d\n", xs, ys, zs);
00646 fprintf(outfile, " Encoding Hex\n");
00647
00648 int x, y, z;
00649 for (z=0; z<zs; z++) {
00650 for (y=0; y<ys; y++) {
00651 int addr = (z * xs * ys) + (y * xs);
00652 for (x=0; x<xs; x++) {
00653 int addr2 = (addr + x) * 3;
00654 fprintf(outfile, "%02x%02x%02x ",
00655 texmap[addr2 ],
00656 texmap[addr2 + 1],
00657 texmap[addr2 + 2]);
00658 }
00659 fprintf(outfile, "\n");
00660 }
00661 fprintf(outfile, "\n");
00662 }
00663 fprintf(outfile, "\n");
00664 fprintf(outfile, "# End of volume texture ::VMDVolTex%d\n", ID);
00665 fprintf(outfile, "\n");
00666 fprintf(outfile, "\n");
00667 }
00668
00669
00670
00671 void TachyonDisplayDevice::volume_texture_on(int texmode) {
00672 involtex = 1;
00673 }
00674
00675
00676
00677 void TachyonDisplayDevice::volume_texture_off(void) {
00678 involtex = 0;
00679 }
00680
00681
00682 void TachyonDisplayDevice::start_clipgroup(void) {
00683 int i;
00684 int planesenabled = 0;
00685
00686 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00687 if (clip_mode[i] > 0) {
00688 planesenabled++;
00689 if (clip_mode[i] > 1)
00690 warningflags |= FILERENDERER_NOCLIP;
00691 }
00692 }
00693
00694 if (planesenabled > 0) {
00695 fprintf(outfile, "Start_ClipGroup\n");
00696 fprintf(outfile, " NumPlanes %d\n", planesenabled);
00697 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00698 if (clip_mode[i] > 0) {
00699 float tachyon_clip_center[3];
00700 float tachyon_clip_normal[3];
00701 float tachyon_clip_distance;
00702
00703 inclipgroup = 1;
00704
00705
00706 (transMat.top()).multpoint3d(clip_center[i], tachyon_clip_center);
00707 (transMat.top()).multnorm3d(clip_normal[i], tachyon_clip_normal);
00708 vec_negate(tachyon_clip_normal, tachyon_clip_normal);
00709
00710
00711
00712 tachyon_clip_distance = dot_prod(tachyon_clip_normal, tachyon_clip_center);
00713
00714 fprintf(outfile, "%g %g %g %g\n", tachyon_clip_normal[0],
00715 tachyon_clip_normal[1], -tachyon_clip_normal[2],
00716 tachyon_clip_distance);
00717 }
00718 }
00719 fprintf(outfile, "\n");
00720 } else {
00721 inclipgroup = 0;
00722 }
00723 }
00724
00725
00727
00728
00729 void TachyonDisplayDevice::write_header() {
00730 fprintf(outfile, "# \n");
00731 fprintf(outfile, "# Molecular graphics exported from VMD %s\n", VMDVERSION);
00732 fprintf(outfile, "# http://www.ks.uiuc.edu/Research/vmd/\n");
00733 fprintf(outfile, "# \n");
00734 fprintf(outfile, "# Requires Tachyon version 0.99.0 or newer\n");
00735 fprintf(outfile, "# \n");
00736 fprintf(outfile, "# Default tachyon rendering command for this scene:\n");
00737 fprintf(outfile, "# tachyon %s\n", TACHYON_RUN_STRING);
00738 fprintf(outfile, "# \n");
00739
00740
00741
00742
00743
00744
00745 fprintf(outfile, "Begin_Scene\n");
00746 fprintf(outfile, "Resolution %d %d\n", (int) xSize, (int) ySize);
00747
00748
00749
00750 fprintf(outfile, "Shader_Mode ");
00751
00752
00753
00754 if (shadows_enabled() || ao_enabled()) {
00755 fprintf(outfile, "Full\n");
00756 } else {
00757 fprintf(outfile, "Medium\n");
00758 }
00759
00760
00761
00762
00763
00764 fprintf(outfile, " Trans_VMD\n");
00765 fprintf(outfile, " Fog_VMD\n");
00766
00767
00768 if (ao_enabled()) {
00769 fprintf(outfile, " Ambient_Occlusion\n");
00770
00771 #if 1
00772
00773 if (getenv("VMDTACHYONAOMAXDIST")) {
00774 float tmp = float(atof(getenv("VMDTACHYONAOMAXDIST")));
00775 printf("LibTachyonDisplayDevice) setting AO maxdist: %f\n", tmp);
00776 fprintf(outfile, " MaxDist %g\n", tmp);
00777 }
00778 #endif
00779
00780 fprintf(outfile, " Ambient_Color %g %g %g\n",
00781 get_ao_ambient(), get_ao_ambient(), get_ao_ambient());
00782 fprintf(outfile, " Rescale_Direct %g\n", get_ao_direct());
00783 fprintf(outfile, " Samples %d\n", aosamples);
00784 }
00785 fprintf(outfile, "End_Shader_Mode\n");
00786
00787 write_camera();
00788 write_lights();
00789 write_materials();
00790 }
00791
00792
00793 void TachyonDisplayDevice::end_clipgroup(void) {
00794 if (inclipgroup) {
00795 fprintf(outfile, "End_ClipGroup\n");
00796 inclipgroup = 0;
00797 }
00798 }
00799
00800
00801 void TachyonDisplayDevice::write_trailer(void){
00802 fprintf(outfile, "End_Scene \n");
00803 if (inclipgroup) {
00804 msgErr << "TachyonDisplayDevice clipping group still active at end of scene\n" << sendmsg;
00805 }
00806 msgInfo << "Tachyon file generation finished" << sendmsg;
00807
00808 reset_vars();
00809 }
00810
00811
00812
00814
00815 void TachyonDisplayDevice::write_camera(void) {
00816 int raydepth = 50;
00817
00818
00819
00820
00821
00822 switch (projection()) {
00823
00824 case DisplayDevice::ORTHOGRAPHIC:
00825 fprintf(outfile, "Camera\n");
00826 fprintf(outfile, " Projection Orthographic\n");
00827 fprintf(outfile, " Zoom %g\n", 1.0 / (vSize / 2.0));
00828 fprintf(outfile, " Aspectratio %g\n", 1.0f);
00829 fprintf(outfile, " Antialiasing %d\n", aasamples);
00830 fprintf(outfile, " Raydepth %d\n", raydepth);
00831 fprintf(outfile, " Center %g %g %g\n", eyePos[0], eyePos[1], -eyePos[2]);
00832 fprintf(outfile, " Viewdir %g %g %g\n", eyeDir[0], eyeDir[1], -eyeDir[2]);
00833 fprintf(outfile, " Updir %g %g %g\n", upDir[0], upDir[1], -upDir[2]);
00834 fprintf(outfile, "End_Camera\n");
00835 break;
00836
00837 case DisplayDevice::PERSPECTIVE:
00838 default:
00839 fprintf(outfile, "Camera\n");
00840
00841
00842 if (dof_enabled() && (projection() == DisplayDevice::PERSPECTIVE)) {
00843 msgInfo << "DoF focal blur enabled." << sendmsg;
00844 fprintf(outfile, " Projection Perspective_DoF\n");
00845 fprintf(outfile, " FocalDist %f\n", get_dof_focal_dist());
00846 fprintf(outfile, " Aperture %f\n", get_dof_fnumber());
00847 }
00848
00849 fprintf(outfile, " Zoom %g\n", (eyePos[2] - zDist) / vSize);
00850 fprintf(outfile, " Aspectratio %g\n", 1.0f);
00851 fprintf(outfile, " Antialiasing %d\n", aasamples);
00852 fprintf(outfile, " Raydepth %d\n", raydepth);
00853 fprintf(outfile, " Center %g %g %g\n", eyePos[0], eyePos[1], -eyePos[2]);
00854 fprintf(outfile, " Viewdir %g %g %g\n", eyeDir[0], eyeDir[1], -eyeDir[2]);
00855 fprintf(outfile, " Updir %g %g %g\n", upDir[0], upDir[1], -upDir[2]);
00856 fprintf(outfile, "End_Camera\n");
00857 break;
00858
00859 }
00860 }
00861
00862
00863 void TachyonDisplayDevice::write_lights(void) {
00864
00865 int i;
00866 int lightcount = 0;
00867 for (i=0; i<DISP_LIGHTS; i++) {
00868 if (lightState[i].on) {
00869
00870 fprintf(outfile, "Directional_Light Direction %g %g %g ",
00871 -lightState[i].pos[0],
00872 -lightState[i].pos[1],
00873 lightState[i].pos[2]);
00874 fprintf(outfile, "Color %g %g %g\n",
00875 lightState[i].color[0], lightState[i].color[1], lightState[i].color[2]);
00876 lightcount++;
00877 }
00878 }
00879
00880 for (i=0; i<DISP_LIGHTS; i++) {
00881 if (advLightState[i].on) {
00882 float pos[3];
00883
00884
00885 vec_copy(pos, advLightState[i].pos);
00886
00887 if (advLightState[i].spoton) {
00888 fprintf(outfile, "# SpotLight not implemented yet ...\n");
00889 } else {
00890
00891 fprintf(outfile, "Light Center %g %g %g Rad 0.0 ",
00892 pos[0], pos[1], -pos[2]);
00893
00894
00895 if (advLightState[i].constfactor != 1.0f ||
00896 advLightState[i].linearfactor != 0.0f ||
00897 advLightState[i].quadfactor != 0.0f) {
00898 fprintf(outfile, "Attenuation Constant %g Linear %g Quadratic %g\n",
00899 advLightState[i].constfactor,
00900 advLightState[i].linearfactor,
00901 advLightState[i].quadfactor);
00902 }
00903
00904 fprintf(outfile, "Color %g %g %g\n",
00905 lightState[i].color[0], lightState[i].color[1], lightState[i].color[2]);
00906 }
00907
00908 lightcount++;
00909 }
00910 }
00911
00912 if (lightcount < 1) {
00913 msgInfo << "Warning: no lights defined in exported scene!!" << sendmsg;
00914 }
00915 }
00916
00917 void TachyonDisplayDevice::write_materials(void) {
00918
00919 fprintf(outfile, "\nBackground %g %g %g\n",
00920 backColor[0], backColor[1], backColor[2]);
00921
00922
00923
00924 if (backgroundmode == 1) {
00925 float bspheremag = 0.5f;
00926
00927
00928 switch (projection()) {
00929 case DisplayDevice::ORTHOGRAPHIC:
00930
00931
00932
00933
00934 bspheremag = vSize / 4.0f;
00935 break;
00936
00937 case DisplayDevice::PERSPECTIVE:
00938 default:
00939
00940
00941
00942
00943 bspheremag = (vSize / 2.0f) / (eyePos[2] - zDist);
00944 if (bspheremag > 1.0f)
00945 bspheremag = 1.0f;
00946 break;
00947 }
00948
00949
00950 fprintf(outfile, "Background_Gradient ");
00951 if (projection() == DisplayDevice::ORTHOGRAPHIC)
00952 fprintf(outfile, "Sky_Ortho_Plane\n");
00953 else
00954 fprintf(outfile, "Sky_Sphere\n");
00955 fprintf(outfile, " UpDir %g %g %g\n", 0.0f, 1.0f, 0.0f);
00956 fprintf(outfile, " TopVal %g\n", bspheremag);
00957 fprintf(outfile, " BottomVal %g\n", -bspheremag);
00958 fprintf(outfile, " TopColor %g %g %g\n", backgradienttopcolor[0],
00959 backgradienttopcolor[1], backgradienttopcolor[2]);
00960 fprintf(outfile, " BottomColor %g %g %g\n", backgradientbotcolor[0],
00961 backgradientbotcolor[1], backgradientbotcolor[2]);
00962 }
00963
00964
00965 if (cueingEnabled) {
00966 switch (cueMode) {
00967 case CUE_LINEAR:
00968 fprintf(outfile,
00969 "Fog Linear Start %g End %g Density %g Color %g %g %g\n",
00970 get_cue_start(), get_cue_end(), 1.0f,
00971 backColor[0], backColor[1], backColor[2]);
00972 break;
00973
00974 case CUE_EXP:
00975 fprintf(outfile,
00976 "Fog Exp Start %g End %g Density %g Color %g %g %g\n",
00977 0.0, get_cue_end(), get_cue_density(),
00978 backColor[0], backColor[1], backColor[2]);
00979 break;
00980
00981 case CUE_EXP2:
00982 fprintf(outfile,
00983 "Fog Exp2 Start %g End %g Density %g Color %g %g %g\n",
00984 0.0, get_cue_end(), get_cue_density(),
00985 backColor[0], backColor[1], backColor[2]);
00986 break;
00987
00988 case NUM_CUE_MODES:
00989
00990 break;
00991 }
00992 }
00993 }
00994
00995 void TachyonDisplayDevice::write_cindexmaterial(int cindex, int material) {
00996 write_colormaterial((float *) &matData[cindex], material);
00997 }
00998
00999
01000 void TachyonDisplayDevice::write_colormaterial(float *rgb, int ) {
01001 fprintf(outfile, "Texture\n");
01002 if (materials_on) {
01003 fprintf(outfile, " Ambient %g Diffuse %g Specular %g Opacity %g\n",
01004 mat_ambient, mat_diffuse, mat_mirror, mat_opacity);
01005 } else {
01006 fprintf(outfile, " Ambient %g Diffuse %g Specular %g Opacity %g\n",
01007 1.0, 0.0, 0.0, mat_opacity);
01008 }
01009
01010 if (mat_transmode != 0) {
01011 fprintf(outfile, " TransMode R3D ");
01012 }
01013 if (mat_outline > 0.0) {
01014 fprintf(outfile, " Outline %g Outline_Width %g ",
01015 mat_outline, mat_outlinewidth);
01016 }
01017 fprintf(outfile, " Phong Plastic %g Phong_size %g ", mat_specular,
01018 mat_shininess);
01019 fprintf(outfile, "Color %g %g %g ", rgb[0], rgb[1], rgb[2]);
01020
01022 if (!involtex) {
01024 fprintf(outfile, "TexFunc 0\n\n");
01025 } else {
01027 float voluaxs[3];
01028 float volvaxs[3];
01029 float volwaxs[3];
01030 float volcent[3];
01031
01032
01033
01034 (transMat.top()).multplaneeq3d(xplaneeq, voluaxs);
01035 (transMat.top()).multplaneeq3d(yplaneeq, volvaxs);
01036 (transMat.top()).multplaneeq3d(zplaneeq, volwaxs);
01037
01038
01039 float invscale = 1.0f / scale_radius(1.0f);
01040 int i;
01041 for (i=0; i<3; i++) {
01042 voluaxs[i] *= invscale;
01043 volvaxs[i] *= invscale;
01044 volwaxs[i] *= invscale;
01045 }
01046
01047
01048
01049
01050 float volorgmol[3] = {0,0,0};
01051 volorgmol[0] = -xplaneeq[3] / norm(xplaneeq);
01052 volorgmol[1] = -yplaneeq[3] / norm(yplaneeq);
01053 volorgmol[2] = -zplaneeq[3] / norm(zplaneeq);
01054
01055
01056 (transMat.top()).multpoint3d(volorgmol, volcent);
01057
01058
01059 fprintf(outfile, "\n TexFunc 10 ::VMDVolTex%d\n", voltexID);
01060 fprintf(outfile, " Center %g %g %g\n", volcent[0], volcent[1], -volcent[2]);
01061 fprintf(outfile, " Rotate 0 0 0\n");
01062 fprintf(outfile, " Scale 1 1 1\n");
01063 fprintf(outfile, " Uaxis %g %g %g\n", voluaxs[0], voluaxs[1], -voluaxs[2]);
01064 fprintf(outfile, " Vaxis %g %g %g\n", volvaxs[0], volvaxs[1], -volvaxs[2]);
01065 fprintf(outfile, " Waxis %g %g %g\n", volwaxs[0], volwaxs[1], -volwaxs[2]);
01066 fprintf(outfile, "\n");
01067 }
01068 }
01069
01070
01071
01072