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