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

LibTachyonDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 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.86 $        $Date: 2012/03/13 19:46:01 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 *
00019 * FileRenderer type for the Tachyon Parallel / Multiprocessor Ray Tracer 
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"    // needed for default image viewer
00033 #include "Hershey.h"   // needed for Hershey font rendering fctns
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();  // initialize internal state
00058   rt_initialize(0, NULL); // init scene-independent parts of Tachyon library
00059 
00060 //  rt_set_ui_message(vmd_rt_ui_message);
00061   rt_set_ui_progress(vmd_rt_ui_progress);
00062 
00063   // Add supported file formats
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   // Set default aa level
00073   has_aa = TRUE;
00074   aasamples = 12;
00075   aosamples = 12;
00076 
00077   reset_vars();
00078 
00079   // Default image format depends on platform
00080   curformat = 0;
00081 }
00082         
00083 LibTachyonDisplayDevice::~LibTachyonDisplayDevice(void) { 
00084   rt_finalize(); // shut down Tachyon library
00085 }
00086 
00087 
00089 
00090 // reset internal state between renders
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; // not currently in a clipping group
00098   involtex = 0;    // volume texturing disabled
00099   voltexID = -1;   // invalid texture ID
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   // transform the world coordinates
00115   (transMat.top()).multpoint3d(pos, textpos);
00116   textsize = size * 1.5f;
00117   textthickness = thickness*DEFAULT_RADIUS;
00118 
00119   // create texture to use for text rendering
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           // if we have both previous and next points, connect them...
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           // ...otherwise, just draw the next point
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 // draw a point
00168 void LibTachyonDisplayDevice::point(float * spdata) {
00169   float vec[3];
00170   void *tex;
00171   // transform the world coordinates
00172   (transMat.top()).multpoint3d(spdata, vec);
00173 
00174   // draw the sphere
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 // draw a sphere
00183 void LibTachyonDisplayDevice::sphere(float * spdata) {
00184   float vec[3];
00185   float radius;
00186   void *tex;
00187     
00188   // transform the world coordinates
00189   (transMat.top()).multpoint3d(spdata, vec);
00190   radius = scale_radius(spdata[3]);
00191    
00192   // draw the sphere
00193   tex=tex_cindexmaterial(colorIndex, materialIndex);
00194   rt_sphere(rtscene, tex, rt_vector(vec[0], vec[1], -vec[2]), radius);
00195 }
00196 
00197 
00198 // draw a sphere array
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     // transform the world coordinates
00208     (transMat.top()).multpoint3d(&centers[ind], vec);
00209     radius = scale_radius(radii[i]);
00210 
00211     // draw the sphere
00212     tex=tex_colormaterial(&colors[ind], materialIndex);
00213     rt_sphere(rtscene, tex, rt_vector(vec[0], vec[1], -vec[2]), radius);
00214     ind += 3; // next sphere
00215   }
00216 
00217   // set final color state after array has been drawn
00218   ind=(spnum-1)*3;
00219   super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00220 }
00221 
00222 
00223 // draw a line (cylinder) from a to b
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     // transform the world coordinates
00232     (transMat.top()).multpoint3d(a, from);
00233     (transMat.top()).multpoint3d(b, to);
00234     
00235     // draw the cylinder
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      // transform the world coordinates
00244     (transMat.top()).multpoint3d(a, tmp1);
00245     (transMat.top()).multpoint3d(b, tmp2);
00246 
00247     // how to create a dashed line
00248     vec_sub(dirvec, tmp2, tmp1);  // vector from a to b
00249     vec_copy(unitdirvec, dirvec);
00250     vec_normalize(unitdirvec);    // unit vector from a to b
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       // draw the cylinder
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 // draw a cylinder
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   // transform the world coordinates
00286   (transMat.top()).multpoint3d(a, from);
00287   (transMat.top()).multpoint3d(b, to);
00288   radius = scale_radius(r);
00289    
00290   // draw the cylinder
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   // Cylinder caps?
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 // draw a triangle
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   // transform the world coordinates
00333   (transMat.top()).multpoint3d(a, vec1);
00334   (transMat.top()).multpoint3d(b, vec2);
00335   (transMat.top()).multpoint3d(c, vec3);
00336 
00337   // and the normals
00338   (transMat.top()).multnorm3d(n1, norm1);
00339   (transMat.top()).multnorm3d(n2, norm2);
00340   (transMat.top()).multnorm3d(n3, norm3);
00341 
00342   // draw the triangle
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 // draw triangle with per-vertex colors
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   // transform the world coordinates
00364   (transMat.top()).multpoint3d(xyz1, vec1);
00365   (transMat.top()).multpoint3d(xyz2, vec2);
00366   (transMat.top()).multpoint3d(xyz3, vec3);
00367 
00368   // and the normals
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   // draw the triangle
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 // draw triangle strips with per-vertex colors
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   /* transform all vertices and normals, copy colors as-is */
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   // draw the triangle strips
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 // initialize the file for output
00476 void LibTachyonDisplayDevice::write_header() {
00477   // NOTE: the vmd variable "Aspect" has absolutely *nothing* to do
00478   //       with aspect ratio correction, it is only the ratio of the
00479   //       width of the graphics window to its height, and so it should
00480   //       be used only to cause the ray tracer to generate a similarly
00481   //       proportioned image.
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);      // get filename from base class
00489 
00490   switch (curformat) {
00491     case 0: // autodetermine...
00492       // set appropriate image file format
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   // use opacity post-multiply transparency mode for output that closely 
00542   // matches what user's see in the OpenGL window in VMD.
00543   rt_trans_mode(rtscene, RT_TRANS_VMD);     
00544 
00545   // use planar fog mode (rather than the more physically correct radial fog)
00546   // for output that closely matches what user's see in the VMD OpenGL window.
00547   rt_fog_rendering_mode(rtscene, RT_FOG_VMD);
00548 
00549   write_camera();    // has to be first thing in the file. 
00550   write_lights();    // could be anywhere.
00551   write_materials(); // has to be before objects that use them.
00552 
00553   // render with/without shadows
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);   // full shading mode required
00559   } else {
00560     rt_shadermode(rtscene, RT_SHADER_MEDIUM); // disable shadows by default
00561   }
00562 
00563   // render with ambient occlusion, but only if shadows are also enabled
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(); // reset internal state between renders
00595 }
00596 
00597 
00598 // define a volumetric texture map
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; // remember current texture ID
00609 
00610   // remember texture plane equations
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   // copy incoming texture map to a new buffer
00618   // XXX ideally we'd have Tachyon use the existing image
00619   //     buffer rather than copy it
00620   rgb = (unsigned char *) malloc(xs * ys * zs * 3);
00621   memcpy(rgb, texmap, xs * ys * zs * 3);
00622 
00623   // define the texture map image within Tachyon
00624   rt_define_teximage_rgb24(texname, xs, ys, zs, rgb);
00625 }
00626 
00627 
00628 // enable volumetric texturing, either in "replace" or "modulate" mode
00629 void LibTachyonDisplayDevice::volume_texture_on(int texmode) {
00630   involtex = 1;
00631 }
00632 
00633 
00634 // disable volumetric texturing
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++;  /* count number of active clipping planes */
00647       if (clip_mode[i] > 1)
00648         warningflags |= FILERENDERER_NOCLIP; /* emit warnings */
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; // we're in a clipping group presently
00663 
00664         // Transform the plane center and the normal
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         // Tachyon uses the distance from the origin to the plane for its
00670         // representation, instead of the plane center
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); // add the clipping planes
00679         j++;
00680       }
00681     }
00682 
00683     free(planes);
00684   } else {
00685     inclipgroup = 0; // Not currently in a clipping group
00686   }
00687 }
00688 
00689 
00690 void LibTachyonDisplayDevice::end_clipgroup(void) {
00691   if (inclipgroup) {
00692     rt_clip_off(rtscene); // disable clipping planes
00693     inclipgroup = 0;      // we're not in a clipping group anymore 
00694   }
00695 }
00696 
00697 
00699 
00700 void LibTachyonDisplayDevice::write_camera(void) {
00701   int raydepth = 50;
00702 
00703   // Camera position
00704   // Tachyon uses a left-handed coordinate system
00705   // VMD uses right-handed, so z(Tachyon) = -z(VMD).
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),           // zoom
00711                      1.0f,                          // aspect ratio
00712                      aasamples,                     // antialiasing
00713                      raydepth,                      // ray depth
00714                      rt_vector(eyePos[0], eyePos[1], -eyePos[2]), // camcent
00715                      rt_vector(eyeDir[0], eyeDir[1], -eyeDir[2]), // camview
00716                      rt_vector(upDir[0],   upDir[1],  -upDir[2]));   // camup
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), // zoom
00724                      1.0f,                          // aspect ratio
00725                      aasamples,                     // antialiasing
00726                      raydepth,                      // ray depth
00727                      rt_vector(eyePos[0], eyePos[1], -eyePos[2]), // camcent
00728                      rt_vector(eyeDir[0], eyeDir[1], -eyeDir[2]), // camview
00729                      rt_vector(upDir[0],   upDir[1], -upDir[2])); // camup
00730       break;
00731   }
00732 }
00733 
00734   
00735 void LibTachyonDisplayDevice::write_lights(void) {  
00736   int i;  
00737   int lightcount = 0;
00738 
00739   /* directional lights */
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                /* give negated light position for direction vector... */ 
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   /* advanced positional lights */
00762   for (i=0; i<DISP_LIGHTS; i++) {
00763     if (advLightState[i].on) {
00764       float pos[3];
00765 
00766       // always use world coordinates for now
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                            /* negate position to correct handedness... */ 
00782                            rt_vector(pos[0], pos[1], -pos[2]), 0.0f);
00783 
00784         /* emit light attentuation parameters if needed */
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   // background color
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   // Specify Tachyon background sky sphere if background gradient
00814   // mode is enabled.
00815   if (backgroundmode == 1) {
00816     float bspheremag = 0.5f;
00817 
00818     // compute positive/negative magnitude of sphere gradient
00819     switch (projection()) {
00820       case DisplayDevice::ORTHOGRAPHIC:
00821         // For orthographic views, Tachyon uses the dot product between
00822         // the incident ray origin and the sky sphere gradient "up" vector,
00823         // since all camera rays have the same direction and differ only
00824         // in their origin.
00825         bspheremag = vSize / 4.0f;
00826         break;
00827 
00828       case DisplayDevice::PERSPECTIVE:
00829       default:
00830         // For perspective views, Tachyon uses the dot product between
00831         // the incident ray and the sky sphere gradient "up" vector,
00832         // so for larger values of vSize, we have to clamp the maximum
00833         // magnitude to 1.0. 
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   // set depth cueing parameters
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         // this should never happen
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     // transform the y/v/w texture coordinate axes from molecule
00931     // coordinates into world coordinates
00932     (transMat.top()).multplaneeq3d(xplaneeq, voluaxs);
00933     (transMat.top()).multplaneeq3d(yplaneeq, volvaxs);
00934     (transMat.top()).multplaneeq3d(zplaneeq, volwaxs);
00935 
00936     // undo the scaling operation applied by the transformation
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     // compute the volume origin in molecule coordinates by
00946     // reverting the scaling factor that was previously applied
00947     // to the texture plane equation
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     // transform the volume origin into world coordinates
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 

Generated on Sat May 26 01:48:04 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002