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

ANARIDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 2013-2014 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: ANARIDisplayDevice.C,v $
00013 *      $Author: johns $      $Locker:  $               $State: Exp $
00014 *      $Revision: 1.3 $         $Date: 2021/05/14 22:13:07 $
00015 *
00016 ***************************************************************************/
00037 #include <math.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <string.h>
00041 
00042 #include "VMDApp.h"    // needed for accelerator memory management
00043 #include "QuickSurf.h" // needed for accelerator memory management
00044 
00045 #include "DispCmds.h"  // CYLINDER_TRAILINGCAP, etc..
00046 #include "ANARIDisplayDevice.h"
00047 #include "ANARIRenderer.h"
00048 #include "config.h"    // needed for default image viewer
00049 #include "Hershey.h"   // needed for Hershey font rendering fctns
00050 
00051 
00052 // The default radius for points and lines (which are displayed
00053 // as small spheres or cylinders, respectively)
00054 #define DEFAULT_RADIUS  0.0025f
00055 
00056 
00057 // Global ANARI initialization routine -- call it only ONCE...
00058 void ANARIDisplayDevice::ANARI_Global_Init(void) {
00059   ANARIRender::ANARI_Global_Init(); // call only ONCE
00060 }
00061 
00062 // Global ANARI shutdown routine -- call it only ONCE...
00063 void ANARIDisplayDevice::ANARI_Global_Shutdown(void) {
00064   ANARIRender::ANARI_Global_Shutdown(); // call only ONCE
00065 }
00066 
00067 
00069 ANARIDisplayDevice::ANARIDisplayDevice(VMDApp *app, int interactive) : FileRenderer((interactive) ? 
00070                "ANARIInteractive" : "ANARIInternal", 
00071                (interactive) ? 
00072                "ANARI (interactive)" : "ANARI (internal, in-memory)",
00073                "vmdscene.ppm", DEF_VMDIMAGEVIEWER) {
00074   vmdapp = app; // save VMDApp handle for init or memory management routines
00075 
00076   reset_vars(); // initialize material cache
00077 
00078   // flag interactive or not
00079   isinteractive = interactive;
00080 
00081   // Add supported file formats
00082   formats.add_name("PPM", 0);
00083 
00084   // Default image format depends on platform
00085   curformat = 0;
00086 
00087   // Set default aa level
00088   has_aa = TRUE;
00089   aasamples = 12;
00090   aosamples = 12;
00091 
00092   ort = new ANARIRender();
00093   ort_timer = wkf_timer_create();
00094 }
00095         
00097 ANARIDisplayDevice::~ANARIDisplayDevice(void) {
00098   delete ort;
00099   ort = NULL;
00100   wkf_timer_destroy(ort_timer);
00101 }
00102 
00103 void ANARIDisplayDevice::add_material(void) {
00104   ort->add_material(materialIndex,
00105                     mat_ambient, mat_diffuse, mat_specular, mat_shininess,
00106                     mat_mirror, mat_opacity, mat_outline, mat_outlinewidth, 
00107                     mat_transmode > 0.5f);
00108 }
00109 
00110 
00112 void ANARIDisplayDevice::reset_vars(void) {
00113 //  reset_cylinder_buffer();
00114   reset_triangle_buffer();
00115 }
00116 
00117 
00118 void ANARIDisplayDevice::comment(const char *s) {
00119   ort->comment(s);
00120 }
00121 
00122 
00123 #if 0
00124 
00125 void ANARIDisplayDevice::send_cylinder_buffer() {
00126   if (cylinder_vert_buffer.num() > 0) {
00127     // send the cylinders...
00128     ort->cylinder_array_color(*cylinder_xform, cylinder_radius_scalefactor,
00129                               cylinder_vert_buffer.num()/6,
00130                               &cylinder_vert_buffer[0],
00131                               &cylinder_radii_buffer[0],
00132                               &cylinder_color_buffer[0],
00133                               cylinder_matindex);
00134 
00135 #if 0
00136     // send the cylinder end caps, if any
00137     if (cylcap_vert_buffer.num() > 0) {
00138       ort->ring_array_color(*cylinder_xform, cylinder_radius_scalefactor,
00139                             cylcap_vert_buffer.num()/3,
00140                             &cylcap_vert_buffer[0],
00141                             &cylcap_norm_buffer[0],
00142                             &cylcap_radii_buffer[0],
00143                             &cylcap_color_buffer[0],
00144                             cylinder_matindex);
00145     }
00146 #endif
00147 
00148     delete cylinder_xform;
00149     cylinder_xform=NULL;
00150   }
00151 //  reset_cylinder_buffer();
00152 }
00153 
00154 
00155 // draw a cylinder
00156 void ANARIDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00157   // if we have a change in transformation matrix, color, or material state,
00158   // we have to emit all accumulated cylinders to ANARI and begin a new batch
00159   if (cylinder_xform != NULL && ((cylinder_matindex != materialIndex) || (memcmp(cylinder_xform->mat, transMat.top().mat, sizeof(cylinder_xform->mat))))) {
00160     send_cylinder_buffer(); // render the accumulated cylinder buffer...
00161   }
00162 
00163   // record all transformation/material/color state on first cylinder call
00164   if (cylinder_xform == NULL) {
00165     // record material, color, and transformation state
00166     cylinder_matindex = materialIndex;
00167     cylinder_xform = new Matrix4(transMat.top());
00168     cylinder_radius_scalefactor = scale_factor();
00169     add_material(); // cause ANARI to cache the current material
00170   }
00171 
00172   // record vertex data
00173   cylinder_vert_buffer.append2x3(&a[0], &b[0]);
00174   cylinder_radii_buffer.append(r);
00175   cylinder_color_buffer.append3(&matData[colorIndex][0]);
00176 
00177 #if 0
00178   // XXX Cylinder caps not yet supported in ANARI
00179   // Cylinder caps?
00180   if (filled) {
00181     float norm[3];
00182     norm[0] = b[0] - a[0];
00183     norm[1] = b[1] - a[1];
00184     norm[2] = b[2] - a[2];
00185 
00186     float div = 1.0f / sqrtf(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
00187     norm[0] *= div;
00188     norm[1] *= div;
00189     norm[2] *= div;
00190 
00191     if (filled & CYLINDER_TRAILINGCAP) {
00192       cylcap_vert_buffer.append3(&a[0]);
00193       cylcap_norm_buffer.append3(&norm[0]);
00194       cylcap_radii_buffer.append2(0.0f, r);
00195       cylcap_color_buffer.append3(&matData[colorIndex][0]);
00196     }
00197 
00198     if (filled & CYLINDER_LEADINGCAP) {
00199       cylcap_vert_buffer.append3(&b[0]);
00200       norm[0] *= -1;
00201       norm[1] *= -1;
00202       norm[2] *= -1;
00203       cylcap_norm_buffer.append3(&norm[0]);
00204       cylcap_radii_buffer.append2(0.0f, r);
00205       cylcap_color_buffer.append3(&matData[colorIndex][0]);
00206     }
00207   }
00208 #endif
00209 }
00210 
00211 #endif
00212 
00213 
00214 // draw a sphere array
00215 void ANARIDisplayDevice::sphere_array(int spnum, int spres, float *centers, 
00216                                       float *radii, float *colors) {
00217   add_material();
00218   ort->sphere_array_color(transMat.top(), scale_factor(), spnum, 
00219                           centers, radii, colors, materialIndex);
00220   
00221   // set final color state after array has been drawn
00222   int ind=(spnum-1)*3;
00223   super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00224 }
00225 
00226 
00227 #if 0
00228 
00229 //
00230 // XXX text needs cylinders to be performant...
00231 //
00232 void ANARIDisplayDevice::text(float *pos, float size, float thickness,
00233                               const char *str) {
00234   float textpos[3];
00235   float textsize, textthickness;
00236   hersheyhandle hh;
00237 
00238   // transform the world coordinates
00239   (transMat.top()).multpoint3d(pos, textpos);
00240   textsize = size * 1.5f;
00241   textthickness = thickness*DEFAULT_RADIUS;
00242 
00243   ResizeArray<float> text_spheres;
00244   ResizeArray<float> text_cylinders;
00245 
00246   while (*str != '\0') {
00247     float lm, rm, x, y, ox, oy;
00248     int draw, odraw;
00249     ox=oy=x=y=0.0f;
00250     draw=odraw=0;
00251 
00252     hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00253     textpos[0] -= lm * textsize;
00254 
00255     while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00256       float oldpt[3], newpt[3];
00257       if (draw) {
00258         newpt[0] = textpos[0] + textsize * x;
00259         newpt[1] = textpos[1] + textsize * y;
00260         newpt[2] = textpos[2];
00261 
00262         if (odraw) {
00263           // if we have both previous and next points, connect them...
00264           oldpt[0] = textpos[0] + textsize * ox;
00265           oldpt[1] = textpos[1] + textsize * oy;
00266           oldpt[2] = textpos[2];
00267 
00268           text_cylinders.append2x3(&oldpt[0], &newpt[0]);
00269           text_spheres.append3(&newpt[0]);
00270         } else {
00271           // ...otherwise, just draw the next point
00272           text_spheres.append3(&newpt[0]);
00273         }
00274       }
00275 
00276       ox=x;
00277       oy=y;
00278       odraw=draw;
00279     }
00280     textpos[0] += rm * textsize;
00281 
00282     str++;
00283   }
00284 
00285   add_material();
00286   // add spheres, which are already in world coordinates
00287   if (text_cylinders.num() > 0) {
00288     ort->cylinder_array(NULL, textthickness, matData[colorIndex],
00289                         text_cylinders.num() / 6, &text_cylinders[0],
00290                         materialIndex);
00291   }
00292   if (text_spheres.num() > 0) {
00293     ort->sphere_array(NULL, textthickness, matData[colorIndex],
00294                       text_spheres.num() / 3, &text_spheres[0], NULL, 
00295                       materialIndex);
00296   }
00297 }
00298 
00299 #endif
00300 
00301 
00302 void ANARIDisplayDevice::send_triangle_buffer() {
00303   if (triangle_vert_buffer.num() > 0) {
00304     ort->trimesh_n3f_v3f(*triangle_xform, 
00305                          matData[triangle_cindex],
00306                          &triangle_norm_buffer[0],
00307                          &triangle_vert_buffer[0],
00308                          triangle_vert_buffer.num()/9,
00309                          triangle_matindex);
00310     delete triangle_xform;
00311     triangle_xform=NULL;
00312   }
00313   reset_triangle_buffer();
00314 }
00315 
00316 
00317 // draw a triangle
00318 void ANARIDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00319   // if we have a change in transformation matrix, color, or material state,
00320   // we have to emit all accumulated triangles to ANARI and begin a new batch
00321   if (triangle_xform != NULL && ((triangle_cindex != colorIndex) || (triangle_matindex != materialIndex) || (memcmp(triangle_xform->mat, transMat.top().mat, sizeof(triangle_xform->mat))))) {
00322     send_triangle_buffer(); // render the accumulated triangle buffer...
00323   } 
00324 
00325   // record all transformation/material/color state on first triangle call
00326   if (triangle_xform == NULL) {
00327     // record material, color, and transformation state
00328     triangle_cindex = colorIndex;
00329     triangle_matindex = materialIndex;
00330     triangle_xform = new Matrix4(transMat.top());
00331     add_material(); // cause ANARI to cache the current material
00332   }
00333 
00334   // record vertex data 
00335   triangle_vert_buffer.append3x3(&a[0], &b[0], &c[0]);
00336 
00337   // record normal data 
00338   triangle_norm_buffer.append3x3(&n1[0], &n2[0], &n3[0]);
00339 }
00340 
00341 
00342 // draw a tricolor
00343 void ANARIDisplayDevice::tricolor(const float *a, const float *b, const float *c,
00344                       const float *n1, const float *n2, const float *n3,
00345                       const float *c1, const float *c2, const float *c3) {
00346   add_material();
00347 
00348   float vnc[27];
00349   vec_copy(&vnc[ 0], a);
00350   vec_copy(&vnc[ 3], b);
00351   vec_copy(&vnc[ 6], c);
00352 
00353   vec_copy(&vnc[ 9], n1);
00354   vec_copy(&vnc[12], n2);
00355   vec_copy(&vnc[15], n3);
00356 
00357   vec_copy(&vnc[18], c1);
00358   vec_copy(&vnc[21], c2);
00359   vec_copy(&vnc[24], c3);
00360 
00361   ort->tricolor_list(transMat.top(), 1, vnc, materialIndex);
00362 }
00363 
00364 
00365 void ANARIDisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, signed char *n,
00366                                              float *v, int numfacets) {
00367   add_material();
00368   ort->trimesh_c4u_n3b_v3f(transMat.top(), c, n, v, numfacets, materialIndex);
00369 }
00370 
00371 
00372 void ANARIDisplayDevice::trimesh_c4u_n3f_v3f(unsigned char *c, float *n,
00373                                              float *v, int numfacets) {
00374   add_material();
00375   ort->trimesh_c4u_n3f_v3f(transMat.top(), c, n, v, numfacets, materialIndex);
00376 }
00377 
00378 void ANARIDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00379                                              int numfacets, int * facets) {
00380   add_material();
00381   ort->trimesh_c4n3v3(transMat.top(), numverts, cnv, numfacets, facets, 
00382                       materialIndex);
00383 }
00384 
00385 void ANARIDisplayDevice::trimesh_n3b_v3f(signed char *n, float *v, int numfacets) {
00386   add_material();
00387   ort->trimesh_n3b_v3f(transMat.top(), matData[colorIndex], n, v, numfacets,  materialIndex);
00388 }
00389 
00390 void ANARIDisplayDevice::trimesh_n3f_v3f(float *n, float *v, int numfacets) {
00391   add_material();
00392   ort->trimesh_n3f_v3f(transMat.top(), matData[colorIndex], n, v, numfacets,  materialIndex);
00393 }
00394 
00395 
00396 #if 0
00397 void ANARIDisplayDevice::trimesh_n3fopt_v3f(float *n, float *v, int numfacets) {
00398   add_material();
00399   ort->trimesh_v3f(transMat.top(), matData[colorIndex], v, numfacets,  materialIndex);
00400 }
00401 
00402 #endif
00403 
00404 void ANARIDisplayDevice::tristrip(int numverts, const float * cnv,
00405                          int numstrips, const int *vertsperstrip,
00406                          const int *facets) {
00407   add_material();
00408   ort->tristrip(transMat.top(), numverts, cnv, numstrips, vertsperstrip, 
00409                 facets, materialIndex);
00410 }
00411 
00412 
00413 
00414 void ANARIDisplayDevice::write_lights() {
00415   int i;
00416   int lightcount = 0;
00417 
00418   // clear all existing lights before (re)appending the current lights,
00419   // otherwise if the ANARI context is reused, we will crash and burn.
00420   ort->clear_all_lights();
00421 
00422   // directional lights
00423   for (i=0; i<DISP_LIGHTS; i++) {
00424     if (lightState[i].on) {
00425       ort->add_directional_light(lightState[i].pos, lightState[i].color);
00426       lightcount++;
00427     }
00428   }
00429 
00430 #if 0
00431   // advanced positional lights
00432   for (i=0; i<DISP_LIGHTS; i++) {
00433     if (advLightState[i].on) {
00434       float pos[3];
00435 
00436       // always use world coordinates for now
00437       vec_copy(pos, advLightState[i].pos);
00438 
00439       if (advLightState[i].spoton) {
00440         printf("ANARIDisplayDevice) SpotLight not implemented yet ...\n");
00441       } else {
00442         apitexture tex;
00443         memset(&tex, 0, sizeof(apitexture));
00444 
00445         tex.col.r=advLightState[i].color[0];
00446         tex.col.g=advLightState[i].color[1];
00447         tex.col.b=advLightState[i].color[2];
00448 
00449         void *l = rt_light(rtscene,
00450                            rt_texture(rtscene, &tex),
00451                            /* negate position to correct handedness... */
00452                            rt_vector(pos[0], pos[1], -pos[2]), 0.0f);
00453 
00454         /* emit light attentuation parameters if needed */
00455         if (advLightState[i].constfactor != 1.0f ||
00456             advLightState[i].linearfactor != 0.0f ||
00457             advLightState[i].quadfactor != 0.0f) {
00458           rt_light_attenuation(l,
00459                                advLightState[i].constfactor,
00460                                advLightState[i].linearfactor,
00461                                advLightState[i].quadfactor);
00462         }
00463       }
00464 
00465       lightcount++;
00466     }
00467   }
00468 #endif
00469 
00470   if (lightcount < 1) {
00471     msgWarn << "No lights defined in molecular scene!!" << sendmsg;
00472   }
00473 }
00474 
00475 
00476 void ANARIDisplayDevice::write_materials() {
00477   ort->set_bg_color(backColor);
00478 
00479   // Specify ANARI background sky sphere if background gradient
00480   // mode is enabled.
00481   if (backgroundmode == 1) {
00482     float bspheremag = 0.5f;
00483 
00484     // compute positive/negative magnitude of sphere gradient
00485     switch (projection()) {
00486       case DisplayDevice::ORTHOGRAPHIC:
00487         // For orthographic views, Tachyon uses the dot product between
00488         // the incident ray origin and the sky sphere gradient "up" vector,
00489         // since all camera rays have the same direction and differ only
00490         // in their origin.
00491         bspheremag = vSize / 4.0f;
00492         break;
00493 
00494       case DisplayDevice::PERSPECTIVE:
00495       default:
00496         // For perspective views, Tachyon uses the dot product between
00497         // the incident ray and the sky sphere gradient "up" vector,
00498         // so for larger values of vSize, we have to clamp the maximum
00499         // magnitude to 1.0.
00500         bspheremag = (vSize / 2.0f) / (eyePos[2] - zDist);
00501         if (bspheremag > 1.0f)
00502           bspheremag = 1.0f;
00503         break;
00504     }
00505 
00506     if (projection() == DisplayDevice::ORTHOGRAPHIC)
00507       ort->set_bg_mode(ANARIRender::RT_BACKGROUND_TEXTURE_SKY_ORTHO_PLANE);
00508     else
00509       ort->set_bg_mode(ANARIRender::RT_BACKGROUND_TEXTURE_SKY_SPHERE);
00510 
00511     float updir[3] = { 0.0f, 1.0f, 0.0f };
00512     ort->set_bg_color_grad_top(backgradienttopcolor);
00513     ort->set_bg_color_grad_bot(backgradientbotcolor);
00514     ort->set_bg_gradient(updir);
00515     ort->set_bg_gradient_topval(bspheremag);
00516     ort->set_bg_gradient_botval(-bspheremag);
00517   } else {
00518     ort->set_bg_mode(ANARIRender::RT_BACKGROUND_TEXTURE_SOLID);
00519   }
00520 }
00521 
00522 
00524 
00525 void ANARIDisplayDevice::write_header() {
00526   wkf_timer_start(ort_timer);
00527 
00528   ort->setup_context(xSize, ySize);
00529   write_materials();
00530   write_lights();
00531 
00532   ort->set_aa_samples(aasamples); // set with current FileRenderer values
00533 
00534   // render with/without shadows
00535   if (shadows_enabled() || ao_enabled()) {
00536     if (shadows_enabled() && !ao_enabled())
00537       msgInfo << "Shadow rendering enabled." << sendmsg;
00538 
00539     ort->shadows_on(1); // shadowing mode required
00540   } else {
00541     ort->shadows_on(0); // disable shadows by default
00542   }
00543 
00544   // render with ambient occlusion, but only if shadows are also enabled
00545   if (ao_enabled()) {
00546     msgInfo << "Ambient occlusion enabled." << sendmsg;
00547     msgInfo << "Shadow rendering enabled." << sendmsg;
00548     ort->set_ao_samples(aosamples); // set with current FileRenderer values
00549   } else {
00550     ort->set_ao_samples(0); // disable AO rendering entirely
00551   }
00552 
00553   // Always set the AO parameters, that way the user can enable/disable
00554   // AO on-the-fly in the interactive renderer
00555   ort->set_ao_ambient(get_ao_ambient());
00556   ort->set_ao_direct(get_ao_direct());
00557 
00558   // render with depth of field, but only for perspective projection
00559   if (dof_enabled()) {
00560     msgInfo << "DoF focal blur enabled." << sendmsg;
00561     ort->dof_on(1); // enable DoF rendering
00562     ort->set_camera_dof_fnumber(get_dof_fnumber());
00563     ort->set_camera_dof_focal_dist(get_dof_focal_dist());
00564   } else {
00565     ort->dof_on(0); // disable DoF rendering
00566   }
00567 
00568   // set depth cueing parameters
00569   float start = get_cue_start();
00570   float end = get_cue_end();
00571   float density = get_cue_density();
00572   if (cueingEnabled) {
00573     switch (cueMode) {
00574       case CUE_LINEAR:
00575         ort->set_cue_mode(ANARIRender::RT_FOG_LINEAR, start, end, density);
00576         break;
00577 
00578       case CUE_EXP:
00579         ort->set_cue_mode(ANARIRender::RT_FOG_EXP, start, end, density);
00580         break;
00581 
00582       case CUE_EXP2:
00583         ort->set_cue_mode(ANARIRender::RT_FOG_EXP2, start, end, density);
00584         break;
00585 
00586       case NUM_CUE_MODES:
00587         // this should never happen
00588         break;
00589     }
00590   } else {
00591     ort->set_cue_mode(ANARIRender::RT_FOG_NONE, start, end, density);
00592   }
00593 }
00594 
00595 
00596 void ANARIDisplayDevice::write_trailer(void){
00597 //  send_cylinder_buffer(); // send any unsent accumulated cylinder buffer...
00598   send_triangle_buffer(); // send any unsent accumulated triangle buffer...
00599 
00600 #if 0
00601   printf("ANARI: z: %f zDist: %f vSize %f\n", eyePos[2], zDist, vSize);
00602 #endif
00603   switch (projection()) {
00604     case DisplayDevice::ORTHOGRAPHIC:
00605       ort->set_camera_projection(ANARIRender::RT_ORTHOGRAPHIC);
00606       ort->set_camera_zoom(0.5f / (1.0 / (vSize / 2.0)));
00607       break;
00608 
00609     case DisplayDevice::PERSPECTIVE:
00610     default:
00611       ort->set_camera_projection(ANARIRender::RT_PERSPECTIVE);
00612       // ort->set_camera_zoom(0.5f / ((eyePos[2] - zDist) / vSize));
00613       ort->set_camera_zoom(0.5f * vSize / (eyePos[2] - zDist));
00614   }
00615 
00616   // set stereoscopic display parameters
00617   ort->set_camera_stereo_eyesep(eyeSep);
00618   ort->set_camera_stereo_convergence_dist(eyeDist);
00619 
00620   char *verbstr = getenv("VMDANARIVERBOSE");
00621   if (verbstr != NULL) {
00622     if (!strupcmp(verbstr, "TIMING") || !strupcmp(verbstr, "DEBUG")) {
00623       double time_scene_graph = wkf_timer_timenow(ort_timer);
00624       printf("ANARIDisplayDevice) scene graph construction time %.2f\n",
00625              time_scene_graph);
00626     }
00627   }
00628 
00629 #if defined(VMDANARI_INTERACTIVE_OPENGL)
00630   if (isinteractive)
00631     ort->render_to_glwin(my_filename); // interactive progressive ray tracer
00632   else
00633 #endif
00634     ort->render_to_file(my_filename);  // render the scene in batch mode...
00635 
00636   reset_vars(); 
00637 
00638   if (getenv("VMDANARINODESTROYCONTEXT") == NULL) {
00639     // destroy the current context, because we haven't done enough to ensure
00640     // that we're managing memory well without tearing it all down.
00641     delete ort;
00642 
00643     // make a new ANARIRender object so we're ready for the next run...
00644     ort = new ANARIRender();
00645   } else {
00646     // reset internal state between renders
00647     // reinitialize material cache, clean context state
00648     ort->destroy_scene();
00649   }
00650 
00651   wkf_timer_stop(ort_timer);
00652   printf("ANARIDisplayDevice) Total rendering time: %.2f sec\n", wkf_timer_time(ort_timer));
00653 }
00654 
00655 
00656 
00657 
00658 

Generated on Fri Nov 8 02:43:50 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002