Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

LibTachyonDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr 
00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 
00004 *cr University of Illinois 
00005 *cr All Rights Reserved 
00006 *cr 
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010 * RCS INFORMATION:
00011 *
00012 * $RCSfile: LibTachyonDisplayDevice.C,v $
00013 * $Author: johns $ $Locker: $ $State: Exp $
00014 * $Revision: 1.99 $ $Date: 2021年03月06日 20:51:52 $
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" // needed for default image viewer
00032 #include "Hershey.h" // needed for Hershey font rendering fctns
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; // save VMDApp handle for GPU memory management routines
00057 
00058 reset_vars(); // initialize internal state
00059 trt_timer = wkf_timer_create();
00060 
00061 #if 0 && defined(VMDMPI)
00062 // init scene-independent parts of Tachyon library
00063 parallel_group = 0;
00064 if (getenv("VMDNOMPI") != NULL || getenv("VMDTACHYONNOMPI") != NULL) {
00065 rt_initialize_nompi();
00066 } else {
00067 // set Tachyon to use MPI_COMM_WORLD initially.
00068 rt_initialize_mpi_comm_world();
00069 
00070 #if 1
00071 // Unless overridden, every VMD node runs Tachyon independently of one another,
00072 // with each node in its own communicator...
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); // init scene-independent parts of Tachyon library
00084 #endif
00085 
00086 #if defined(VMDMPI)
00087 // When VMD is running with MPI enabled, we disable console output
00088 // for Tachyon rendering status and progress messages. If VMD
00089 // was compiled with MPI support, we only turn on console output
00090 // when we detect that MPI has been disabled.
00091 if (getenv("VMDNOMPI") != NULL) {
00092 // rt_set_ui_message(vmd_rt_ui_message);
00093 rt_set_ui_progress(vmd_rt_ui_progress);
00094 }
00095 #else
00096 // rt_set_ui_message(vmd_rt_ui_message);
00097 rt_set_ui_progress(vmd_rt_ui_progress);
00098 #endif
00099 
00100 // Add supported file formats
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 // Default image format depends on platform
00110 curformat = 0;
00111 
00112 // Set default aa level
00113 has_aa = TRUE;
00114 aasamples = 12;
00115 aosamples = 12;
00116 }
00117 
00118 LibTachyonDisplayDevice::~LibTachyonDisplayDevice(void) { 
00119 rt_finalize(); // shut down Tachyon library
00120 wkf_timer_destroy(trt_timer);
00121 }
00122 
00123 
00125 
00126 // reset internal state between renders
00127 void LibTachyonDisplayDevice::reset_vars(void) {
00128 inclipgroup = 0; // not currently in a clipping group
00129 involtex = 0; // volume texturing disabled
00130 voltexID = -1; // invalid texture ID
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 // transform the world coordinates
00146 (transMat.top()).multpoint3d(pos, textpos);
00147 textsize = size * 1.5f;
00148 textthickness = thickness*DEFAULT_RADIUS;
00149 
00150 // create texture to use for text rendering
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 // if we have both previous and next points, connect them...
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 // ...otherwise, just draw the next point
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 // draw a point
00199 void LibTachyonDisplayDevice::point(float * spdata) {
00200 float vec[3];
00201 void *tex;
00202 // transform the world coordinates
00203 (transMat.top()).multpoint3d(spdata, vec);
00204 
00205 // draw the sphere
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 // draw a sphere
00214 void LibTachyonDisplayDevice::sphere(float * spdata) {
00215 float vec[3];
00216 float radius;
00217 void *tex;
00218 
00219 // transform the world coordinates
00220 (transMat.top()).multpoint3d(spdata, vec);
00221 radius = scale_radius(spdata[3]);
00222 
00223 // draw the sphere
00224 tex=tex_cindexmaterial(colorIndex, materialIndex);
00225 rt_sphere(rtscene, tex, rt_vector(vec[0], vec[1], -vec[2]), radius);
00226 }
00227 
00228 
00229 // draw a sphere array
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 // transform the world coordinates
00239 (transMat.top()).multpoint3d(&centers[ind], vec);
00240 radius = scale_radius(radii[i]);
00241 
00242 // draw the sphere
00243 tex=tex_colormaterial(&colors[ind], materialIndex);
00244 rt_sphere(rtscene, tex, rt_vector(vec[0], vec[1], -vec[2]), radius);
00245 ind += 3; // next sphere
00246 }
00247 
00248 // set final color state after array has been drawn
00249 ind=(spnum-1)*3;
00250 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00251 }
00252 
00253 
00254 // draw a line (cylinder) from a to b
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 // transform the world coordinates
00263 (transMat.top()).multpoint3d(a, from);
00264 (transMat.top()).multpoint3d(b, to);
00265 
00266 // draw the cylinder
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 // transform the world coordinates
00275 (transMat.top()).multpoint3d(a, tmp1);
00276 (transMat.top()).multpoint3d(b, tmp2);
00277 
00278 // how to create a dashed line
00279 vec_sub(dirvec, tmp2, tmp1); // vector from a to b
00280 vec_copy(unitdirvec, dirvec);
00281 vec_normalize(unitdirvec); // unit vector from a to b
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 // draw the cylinder
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 // draw a cylinder
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 // transform the world coordinates
00316 (transMat.top()).multpoint3d(a, from);
00317 (transMat.top()).multpoint3d(b, to);
00318 radius = scale_radius(r);
00319 
00320 // draw the cylinder
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 // Cylinder caps?
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 // draw a triangle
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 // transform the world coordinates
00363 (transMat.top()).multpoint3d(a, vec1);
00364 (transMat.top()).multpoint3d(b, vec2);
00365 (transMat.top()).multpoint3d(c, vec3);
00366 
00367 // and the normals
00368 (transMat.top()).multnorm3d(n1, norm1);
00369 (transMat.top()).multnorm3d(n2, norm2);
00370 (transMat.top()).multnorm3d(n3, norm3);
00371 
00372 // draw the triangle
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 // draw triangle with per-vertex colors
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 // transform the world coordinates
00394 (transMat.top()).multpoint3d(xyz1, vec1);
00395 (transMat.top()).multpoint3d(xyz2, vec2);
00396 (transMat.top()).multpoint3d(xyz3, vec3);
00397 
00398 // and the normals
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 // draw the triangle
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 // draw triangle strips with per-vertex colors
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 /* transform all vertices and normals, copy colors as-is */
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 // draw the triangle strips
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 // initialize the file for output
00506 void LibTachyonDisplayDevice::write_header() {
00507 wkf_timer_start(trt_timer);
00508 
00509 // NOTE: the vmd variable "Aspect" has absolutely *nothing* to do
00510 // with aspect ratio correction, it is only the ratio of the
00511 // width of the graphics window to its height, and so it should
00512 // be used only to cause the ray tracer to generate a similarly
00513 // proportioned image.
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 // Unless overridden, every VMD node runs Tachyon independently of one another,
00523 // with each node in its own communicator...
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); // get filename from base class
00536 
00537 switch (curformat) {
00538 case 0: // autodetermine...
00539 // set appropriate image file format
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 // use opacity post-multiply transparency mode for output that closely 
00589 // matches what user's see in the OpenGL window in VMD.
00590 rt_trans_mode(rtscene, RT_TRANS_VMD); 
00591 
00592 // use planar fog mode (rather than the more physically correct radial fog)
00593 // for output that closely matches what user's see in the VMD OpenGL window.
00594 rt_fog_rendering_mode(rtscene, RT_FOG_VMD);
00595 
00596 write_camera(); // has to be first thing in the file. 
00597 write_lights(); // could be anywhere.
00598 write_materials(); // has to be before objects that use them.
00599 
00600 // render with/without shadows
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); // full shading mode required
00606 } else {
00607 rt_shadermode(rtscene, RT_SHADER_MEDIUM); // disable shadows by default
00608 }
00609 
00610 // render with ambient occlusion, but only if shadows are also enabled
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 // render with depth of field, but only for perspective projection
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(); // reset internal state between renders
00665 }
00666 
00667 
00668 // define a volumetric texture map
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; // remember current texture ID
00679 
00680 // remember texture plane equations
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 // copy incoming texture map to a new buffer
00688 // XXX ideally we'd have Tachyon use the existing image
00689 // buffer rather than copy it
00690 long txsz = long(xs) * long(ys) * long(zs) * 3L;
00691 rgb = (unsigned char *) malloc(txsz);
00692 memcpy(rgb, texmap, txsz);
00693 
00694 // define the texture map image within Tachyon
00695 rt_define_teximage_rgb24(texname, xs, ys, zs, rgb);
00696 }
00697 
00698 
00699 // enable volumetric texturing, either in "replace" or "modulate" mode
00700 void LibTachyonDisplayDevice::volume_texture_on(int texmode) {
00701 involtex = 1;
00702 }
00703 
00704 
00705 // disable volumetric texturing
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++; /* count number of active clipping planes */
00718 if (clip_mode[i] > 1)
00719 warningflags |= FILERENDERER_NOCLIP; /* emit warnings */
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; // we're in a clipping group presently
00734 
00735 // Transform the plane center and the normal
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 // Tachyon uses the distance from the origin to the plane for its
00741 // representation, instead of the plane center
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); // add the clipping planes
00750 j++;
00751 }
00752 }
00753 
00754 free(planes);
00755 } else {
00756 inclipgroup = 0; // Not currently in a clipping group
00757 }
00758 }
00759 
00760 
00761 void LibTachyonDisplayDevice::end_clipgroup(void) {
00762 if (inclipgroup) {
00763 rt_clip_off(rtscene); // disable clipping planes
00764 inclipgroup = 0; // we're not in a clipping group anymore 
00765 }
00766 }
00767 
00768 
00770 
00771 void LibTachyonDisplayDevice::write_camera(void) {
00772 int raydepth = 50;
00773 
00774 // Camera position
00775 // Tachyon uses a left-handed coordinate system
00776 // VMD uses right-handed, so z(Tachyon) = -z(VMD).
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), // zoom
00782 1.0f, // aspect ratio
00783 aasamples, // antialiasing
00784 raydepth, // ray depth
00785 rt_vector(eyePos[0], eyePos[1], -eyePos[2]), // camcent
00786 rt_vector(eyeDir[0], eyeDir[1], -eyeDir[2]), // camview
00787 rt_vector(upDir[0], upDir[1], -upDir[2])); // camup
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), // zoom
00795 1.0f, // aspect ratio
00796 aasamples, // antialiasing
00797 raydepth, // ray depth
00798 rt_vector(eyePos[0], eyePos[1], -eyePos[2]), // camcent
00799 rt_vector(eyeDir[0], eyeDir[1], -eyeDir[2]), // camview
00800 rt_vector(upDir[0], upDir[1], -upDir[2])); // camup
00801 break;
00802 }
00803 }
00804 
00805 
00806 void LibTachyonDisplayDevice::write_lights(void) { 
00807 int i; 
00808 int lightcount = 0;
00809 
00810 /* directional lights */
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 /* give negated light position for direction vector... */ 
00823 rt_vector(-lightState[i].pos[0], 
00824 -lightState[i].pos[1], 
00825 lightState[i].pos[2]));
00826 
00827 lightcount++;
00828 }
00829 }
00830 
00831 /* advanced positional lights */
00832 for (i=0; i<DISP_LIGHTS; i++) {
00833 if (advLightState[i].on) {
00834 float pos[3];
00835 
00836 // always use world coordinates for now
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 /* negate position to correct handedness... */ 
00852 rt_vector(pos[0], pos[1], -pos[2]), 0.0f);
00853 
00854 /* emit light attentuation parameters if needed */
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 // background color
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 // Specify Tachyon background sky sphere if background gradient
00883 // mode is enabled.
00884 if (backgroundmode == 1) {
00885 float bspheremag = 0.5f;
00886 
00887 // compute positive/negative magnitude of sphere gradient
00888 switch (projection()) {
00889 case DisplayDevice::ORTHOGRAPHIC:
00890 // For orthographic views, Tachyon uses the dot product between
00891 // the incident ray origin and the sky sphere gradient "up" vector,
00892 // since all camera rays have the same direction and differ only
00893 // in their origin.
00894 bspheremag = vSize / 4.0f;
00895 break;
00896 
00897 case DisplayDevice::PERSPECTIVE:
00898 default:
00899 // For perspective views, Tachyon uses the dot product between
00900 // the incident ray and the sky sphere gradient "up" vector,
00901 // so for larger values of vSize, we have to clamp the maximum
00902 // magnitude to 1.0. 
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 // set depth cueing parameters
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 // this should never happen
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 // transform the y/v/w texture coordinate axes from molecule
00997 // coordinates into world coordinates
00998 (transMat.top()).multplaneeq3d(xplaneeq, voluaxs);
00999 (transMat.top()).multplaneeq3d(yplaneeq, volvaxs);
01000 (transMat.top()).multplaneeq3d(zplaneeq, volwaxs);
01001 
01002 // undo the scaling operation applied by the transformation
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 // compute the volume origin in molecule coordinates by
01012 // reverting the scaling factor that was previously applied
01013 // to the texture plane equation
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 // transform the volume origin into world coordinates
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 

Generated on Mon Nov 17 02:46:20 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /