00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <math.h>
00026 #include "LibTachyonDisplayDevice.h"
00027 #include "Matrix4.h"
00028 #include "DispCmds.h"
00029 #include "Inform.h"
00030 #include "utilities.h"
00031 #include "config.h"
00032 #include "Hershey.h"
00033
00034 #if !(((TACHYON_MAJOR_VERSION >= 0) && (TACHYON_MINOR_VERSION >= 99)) || ((TACHYON_MAJOR_VERSION == 0) && (TACHYON_MINOR_VERSION == 99) && (TACHYON_PATCH_VERSION >= 0)))
00035 #error "LibTachyonDisplayDevice requires Tachyon version 0.99.0 or higher."
00036 #endif
00037
00038 #define DEFAULT_RADIUS 0.002f
00039 #define DASH_LENGTH 0.02f
00040
00041 extern "C" {
00042
00043 void vmd_rt_ui_message(int a, char * msg) {
00044 printf("Tachyon) %s\n", msg);
00045 }
00046
00047 void vmd_rt_ui_progress(int percent) {
00048 printf("\rTachyon) Rendering progress: %3d%% complete \r", percent);
00049 fflush(stdout);
00050 }
00051
00052 }
00053
00055 LibTachyonDisplayDevice::LibTachyonDisplayDevice(VMDApp *app) : FileRenderer ("TachyonInternal", "Tachyon (internal, in-memory rendering)", "vmdscene.tga", DEF_VMDIMAGEVIEWER) {
00056 vmdapp = app;
00057
00058 reset_vars();
00059 trt_timer = wkf_timer_create();
00060
00061 #if 0 && defined(VMDMPI)
00062
00063 parallel_group = 0;
00064 if (getenv("VMDNOMPI") != NULL || getenv("VMDTACHYONNOMPI") != NULL) {
00065 rt_initialize_nompi();
00066 } else {
00067
00068 rt_initialize_mpi_comm_world();
00069
00070 #if 1
00071
00072
00073 if (getenv("VMDTACHYONWORKGROUP") == NULL) {
00074 parallel_group = -1;
00075 rt_set_mpi_comm_world_split_all();
00076 } else {
00077 parallel_group = atoi(getenv("VMDTACHYONWORKGROUP"));
00078 rt_set_mpi_comm_world_split(parallel_group, 0);
00079 }
00080 #endif
00081 }
00082 #else
00083 rt_initialize(0, NULL);
00084 #endif
00085
00086 #if defined(VMDMPI)
00087
00088
00089
00090
00091 if (getenv("VMDNOMPI") != NULL) {
00092
00093 rt_set_ui_progress(vmd_rt_ui_progress);
00094 }
00095 #else
00096
00097 rt_set_ui_progress(vmd_rt_ui_progress);
00098 #endif
00099
00100
00101 formats.add_name("Auto", 0);
00102 formats.add_name("BMP", 0);
00103 formats.add_name("PPM", 0);
00104 formats.add_name("PPM48", 0);
00105 formats.add_name("PSD48", 0);
00106 formats.add_name("RGB", 0);
00107 formats.add_name("TGA", 0);
00108
00109
00110 curformat = 0;
00111
00112
00113 has_aa = TRUE;
00114 aasamples = 12;
00115 aosamples = 12;
00116 }
00117
00118 LibTachyonDisplayDevice::~LibTachyonDisplayDevice(void) {
00119 rt_finalize();
00120 wkf_timer_destroy(trt_timer);
00121 }
00122
00123
00125
00126
00127 void LibTachyonDisplayDevice::reset_vars(void) {
00128 inclipgroup = 0;
00129 involtex = 0;
00130 voltexID = -1;
00131 memset(xplaneeq, 0, sizeof(xplaneeq));
00132 memset(yplaneeq, 0, sizeof(xplaneeq));
00133 memset(zplaneeq, 0, sizeof(xplaneeq));
00134 }
00135
00136
00138
00139 void LibTachyonDisplayDevice::text(float *pos, float size, float thickness,
00140 const char *str) {
00141 float textpos[3];
00142 float textsize, textthickness;
00143 hersheyhandle hh;
00144
00145
00146 (transMat.top()).multpoint3d(pos, textpos);
00147 textsize = size * 1.5f;
00148 textthickness = thickness*DEFAULT_RADIUS;
00149
00150
00151 void *tex=tex_cindexmaterial(colorIndex, materialIndex);
00152
00153 while (*str != '\0') {
00154 float lm, rm, x, y, ox, oy;
00155 int draw, odraw;
00156 ox=oy=x=y=0.0f;
00157 draw=odraw=0;
00158
00159 hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00160 textpos[0] -= lm * textsize;
00161
00162 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00163 float oldpt[3], newpt[3];
00164 if (draw) {
00165 newpt[0] = textpos[0] + textsize * x;
00166 newpt[1] = textpos[1] + textsize * y;
00167 newpt[2] = textpos[2];
00168
00169 if (odraw) {
00170
00171 oldpt[0] = textpos[0] + textsize * ox;
00172 oldpt[1] = textpos[1] + textsize * oy;
00173 oldpt[2] = textpos[2];
00174
00175 rt_fcylinder(rtscene, tex, rt_vector(oldpt[0], oldpt[1], -oldpt[2]),
00176 rt_vector(newpt[0]-oldpt[0], newpt[1]-oldpt[1], -newpt[2]+oldpt[2]),
00177 textthickness);
00178 rt_sphere(rtscene, tex,
00179 rt_vector(newpt[0], newpt[1], -newpt[2]), textthickness);
00180 } else {
00181
00182 rt_sphere(rtscene, tex,
00183 rt_vector(newpt[0], newpt[1], -newpt[2]), textthickness);
00184 }
00185 }
00186
00187 ox=x;
00188 oy=y;
00189 odraw=draw;
00190 }
00191 textpos[0] += rm * textsize;
00192
00193 str++;
00194 }
00195 }
00196
00197
00198
00199 void LibTachyonDisplayDevice::point(float * spdata) {
00200 float vec[3];
00201 void *tex;
00202
00203 (transMat.top()).multpoint3d(spdata, vec);
00204
00205
00206 tex=tex_cindexmaterial(colorIndex, materialIndex);
00207 rt_sphere(rtscene, tex,
00208 rt_vector(vec[0], vec[1], -vec[2]),
00209 float(lineWidth)*DEFAULT_RADIUS);
00210 }
00211
00212
00213
00214 void LibTachyonDisplayDevice::sphere(float * spdata) {
00215 float vec[3];
00216 float radius;
00217 void *tex;
00218
00219
00220 (transMat.top()).multpoint3d(spdata, vec);
00221 radius = scale_radius(spdata[3]);
00222
00223
00224 tex=tex_cindexmaterial(colorIndex, materialIndex);
00225 rt_sphere(rtscene, tex, rt_vector(vec[0], vec[1], -vec[2]), radius);
00226 }
00227
00228
00229
00230 void LibTachyonDisplayDevice::sphere_array(int spnum, int spres, float *centers, float *radii, float *colors) {
00231 float vec[3];
00232 float radius;
00233 int i, ind;
00234 void *tex;
00235
00236 ind = 0;
00237 for (i=0; i<spnum; i++) {
00238
00239 (transMat.top()).multpoint3d(¢ers[ind], vec);
00240 radius = scale_radius(radii[i]);
00241
00242
00243 tex=tex_colormaterial(&colors[ind], materialIndex);
00244 rt_sphere(rtscene, tex, rt_vector(vec[0], vec[1], -vec[2]), radius);
00245 ind += 3;
00246 }
00247
00248
00249 ind=(spnum-1)*3;
00250 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00251 }
00252
00253
00254
00255 void LibTachyonDisplayDevice::line(float *a, float*b) {
00256 int i, j, test;
00257 float dirvec[3], unitdirvec[3];
00258 float from[3], to[3], tmp1[3], tmp2[3];
00259 void *tex;
00260
00261 if (lineStyle == ::SOLIDLINE) {
00262
00263 (transMat.top()).multpoint3d(a, from);
00264 (transMat.top()).multpoint3d(b, to);
00265
00266
00267 tex=tex_cindexmaterial(colorIndex, materialIndex);
00268 rt_fcylinder(rtscene, tex,
00269 rt_vector(from[0], from[1], -from[2]),
00270 rt_vector(to[0]-from[0], to[1]-from[1], -to[2]+from[2]),
00271 float(lineWidth)*DEFAULT_RADIUS);
00272
00273 } else if (lineStyle == ::DASHEDLINE) {
00274
00275 (transMat.top()).multpoint3d(a, tmp1);
00276 (transMat.top()).multpoint3d(b, tmp2);
00277
00278
00279 vec_sub(dirvec, tmp2, tmp1);
00280 vec_copy(unitdirvec, dirvec);
00281 vec_normalize(unitdirvec);
00282 test = 1;
00283 i = 0;
00284 while (test == 1) {
00285 for (j=0; j<3; j++) {
00286 from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]);
00287 to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]);
00288 }
00289 if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) {
00290 vec_copy(to, tmp2);
00291 test = 0;
00292 }
00293
00294
00295 tex=tex_cindexmaterial(colorIndex, materialIndex);
00296 rt_fcylinder(rtscene, tex,
00297 rt_vector(from[0], from[1], -from[2]),
00298 rt_vector(to[0]-from[0], to[1]-from[1], -to[2]+from[2]),
00299 float(lineWidth)*DEFAULT_RADIUS);
00300 i++;
00301 }
00302 } else {
00303 msgErr << "LibTachyonDisplayDevice: Unknown line style "
00304 << lineStyle << sendmsg;
00305 }
00306 }
00307
00308
00309
00310 void LibTachyonDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00311 float from[3], to[3], norm[3];
00312 float radius;
00313 void * tex;
00314
00315
00316 (transMat.top()).multpoint3d(a, from);
00317 (transMat.top()).multpoint3d(b, to);
00318 radius = scale_radius(r);
00319
00320
00321 tex=tex_cindexmaterial(colorIndex, materialIndex);
00322 rt_fcylinder(rtscene, tex,
00323 rt_vector(from[0], from[1], -from[2]),
00324 rt_vector(to[0]-from[0], to[1]-from[1], -to[2]+from[2]),
00325 radius);
00326
00327
00328 if (filled) {
00329 float div;
00330
00331 norm[0] = to[0] - from[0];
00332 norm[1] = to[1] - from[1];
00333 norm[2] = to[2] - from[2];
00334
00335 div = 1.0f / sqrtf(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
00336 norm[0] *= div;
00337 norm[1] *= div;
00338 norm[2] *= div;
00339
00340 if (filled & CYLINDER_TRAILINGCAP) {
00341 rt_ring(rtscene, tex,
00342 rt_vector(from[0], from[1], -from[2]),
00343 rt_vector(norm[0], norm[1], -norm[2]),
00344 0.0, radius);
00345 }
00346
00347 if (filled & CYLINDER_LEADINGCAP) {
00348 rt_ring(rtscene, tex,
00349 rt_vector(to[0], to[1], -to[2]),
00350 rt_vector(-norm[0], -norm[1], norm[2]),
00351 0.0, radius);
00352 }
00353 }
00354 }
00355
00356
00357 void LibTachyonDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00358 float vec1[3], vec2[3], vec3[3];
00359 float norm1[3], norm2[3], norm3[3];
00360 void *tex;
00361
00362
00363 (transMat.top()).multpoint3d(a, vec1);
00364 (transMat.top()).multpoint3d(b, vec2);
00365 (transMat.top()).multpoint3d(c, vec3);
00366
00367
00368 (transMat.top()).multnorm3d(n1, norm1);
00369 (transMat.top()).multnorm3d(n2, norm2);
00370 (transMat.top()).multnorm3d(n3, norm3);
00371
00372
00373 tex=tex_cindexmaterial(colorIndex, materialIndex);
00374 rt_stri(rtscene, tex,
00375 rt_vector(vec1[0], vec1[1], -vec1[2]),
00376 rt_vector(vec2[0], vec2[1], -vec2[2]),
00377 rt_vector(vec3[0], vec3[1], -vec3[2]),
00378 rt_vector(-norm1[0], -norm1[1], norm1[2]),
00379 rt_vector(-norm2[0], -norm2[1], norm2[2]),
00380 rt_vector(-norm3[0], -norm3[1], norm3[2]));
00381 }
00382
00383
00384
00385 void LibTachyonDisplayDevice::tricolor(const float * xyz1, const float * xyz2, const float * xyz3,
00386 const float * n1, const float * n2, const float * n3,
00387 const float *c1, const float *c2, const float *c3) {
00388 float vec1[3], vec2[3], vec3[3];
00389 float norm1[3], norm2[3], norm3[3];
00390 float rgb[3];
00391 void *tex;
00392
00393
00394 (transMat.top()).multpoint3d(xyz1, vec1);
00395 (transMat.top()).multpoint3d(xyz2, vec2);
00396 (transMat.top()).multpoint3d(xyz3, vec3);
00397
00398
00399 (transMat.top()).multnorm3d(n1, norm1);
00400 (transMat.top()).multnorm3d(n2, norm2);
00401 (transMat.top()).multnorm3d(n3, norm3);
00402
00403 rgb[0] = 0.0;
00404 rgb[1] = 0.0;
00405 rgb[2] = 0.0;
00406
00407
00408 tex=tex_colormaterial(rgb, materialIndex);
00409
00410 if (!involtex) {
00411 rt_vcstri(rtscene, tex,
00412 rt_vector(vec1[0], vec1[1], -vec1[2]),
00413 rt_vector(vec2[0], vec2[1], -vec2[2]),
00414 rt_vector(vec3[0], vec3[1], -vec3[2]),
00415 rt_vector(-norm1[0], -norm1[1], norm1[2]),
00416 rt_vector(-norm2[0], -norm2[1], norm2[2]),
00417 rt_vector(-norm3[0], -norm3[1], norm3[2]),
00418 rt_color(c1[0], c1[1], c1[2]),
00419 rt_color(c2[0], c2[1], c2[2]),
00420 rt_color(c3[0], c3[1], c3[2]));
00421 } else {
00422 rt_stri(rtscene, tex,
00423 rt_vector(vec1[0], vec1[1], -vec1[2]),
00424 rt_vector(vec2[0], vec2[1], -vec2[2]),
00425 rt_vector(vec3[0], vec3[1], -vec3[2]),
00426 rt_vector(-norm1[0], -norm1[1], norm1[2]),
00427 rt_vector(-norm2[0], -norm2[1], norm2[2]),
00428 rt_vector(-norm3[0], -norm3[1], norm3[2]));
00429 }
00430 }
00431
00432
00433
00434 void LibTachyonDisplayDevice::tristrip(int numverts, const float *cnv,
00435 int numstrips, const int *vertsperstrip,
00436 const int *facets) {
00437 int i;
00438 float rgb[3];
00439 void *tex;
00440
00441 Matrix4 topMatrix = transMat.top();
00442
00443
00444 float *tcnv = new float[numverts * 10];
00445
00446 for (i=0; i<numverts; i++) {
00447 int addr = i * 10;
00448 int j;
00449
00450 for (j=0; j<3; j++)
00451 tcnv[addr + j] = cnv[addr + j];
00452
00453 topMatrix.multnorm3d(&cnv[addr + 4], &tcnv[addr + 4]);
00454 tcnv[addr + 4] = -tcnv[addr + 4];
00455 tcnv[addr + 5] = -tcnv[addr + 5];
00456 topMatrix.multpoint3d(&cnv[addr + 7], &tcnv[addr + 7]);
00457 tcnv[addr + 9] = -tcnv[addr + 9];
00458 }
00459
00460 rgb[0] = 0.0;
00461 rgb[1] = 0.0;
00462 rgb[2] = 0.0;
00463
00464
00465 tex=tex_colormaterial(rgb, materialIndex);
00466 rt_tristripscnv3fv(rtscene, tex, numverts, tcnv,
00467 numstrips, vertsperstrip, facets);
00468
00469 delete [] tcnv;
00470 }
00471
00472
00473
00475
00476 int LibTachyonDisplayDevice::open_file(const char *filename) {
00477 my_filename = stringdup(filename);
00478 isOpened = TRUE;
00479 reset_state();
00480 return TRUE;
00481 }
00482
00483 void LibTachyonDisplayDevice::close_file(void) {
00484 outfile = NULL;
00485 delete [] my_filename;
00486 my_filename = NULL;
00487 isOpened = FALSE;
00488 }
00489
00490 static int checkfileextension(const char * s, const char * extension) {
00491 int sz, extsz;
00492 sz = strlen(s);
00493 extsz = strlen(extension);
00494
00495 if (extsz > sz)
00496 return 0;
00497
00498 if (!strupncmp(s + (sz - extsz), extension, extsz)) {
00499 return 1;
00500 }
00501
00502 return 0;
00503 }
00504
00505
00506 void LibTachyonDisplayDevice::write_header() {
00507 wkf_timer_start(trt_timer);
00508
00509
00510
00511
00512
00513
00514
00515 buildtime = rt_timer_create();
00516 rendertime = rt_timer_create();
00517
00518 rt_timer_start(buildtime);
00519
00520 #if 0 && defined(VMDMPI)
00521 if (getenv("VMDNOMPI") == NULL || getenv("VMDTACHYONNOMPI") == NULL) {
00522
00523
00524 if (getenv("VMDTACHYONWORKGROUP") == NULL) {
00525 parallel_group = -1;
00526 rt_set_mpi_comm_world_split_all();
00527 } else {
00528 parallel_group = atoi(getenv("VMDTACHYONWORKGROUP"));
00529 rt_set_mpi_comm_world_split(parallel_group, 0);
00530 }
00531 }
00532 #endif
00533
00534 rtscene = rt_newscene();
00535 rt_outputfile(rtscene, my_filename);
00536
00537 switch (curformat) {
00538 case 0:
00539
00540 if (checkfileextension(my_filename, ".bmp")) {
00541 rt_outputformat(rtscene, RT_FORMAT_WINBMP);
00542 } else if (checkfileextension(my_filename, ".ppm")) {
00543 rt_outputformat(rtscene, RT_FORMAT_PPM);
00544 } else if (checkfileextension(my_filename, ".psd")) {
00545 rt_outputformat(rtscene, RT_FORMAT_PSD48);
00546 } else if (checkfileextension(my_filename, ".rgb")) {
00547 rt_outputformat(rtscene, RT_FORMAT_SGIRGB);
00548 } else if (checkfileextension(my_filename, ".tga")) {
00549 rt_outputformat(rtscene, RT_FORMAT_TARGA);
00550 } else {
00551 #if defined(_MSC_VER) || defined(WIN32)
00552 msgErr << "Unrecognized image file extension, writing Windows Bitmap file."
00553 << sendmsg;
00554 rt_outputformat(rtscene, RT_FORMAT_WINBMP);
00555 #else
00556 msgErr << "Unrecognized image file extension, writing Targa file."
00557 << sendmsg;
00558 rt_outputformat(rtscene, RT_FORMAT_TARGA);
00559 #endif
00560 }
00561 break;
00562
00563 case 1:
00564 rt_outputformat(rtscene, RT_FORMAT_WINBMP);
00565 break;
00566
00567 case 2:
00568 rt_outputformat(rtscene, RT_FORMAT_PPM);
00569 break;
00570
00571 case 3:
00572 rt_outputformat(rtscene, RT_FORMAT_PPM48);
00573
00574 case 4:
00575 rt_outputformat(rtscene, RT_FORMAT_PSD48);
00576
00577 case 5:
00578 rt_outputformat(rtscene, RT_FORMAT_SGIRGB);
00579
00580 case 6:
00581 default:
00582 rt_outputformat(rtscene, RT_FORMAT_TARGA);
00583 }
00584
00585
00586 rt_resolution(rtscene, (int) xSize, (int) ySize);
00587
00588
00589
00590 rt_trans_mode(rtscene, RT_TRANS_VMD);
00591
00592
00593
00594 rt_fog_rendering_mode(rtscene, RT_FOG_VMD);
00595
00596 write_camera();
00597 write_lights();
00598 write_materials();
00599
00600
00601 if (shadows_enabled() || ao_enabled()) {
00602 if (shadows_enabled() && !ao_enabled())
00603 msgInfo << "Shadow rendering enabled." << sendmsg;
00604
00605 rt_shadermode(rtscene, RT_SHADER_FULL);
00606 } else {
00607 rt_shadermode(rtscene, RT_SHADER_MEDIUM);
00608 }
00609
00610
00611 if (ao_enabled()) {
00612 apicolor skycol;
00613 skycol.r = get_ao_ambient();
00614 skycol.g = get_ao_ambient();
00615 skycol.b = get_ao_ambient();
00616
00617 msgInfo << "Ambient occlusion rendering enabled." << sendmsg;
00618 rt_rescale_lights(rtscene, get_ao_direct());
00619
00620 #if ((TACHYON_MAJOR_VERSION == 0) && (TACHYON_MINOR_VERSION == 99) && (TACHYON_PATCH_VERSION <= 1))
00621 rt_ambient_occlusion(rtscene, aosamples, skycol);
00622 #else
00623 float ao_maxdist = RT_AO_MAXDIST_UNLIMITED;
00624
00625 if (getenv("VMDTACHYONAOMAXDIST")) {
00626 float tmp = atof(getenv("VMDTACHYONAOMAXDIST"));
00627 printf("LibTachyonDisplayDevice) setting AO maxdist: %f\n", tmp);
00628 ao_maxdist = tmp;
00629 }
00630
00631 rt_ambient_occlusion(rtscene, aosamples, ao_maxdist, skycol);
00632 #endif
00633 }
00634
00635
00636 if (dof_enabled() && (projection() == DisplayDevice::PERSPECTIVE)) {
00637 msgInfo << "DoF focal blur enabled." << sendmsg;
00638 rt_camera_projection(rtscene, RT_PROJECTION_PERSPECTIVE_DOF);
00639 rt_camera_dof(rtscene, get_dof_focal_dist(), get_dof_fnumber());
00640 }
00641 }
00642
00643
00644 void LibTachyonDisplayDevice::write_trailer(void){
00645 rt_timer_stop(buildtime);
00646 rt_timer_start(rendertime);
00647 rt_renderscene(rtscene);
00648 rt_timer_stop(rendertime);
00649 rt_deletescene(rtscene);
00650
00651 msgInfo << "Tachyon: preprocessing time "
00652 << rt_timer_time(buildtime) << " sec, render time "
00653 << rt_timer_time(rendertime) << " sec." << sendmsg;
00654 rt_timer_destroy(buildtime);
00655 rt_timer_destroy(rendertime);
00656
00657 if (inclipgroup) {
00658 msgErr << "LibTachyonDisplayDevice clip group still active at end of scene" << sendmsg;
00659 }
00660
00661 wkf_timer_stop(trt_timer);
00662 printf("Total Tachyon rendering time: %.1f sec\n", wkf_timer_time(trt_timer));
00663
00664 reset_vars();
00665 }
00666
00667
00668
00669 void LibTachyonDisplayDevice::define_volume_texture(int ID,
00670 int xs, int ys, int zs,
00671 const float *xpq,
00672 const float *ypq,
00673 const float *zpq,
00674 unsigned char *texmap) {
00675 char texname[1024];
00676 unsigned char *rgb=NULL;
00677
00678 voltexID = ID;
00679
00680
00681 memcpy(xplaneeq, xpq, sizeof(xplaneeq));
00682 memcpy(yplaneeq, ypq, sizeof(yplaneeq));
00683 memcpy(zplaneeq, zpq, sizeof(zplaneeq));
00684
00685 sprintf(texname, "::VMDVolTex%d", voltexID);
00686
00687
00688
00689
00690 long txsz = long(xs) * long(ys) * long(zs) * 3L;
00691 rgb = (unsigned char *) malloc(txsz);
00692 memcpy(rgb, texmap, txsz);
00693
00694
00695 rt_define_teximage_rgb24(texname, xs, ys, zs, rgb);
00696 }
00697
00698
00699
00700 void LibTachyonDisplayDevice::volume_texture_on(int texmode) {
00701 involtex = 1;
00702 }
00703
00704
00705
00706 void LibTachyonDisplayDevice::volume_texture_off(void) {
00707 involtex = 0;
00708 }
00709
00710
00711 void LibTachyonDisplayDevice::start_clipgroup(void) {
00712 int i;
00713 int planesenabled = 0;
00714
00715 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00716 if (clip_mode[i] > 0) {
00717 planesenabled++;
00718 if (clip_mode[i] > 1)
00719 warningflags |= FILERENDERER_NOCLIP;
00720 }
00721 }
00722
00723 if (planesenabled > 0) {
00724 float *planes = (float *) malloc(planesenabled * 4 * sizeof(float));
00725
00726 int j=0;
00727 for (i=0; i<VMD_MAX_CLIP_PLANE; i++) {
00728 if (clip_mode[i] > 0) {
00729 float tachyon_clip_center[3];
00730 float tachyon_clip_normal[3];
00731 float tachyon_clip_distance;
00732
00733 inclipgroup = 1;
00734
00735
00736 (transMat.top()).multpoint3d(clip_center[i], tachyon_clip_center);
00737 (transMat.top()).multnorm3d(clip_normal[i], tachyon_clip_normal);
00738 vec_negate(tachyon_clip_normal, tachyon_clip_normal);
00739
00740
00741
00742 tachyon_clip_distance = dot_prod(tachyon_clip_normal, tachyon_clip_center);
00743
00744 planes[j * 4 ] = tachyon_clip_normal[0];
00745 planes[j * 4 + 1] = tachyon_clip_normal[1];
00746 planes[j * 4 + 2] = -tachyon_clip_normal[2];
00747 planes[j * 4 + 3] = tachyon_clip_distance;
00748
00749 rt_clip_fv(rtscene, planesenabled, planes);
00750 j++;
00751 }
00752 }
00753
00754 free(planes);
00755 } else {
00756 inclipgroup = 0;
00757 }
00758 }
00759
00760
00761 void LibTachyonDisplayDevice::end_clipgroup(void) {
00762 if (inclipgroup) {
00763 rt_clip_off(rtscene);
00764 inclipgroup = 0;
00765 }
00766 }
00767
00768
00770
00771 void LibTachyonDisplayDevice::write_camera(void) {
00772 int raydepth = 50;
00773
00774
00775
00776
00777 switch (projection()) {
00778 case DisplayDevice::ORTHOGRAPHIC:
00779 rt_camera_projection(rtscene, RT_PROJECTION_ORTHOGRAPHIC);
00780 rt_camera_setup(rtscene,
00781 1.0 / (vSize / 2.0),
00782 1.0f,
00783 aasamples,
00784 raydepth,
00785 rt_vector(eyePos[0], eyePos[1], -eyePos[2]),
00786 rt_vector(eyeDir[0], eyeDir[1], -eyeDir[2]),
00787 rt_vector(upDir[0], upDir[1], -upDir[2]));
00788 break;
00789
00790 case DisplayDevice::PERSPECTIVE:
00791 default:
00792 rt_camera_projection(rtscene, RT_PROJECTION_PERSPECTIVE);
00793 rt_camera_setup(rtscene,
00794 ((eyePos[2] - zDist) / vSize),
00795 1.0f,
00796 aasamples,
00797 raydepth,
00798 rt_vector(eyePos[0], eyePos[1], -eyePos[2]),
00799 rt_vector(eyeDir[0], eyeDir[1], -eyeDir[2]),
00800 rt_vector(upDir[0], upDir[1], -upDir[2]));
00801 break;
00802 }
00803 }
00804
00805
00806 void LibTachyonDisplayDevice::write_lights(void) {
00807 int i;
00808 int lightcount = 0;
00809
00810
00811 for (i=0; i<DISP_LIGHTS; i++) {
00812 if (lightState[i].on) {
00813 apitexture tex;
00814 memset(&tex, 0, sizeof(apitexture));
00815
00816 tex.col.r=lightState[i].color[0];
00817 tex.col.g=lightState[i].color[1];
00818 tex.col.b=lightState[i].color[2];
00819
00820 rt_directional_light(rtscene,
00821 rt_texture(rtscene, &tex),
00822
00823 rt_vector(-lightState[i].pos[0],
00824 -lightState[i].pos[1],
00825 lightState[i].pos[2]));
00826
00827 lightcount++;
00828 }
00829 }
00830
00831
00832 for (i=0; i<DISP_LIGHTS; i++) {
00833 if (advLightState[i].on) {
00834 float pos[3];
00835
00836
00837 vec_copy(pos, advLightState[i].pos);
00838
00839 if (advLightState[i].spoton) {
00840 printf("TachyonInternal) SpotLight not implemented yet ...\n");
00841 } else {
00842 apitexture tex;
00843 memset(&tex, 0, sizeof(apitexture));
00844
00845 tex.col.r=advLightState[i].color[0];
00846 tex.col.g=advLightState[i].color[1];
00847 tex.col.b=advLightState[i].color[2];
00848
00849 void *l = rt_light(rtscene,
00850 rt_texture(rtscene, &tex),
00851
00852 rt_vector(pos[0], pos[1], -pos[2]), 0.0f);
00853
00854
00855 if (advLightState[i].constfactor != 1.0f ||
00856 advLightState[i].linearfactor != 0.0f ||
00857 advLightState[i].quadfactor != 0.0f) {
00858 rt_light_attenuation(l,
00859 advLightState[i].constfactor,
00860 advLightState[i].linearfactor,
00861 advLightState[i].quadfactor);
00862 }
00863 }
00864
00865 lightcount++;
00866 }
00867 }
00868
00869 if (lightcount < 1) {
00870 msgInfo << "Warning: no lights defined in exported scene!!" << sendmsg;
00871 }
00872 }
00873
00874 void LibTachyonDisplayDevice::write_materials(void) {
00875
00876 apicolor col;
00877 col.r = backColor[0];
00878 col.g = backColor[1];
00879 col.b = backColor[2];
00880 rt_background(rtscene, col);
00881
00882
00883
00884 if (backgroundmode == 1) {
00885 float bspheremag = 0.5f;
00886
00887
00888 switch (projection()) {
00889 case DisplayDevice::ORTHOGRAPHIC:
00890
00891
00892
00893
00894 bspheremag = vSize / 4.0f;
00895 break;
00896
00897 case DisplayDevice::PERSPECTIVE:
00898 default:
00899
00900
00901
00902
00903 bspheremag = (vSize / 2.0f) / (eyePos[2] - zDist);
00904 if (bspheremag > 1.0f)
00905 bspheremag = 1.0f;
00906 break;
00907 }
00908
00909 if (projection() == DisplayDevice::ORTHOGRAPHIC)
00910 rt_background_mode(rtscene, RT_BACKGROUND_TEXTURE_SKY_ORTHO_PLANE);
00911 else
00912 rt_background_mode(rtscene, RT_BACKGROUND_TEXTURE_SKY_SPHERE);
00913 rt_background_gradient(rtscene,
00914 rt_vector(0, 1, 0),
00915 bspheremag, -bspheremag,
00916 rt_color(backgradienttopcolor[0],
00917 backgradienttopcolor[1],
00918 backgradienttopcolor[2]),
00919 rt_color(backgradientbotcolor[0],
00920 backgradientbotcolor[1],
00921 backgradientbotcolor[2]));
00922 }
00923
00924
00925 if (cueingEnabled) {
00926 switch (cueMode) {
00927 case CUE_LINEAR:
00928 rt_fog_mode(rtscene, RT_FOG_LINEAR);
00929 rt_fog_parms(rtscene, col, get_cue_start(), get_cue_end(), 1.0f);
00930 break;
00931
00932 case CUE_EXP:
00933 rt_fog_mode(rtscene, RT_FOG_EXP);
00934 rt_fog_parms(rtscene, col, 0.0, get_cue_end(), get_cue_density());
00935 break;
00936
00937 case CUE_EXP2:
00938 rt_fog_mode(rtscene, RT_FOG_EXP2);
00939 rt_fog_parms(rtscene, col, 0.0, get_cue_end(), get_cue_density());
00940 break;
00941
00942 case NUM_CUE_MODES:
00943
00944 break;
00945 }
00946 } else {
00947 rt_fog_mode(rtscene, RT_FOG_NONE);
00948 }
00949 }
00950
00951
00952 void * LibTachyonDisplayDevice::tex_cindexmaterial(int cindex, int material) {
00953 float *rgb = (float *) &matData[cindex];
00954 void *voidtex;
00955
00956 voidtex = tex_colormaterial(rgb, material);
00957
00958 return voidtex;
00959 }
00960
00961
00962 void * LibTachyonDisplayDevice::tex_colormaterial(float *rgb, int material) {
00963 apitexture tex;
00964 void *voidtex;
00965
00966 memset(&tex, 0, sizeof(apitexture));
00967
00968 if (materials_on) {
00969 tex.ambient = mat_ambient;
00970 tex.diffuse = mat_diffuse;
00971 tex.specular = mat_mirror;
00972 } else {
00973 tex.ambient = 1.0;
00974 tex.diffuse = 0.0;
00975 tex.specular = 0.0;
00976 }
00977
00978 tex.opacity = mat_opacity;
00979 tex.col.r = rgb[0];
00980 tex.col.g = rgb[1];
00981 tex.col.b = rgb[2];
00982
00984 if (!involtex) {
00986 tex.texturefunc = RT_TEXTURE_CONSTANT;
00987 } else {
00991 float voluaxs[3];
00992 float volvaxs[3];
00993 float volwaxs[3];
00994 float volcent[3];
00995
00996
00997
00998 (transMat.top()).multplaneeq3d(xplaneeq, voluaxs);
00999 (transMat.top()).multplaneeq3d(yplaneeq, volvaxs);
01000 (transMat.top()).multplaneeq3d(zplaneeq, volwaxs);
01001
01002
01003 float invscale = 1.0f / scale_radius(1.0f);
01004 int i;
01005 for (i=0; i<3; i++) {
01006 voluaxs[i] *= invscale;
01007 volvaxs[i] *= invscale;
01008 volwaxs[i] *= invscale;
01009 }
01010
01011
01012
01013
01014 float volorgmol[3] = {0,0,0};
01015 volorgmol[0] = -xplaneeq[3] / norm(xplaneeq);
01016 volorgmol[1] = -yplaneeq[3] / norm(yplaneeq);
01017 volorgmol[2] = -zplaneeq[3] / norm(zplaneeq);
01018
01019
01020 (transMat.top()).multpoint3d(volorgmol, volcent);
01021
01022 tex.texturefunc = RT_TEXTURE_VOLUME_IMAGE;
01023
01024 sprintf(tex.imap, "::VMDVolTex%d", voltexID);
01025 tex.ctr.x = volcent[0];
01026 tex.ctr.y = volcent[1];
01027 tex.ctr.z = -volcent[2];
01028 tex.rot.x = 0;
01029 tex.rot.y = 0;
01030 tex.rot.z = 0;
01031 tex.scale.x = 1;
01032 tex.scale.y = 1;
01033 tex.scale.z = 1;
01034 tex.uaxs.x = voluaxs[0];
01035 tex.uaxs.y = voluaxs[1];
01036 tex.uaxs.z = -voluaxs[2];
01037 tex.vaxs.x = volvaxs[0];
01038 tex.vaxs.y = volvaxs[1];
01039 tex.vaxs.z = -volvaxs[2];
01040 tex.waxs.x = volwaxs[0];
01041 tex.waxs.y = volwaxs[1];
01042 tex.waxs.z = -volwaxs[2];
01043 }
01044
01046 voidtex=rt_texture(rtscene, &tex);
01047
01049 rt_tex_phong(voidtex, mat_specular, mat_shininess, RT_PHONG_PLASTIC);
01050
01052 if (mat_transmode)
01053 rt_tex_transmode(voidtex, RT_TRANS_RASTER3D);
01054
01056 rt_tex_outline(voidtex, mat_outline, mat_outlinewidth);
01057
01058 return voidtex;
01059 }
01060
01061