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

OSPRayRenderer.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: OSPRayRenderer.C,v $
00013 *      $Author: johns $      $Locker:  $               $State: Exp $
00014 *      $Revision: 1.92 $         $Date: 2021/12/21 06:44:17 $
00015 *
00016 ***************************************************************************/
00038 #include <math.h>
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 #include <string.h>
00042 
00043 #if defined(__linux)
00044 #include <unistd.h>   // needed for symlink() in movie recorder
00045 #endif
00046 
00047 #include "Inform.h"
00048 #include "ImageIO.h"
00049 #include "OSPRayRenderer.h"
00050 // #include "OSPRayShaders.ih" /// ISPC code at some point?
00051 #include "Matrix4.h"
00052 #include "utilities.h"
00053 #include "WKFUtils.h"
00054 
00055 #if !(OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 2)
00056 #error VMD requires OSPRay >= 1.2.0 for correct transparent AO shading
00057 // VMD requires OSPRay >= 1.1.2 for correct rendering of cylinders
00058 #endif
00059 
00060 // enable the interactive ray tracing capability
00061 #if defined(VMDOSPRAY_INTERACTIVE_OPENGL)
00062 #if (defined(WIN32) || defined(_WIN64)) && defined(_MSC_VER)
00063 #include <windows.h> // must include windows.h prior to GL 
00064 #endif
00065 
00066 #include <GL/gl.h>
00067 #endif
00068 
00069 #if 1
00070 #define DBG() 
00071 #else
00072 #define DBG() printf("OSPRayRenderer) %s\n", __func__);
00073 #endif
00074 
00075 static void vmd_ospray_error_callback(OSPError err, const char *detailstr) {
00076   printf("OSPRayRenderer) ERROR: '%s'\n", detailstr);
00077 }
00078 
00079 static void vmd_ospray_status_callback(const char *detailstr) {
00080   printf("OSPRayRenderer) STATUS: %s\n", detailstr);
00081 }
00082 
00083 
00084 
00085 // Global OSPRay initialization routine -- call it only ONCE...
00086 int OSPRayRenderer::OSPRay_Global_Init(void) {
00087   DBG();
00088 
00089   // initialize OSPRay itself
00090   const char *ospraynormalargs[] = {"vmd", "--osp:mpi"};
00091   const char *ospraydebugargs[] = {"vmd", "--osp:debug", "--osp:mpi"};
00092   const char **osprayargs = ospraynormalargs; 
00093   int argcount = 1;
00094 
00095   if (getenv("VMDOSPRAYDEBUG") != NULL) {
00096     osprayargs = ospraydebugargs;
00097     argcount=2;    
00098   }
00099 
00100   // only pass in the second "--osp:mpi" flag if the user has
00101   // requested that the MPI renderer back-end be enabled through
00102   // environment variable flags
00103   if (getenv("VMDOSPRAYMPI") || getenv("VMD_OSPRAY_MPI")) {
00104     msgInfo << "OSPRayRenderer) Initializing OSPRay in MPI mode" << sendmsg;
00105     argcount++;
00106   }
00107 
00108   OSPError osprc = ospInit(&argcount, osprayargs);
00109 
00110   if (osprc != OSP_NO_ERROR)
00111     return -1; // return indication of failure
00112 
00113   return 0;  
00114 }
00115 
00116 
00117 // Global OSPRay initialization routine -- call it only ONCE...
00118 void OSPRayRenderer::OSPRay_Global_Shutdown(void) {
00119   ospShutdown();
00120 }
00121 
00123 OSPRayRenderer::OSPRayRenderer(void) {
00124   DBG();
00125 
00126   osp_timer = wkf_timer_create(); // create and initialize timer
00127   wkf_timer_start(osp_timer);
00128 
00129   // set OSPRay state handles/variables to NULL
00130   ospRenderer = NULL;
00131   ospFrameBuffer = NULL;
00132   ospCamera = NULL;
00133   ospModel = NULL;
00134   ospLightData = NULL;
00135 
00136   lasterror = 0;               // begin with no error state set
00137   context_created = 0;         // no context yet
00138   buffers_allocated = 0;       // flag no buffer allocated yet
00139   scene_created = 0;           // scene has been created
00140 
00141   destroy_scene();             // clear/init geometry vectors
00142 
00143   // clear timers
00144   time_ctx_create = 0.0;
00145   time_ctx_setup = 0.0;
00146   time_ctx_validate = 0.0;
00147   time_ctx_AS_build = 0.0;
00148   time_ray_tracing = 0.0;
00149   time_image_io = 0.0;
00150 
00151   // set default scene background state
00152   scene_background_mode = RT_BACKGROUND_TEXTURE_SOLID;
00153   memset(scene_bg_color, 0, sizeof(scene_bg_color));
00154   memset(scene_bg_grad_top, 0, sizeof(scene_bg_grad_top));
00155   memset(scene_bg_grad_bot, 0, sizeof(scene_bg_grad_bot));
00156   memset(scene_gradient, 0, sizeof(scene_gradient));
00157   scene_gradient_topval = 1.0f;
00158   scene_gradient_botval = 0.0f;
00159   // XXX this has to be recomputed prior to rendering..
00160   scene_gradient_invrange = 1.0f / (scene_gradient_topval - scene_gradient_botval);
00161 
00162   cam_zoom = 1.0f;
00163   cam_stereo_eyesep = 0.06f;
00164   cam_stereo_convergence_dist = 2.0f;
00165 
00166   headlight_enabled = 0;     // VR HMD headlight disabled by default
00167 
00168   shadows_enabled = RT_SHADOWS_OFF; // disable shadows by default 
00169   aa_samples = 0;            // no AA samples by default
00170 
00171   ao_samples = 0;            // no AO samples by default
00172   ao_direct = 0.3f;          // AO direct contribution is 30%
00173   ao_ambient = 0.7f;         // AO ambient contribution is 70%
00174 
00175   dof_enabled = 0;           // disable DoF by default
00176   cam_dof_focal_dist = 2.0f;
00177   cam_dof_fnumber = 64.0f;
00178 
00179   fog_mode = RT_FOG_NONE;    // fog/cueing disabled by default
00180   fog_start = 0.0f;
00181   fog_end = 10.0f;
00182   fog_density = 0.32f;
00183 
00184   verbose = RT_VERB_MIN;  // keep console quiet except for perf/debugging cases
00185   check_verbose_env();    // see if the user has overridden verbose flag
00186 
00187   // clear all primitive lists
00188   trimesh_v3f_n3f_c3f.clear();
00189   spheres.clear();
00190   spheres_color.clear();
00191   cylinders_color.clear();
00192 
00193   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating context...\n");
00194 
00195   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) setting error / status callbacks...\n");
00196   OSPDevice dev = ospGetCurrentDevice();
00197   ospDeviceSetErrorFunc(dev, vmd_ospray_error_callback);
00198   ospDeviceSetStatusFunc(dev, vmd_ospray_status_callback);
00199   int loglevel = 0;
00200 //  loglevel = 2;
00201   ospDeviceSet1i(dev, "logLevel", loglevel);
00202   ospDeviceCommit(dev);
00203 
00204   double starttime = wkf_timer_timenow(osp_timer);
00205 
00206   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating context...\n");
00207 
00208   //
00209   // create the main renderer object needed early on for 
00210   // instantiation of materials, lights, etc.
00211   // 
00212   if ((ospRenderer = ospNewRenderer("scivis")) == NULL) {
00213     printf("OSPRayRenderer) Failed to load OSPRay renderer 'scivis'!\n");
00214   }
00215 
00216   // load and initialize all of the materials
00217   init_materials();
00218 
00219   time_ctx_create = wkf_timer_timenow(osp_timer) - starttime;
00220   
00221   if (verbose == RT_VERB_TIMING || verbose == RT_VERB_DEBUG) {
00222     printf("OSPRayRenderer) context creation time: %.2f\n", time_ctx_create);
00223   }
00224 
00225   context_created = 1;
00226 }
00227 
00228         
00230 OSPRayRenderer::~OSPRayRenderer(void) {
00231   DBG();
00232 
00233   int lcnt = ospLights.size();
00234   for (int i = 0; i < lcnt; ++i) {
00235     ospRelease(ospLights[i]);
00236   }
00237   ospLights.clear();
00238 
00239   framebuffer_destroy();
00240 
00241   if (context_created && (ospRenderer != NULL))
00242     ospRelease(ospRenderer);
00243 
00244   if (context_created && (ospModel != NULL))
00245     ospRelease(ospModel);
00246 
00247   wkf_timer_destroy(osp_timer);
00248 }
00249 
00250 
00251 void OSPRayRenderer::check_verbose_env() {
00252   DBG();
00253 
00254   char *verbstr = getenv("VMDOSPRAYVERBOSE");
00255   if (verbstr != NULL) {
00256 //    printf("OSPRayRenderer) verbosity config request: '%s'\n", verbstr);
00257     if (!strupcmp(verbstr, "MIN")) {
00258       verbose = RT_VERB_MIN;
00259       printf("OSPRayRenderer) verbose setting: minimum\n");
00260     } else if (!strupcmp(verbstr, "TIMING")) {
00261       verbose = RT_VERB_TIMING;
00262       printf("OSPRayRenderer) verbose setting: timing data\n");
00263     } else if (!strupcmp(verbstr, "DEBUG")) {
00264       verbose = RT_VERB_DEBUG;
00265       printf("OSPRayRenderer) verbose setting: full debugging data\n");
00266     }
00267   }
00268 }
00269 
00270 
00271 void OSPRayRenderer::setup_context(int w, int h) {
00272   DBG();
00273   double starttime = wkf_timer_timenow(osp_timer);
00274   time_ctx_setup = 0;
00275 
00276   lasterror = 0; /* XXX SUCCESS; */ // clear any error state
00277   width = w;
00278   height = h;
00279 
00280   if (!context_created)
00281     return;
00282 
00283   check_verbose_env(); // update verbose flag if changed since last run
00284 
00285   if (getenv("VMDOSPRAYMAXDEPTH")) {
00286     int maxdepth = atoi(getenv("VMDOSPRAYMAXDEPTH"));
00287     if (maxdepth > 0 && maxdepth <= 20) {
00288       printf("OSPRayRenderer) Setting maxdepth to %d...\n", maxdepth);
00289       ospSet1i(ospRenderer, "maxDepth", maxdepth);  
00290     } else {
00291       printf("OSPRayRenderer) ignoring out-of-range maxdepth: %d...\n", maxdepth);
00292     }
00293   } else {
00294     ospSet1i(ospRenderer, "maxDepth", 20);  
00295   }
00296 
00297   float scene_epsilon = 5.e-5f;
00298   if (getenv("VMDOSPRAYSCENEEPSILON") != NULL) {
00299     scene_epsilon = float(atof(getenv("VMDOSPRAYSCENEEPSILON")));
00300     printf("OSPRayRenderer) user override of scene epsilon: %g\n", scene_epsilon);
00301   }
00302   ospSet1f(ospRenderer, "epsilon", scene_epsilon);
00303 
00304   // Implore OSPRay to correctly handle lighting through transparent 
00305   // surfaces when AO is enabled
00306   ospSet1i(ospRenderer, "aoTransparencyEnabled", 1);
00307 
00308   // Current accumulation subframe count, used as part of generating
00309   // AA and AO random number sequences
00310   // XXX set OSPRay accum count
00311 
00312   time_ctx_setup = wkf_timer_timenow(osp_timer) - starttime;
00313 }
00314 
00315 
00316 void OSPRayRenderer::destroy_scene() {
00317   DBG();
00318 
00319   double starttime = wkf_timer_timenow(osp_timer);
00320   time_ctx_destroy_scene = 0;
00321 
00322   // zero out all object counters
00323   cylinder_array_cnt = 0;
00324   cylinder_array_color_cnt = 0;
00325   ring_array_color_cnt = 0;
00326   sphere_array_cnt = 0;
00327   sphere_array_color_cnt = 0;
00328   tricolor_cnt = 0;
00329   trimesh_c4u_n3b_v3f_cnt = 0;
00330   trimesh_n3b_v3f_cnt = 0;
00331   trimesh_n3f_v3f_cnt = 0;
00332   trimesh_v3f_cnt = 0;
00333 
00334   // clear lists of primitives
00335   trimesh_v3f_n3f_c3f.clear();
00336   spheres.clear();
00337   spheres_color.clear();
00338   cylinders_color.clear();
00339 
00340   int i;
00341   for (i=0; i<materialcache.num(); i++) {
00342     ospRelease(materialcache[i].mat);
00343   }
00344   materialcache.clear();
00345 
00346   int lcnt = ospLights.size();
00347   for (i = 0; i < lcnt; ++i) {
00348     ospRelease(ospLights[i]);
00349   }
00350   ospLights.clear();
00351 
00352   ospRelease(ospCamera);
00353   ospCamera = NULL;
00354 
00355   double endtime = wkf_timer_timenow(osp_timer);
00356   time_ctx_destroy_scene = endtime - starttime;
00357 
00358   scene_created = 0; // scene has been destroyed
00359 }
00360 
00361 
00362 void OSPRayRenderer::update_rendering_state(int interactive) {
00363   DBG();
00364   if (!context_created)
00365     return;
00366 
00367   wkf_timer_start(osp_timer);
00368 
00369   // Set interactive/progressive rendering flag so that we wire up
00370   // the most appropriate renderer for the task.  For batch rendering
00371   // with AO, we would choose the largest possible sample batch size,
00372   // but for interactive we will always choose a batch size of 1 or maybe 2
00373   // to yield the best interactivity.
00374   interactive_renderer = interactive;
00375 
00376   // XXX set OSPRay rendering state
00377 
00378   long totaltris = tricolor_cnt + trimesh_c4u_n3b_v3f_cnt + 
00379                    trimesh_n3b_v3f_cnt + trimesh_n3f_v3f_cnt + trimesh_v3f_cnt;
00380 
00381   if (verbose == RT_VERB_TIMING || verbose == RT_VERB_DEBUG) {
00382     printf("OSPRayRenderer) cyl %ld, ring %ld, sph %ld, tri %ld, tot: %ld  lt %ld\n",
00383            cylinder_array_cnt + cylinder_array_color_cnt,
00384            ring_array_color_cnt,
00385            sphere_array_cnt + sphere_array_color_cnt,
00386            totaltris,
00387            cylinder_array_cnt +  cylinder_array_color_cnt + ring_array_color_cnt + sphere_array_cnt + sphere_array_color_cnt + totaltris,
00388            directional_lights.num() + positional_lights.num());
00389   }
00390 
00391   if (verbose == RT_VERB_DEBUG) {
00392     printf("OSPRayRenderer) using fully general shader and materials.\n");
00393   }
00394 
00395   // XXX set OSPRay background color
00396 
00397   if (verbose == RT_VERB_DEBUG) {
00398     printf("OSPRayRenderer) scene bg mode: %d\n", scene_background_mode);
00399 
00400     printf("OSPRayRenderer) scene bgsolid: %.2f %.2f %.2f\n", 
00401            scene_bg_color[0], scene_bg_color[1], scene_bg_color[2]);
00402 
00403     printf("OSPRayRenderer) scene bggradT: %.2f %.2f %.2f\n", 
00404            scene_bg_grad_top[0], scene_bg_grad_top[1], scene_bg_grad_top[2]);
00405 
00406     printf("OSPRayRenderer) scene bggradB: %.2f %.2f %.2f\n", 
00407            scene_bg_grad_bot[0], scene_bg_grad_bot[1], scene_bg_grad_bot[2]);
00408   
00409     printf("OSPRayRenderer) bg gradient: %f %f %f  top: %f  bot: %f\n",
00410            scene_gradient[0], scene_gradient[1], scene_gradient[2],
00411            scene_gradient_topval, scene_gradient_botval);
00412   }
00413 
00414   // update in case the caller changed top/bottom values since last recalc
00415   scene_gradient_invrange = 1.0f / (scene_gradient_topval - scene_gradient_botval);
00416   // XXX set OSPRay background gradient
00417 
00418   // XXX set OSPRay fog mode
00419 
00420   if (verbose == RT_VERB_DEBUG) {
00421     printf("OSPRayRenderer) adding lights: dir: %ld  pos: %ld\n", 
00422            directional_lights.num(), positional_lights.num());
00423   }
00424 
00425   // XXX set OSPRay lights
00426 
00427   if (verbose == RT_VERB_DEBUG) 
00428     printf("OSPRayRenderer) Finalizing OSPRay scene graph...\n");
00429 
00430   // create group to hold instances
00431 
00432   // XXX we should create an acceleration object the instance shared
00433   //     by multiple PBC images
00434 
00435 
00436   // XXX OSPRay AS builder initialization if there's any customization...
00437  
00438 
00439   // do final state variable updates before rendering begins
00440   if (verbose == RT_VERB_DEBUG) {
00441     printf("OSPRayRenderer) cam zoom factor %f\n", cam_zoom);
00442     printf("OSPRayRenderer) cam stereo eye separation  %f\n", cam_stereo_eyesep);
00443     printf("OSPRayRenderer) cam stereo convergence distance %f\n", 
00444            cam_stereo_convergence_dist);
00445     printf("OSPRayRenderer) cam DoF focal distance %f\n", cam_dof_focal_dist);
00446     printf("OSPRayRenderer) cam DoF f/stop %f\n", cam_dof_fnumber);
00447   }
00448 
00449   // define all of the standard camera params
00450   // XXX set OSPRay camera state
00451 
00452   // define stereoscopic camera parameters
00453   // XXX set OSPRay camera state
00454 
00455   // define camera DoF parameters
00456   // XXX set OSPRay camera state
00457 
00458   // XXX set OSPRay AO sample counts and light scaling factors
00459 
00460   if (verbose == RT_VERB_DEBUG) {
00461     printf("OSPRayRenderer) setting sample counts:  AA %d  AO %d\n", aa_samples, ao_samples);
00462     printf("OSPRayRenderer) setting AO factors:  AOA %f  AOD %f\n", ao_ambient, ao_direct);
00463   }
00464 
00465   //
00466   // Handle AA samples either internally with loops internal to 
00467   // each ray launch point thread, or externally by iterating over
00468   // multiple launches, adding each sample to an accumulation buffer,
00469   // or a hybrid combination of the two.  
00470   //
00471 #if 1
00472   ext_aa_loops = 1;
00473 #else
00474   ext_aa_loops = 1;
00475   if (ao_samples > 0 || (aa_samples > 4)) {
00476     // if we have too much work for a single-pass rendering, we need to 
00477     // break it up into multiple passes of the right counts in each pass
00478     ext_aa_loops = 1 + aa_samples;
00479     // XXX set OSPRay sample counts per launch...
00480   } else { 
00481     // if the scene is simple, e.g. no AO rays and AA sample count is small,
00482     // we can run it in a single pass and get better performance
00483     // XXX set OSPRay sample counts per launch...
00484   }
00485   // XXX set OSPRay accum buf normalization scaling factors
00486 #endif
00487 
00488   if (verbose == RT_VERB_DEBUG) {
00489     if (ext_aa_loops > 1)
00490       printf("OSPRayRenderer) Running OSPRay multi-pass: %d loops\n", ext_aa_loops);
00491     else
00492       printf("OSPRayRenderer) Running OSPRay single-pass: %d total samples\n", 1+aa_samples);
00493   }
00494 
00495   // set the ray generation program to the active camera code...
00496   // XXX set OSPRay camera mode and clear accum buf
00497   // set the active color accumulation ray gen program based on the 
00498   // camera/projection mode, stereoscopic display mode, 
00499   // and depth-of-field state
00500   // XXX set OSPRay camera mode and accum buf mode
00501   // XXX set OSPRay "miss" shading mode (solid or gradient)
00502 }
00503 
00504 
00505 void OSPRayRenderer::framebuffer_config(int fbwidth, int fbheight) {
00506   if (!context_created)
00507     return;
00508 
00509   width = fbwidth;
00510   height = fbheight;
00511 
00512   // allocate and resize buffers to match request
00513   if (buffers_allocated) {
00514     // if the buffers already exist and match the current 
00515     // progressive/non-progressive rendering mode, just resize them
00516     if (verbose == RT_VERB_DEBUG) {
00517       printf("OSPRayRenderer) resizing framebuffer\n");
00518     }
00519     framebuffer_resize(width, height);
00520   } else {
00521     // (re)allocate framebuffer and associated accumulation buffers if they
00522     // don't already exist or if they weren't bound properly for
00523     // current progressive/non-progressive rendering needs.
00524     if (verbose == RT_VERB_DEBUG) {
00525       printf("OSPRayRenderer) creating framebuffer and accum. buffer\n");
00526     }
00527 
00528     // create intermediate output and accumulation buffers
00529     osp::vec2i fbsize = { width, height };   
00530     ospFrameBuffer = ospNewFrameBuffer(fbsize, OSP_FB_RGBA8, OSP_FB_COLOR | OSP_FB_ACCUM);
00531     ospFrameBufferClear(ospFrameBuffer, OSP_FB_COLOR | /* OSP_FB_DEPTH | */ OSP_FB_ACCUM);
00532 
00533     buffers_allocated = 1;
00534   }
00535 }
00536 
00537 
00538 void OSPRayRenderer::framebuffer_resize(int fbwidth, int fbheight) {
00539   if (!context_created)
00540     return;
00541 
00542   width = fbwidth;
00543   height = fbheight;
00544 
00545   if (buffers_allocated) {
00546     if (verbose == RT_VERB_DEBUG) 
00547       printf("OSPRayRenderer) framebuffer_resize(%d x %d)\n", width, height);
00548     framebuffer_destroy();
00549   }
00550 
00551   osp::vec2i fbsize = { width, height };   
00552   ospFrameBuffer = ospNewFrameBuffer(fbsize, OSP_FB_RGBA8, OSP_FB_COLOR | OSP_FB_ACCUM);
00553 
00554   ospFrameBufferClear(ospFrameBuffer, OSP_FB_COLOR | /* OSP_FB_DEPTH | */ OSP_FB_ACCUM);
00555   buffers_allocated = 1;
00556 }
00557 
00558 
00559 void OSPRayRenderer::framebuffer_destroy() {
00560   if (!context_created)
00561     return;
00562 
00563   if (buffers_allocated) {
00564     if (ospFrameBuffer)
00565 #if OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 6
00566       ospRelease(ospFrameBuffer);
00567 #else
00568       ospFreeFrameBuffer(ospFrameBuffer);
00569 #endif
00570   }
00571   buffers_allocated = 0;
00572 }
00573 
00574 
00575 void OSPRayRenderer::render_compile_and_validate(void) {
00576   int i;
00577 
00578   DBG();
00579   if (!context_created)
00580     return;
00581 
00582   //
00583   // finalize context validation, compilation, and AS generation 
00584   //
00585   double startctxtime = wkf_timer_timenow(osp_timer);
00586 
00587   // XXX any last OSPRay state updates/checks
00588 
00589   if ((ospModel = ospNewModel()) == NULL) {
00590     printf("OSPRayRenderer) Failed to create new model!\n");
00591   }
00592 
00593 
00594   //
00595   // commit sphere geometry
00596   //
00597   if (spheres.size() > 0) {
00598     OSPData data = ospNewData(5 * spheres.size(), OSP_FLOAT, &spheres[0]);
00599     OSPGeometry sphere_geom = ospNewGeometry("spheres");
00600     ospSet1i(sphere_geom, "bytes_per_sphere", sizeof(Sphere));
00601     ospSet1i(sphere_geom, "offset_center", 0);
00602     ospSet1i(sphere_geom, "offset_radius", sizeof(vec3));
00603     ospSet1i(sphere_geom, "offset_materialID", sizeof(vec3) + sizeof(float));
00604     ospSetData(sphere_geom, "spheres", data);
00605     ospCommit(sphere_geom);
00606     ospAddGeometry(ospModel, sphere_geom);
00607     ospRelease(data);
00608     ospRelease(sphere_geom);
00609   }
00610  
00611   if (verbose == RT_VERB_DEBUG)
00612     printf("OSPRayReenderer) num spheres = %ld\n", spheres.size());
00613 
00614 
00615   // 
00616   // Set camera parms
00617   // 
00618   float cam_pos_orig[3] = {0.0f, 0.0f, 2.0f};
00619   float cam_U_orig[3] = {1.0f, 0.0f, 0.0f};
00620   float cam_V_orig[3] = {0.0f, 1.0f, 0.0f};
00621   float cam_W_orig[3] = {0.0f, 0.0f, -1.0f};
00622 
00623   float cam_pos[3], cam_U[3], cam_V[3], cam_W[3];
00624   vec_copy(cam_pos, cam_pos_orig);
00625   vec_copy(cam_U, cam_U_orig);
00626   vec_copy(cam_V, cam_V_orig);
00627   vec_copy(cam_W, cam_W_orig);
00628 
00629   if (camera_projection == OSPRayRenderer::RT_ORTHOGRAPHIC) {
00630     if(!ospCamera) ospCamera = ospNewCamera("orthographic");
00631  
00632     ospSet1f(ospCamera, "aspect", width / ((float) height));
00633     float orthoheight = 2.0f * cam_zoom;
00634     ospSet1f(ospCamera, "height", orthoheight);
00635 
00636     if (dof_enabled) {
00637       msgWarn << "OSPRayRenderer) DoF not implemented for orthographic camera!" << sendmsg;
00638     }
00639   } else {
00640     if(!ospCamera) ospCamera = ospNewCamera("perspective");
00641 
00642     ospSet1f(ospCamera, "aspect", width / ((float) height));
00643     ospSet1f(ospCamera, "fovy", 2.0f*180.0f*(atanf(cam_zoom)/float(VMD_PI)));
00644 
00645     if (dof_enabled) {
00646       ospSet1f(ospCamera, "focusDistance", cam_dof_focal_dist);
00647       ospSet1f(ospCamera, "apertureRadius", cam_dof_focal_dist / (2.0f * cam_zoom * cam_dof_fnumber));
00648     } else {
00649       ospSet1f(ospCamera, "apertureRadius", 0.0f);
00650     }
00651   }
00652 
00653   if (ospCamera) {
00654     ospSet3fv(ospCamera, "pos", cam_pos);
00655     ospSet3fv(ospCamera, "dir",   cam_W);
00656     ospSet3fv(ospCamera,  "up",   cam_V);
00657     ospCommit(ospCamera);
00658     //  ospSet1f(ospCamera, "nearClip", 0.5f);
00659     //  ospSet1f(ospCamera, "far", 10.0f);
00660   }
00661 
00662   // 
00663   // Set framebuffer 
00664   // 
00665   framebuffer_config(width, height);
00666 
00667   //
00668   // Set all lights
00669   //
00670 
00671   // The direct lighting scaling factor all of the other lights.
00672   float lightscale = 1.0f;
00673   if (ao_samples != 0)
00674     lightscale = ao_direct;
00675 
00676   for (i = 0; i < directional_lights.num(); ++i) {
00677 #if OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 7
00678     OSPLight light = ospNewLight3("distant");
00679 #elif OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 6
00680     OSPLight light = ospNewLight2("scivis", "distant");
00681 #elif 1
00682     OSPLight light = ospNewLight(ospRenderer, "distant");
00683 #else
00684     OSPLight light = ospNewLight(ospRenderer, "DirectionalLight");
00685 #endif
00686 
00687     // The direct lighting scaling factor is applied to the lights here.
00688     ospSet1f(light, "intensity", lightscale);
00689     ospSet3fv(light, "color", directional_lights[i].color);
00690 
00691     float lightDir[3];
00692     vec_copy(lightDir, directional_lights[i].dir);
00693     vec_normalize(lightDir); // just for good measure
00694 
00695     // OSPRay uses a light direction vector opposite to VMD and Tachyon 
00696     ospSet3f(light, "direction", -lightDir[0], -lightDir[1], -lightDir[2]);
00697 
00698     ospCommit(light);
00699     ospLights.push_back(light);
00700   }
00701 
00702   // AO scaling factor is applied to a special ambient light.
00703   if (ao_samples != 0) {
00704 #if OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 7
00705     OSPLight light = ospNewLight3("ambient");
00706 #elif OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 6
00707     OSPLight light = ospNewLight2("scivis", "ambient");
00708 #else
00709     OSPLight light = ospNewLight(ospRenderer, "ambient");
00710 #endif
00711 
00712     // AO scaling factor is applied to the special ambient light
00713     ospSet1f(light, "intensity", ao_ambient);
00714     ospSet3f(light, "color", 1.0f, 1.0f, 1.0f);
00715 
00716     ospCommit(light);
00717     ospLights.push_back(light); // add AO ambient light
00718   } 
00719 
00720   // 
00721   // update renderer state
00722   //
00723   if (ao_samples && interactive_renderer) {
00724     ospSet1i(ospRenderer, "aoSamples", 1);
00725     ospSet1i(ospRenderer, "spp", 1);
00726   } else {
00727     ospSet1i(ospRenderer, "spp", aa_samples);
00728     ospSet1i(ospRenderer, "aoSamples", ao_samples);
00729   }
00730 
00731   if (getenv("VMDOSPRAYAOMAXDIST")) {
00732     float tmp = float(atof(getenv("VMDOSPRAYAOMAXDIST")));
00733     if (verbose == RT_VERB_DEBUG) {
00734       printf("OSPRayRenderer) setting AO maxdist: %f\n", tmp);
00735     }
00736     ospSet1f(ospRenderer, "aoOcclusionDistance", tmp);
00737   }
00738 
00739   float scene_epsilon = 5.e-5f;
00740   if (getenv("VMDOSPRAYSCENEEPSILON") != NULL) {
00741     scene_epsilon = float(atof(getenv("VMDOSPRAYSCENEEPSILON")));
00742     printf("OSPRayRenderer) User override of scene epsilon: %g\n", scene_epsilon);
00743   }
00744   ospSet1f(ospRenderer, "epsilon", scene_epsilon);
00745 
00746   // render with/without shadows
00747   if (shadows_enabled || ao_samples) {
00748     if (shadows_enabled && !ao_samples)
00749       msgInfo << "Shadow rendering enabled." << sendmsg;
00750 
00751     ospSet1i(ospRenderer, "shadowsEnabled", 1);
00752   } else {
00753     ospSet1i(ospRenderer, "shadowsEnabled", 0);
00754   }
00755 
00756   // render with ambient occlusion, but only if shadows are also enabled
00757   if (ao_samples) {
00758     msgInfo << "Ambient occlusion enabled." << sendmsg;
00759     msgInfo << "Shadow rendering enabled." << sendmsg;
00760   }
00761 
00762   // commit triangle mesh geometry after assigning materials
00763   for (i=0; i<trimesh_v3f_n3f_c3f.num(); i++) {
00764     if (verbose == RT_VERB_DEBUG)
00765       printf("OSPRayRenderer) Adding triangle mesh[%d]: %d tris ...\n", 
00766              i, trimesh_v3f_n3f_c3f[i].numtris);
00767     ospAddGeometry(ospModel, trimesh_v3f_n3f_c3f[i].geom);
00768     ospRelease(trimesh_v3f_n3f_c3f[i].geom);
00769   } 
00770 
00771   // commit sphere geometry after assigning materials
00772   for (i=0; i<spheres_color.num(); i++) {
00773     if (verbose == RT_VERB_DEBUG)
00774       printf("OSPRayRenderer) Adding sphere_color array [%d]: %d spheres ...\n",
00775              i, spheres_color[i].num);
00776     ospAddGeometry(ospModel, spheres_color[i].geom);
00777     ospRelease(spheres_color[i].geom);
00778   } 
00779 
00780   // commit cylinder geometry after assigning materials
00781   for (i=0; i<cylinders_color.num(); i++) {
00782     if (verbose == RT_VERB_DEBUG)
00783       printf("OSPRayRenderer) Adding cylinders_color array [%d]: %d cylinders...\n",
00784              i, cylinders_color[i].num);
00785     ospAddGeometry(ospModel, cylinders_color[i].geom);
00786     ospRelease(cylinders_color[i].geom);
00787   }
00788 
00789   // commit the completed scene
00790   ospCommit(ospModel);
00791 
00792   //
00793   // attach all lights to the scene
00794   //
00795   ospLightData = ospNewData(ospLights.size(), OSP_OBJECT, &ospLights[0], 0);
00796   ospSetData(ospRenderer, "lights", ospLightData);
00797   ospSet3fv(ospRenderer, "bgColor", scene_bg_color);
00798   ospSetObject(ospRenderer, "camera", ospCamera);
00799   ospSetObject(ospRenderer, "world", ospModel);
00800   ospCommit(ospRenderer);
00801   ospRelease(ospLightData);
00802 
00803   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) Finalizing OSPRay rendering kernels...\n");
00804   // XXX any last OSPRay state updates/checks
00805 
00806   double contextinittime = wkf_timer_timenow(osp_timer);
00807   time_ctx_validate = contextinittime - startctxtime;
00808 
00809   //
00810   // Force OSPRay to build the acceleration structure _now_, so we can time it
00811   //
00812   // XXX No way to force-build OSPRay AS for timing?
00813 
00814   time_ctx_AS_build = wkf_timer_timenow(osp_timer) - contextinittime;
00815   if (verbose == RT_VERB_DEBUG) {
00816     printf("OSPRayRenderer) launching render: %d x %d\n", width, height);
00817   }
00818 }
00819 
00820 
00821 #if defined(VMDOSPRAY_INTERACTIVE_OPENGL)
00822 
00823 static void *createospraywindow(const char *wintitle, int width, int height) {
00824   printf("OSPRayRenderer) Creating OSPRay window: %d x %d...\n", width, height);
00825 
00826   void *win = glwin_create(wintitle, width, height);
00827   while (glwin_handle_events(win, GLWIN_EV_POLL_NONBLOCK) != 0);
00828 
00829   glDrawBuffer(GL_BACK);
00830   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00831   glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
00832   glViewport(0, 0, width, height);
00833   glClear(GL_COLOR_BUFFER_BIT);
00834 
00835   glShadeModel(GL_FLAT);
00836   glMatrixMode(GL_PROJECTION);
00837   glLoadIdentity();
00838   glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
00839   glMatrixMode(GL_MODELVIEW);
00840   glLoadIdentity();
00841 
00842   glDrawBuffer(GL_BACK);
00843   glClear(GL_COLOR_BUFFER_BIT);
00844 
00845   glwin_swap_buffers(win);
00846 
00847   return win;
00848 }
00849 
00850 
00851 static void interactive_viewer_usage(void *win) {
00852   printf("OSPRayRenderer) VMD TachyonL-OSPRay Interactive Ray Tracer help:\n");
00853   printf("OSPRayRenderer) ================================================\n");
00854 
00855   // check for Spaceball/SpaceNavigator/Magellan input devices
00856   int havespaceball = ((glwin_spaceball_available(win)) && (getenv("VMDDISABLESPACEBALLXDRV") == NULL));
00857   printf("OSPRayRenderer) Spaceball/SpaceNavigator/Magellan: %s\n",
00858          (havespaceball) ? "Available" : "Not available");
00859 
00860   // check for stereo-capable display
00861   int havestereo, havestencil;
00862   glwin_get_wininfo(win, &havestereo, &havestencil);
00863   printf("OSPRayRenderer) Stereoscopic display: %s\n",
00864          (havestereo) ? "Available" : "Not available");
00865 
00866   // check for vertical retrace sync
00867   int vsync=0, rc=0;
00868   if ((rc = glwin_query_vsync(win, &vsync)) == GLWIN_SUCCESS) {
00869     printf("OSPRayRenderer) Vert retrace sync: %s\n", (vsync) ? "On" : "Off");
00870   } else {
00871     printf("OSPRayRenderer) Vert retrace sync: indeterminate\n");
00872   }
00873 
00874   printf("OSPRayRenderer)\n");
00875   printf("OSPRayRenderer) General controls:\n");
00876   printf("OSPRayRenderer)   space: save numbered snapshot image\n");
00877   printf("OSPRayRenderer)       =: reset to initial view\n");
00878   printf("OSPRayRenderer)       h: print this help info\n");
00879   printf("OSPRayRenderer)       p: print current rendering parameters\n");
00880   printf("OSPRayRenderer)   ESC,q: quit viewer\n");
00881   printf("OSPRayRenderer)\n");
00882   printf("OSPRayRenderer) Display controls\n");
00883   printf("OSPRayRenderer)      F1: override shadows on/off (off=AO off too)\n");
00884   printf("OSPRayRenderer)      F2: override AO on/off\n");
00885   printf("OSPRayRenderer)      F3: override DoF on/off\n");
00886   printf("OSPRayRenderer)      F4: override Depth cueing on/off\n");
00887 // Not currently applicable to OSPRay
00888 // #ifdef USE_REVERSE_SHADOW_RAYS
00889 //   printf("OSPRayRenderer)      F5: enable/disable shadow ray optimizations\n");
00890 // #endif
00891   printf("OSPRayRenderer)     F12: toggle full-screen display on/off\n");
00892   printf("OSPRayRenderer)   1-9,0: override samples per update auto-FPS off\n");
00893   printf("OSPRayRenderer)      Up: increase DoF focal distance\n");
00894   printf("OSPRayRenderer)    Down: decrease DoF focal distance\n");
00895   printf("OSPRayRenderer)    Left: decrease DoF f/stop\n");
00896   printf("OSPRayRenderer)   Right: increase DoF f/stop\n");
00897   printf("OSPRayRenderer)       S: toggle stereoscopic display on/off (if avail)\n");
00898   printf("OSPRayRenderer)       a: toggle AA/AO auto-FPS tuning on/off (on)\n");
00899   printf("OSPRayRenderer)       g: toggle gradient sky xforms on/off (on)\n");
00900   printf("OSPRayRenderer)       l: toggle light xforms on/off (on)\n");
00901   printf("OSPRayRenderer)\n");
00902   printf("OSPRayRenderer) Mouse controls:\n");
00903   printf("OSPRayRenderer)       f: mouse depth-of-field mode\n");
00904   printf("OSPRayRenderer)       r: mouse rotation mode\n");
00905   printf("OSPRayRenderer)       s: mouse scaling mode\n");
00906   printf("OSPRayRenderer)       t: mouse translation mode\n");
00907 
00908   int movie_recording_enabled = (getenv("VMDOSPRAYLIVEMOVIECAPTURE") != NULL);
00909   if (movie_recording_enabled) {
00910     printf("OSPRayRenderer)\n");
00911     printf("OSPRayRenderer) Movie recording controls:\n");
00912     printf("OSPRayRenderer)       R: start/stop movie recording\n");
00913     printf("OSPRayRenderer)       F: toggle movie FPS (24, 30, 60)\n");
00914   }
00915 }
00916 
00917 
00918 void OSPRayRenderer::render_to_glwin(const char *filename) {
00919   DBG();
00920   int i;
00921 
00922   if (!context_created)
00923     return;
00924 
00925   enum RtMouseMode { RTMM_ROT=0, RTMM_TRANS=1, RTMM_SCALE=2, RTMM_DOF=3 };
00926   enum RtMouseDown { RTMD_NONE=0, RTMD_LEFT=1, RTMD_MIDDLE=2, RTMD_RIGHT=3 };
00927   RtMouseMode mm = RTMM_ROT;
00928   RtMouseDown mousedown = RTMD_NONE;
00929 
00930   // flags to interactively enable/disable shadows, AO, DoF
00931   int gl_shadows_on=(shadows_enabled) ? RT_SHADOWS_ON : RT_SHADOWS_OFF;
00932 
00933   int gl_fs_on=0; // fullscreen window state
00934   int owsx=0, owsy=0; // store last win size before fullscreen
00935   int gl_ao_on=(ao_samples > 0);
00936   int gl_dof_on, gl_dof_on_old;
00937   gl_dof_on=gl_dof_on_old=dof_enabled; 
00938   int gl_fog_on=(fog_mode != RT_FOG_NONE);
00939 
00940   // Enable live recording of a session to a stream of image files indexed
00941   // by their display presentation time, mapped to the nearest frame index
00942   // in a fixed-frame-rate image sequence (e.g. 24, 30, or 60 FPS), 
00943   // to allow subsequent encoding into a standard movie format.
00944   // XXX this feature is disabled by default at present, to prevent people
00945   //     from accidentally turning it on during a live demo or the like
00946   int movie_recording_enabled = (getenv("VMDOSPRAYLIVEMOVIECAPTURE") != NULL);
00947   int movie_recording_on = 0;
00948   double movie_recording_start_time = 0.0;
00949   int movie_recording_fps = 30;
00950   int movie_framecount = 0;
00951   int movie_lastframeindex = 0;
00952   const char *movie_recording_filebase = "vmdlivemovie.%05d.tga";
00953   if (getenv("VMDOSPRAYLIVEMOVIECAPTUREFILEBASE"))
00954     movie_recording_filebase = getenv("VMDOSPRAYLIVEMOVIECAPTUREFILEBASE");
00955 
00956   // Enable/disable Spaceball/SpaceNavigator/Magellan input 
00957   int spaceballenabled=(getenv("VMDDISABLESPACEBALLXDRV") == NULL) ? 1 : 0;
00958   int spaceballmode=0;       // default mode is rotation/translation
00959   int spaceballflightmode=0; // 0=moves object, 1=camera fly
00960   if (getenv("VMDOSPRAYSPACEBALLFLIGHT"))
00961     spaceballflightmode=1;
00962 
00963 
00964   // total AA/AO sample count
00965   int totalsamplecount=0;
00966 
00967   // counter for snapshots of live image...
00968   int snapshotcount=0;
00969 
00970   // flag to enable automatic AO sample count adjustment for FPS rate control
00971   int autosamplecount=1;
00972 
00973   // flag to enable transformation of lights and gradient sky sphere, 
00974   // so that they track camera orientation as they do in the VMD OpenGL display
00975   int xformlights=1, xformgradientsphere=1;
00976 
00977   //
00978   // allocate or reconfigure the framebuffer, accumulation buffer, 
00979   // and output streams required for progressive rendering, either
00980   // using the new progressive APIs, or using our own code.
00981   //
00982   // Unless overridden by environment variables, we use the incoming
00983   // window size parameters from VMD to initialize the RT image dimensions.
00984   // If image size is overridden, often when using HMDs, the incoming 
00985   // dims are window dims are used to size the GL window, but the image size
00986   // is set independently.
00987   int wsx=width, wsy=height;
00988   const char *imageszstr = getenv("VMDOSPRAYIMAGESIZE");
00989   if (imageszstr) {
00990     if (sscanf(imageszstr, "%d %d", &width, &height) != 2) {
00991       width=wsx;
00992       height=wsy;
00993     } 
00994   } 
00995   framebuffer_config(width, height);
00996 
00997   // prepare the majority of OSPRay rendering state before we go into 
00998   // the interactive rendering loop
00999   update_rendering_state(1);
01000   render_compile_and_validate();
01001 
01002   // make a copy of state we're going to interactively manipulate,
01003   // so that we can recover to the original state on-demand
01004   int samples_per_pass = 1;
01005   int cur_aa_samples = aa_samples;
01006   int cur_ao_samples = ao_samples;
01007   float cam_zoom_orig = cam_zoom;
01008   float scene_gradient_orig[3] = {0.0f, 1.0f, 0.0f};
01009   vec_copy(scene_gradient_orig, scene_gradient);
01010 
01011   float cam_pos_orig[3] = {0.0f, 0.0f, 2.0f};
01012   float cam_U_orig[3] = {1.0f, 0.0f, 0.0f};
01013   float cam_V_orig[3] = {0.0f, 1.0f, 0.0f};
01014   float cam_W_orig[3] = {0.0f, 0.0f, -1.0f};
01015   float cam_pos[3], cam_U[3], cam_V[3], cam_W[3];
01016   float hmd_U[3], hmd_V[3], hmd_W[3];
01017 
01018   vec_copy(cam_pos, cam_pos_orig);
01019   vec_copy(cam_U, cam_U_orig);
01020   vec_copy(cam_V, cam_V_orig);
01021   vec_copy(cam_W, cam_W_orig);
01022 
01023   // copy light directions
01024   osp_directional_light *cur_dlights = (osp_directional_light *) calloc(1, directional_lights.num() * sizeof(osp_directional_light));
01025   for (i=0; i<directional_lights.num(); i++) {
01026     vec_copy((float*)&cur_dlights[i].color, directional_lights[i].color);
01027     vec_copy((float*)&cur_dlights[i].dir, directional_lights[i].dir);
01028     vec_normalize((float*)&cur_dlights[i].dir);
01029   }
01030 
01031   // create the display window
01032   void *win = createospraywindow("VMD TachyonL-OSPRay Interactive Ray Tracer", width, height);
01033   interactive_viewer_usage(win);
01034   
01035   // check for stereo-capable display
01036   int havestereo=0, havestencil=0;
01037   int stereoon=0, stereoon_old=0;
01038   glwin_get_wininfo(win, &havestereo, &havestencil);
01039 
01040   // Override AA/AO sample counts since we're doing progressive rendering.
01041   // Choosing an initial AO sample count of 1 will give us the peak progressive 
01042   // display update rate, but we end up wasting time on re-tracing many
01043   // primary rays.  The automatic FPS optimization scheme below will update
01044   // the number of samples per rendering pass and assign the best values for
01045   // AA/AO samples accordingly.
01046   cur_aa_samples = samples_per_pass;
01047   if (cur_ao_samples > 0) {
01048     cur_aa_samples = 1;
01049     cur_ao_samples = samples_per_pass;
01050   }
01051 
01052   const char *statestr = "|/-\\.";
01053   int done=0, winredraw=1, accum_count=0;
01054   int state=0, mousedownx=0, mousedowny=0;
01055   float cur_cam_zoom = cam_zoom_orig;
01056 
01057   double fpsexpave=0.0; 
01058   double mapbuftotaltime=0.0;
01059   
01060   double oldtime = wkf_timer_timenow(osp_timer);
01061   while (!done) { 
01062     int winevent=0;
01063 
01064     while ((winevent = glwin_handle_events(win, GLWIN_EV_POLL_NONBLOCK)) != 0) {
01065       int evdev, evval;
01066       char evkey;
01067 
01068       glwin_get_lastevent(win, &evdev, &evval, &evkey);
01069       glwin_get_winsize(win, &wsx, &wsy);
01070 
01071       if (evdev == GLWIN_EV_WINDOW_CLOSE) {
01072         printf("OSPRayRenderer) display window closed, exiting...\n");
01073         done = 1;
01074         winredraw = 0;
01075       } else if (evdev == GLWIN_EV_KBD) {
01076         switch (evkey) {
01077           case  '1': autosamplecount=0; samples_per_pass=1; winredraw=1; break;
01078           case  '2': autosamplecount=0; samples_per_pass=2; winredraw=1; break;
01079           case  '3': autosamplecount=0; samples_per_pass=3; winredraw=1; break;
01080           case  '4': autosamplecount=0; samples_per_pass=4; winredraw=1; break;
01081           case  '5': autosamplecount=0; samples_per_pass=5; winredraw=1; break;
01082           case  '6': autosamplecount=0; samples_per_pass=6; winredraw=1; break;
01083           case  '7': autosamplecount=0; samples_per_pass=7; winredraw=1; break;
01084           case  '8': autosamplecount=0; samples_per_pass=8; winredraw=1; break;
01085           case  '9': autosamplecount=0; samples_per_pass=9; winredraw=1; break;
01086           case  '0': autosamplecount=0; samples_per_pass=10; winredraw=1; break;
01087 
01088           case  '=': /* recover back to initial state */
01089             vec_copy(scene_gradient, scene_gradient_orig);
01090             cam_zoom = cam_zoom_orig;
01091             vec_copy(cam_pos, cam_pos_orig);
01092             vec_copy(cam_U, cam_U_orig);
01093             vec_copy(cam_V, cam_V_orig);
01094             vec_copy(cam_W, cam_W_orig);
01095 
01096             // restore original light directions
01097             for (i=0; i<directional_lights.num(); i++) {
01098               vec_copy((float*)&cur_dlights[i].dir, directional_lights[i].dir);
01099               vec_normalize((float*)&cur_dlights[i].dir);
01100             }
01101             winredraw = 1;
01102             break;
01103  
01104           case  ' ': /* spacebar saves current image with counter */
01105             {
01106               char snapfilename[256];
01107               sprintf(snapfilename, "vmdsnapshot.%04d.tga", snapshotcount);
01108               const unsigned char *FB = (const unsigned char*)ospMapFrameBuffer(ospFrameBuffer, OSP_FB_COLOR);
01109               if (write_image_file_rgb4u(snapfilename, FB, width, height)) {
01110                 printf("OSPRayRenderer) Failed to write output image!\n");
01111               } else {
01112                 printf("OSPRayRenderer) Saved snapshot to '%s'             \n",
01113                        snapfilename);
01114               }
01115               ospUnmapFrameBuffer(FB, ospFrameBuffer);
01116               snapshotcount++; 
01117             }
01118             break;
01119 
01120           case  'a': /* toggle automatic sample count FPS tuning */
01121             autosamplecount = !(autosamplecount);
01122             printf("\nOSPRayRenderer) Automatic AO sample count FPS tuning %s\n",
01123                    (autosamplecount) ? "enabled" : "disabled");
01124             break;
01125 
01126           case  'f': /* DoF mode */
01127             mm = RTMM_DOF;
01128             printf("\nOSPRayRenderer) Mouse DoF aperture and focal dist. mode\n");
01129             break;
01130 
01131           case  'g': /* toggle gradient sky sphere xforms */
01132             xformgradientsphere = !(xformgradientsphere);
01133             printf("\nOSPRayRenderer) Gradient sky sphere transformations %s\n",
01134                    (xformgradientsphere) ? "enabled" : "disabled");
01135             break;
01136 
01137           case  'h': /* print help message */
01138             printf("\n");
01139             interactive_viewer_usage(win);
01140             break;
01141 
01142           case  'l': /* toggle lighting xforms */
01143             xformlights = !(xformlights);
01144             printf("\nOSPRayRenderer) Light transformations %s\n",
01145                    (xformlights) ? "enabled" : "disabled");
01146             break;
01147 
01148           case  'p': /* print current RT settings */
01149             printf("\nOSPRayRenderer) Current Ray Tracing Parameters:\n"); 
01150             printf("OSPRayRenderer) -------------------------------\n"); 
01151             printf("OSPRayRenderer) Camera zoom: %f\n", cur_cam_zoom);
01152             printf("OSPRayRenderer) Shadows: %s  Ambient occlusion: %s\n",
01153                    (gl_shadows_on) ? "on" : "off",
01154                    (gl_ao_on) ? "on" : "off");
01155             printf("OSPRayRenderer) Antialiasing samples per-pass: %d\n",
01156                    cur_aa_samples);
01157             printf("OSPRayRenderer) Ambient occlusion samples per-pass: %d\n",
01158                    cur_ao_samples);
01159             printf("OSPRayRenderer) Depth-of-Field: %s f/num: %.1f  Foc. Dist: %.2f\n",
01160                    (gl_dof_on) ? "on" : "off", 
01161                    cam_dof_fnumber, cam_dof_focal_dist);
01162             printf("OSPRayRenderer) Image size: %d x %d\n", width, height);
01163             break;
01164 
01165           case  'r': /* rotate mode */
01166             mm = RTMM_ROT;
01167             printf("\nOSPRayRenderer) Mouse rotation mode\n");
01168             break;
01169 
01170           case  's': /* scaling mode */
01171             mm = RTMM_SCALE;
01172             printf("\nOSPRayRenderer) Mouse scaling mode\n");
01173             break;
01174 
01175           case  'F': /* toggle live movie recording FPS (24, 30, 60) */
01176             if (movie_recording_enabled) {
01177               switch (movie_recording_fps) {
01178                 case 24: movie_recording_fps = 30; break;
01179                 case 30: movie_recording_fps = 60; break;
01180                 case 60:
01181                 default: movie_recording_fps = 24; break;
01182               }
01183               printf("\nOSPRayRenderer) Movie recording FPS rate: %d\n", 
01184                      movie_recording_fps);
01185             } else {
01186               printf("\nOSPRayRenderer) Movie recording not available.\n");
01187             }
01188             break;
01189 
01190           case  'R': /* toggle live movie recording mode on/off */
01191             if (movie_recording_enabled) {
01192               movie_recording_on = !(movie_recording_on);
01193               printf("\nOSPRayRenderer) Movie recording %s\n",
01194                      (movie_recording_on) ? "STARTED" : "STOPPED");
01195               if (movie_recording_on) {
01196                 movie_recording_start_time = wkf_timer_timenow(osp_timer);
01197                 movie_framecount = 0;
01198                 movie_lastframeindex = 0;
01199               } else {
01200                 printf("OSPRayRenderer) Encode movie with:\n");
01201                 printf("OSPRayRenderer)   ffmpeg -f image2 -i vmdlivemovie.%%05d.tga -c:v libx264 -profile:v baseline -level 3.0 -pix_fmt yuv420p -b:v 15000000 output.mp4\n");
01202               }
01203             } else {
01204               printf("\nOSPRayRenderer) Movie recording not available.\n");
01205             }
01206             break;
01207 
01208           case  'S': /* toggle stereoscopic display mode */
01209             if (havestereo) {
01210               stereoon = (!stereoon);
01211               printf("\nOSPRayRenderer) Stereoscopic display %s\n",
01212                      (stereoon) ? "enabled" : "disabled");
01213               winredraw = 1;
01214             } else {
01215               printf("\nOSPRayRenderer) Stereoscopic display unavailable\n");
01216             }
01217             break;
01218  
01219           case  't': /* translation mode */
01220             mm = RTMM_TRANS;
01221             printf("\nOSPRayRenderer) Mouse translation mode\n");
01222             break;
01223             
01224           case  'q': /* 'q' key */
01225           case  'Q': /* 'Q' key */
01226           case 0x1b: /* ESC key */
01227             printf("\nOSPRayRenderer) Exiting on user input.               \n");
01228             done=1; /* exit from interactive RT window */
01229             break;
01230         }
01231       } else if (evdev != GLWIN_EV_NONE) {
01232         switch (evdev) {
01233           case GLWIN_EV_KBD_F1: /* turn shadows on/off */
01234             gl_shadows_on=(!gl_shadows_on) ? RT_SHADOWS_ON : RT_SHADOWS_OFF;
01235             // gl_shadows_on = (!gl_shadows_on);
01236             printf("\n");
01237             printf("OSPRayRenderer) Shadows %s\n",
01238                    (gl_shadows_on) ? "enabled" : "disabled");
01239             winredraw = 1; 
01240             break;
01241 
01242           case GLWIN_EV_KBD_F2: /* turn AO on/off */
01243             gl_ao_on = (!gl_ao_on); 
01244             printf("\n");
01245             printf("OSPRayRenderer) Ambient occlusion %s\n",
01246                    (gl_ao_on) ? "enabled" : "disabled");
01247             winredraw = 1; 
01248             break;
01249 
01250           case GLWIN_EV_KBD_F3: /* turn DoF on/off */
01251             gl_dof_on = (!gl_dof_on);
01252             printf("\n");
01253             if ((camera_projection == RT_ORTHOGRAPHIC) && gl_dof_on) {
01254               gl_dof_on=0; 
01255               printf("OSPRayRenderer) Depth-of-field not available in orthographic mode\n");
01256             }
01257             printf("OSPRayRenderer) Depth-of-field %s\n",
01258                    (gl_dof_on) ? "enabled" : "disabled");
01259             winredraw = 1;
01260             break;
01261 
01262           case GLWIN_EV_KBD_F4: /* turn fog/depth cueing on/off */
01263             gl_fog_on = (!gl_fog_on); 
01264             printf("\n");
01265             printf("OSPRayRenderer) Depth cueing %s\n",
01266                    (gl_fog_on) ? "enabled" : "disabled");
01267             winredraw = 1; 
01268             break;
01269 
01270           case GLWIN_EV_KBD_F12: /* toggle full-screen window on/off */
01271             gl_fs_on = (!gl_fs_on);
01272             printf("\nOSPRayRenderer) Toggling fullscreen window %s\n",
01273                    (gl_fs_on) ? "on" : "off");
01274             if (gl_fs_on) { 
01275               if (glwin_fullscreen(win, gl_fs_on, 0) == 0) {
01276                 owsx = wsx;
01277                 owsy = wsy;
01278                 glwin_get_winsize(win, &wsx, &wsy);
01279               } else {
01280                 printf("OSPRayRenderer) Fullscreen mode note available\n");
01281               }
01282             } else {
01283               glwin_fullscreen(win, gl_fs_on, 0);
01284               glwin_resize(win, owsx, owsy);
01285             }
01286             winredraw = 1; 
01287             break;
01288 
01289           case GLWIN_EV_KBD_UP: /* change depth-of-field focal dist */
01290             cam_dof_focal_dist *= 1.02f; 
01291             printf("\nOSPRayRenderer) DoF focal dist: %f\n", cam_dof_focal_dist);
01292             winredraw = 1; 
01293             break;
01294 
01295           case GLWIN_EV_KBD_DOWN: /* change depth-of-field focal dist */
01296             cam_dof_focal_dist *= 0.96f; 
01297             if (cam_dof_focal_dist < 0.02f) cam_dof_focal_dist = 0.02f;
01298             printf("\nOSPRayRenderer) DoF focal dist: %f\n", cam_dof_focal_dist);
01299             winredraw = 1; 
01300             break;
01301 
01302           case GLWIN_EV_KBD_RIGHT: /* change depth-of-field f/stop number */
01303             cam_dof_fnumber += 1.0f; 
01304             printf("\nOSPRayRenderer) DoF f/stop: %f\n", cam_dof_fnumber);
01305             winredraw = 1; 
01306             break;
01307 
01308           case GLWIN_EV_KBD_LEFT: /* change depth-of-field f/stop number */
01309             cam_dof_fnumber -= 1.0f; 
01310             if (cam_dof_fnumber < 1.0f) cam_dof_fnumber = 1.0f;
01311             printf("\nOSPRayRenderer) DoF f/stop: %f\n", cam_dof_fnumber);
01312             winredraw = 1; 
01313             break;
01314 
01315           case GLWIN_EV_MOUSE_MOVE:
01316             if (mousedown != RTMD_NONE) {
01317               int x, y;
01318               glwin_get_mousepointer(win, &x, &y);
01319 
01320               float zoommod = 2.0f*cur_cam_zoom/cam_zoom_orig;
01321               float txdx = (x - mousedownx) * zoommod / wsx;
01322               float txdy = (y - mousedowny) * zoommod / wsy;
01323               if (mm != RTMM_SCALE) {
01324                 mousedownx = x;
01325                 mousedowny = y;
01326               }
01327 
01328               if (mm == RTMM_ROT) {
01329                 Matrix4 rm;
01330                 if (mousedown == RTMD_LEFT) {
01331                   // when zooming in further from the initial view, we
01332                   // rotate more slowly so control remains smooth
01333                   rm.rotate_axis(cam_V, -txdx);
01334                   rm.rotate_axis(cam_U, -txdy);
01335                 } else if (mousedown == RTMD_MIDDLE || 
01336                            mousedown == RTMD_RIGHT) {
01337                   rm.rotate_axis(cam_W, txdx);
01338                 }
01339                 rm.multpoint3d(cam_pos, cam_pos);
01340                 rm.multnorm3d(cam_U, cam_U);
01341                 rm.multnorm3d(cam_V, cam_V);
01342                 rm.multnorm3d(cam_W, cam_W);
01343 
01344                 if (xformgradientsphere) {
01345                   rm.multnorm3d(scene_gradient, scene_gradient);
01346                 }
01347  
01348                 if (xformlights) {
01349                   // update light directions (comparatively costly)
01350                   for (i=0; i<directional_lights.num(); i++) {
01351                     rm.multnorm3d((float*)&cur_dlights[i].dir, (float*)&cur_dlights[i].dir);
01352                   }
01353                 }
01354 
01355                 winredraw = 1;
01356               } else if (mm == RTMM_TRANS) {
01357                 if (mousedown == RTMD_LEFT) {
01358                   float dU[3], dV[3];
01359                   vec_scale(dU, -txdx, cam_U);
01360                   vec_scale(dV,  txdy, cam_V);
01361                   vec_add(cam_pos, cam_pos, dU); 
01362                   vec_add(cam_pos, cam_pos, dV); 
01363                 } else if (mousedown == RTMD_MIDDLE || 
01364                            mousedown == RTMD_RIGHT) {
01365                   float dW[3];
01366                   vec_scale(dW, txdx, cam_W);
01367                   vec_add(cam_pos, cam_pos, dW); 
01368                 } 
01369                 winredraw = 1;
01370               } else if (mm == RTMM_SCALE) {
01371                 float txdx = (x - mousedownx) * 2.0f / wsx;
01372                 float zoominc = 1.0f - txdx;
01373                 if (zoominc < 0.01f) zoominc = 0.01f;
01374                 cam_zoom = cur_cam_zoom * zoominc;
01375                 winredraw = 1;
01376               } else if (mm == RTMM_DOF) {
01377                 cam_dof_fnumber += txdx * 20.0f;
01378                 if (cam_dof_fnumber < 1.0f) cam_dof_fnumber = 1.0f;
01379                 cam_dof_focal_dist += -txdy; 
01380                 if (cam_dof_focal_dist < 0.01f) cam_dof_focal_dist = 0.01f;
01381                 winredraw = 1;
01382               }
01383             }
01384             break;
01385 
01386           case GLWIN_EV_MOUSE_LEFT:
01387           case GLWIN_EV_MOUSE_MIDDLE:
01388           case GLWIN_EV_MOUSE_RIGHT:
01389             if (evval) {
01390               glwin_get_mousepointer(win, &mousedownx, &mousedowny);
01391               cur_cam_zoom = cam_zoom;
01392 
01393               if (evdev == GLWIN_EV_MOUSE_LEFT) mousedown = RTMD_LEFT;
01394               else if (evdev == GLWIN_EV_MOUSE_MIDDLE) mousedown = RTMD_MIDDLE;
01395               else if (evdev == GLWIN_EV_MOUSE_RIGHT) mousedown = RTMD_RIGHT;
01396             } else {
01397               mousedown = RTMD_NONE;
01398             }
01399             break;
01400 
01401           case GLWIN_EV_MOUSE_WHEELUP:
01402             cam_zoom /= 1.1f; winredraw = 1; break;
01403 
01404           case GLWIN_EV_MOUSE_WHEELDOWN:
01405             cam_zoom *= 1.1f; winredraw = 1; break;
01406         }
01407       }
01408     }
01409 
01410 
01411     //
01412     // Support for Spaceball/Spacenavigator/Magellan devices that use
01413     // X11 ClientMessage protocol....
01414     //
01415     //
01416     // Support for Spaceball/Spacenavigator/Magellan devices that use
01417     // X11 ClientMessage protocol....
01418     //
01419     if (spaceballenabled) {
01420       // Spaceball/Spacenavigator/Magellan event state variables
01421       int tx=0, ty=0, tz=0, rx=0, ry=0, rz=0, buttons=0;
01422       if (glwin_get_spaceball(win, &rx, &ry, &rz, &tx, &ty, &tz, &buttons)) {
01423         // negate directions if we're in flight mode...
01424         if (spaceballflightmode) {
01425           rx= -rx;
01426           ry= -ry;
01427           rz= -rz;
01428 
01429           tx= -tx;
01430           ty= -ty;
01431           tz= -tz;
01432         }
01433 
01434         // check for button presses to reset the view
01435         if (buttons & 1) {
01436           printf("OSPRayRenderer) spaceball button 1 pressed: reset view\n");
01437           vec_copy(scene_gradient, scene_gradient_orig);
01438           cam_zoom = cam_zoom_orig;
01439           vec_copy(cam_pos, cam_pos_orig);
01440           vec_copy(cam_U, cam_U_orig);
01441           vec_copy(cam_V, cam_V_orig);
01442           vec_copy(cam_W, cam_W_orig);
01443 
01444           // restore original light directions
01445           for (i=0; i<directional_lights.num(); i++) {
01446             vec_copy((float*)&cur_dlights[i].dir, directional_lights[i].dir);
01447             vec_normalize((float*)&cur_dlights[i].dir);
01448           }
01449           winredraw = 1;
01450         }
01451 
01452         // check for button presses to toggle spaceball mode
01453         if (buttons & 2) {
01454           spaceballmode = !(spaceballmode);
01455           printf("OSPRayRenderer) spaceball mode: %s                       \n",
01456                  (spaceballmode) ? "scaling" : "rotation/translation");
01457         }
01458 
01459         // rotation/translation mode
01460         if (spaceballmode == 0) {
01461           float zoommod = 2.0f*cam_zoom/cam_zoom_orig;
01462           float divlen = sqrtf(wsx*wsx + wsy*wsy) * 50.0f;
01463 
01464           // check for rotation and handle it...
01465           if (rx != 0 || ry !=0 || rz !=0) {
01466             Matrix4 rm;
01467             rm.rotate_axis(cam_U, -rx * zoommod / divlen);
01468             rm.rotate_axis(cam_V, -ry * zoommod / divlen);
01469             rm.rotate_axis(cam_W, -rz * zoommod / divlen);
01470 
01471             rm.multpoint3d(cam_pos, cam_pos);
01472             rm.multnorm3d(cam_U, cam_U);
01473             rm.multnorm3d(cam_V, cam_V);
01474             rm.multnorm3d(cam_W, cam_W);
01475 
01476             if (xformgradientsphere) {
01477               rm.multnorm3d(scene_gradient, scene_gradient);
01478             }
01479 
01480             if (xformlights) {
01481               // update light directions (comparatively costly)
01482               for (i=0; i<directional_lights.num(); i++) {
01483                 rm.multnorm3d((float*)&cur_dlights[i].dir, (float*)&cur_dlights[i].dir);
01484               }
01485             }
01486             winredraw = 1;
01487           }
01488 
01489           // check for translation and handle it...
01490           if (tx != 0 || ty !=0 || tz !=0) {
01491             float dU[3], dV[3], dW[3];
01492             vec_scale(dU, -tx * zoommod / divlen, cam_U);
01493             vec_scale(dV, -ty * zoommod / divlen, cam_V);
01494             vec_scale(dW, -tz * zoommod / divlen, cam_W);
01495             vec_add(cam_pos, cam_pos, dU);
01496             vec_add(cam_pos, cam_pos, dV);
01497             vec_add(cam_pos, cam_pos, dW);
01498             winredraw = 1;
01499           }
01500         }
01501     
01502         // scaling mode
01503         if (spaceballmode == 1) {
01504           const float sbscale = 1.0f / (1024.0f * 8.0f);
01505           float zoominc = 1.0f - (rz * sbscale);
01506           if (zoominc < 0.01f) zoominc = 0.01f;
01507             cam_zoom *= zoominc;
01508             winredraw = 1;
01509         }
01510 
01511       }
01512     }
01513 
01514 
01515     // if there is no HMD, we use the camera orientation directly  
01516     vec_copy(hmd_U, cam_U);
01517     vec_copy(hmd_V, cam_V);
01518     vec_copy(hmd_W, cam_W);
01519 
01520     // XXX HMD handling goes here
01521 
01522     //
01523     // handle window resizing, stereoscopic mode changes,
01524     // destroy and recreate affected OSPRay buffers
01525     //
01526     int resize_buffers=0;
01527 
01528     if (wsx != width) {
01529       width = wsx;
01530       resize_buffers=1;
01531     }
01532  
01533     if (wsy != height || (stereoon != stereoon_old)) {
01534       if (stereoon) {
01535         if (height != wsy * 2) {
01536           height = wsy * 2; 
01537           resize_buffers=1;
01538         }
01539       } else {
01540         height = wsy;
01541         resize_buffers=1;
01542       }
01543     }
01544 
01545 
01546     // check if stereo mode or DoF mode changed, both cases
01547     // require changing the active color accumulation ray gen program
01548     if ((stereoon != stereoon_old) || (gl_dof_on != gl_dof_on_old)) {
01549       // when stereo mode changes, we have to regenerate the
01550       // the RNG, accumulation buffer, and framebuffer
01551       if (stereoon != stereoon_old) {
01552         resize_buffers=1;
01553       }
01554 
01555       // update stereo and DoF state
01556       stereoon_old = stereoon;
01557       gl_dof_on_old = gl_dof_on;
01558 
01559       // set the active color accumulation ray gen mode based on the 
01560       // camera/projection mode, stereoscopic display mode, 
01561       // and depth-of-field state
01562       winredraw=1;
01563     }
01564 
01565     if (resize_buffers) {
01566       framebuffer_resize(width, height);
01567 
01568       // when movie recording is enabled, print the window size as a guide
01569       // since the user might want to precisely control the size or 
01570       // aspect ratio for a particular movie format, e.g. 1080p, 4:3, 16:9
01571       if (movie_recording_enabled) {
01572         printf("\rOSPRayRenderer) Window resize: %d x %d                               \n", width, height);
01573       }
01574 
01575       winredraw=1;
01576     }
01577 
01578     int frame_ready = 1; // Default to true
01579     unsigned int subframe_count = 1;
01580     if (!done) {
01581       //
01582       // If the user interacted with the window in a meaningful way, we
01583       // need to update the OSPRay rendering state, recompile and re-validate
01584       // the context, and then re-render...
01585       //
01586       if (winredraw) {
01587         // update camera parameters
01588         ospSet3fv(ospCamera, "pos", cam_pos);
01589         ospSet3fv(ospCamera, "dir",   hmd_W);
01590         ospSet3fv(ospCamera,  "up",   hmd_V);
01591         ospSet1f(ospCamera, "aspect", width / ((float) height));
01592         ospSet1f(ospCamera, "fovy", 2.0f*180.0f*(atanf(cam_zoom)/float(VMD_PI)));
01593  
01594         // update shadow state 
01595         ospSet1i(ospRenderer, "shadowsEnabled", gl_shadows_on);
01596 
01597         // update AO state 
01598         if (gl_shadows_on && gl_ao_on) {
01599           ospSet1i(ospRenderer, "aoSamples", 1);
01600         } else {
01601           ospSet1i(ospRenderer, "aoSamples", 0);
01602         }
01603 
01604         // update depth cueing state
01605         // XXX update OSPRay depth cueing state
01606  
01607         // update/recompute DoF values 
01608         // XXX OSPRay only implements DoF for the perspective
01609         //     camera at the present time
01610         if (camera_projection == OSPRayRenderer::RT_PERSPECTIVE) {
01611           if (gl_dof_on) {
01612             ospSet1f(ospCamera, "focusDistance", cam_dof_focal_dist);
01613             ospSet1f(ospCamera, "apertureRadius", cam_dof_focal_dist / (2.0f * cam_zoom * cam_dof_fnumber));
01614           } else {
01615             ospSet1f(ospCamera, "apertureRadius", 0.0f);
01616           }
01617         }
01618 
01619         // commit camera updates once they're all done...
01620         ospCommit(ospCamera);
01621 
01622         //
01623         // Update light directions in the OSPRay light buffers
01624         //
01625         if (xformlights) {
01626           // AO scaling factor is applied at the renderer level, but
01627           // we apply the direct lighting scaling factor to the lights.
01628           float lightscale = 1.0f;
01629           if (ao_samples != 0)
01630             lightscale = ao_direct;
01631 
01632           // XXX assumes the only contents in the first part of the 
01633           //     light list are directional lights.  The new AO "ambient"
01634           //     light is the last light in the list now, so we can get
01635           //     away with this, but refactoring is still needed here.
01636           for (i=0; i<directional_lights.num(); i++) {
01637             ospSet1f(ospLights[i], "intensity", lightscale);
01638 
01639             ospSet3fv(ospLights[i], "color", cur_dlights[i].color);
01640 
01641             ospSet3f(ospLights[i], "direction",
01642                      -cur_dlights[i].dir[0],
01643                      -cur_dlights[i].dir[1],
01644                      -cur_dlights[i].dir[2]);
01645 
01646             ospCommit(ospLights[i]);
01647           }
01648         }
01649 
01650         // commit pending changes...
01651         ospCommit(ospRenderer);
01652 
01653         // reset accumulation buffer 
01654         accum_count=0;
01655         totalsamplecount=0;
01656         if (ospFrameBuffer != NULL) {
01657           ospFrameBufferClear(ospFrameBuffer, OSP_FB_COLOR | /* OSP_FB_DEPTH | */ OSP_FB_ACCUM);
01658         }
01659 
01660         // 
01661         // Sample count updates and OSPRay state must always remain in 
01662         // sync, so if we only update sample count state during redraw events,
01663         // that's the only time we should recompute the sample counts, since
01664         // they also affect normalization factors for the accumulation buffer
01665         //
01666 
01667         // Update sample counts to achieve target interactivity
01668         if (autosamplecount) {
01669           if (fpsexpave > 37)
01670             samples_per_pass++;
01671           else if (fpsexpave < 30) 
01672             samples_per_pass--;
01673     
01674           // clamp sample counts to a "safe" range
01675           if (samples_per_pass > 14)
01676             samples_per_pass=14;
01677           if (samples_per_pass < 1)
01678             samples_per_pass=1;
01679         } 
01680 
01681         // split samples per pass either among AA and AO, depending on
01682         // whether DoF and AO are enabled or not. 
01683         if (gl_shadows_on && gl_ao_on) {
01684           if (gl_dof_on) {
01685             if (samples_per_pass < 4) {
01686               cur_aa_samples=samples_per_pass;
01687               cur_ao_samples=1;
01688             } else {
01689               int s = (int) sqrtf(samples_per_pass);
01690               cur_aa_samples=s;
01691               cur_ao_samples=s;
01692             }
01693           } else {
01694             cur_aa_samples=1;
01695             cur_ao_samples=samples_per_pass;
01696           }
01697         } else {
01698           cur_aa_samples=samples_per_pass;
01699           cur_ao_samples=0;
01700         }
01701 
01702         // update the current AA/AO sample counts since they may be changing if
01703         // FPS autotuning is enabled...
01704         // XXX update OSPRay AA sample counts
01705 
01706         // observe latest AO enable/disable flag, and sample count
01707         if (gl_shadows_on && gl_ao_on) {
01708           // XXX update OSPRay AA/AO sample counts
01709         } else {
01710           cur_ao_samples = 0;
01711           // XXX update OSPRay AA/AO sample counts
01712         }
01713       } 
01714 
01715 
01716       // The accumulation buffer normalization factor must be updated
01717       // to reflect the total accumulation count before the accumulation
01718       // buffer is drawn to the output framebuffer
01719       // XXX update OSPRay accum buf normalization factor
01720 
01721       // The accumulation buffer subframe index must be updated to ensure that
01722       // the RNGs for AA and AO get correctly re-seeded
01723       // XXX update OSPRay accum subframe count
01724 
01725       // Force context compilation/validation
01726       // render_compile_and_validate();
01727 
01728       //
01729       // run the renderer 
01730       //
01731       frame_ready = 1; // Default to true
01732       subframe_count = 1;
01733       if (lasterror == 0 /* XXX SUCCESS */) {
01734         if (winredraw) {
01735           ospFrameBufferClear(ospFrameBuffer, OSP_FB_COLOR | /* OSP_FB_DEPTH | */ OSP_FB_ACCUM);
01736           winredraw=0;
01737         }
01738 
01739         // iterate, adding to the accumulation buffer...
01740 //printf("OSPRayRenderer) ospRenderFrame(): [%d] ...\n", accum_sample);
01741         ospRenderFrame(ospFrameBuffer, ospRenderer, OSP_FB_COLOR | OSP_FB_ACCUM);
01742         subframe_count++; // increment subframe index
01743         totalsamplecount += samples_per_pass;
01744         accum_count += cur_aa_samples;
01745 
01746         // copy the accumulation buffer image data to the framebuffer and
01747         // perform type conversion and normaliztion on the image data...
01748         // XXX launch OSPRay accum copy/norm/finish
01749 
01750         if (lasterror == 0 /* XXX SUCCESS */) {
01751           if (frame_ready) {
01752             double bufnewtime = wkf_timer_timenow(osp_timer);
01753 
01754             // display output image
01755             const unsigned char * img;
01756             img = (const unsigned char*)ospMapFrameBuffer(ospFrameBuffer, OSP_FB_COLOR);
01757 
01758 #if 0
01759             glwin_draw_image_tex_rgb3u(win, (stereoon!=0)*GLWIN_STEREO_OVERUNDER, width, height, img);
01760 #else
01761             glwin_draw_image_rgb3u(win, (stereoon!=0)*GLWIN_STEREO_OVERUNDER, width, height, img);
01762 #endif
01763             ospUnmapFrameBuffer(img, ospFrameBuffer);
01764             mapbuftotaltime = wkf_timer_timenow(osp_timer) - bufnewtime;
01765 
01766 
01767             // if live movie recording is on, we save every displayed frame
01768             // to a sequence sequence of image files, with each file numbered
01769             // by its frame index, which is computed by the multiplying image
01770             // presentation time by the image sequence fixed-rate-FPS value.
01771             if (movie_recording_enabled && movie_recording_on) {
01772               char moviefilename[2048];
01773 
01774               // compute frame number from wall clock time and the
01775               // current fixed-rate movie playback frame rate
01776               double now = wkf_timer_timenow(osp_timer);
01777               double frametime = now - movie_recording_start_time;
01778               int fidx = frametime * movie_recording_fps;
01779 
01780               // always force the first recorded frame to be 0
01781               if (movie_framecount==0)
01782                 fidx=0;
01783               movie_framecount++;
01784 
01785 #if defined(__linux)
01786               // generate symlinks for frame indices between the last written
01787               // frame and the current one so that video encoders such as
01788               // ffmpeg and mencoder can be fed the contiguous frame sequence
01789               // at a fixed frame rate, as they require
01790               sprintf(moviefilename, movie_recording_filebase,
01791                       movie_lastframeindex);
01792               int symidx;
01793               for (symidx=movie_lastframeindex; symidx<fidx; symidx++) {
01794                 char symlinkfilename[2048];
01795                 sprintf(symlinkfilename, movie_recording_filebase, symidx);
01796                 symlink(moviefilename, symlinkfilename);
01797               }
01798 #endif
01799 
01800               // write the new movie frame
01801               sprintf(moviefilename, movie_recording_filebase, fidx);
01802               const unsigned char *FB = (const unsigned char*)ospMapFrameBuffer(ospFrameBuffer, OSP_FB_COLOR);
01803               if (write_image_file_rgb4u(moviefilename, FB, width, height)) {
01804                 movie_recording_on = 0;
01805                 printf("\n");
01806                 printf("OSPRayRenderer) ERROR during writing image during movie recording!\n");
01807                 printf("OSPRayRenderer) Movie recording STOPPED\n");
01808               }
01809               ospUnmapFrameBuffer(FB, ospFrameBuffer);
01810 
01811               movie_lastframeindex = fidx; // update last frame index written
01812             }
01813           }
01814         } else {
01815           printf("OSPRayRenderer) An error occured during rendering. Rendering is aborted.\n");
01816           done=1;
01817           break;
01818         }
01819       } else {
01820         printf("OSPRayRenderer) An error occured in AS generation. Rendering is aborted.\n");
01821         done=1;
01822         break;
01823       }
01824     }
01825 
01826     if (!done && frame_ready) {
01827       double newtime = wkf_timer_timenow(osp_timer);
01828       double frametime = (newtime-oldtime) + 0.00001f;
01829       oldtime=newtime;
01830 
01831       // compute exponential moving average for exp(-1/10)
01832       double framefps = 1.0f/frametime;
01833       fpsexpave = (fpsexpave * 0.90) + (framefps * 0.10);
01834 
01835       printf("OSPRayRenderer) %c AA:%2d AO:%2d, %4d tot RT FPS: %.1f  %.4f s/frame sf: %d  \r",
01836              statestr[state], cur_aa_samples, cur_ao_samples, 
01837              totalsamplecount, fpsexpave, frametime, subframe_count);
01838 
01839       fflush(stdout);
01840       state = (state+1) & 3;
01841     }
01842 
01843   } // end of per-cycle event processing
01844 
01845   printf("\n");
01846 
01847   // write the output image upon exit...
01848   if (lasterror == 0 /* XXX SUCCESS */) {
01849     wkf_timer_start(osp_timer);
01850     // write output image
01851     const unsigned char *FB = (const unsigned char*)ospMapFrameBuffer(ospFrameBuffer, OSP_FB_COLOR);
01852     if (write_image_file_rgb4u(filename, FB, width, height)) {
01853       printf("OSPRayRenderer) Failed to write output image!\n");
01854     }
01855     ospUnmapFrameBuffer(FB, ospFrameBuffer);
01856     wkf_timer_stop(osp_timer);
01857 
01858     if (verbose == RT_VERB_TIMING || verbose == RT_VERB_DEBUG) {
01859       printf("OSPRayRenderer) image file I/O time: %f secs\n", wkf_timer_time(osp_timer));
01860     }
01861   }
01862 
01863   glwin_destroy(win);
01864 }
01865 
01866 #endif
01867 
01868 
01869 void OSPRayRenderer::render_to_file(const char *filename) {
01870   DBG();
01871   if (!context_created)
01872     return;
01873 
01874   // Unless overridden by environment variables, we use the incoming
01875   // window size parameters from VMD to initialize the RT image dimensions.
01876   int wsx=width, wsy=height;
01877   const char *imageszstr = getenv("VMDOSPRAYIMAGESIZE");
01878   if (imageszstr) {
01879     if (sscanf(imageszstr, "%d %d", &width, &height) != 2) {
01880       width=wsx;
01881       height=wsy;
01882     } 
01883   } 
01884 
01885   // config/allocate framebuffer and accumulation buffer
01886   framebuffer_config(width, height);
01887 
01888   update_rendering_state(0);
01889   render_compile_and_validate();
01890   double starttime = wkf_timer_timenow(osp_timer);
01891 
01892   //
01893   // run the renderer 
01894   //
01895   if (lasterror == 0 /* XXX SUCCESS */) {
01896     // clear the accumulation buffer
01897     ospFrameBufferClear(ospFrameBuffer, OSP_FB_COLOR | /* OSP_FB_DEPTH | */ OSP_FB_ACCUM);
01898 
01899     // Render to the accumulation buffer for the required number of passes
01900     if (getenv("VMDOSPRAYNORENDER") == NULL) {
01901       int accum_sample;
01902       for (accum_sample=0; accum_sample<ext_aa_loops; accum_sample++) {
01903         // The accumulation subframe count must be updated to ensure that
01904         // any custom RNGs for AA and AO get correctly re-seeded
01905         ospRenderFrame(ospFrameBuffer, ospRenderer, OSP_FB_COLOR | OSP_FB_ACCUM);
01906       }
01907     }
01908 
01909     // copy the accumulation buffer image data to the framebuffer and perform
01910     // type conversion and normaliztion on the image data...
01911     double rtendtime = wkf_timer_timenow(osp_timer);
01912     time_ray_tracing = rtendtime - starttime;
01913 
01914     if (lasterror == 0 /* XXX SUCCESS */) {
01915       // write output image to a file unless we are benchmarking
01916       if (getenv("VMDOSPRAYNOSAVE") == NULL) {
01917         const unsigned char *FB = (const unsigned char*)ospMapFrameBuffer(ospFrameBuffer, OSP_FB_COLOR);
01918         if (write_image_file_rgb4u(filename, FB, width, height)) {
01919           printf("OSPRayRenderer) Failed to write output image!\n");
01920         }
01921         ospUnmapFrameBuffer(FB, ospFrameBuffer);
01922       }
01923       time_image_io = wkf_timer_timenow(osp_timer) - rtendtime;
01924     } else {
01925       printf("OSPRayRenderer) Error during rendering.  Rendering aborted.\n");
01926     }
01927 
01928     if (verbose == RT_VERB_TIMING || verbose == RT_VERB_DEBUG) {
01929       printf("OSPRayRenderer) ctx setup %.2f  valid %.2f  AS %.2f  RT %.2f io %.2f\n", time_ctx_setup, time_ctx_validate, time_ctx_AS_build, time_ray_tracing, time_image_io);
01930     }
01931   } else {
01932     printf("OSPRayRenderer) Error during AS generation.  Rendering aborted.\n");
01933   }
01934 }
01935 
01936 
01937 void OSPRayRenderer::add_material(int matindex,
01938                                  float ambient, float diffuse, float specular,
01939                                  float shininess, float reflectivity,
01940                                  float opacity, 
01941                                  float outline, float outlinewidth,
01942                                  int transmode) {
01943   int oldmatcount = materialcache.num();
01944   if (oldmatcount <= matindex) {
01945     osp_material m;
01946     memset(&m, 0, sizeof(m));
01947 
01948     // XXX do something noticable so we see that we got a bad entry...
01949     m.ambient = 0.5f;
01950     m.diffuse = 0.7f;
01951     m.specular = 0.0f;
01952     m.shininess = 10.0f;
01953     m.reflectivity = 0.0f;
01954     m.opacity = 1.0f;
01955     m.transmode = 0;
01956 
01957     materialcache.appendN(m, matindex - oldmatcount + 1);
01958   }
01959  
01960   if (materialcache[matindex].isvalid) {
01961     return;
01962   } else {
01963     if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) Adding material[%d]\n", matindex);
01964 
01965     materialcache[matindex].ambient      = ambient;
01966     materialcache[matindex].diffuse      = diffuse; 
01967     materialcache[matindex].specular     = specular;
01968     materialcache[matindex].shininess    = shininess;
01969     materialcache[matindex].reflectivity = reflectivity;
01970     materialcache[matindex].opacity      = opacity;
01971     materialcache[matindex].outline      = outline;
01972     materialcache[matindex].outlinewidth = outlinewidth;
01973     materialcache[matindex].transmode    = transmode;
01974 
01975     // create an OSPRay material object too...
01976 #if OSPRAY_VERSION_MAJOR >= 1 && OSPRAY_VERSION_MINOR >= 5
01977     OSPMaterial ospMat = ospNewMaterial2("scivis", "RaytraceMaterial");
01978 #else
01979     OSPMaterial ospMat = ospNewMaterial(ospRenderer, "RaytraceMaterial");
01980 #endif
01981     ospSet3f(ospMat, "Ka", materialcache[matindex].ambient, materialcache[matindex].ambient, materialcache[matindex].ambient);
01982     ospSet3f(ospMat, "Kd", materialcache[matindex].diffuse, materialcache[matindex].diffuse, materialcache[matindex].diffuse);
01983     ospSet3f(ospMat, "Ks", materialcache[matindex].specular, materialcache[matindex].specular, materialcache[matindex].specular);
01984     ospSet1f(ospMat, "d", materialcache[matindex].opacity);
01985     ospSet1f(ospMat, "Ns", materialcache[matindex].shininess);
01986 
01991 
01992     ospCommit(ospMat);
01993     materialcache[matindex].mat = ospMat;
01994 
01995     materialcache[matindex].isvalid      = 1;
01996   }
01997 }
01998 
01999 
02000 void OSPRayRenderer::init_materials() {
02001   DBG();
02002   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer: init_materials()\n");
02003 
02004 }
02005 
02006 
02007 void OSPRayRenderer::set_material(OSPGeometry &geom, int matindex, float *uniform_color) {
02008   if (!context_created)
02009     return;
02010 
02011   if (verbose == RT_VERB_DEBUG) printf("OSPRay: setting material\n");
02012   ospSetMaterial(geom, materialcache[matindex].mat);
02013 }
02014 
02015 
02016 void OSPRayRenderer::add_directional_light(const float *dir, const float *color) {
02017   DBG();
02018   osp_directional_light l;
02019   vec_copy(l.dir, dir);
02020   vec_copy(l.color, color);
02021 
02022   directional_lights.append(l);
02023 }
02024 
02025 
02026 void OSPRayRenderer::add_positional_light(const float *pos, const float *color) {
02027   DBG();
02028   osp_positional_light l;
02029   vec_copy(l.pos, pos);
02030   vec_copy(l.color, color);
02031 
02032   positional_lights.append(l);
02033 }
02034 
02035 
02036 void OSPRayRenderer::cylinder_array(Matrix4 *wtrans, float radius,
02037                                    float *uniform_color,
02038                                    int cylnum, float *points, int matindex) {
02039   DBG();
02040   if (!context_created) return;
02041   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating cylinder array: %d...\n", cylnum);
02042   cylinder_array_cnt += cylnum;
02043   
02044   osp_cylinder_array_color ca;
02045   memset(&ca, 0, sizeof(ca));
02046   ca.num = cylnum;
02047 
02048   // each cylinder contains 7 32bit values.
02049   // compute bytes per cylinder: sizeof(v0) + sizeof(v1) + sizeof(radius)
02050   int bytes_per_cylinder = 3*sizeof(float) + 3*sizeof(float) + sizeof(float);
02051   ca.cylinders = (float *) calloc(1, cylnum * bytes_per_cylinder);
02052   ca.colors = (float *) calloc(1, cylnum * 4 * sizeof(float));
02053 
02054   int i,ind4,ind6,ind7;
02055   const int rOffset = 6; // radius offset
02056   if (wtrans == NULL) {
02057     for (i=0,ind4=0,ind6=0,ind7=0; i<cylnum; i++,ind4+=4,ind6+=6,ind7+=7) {
02058       vec_copy(&ca.cylinders[ind7  ], &points[ind6  ]);
02059       vec_copy(&ca.cylinders[ind7+3], &points[ind6+3]);
02060       ca.cylinders[ind7+rOffset] = radius;
02061       vec_copy(&ca.colors[ind4], &uniform_color[0]);
02062       ca.colors[ind4 + 3] = 1.0f;
02063     }
02064   } else {
02065     for (i=0,ind4=0,ind6=0,ind7=0; i<cylnum; i++,ind4+=4,ind6+=6,ind7+=7) {
02066       // apply transforms on points, radii
02067       wtrans->multpoint3d(&points[ind6  ], &ca.cylinders[ind7  ]);
02068       wtrans->multpoint3d(&points[ind6+3], &ca.cylinders[ind7+3]);
02069       ca.cylinders[ind7+rOffset] = radius;
02070       vec_copy(&ca.colors[ind4], &uniform_color[0]);
02071       ca.colors[ind4 + 3] = 1.0f;
02072     }
02073   }
02074 
02075   ca.matindex = matindex;
02076   ca.geom  = ospNewGeometry("cylinders");
02077   ca.cyls = ospNewData(cylnum*bytes_per_cylinder, OSP_CHAR, ca.cylinders, 0);
02078   ca.cols = ospNewData(cylnum, OSP_FLOAT4, ca.colors, 0);
02079   ospSetData(ca.geom, "cylinders", ca.cyls);
02080   ospSet1i(ca.geom, "bytes_per_cylinder", bytes_per_cylinder);
02081   ospSet1i(ca.geom, "offset_v0", 0);
02082   ospSet1i(ca.geom, "offset_v1", 3*sizeof(float));
02083   ospSet1i(ca.geom, "offset_radius", rOffset*sizeof(float));
02084   ospSetData(ca.geom, "color", ca.cols);
02085   set_material(ca.geom, matindex, NULL);
02086   ospCommit(ca.geom);
02087   ospRelease(ca.cyls);
02088   ospRelease(ca.cols);
02089 
02090   free(ca.cylinders); // ospSetData() is copying presently...
02091   ca.cylinders = NULL;
02092   free(ca.colors);
02093   ca.colors = NULL;
02094 
02095   cylinders_color.append(ca);
02096 }
02097 
02098 
02099 void OSPRayRenderer::cylinder_array_color(Matrix4 & wtrans, float rscale,
02100                                          int cylnum, float *points,
02101                                          float *radii, float *colors,
02102                                          int matindex) {
02103   DBG();
02104   if (!context_created) return;
02105   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating color cylinder array: %d...\n", cylnum);
02106   cylinder_array_color_cnt += cylnum;
02107 
02108   osp_cylinder_array_color cac;
02109   memset(&cac, 0, sizeof(cac));
02110   cac.num = cylnum;
02111 
02112   // each cylinder contains 7 32bit values.
02113   // compute bytes per cylinder: sizeof(v0) + sizeof(v1) + sizeof(radius)
02114   int bytes_per_cylinder = 3*sizeof(float) + 3*sizeof(float) + sizeof(float);
02115   cac.cylinders = (float *) calloc(1, cylnum * bytes_per_cylinder);
02116   cac.colors = (float *) calloc(1, cylnum * 4 * sizeof(float));
02117 
02118   int i, ind3, ind4, ind6, ind7;
02119   const int rOffset = 6; // radius offset
02120   for (i=0,ind3=0,ind4=0,ind6=0,ind7=0; i<cylnum; i++,ind3+=3,ind4+=4,ind6+=6,ind7+=7) {
02121     // apply transforms on points, radii
02122     wtrans.multpoint3d(&points[ind6  ], &cac.cylinders[ind7  ]);
02123     wtrans.multpoint3d(&points[ind6+3], &cac.cylinders[ind7+3]);
02124     cac.cylinders[ind7+rOffset] = radii[i] * rscale; // radius
02125     vec_copy(&cac.colors[ind4], &colors[ind3]);
02126     cac.colors[ind4 + 3] = 1.0f;
02127   }
02128 
02129   cac.matindex = matindex;
02130   cac.geom  = ospNewGeometry("cylinders");
02131   cac.cyls = ospNewData(cylnum*bytes_per_cylinder, OSP_CHAR, cac.cylinders, 0);
02132   cac.cols = ospNewData(cylnum, OSP_FLOAT4, cac.colors, 0);
02133   ospSetData(cac.geom, "cylinders", cac.cyls);
02134   ospSet1i(cac.geom, "bytes_per_cylinder", bytes_per_cylinder);
02135   ospSet1i(cac.geom, "offset_v0", 0);
02136   ospSet1i(cac.geom, "offset_v1", 3*sizeof(float));
02137   ospSet1i(cac.geom, "offset_radius", rOffset*sizeof(float));
02138   ospSetData(cac.geom, "color", cac.cols);
02139   set_material(cac.geom, matindex, NULL);
02140   ospCommit(cac.geom);
02141   ospRelease(cac.cyls);
02142   ospRelease(cac.cols);
02143 
02144   free(cac.cylinders); // ospSetData() is copying presently...
02145   cac.cylinders = NULL;
02146   free(cac.colors);
02147   cac.colors = NULL;
02148 
02149   cylinders_color.append(cac);
02150 }
02151 
02152 #if 0
02153 void OSPRayRenderer::ring_array_color(Matrix4 & wtrans, float rscale,
02154                                      int rnum, float *centers,
02155                                      float *norms, float *radii, 
02156                                      float *colors, int matindex) {
02157 }
02158 #endif
02159 
02160 
02161 void OSPRayRenderer::sphere_array(Matrix4 *wtrans, float rscale,
02162                                  float *uniform_color,
02163                                  int numsp, float *centers,
02164                                  float *radii,
02165                                  int matindex) {
02166   DBG();
02167   if (!context_created) return;
02168   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating sphere array: %d...\n", numsp);
02169   sphere_array_cnt += numsp;
02170 
02171   const rgba c = { uniform_color[0], uniform_color[1], uniform_color[2], 1.0f};
02172 
02173   osp_sphere_array_color sp;
02174   memset(&sp, 0, sizeof(sp));
02175   sp.num = numsp;
02176   sp.xyzr = (float *) calloc(1, numsp * 4*sizeof(float));
02177   sp.colors = (float *) calloc(1, numsp * 4*sizeof(float));
02178 
02179   int i, ind3, ind4;
02180   if (wtrans == NULL) {
02181     if (radii == NULL) {
02182       for (i=0,ind3=0,ind4=0; i<numsp; i++,ind3+=3,ind4+=4) {
02183         // transform to eye coordinates
02184         vec_copy((float*) &sp.xyzr[ind4], &centers[ind3]);
02185         sp.xyzr[ind4+3] = rscale;
02186         memcpy((float*) &sp.colors[ind4], &c, 4*sizeof(float));
02187       }
02188     } else {
02189       for (i=0,ind3=0,ind4=0; i<numsp; i++,ind3+=3,ind4+=4) {
02190         // transform to eye coordinates
02191         vec_copy((float*) &sp.xyzr[ind4], &centers[ind3]);
02192         sp.xyzr[ind4+3] = radii[i] * rscale;
02193         memcpy((float*) &sp.colors[ind4], &c, 4*sizeof(float));
02194       }
02195     }
02196   } else {
02197     if (radii == NULL) {
02198       for (i=0,ind3=0,ind4=0; i<numsp; i++,ind3+=3,ind4+=4) {
02199         wtrans->multpoint3d(&centers[ind3], &sp.xyzr[ind4]);
02200         sp.xyzr[ind4+3] = rscale;
02201         memcpy((float*) &sp.colors[ind4], &c, 4*sizeof(float));
02202       }
02203     } else {
02204       for (i=0,ind3=0,ind4=0; i<numsp; i++,ind3+=3,ind4+=4) {
02205         // transform to eye coordinates
02206         wtrans->multpoint3d(&centers[ind3], &sp.xyzr[ind4]);
02207         sp.xyzr[ind4+3] = radii[i] * rscale;
02208         memcpy((float*) &sp.colors[ind4], &c, 4*sizeof(float));
02209       }
02210     }
02211   }
02212 
02213   sp.matindex = matindex;
02214   sp.geom  = ospNewGeometry("spheres");
02215   sp.cents = ospNewData(numsp, OSP_FLOAT4, sp.xyzr, 0);
02216   sp.cols  = ospNewData(numsp, OSP_FLOAT4, sp.colors, 0);
02217   ospSetData(sp.geom, "spheres", sp.cents);
02218   ospSet1i(sp.geom, "bytes_per_sphere", 4*sizeof(float));
02219   ospSet1i(sp.geom, "offset_center", 0);
02220   ospSet1i(sp.geom, "offset_radius", 3*sizeof(float));
02221   ospSetData(sp.geom, "color",  sp.cols);
02222   set_material(sp.geom, matindex, NULL);
02223   ospCommit(sp.geom);
02224   ospRelease(sp.cents);
02225   ospRelease(sp.cols);
02226 
02227   free(sp.xyzr); // ospSetData() is copying presently...
02228   sp.xyzr = NULL;
02229   free(sp.colors);
02230   sp.colors = NULL;
02231 
02232   spheres_color.append(sp);
02233 }
02234 
02235 
02236 void OSPRayRenderer::sphere_array_color(Matrix4 & wtrans, float rscale,
02237                                        int numsp, float *centers,
02238                                        float *radii, float *colors,
02239                                        int matindex) {
02240   DBG();
02241   if (!context_created) return;
02242   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating sphere array color: %d...\n", numsp);
02243   sphere_array_color_cnt += numsp;
02244 
02245   osp_sphere_array_color sp;
02246   memset(&sp, 0, sizeof(sp));
02247   sp.num = numsp;
02248   sp.xyzr = (float *) calloc(1, numsp * 4*sizeof(float));
02249   sp.colors = (float *) calloc(1, numsp * 4*sizeof(float));
02250 
02251   int i, ind3, ind4;
02252   for (i=0,ind3=0,ind4=0; i<numsp; i++,ind3+=3,ind4+=4) {
02253     wtrans.multpoint3d(&centers[ind3], &sp.xyzr[ind4]);
02254     sp.xyzr[ind4+3] = radii[i] * rscale;
02255     vec_copy((float*) &sp.colors[ind4], &colors[ind3]);
02256     sp.colors[ind4 + 3] = 1.0f;
02257   }
02258 
02259   sp.matindex = matindex;
02260   sp.geom  = ospNewGeometry("spheres");
02261   sp.cents = ospNewData(numsp, OSP_FLOAT4, sp.xyzr, 0);
02262   sp.cols  = ospNewData(numsp, OSP_FLOAT4, sp.colors, 0);
02263   ospSetData(sp.geom, "spheres", sp.cents);
02264   ospSet1i(sp.geom, "bytes_per_sphere", 4*sizeof(float));
02265   ospSet1i(sp.geom, "offset_center", 0);
02266   ospSet1i(sp.geom, "offset_radius", 3*sizeof(float));
02267   ospSetData(sp.geom, "color",  sp.cols);
02268   set_material(sp.geom, matindex, NULL);
02269   ospCommit(sp.geom);
02270   ospRelease(sp.cents);
02271   ospRelease(sp.cols);
02272 
02273   free(sp.xyzr); // ospSetData() is copying presently...
02274   sp.xyzr = NULL;
02275   free(sp.colors);
02276   sp.colors = NULL;
02277 
02278   spheres_color.append(sp);
02279 }
02280 
02281 
02282 void OSPRayRenderer::append_trimesh_v3f_n3f_c3f(osp_trimesh_v3f_n3f_c3f &mesh) {
02283   mesh.geom  = ospNewGeometry("triangles");
02284   mesh.verts = ospNewData(mesh.numverts, OSP_FLOAT3, mesh.v, 0);
02285   mesh.norms = ospNewData(mesh.numverts, OSP_FLOAT3, mesh.n, 0);
02286   mesh.cols  = ospNewData(mesh.numverts, OSP_FLOAT4, mesh.c, 0);
02287   mesh.ind   = ospNewData(mesh.numtris, OSP_INT3,   mesh.f, 0);
02288 
02289   ospSetData(mesh.geom, "vertex", mesh.verts);
02290   ospSetData(mesh.geom, "vertex.normal", mesh.norms);
02291   ospSetData(mesh.geom, "index",  mesh.ind);
02292   ospSetData(mesh.geom, "vertex.color",  mesh.cols);
02293   set_material(mesh.geom, mesh.matindex, NULL);
02294 
02295   ospCommit(mesh.geom);
02296   ospRelease(mesh.verts);
02297   ospRelease(mesh.norms);
02298   ospRelease(mesh.cols);
02299   ospRelease(mesh.ind);
02300 
02301   free(mesh.v); // ospSetData() is copying presently...
02302   mesh.v = NULL;
02303   free(mesh.n);
02304   mesh.n = NULL;
02305   free(mesh.c);
02306   mesh.c = NULL;
02307   free(mesh.f);
02308   mesh.f = NULL;
02309 
02310   trimesh_v3f_n3f_c3f.append(mesh); 
02311 }
02312 
02313 
02314 
02315 void OSPRayRenderer::tricolor_list(Matrix4 & wtrans, int numtris, float *vnc,
02316                                   int matindex) {
02317   if (!context_created) return;
02318 //if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating tricolor list: %d...\n", numtris);
02319   tricolor_cnt += numtris;
02320 
02321   // create and fill the OSPRay trimesh memory buffer
02322   osp_trimesh_v3f_n3f_c3f mesh;
02323   memset(&mesh, 0, sizeof(mesh));
02324   mesh.numtris = numtris;
02325   mesh.numverts = 3L * numtris;
02326   mesh.matindex = matindex;
02327   mesh.v = (float *) calloc(1, numtris * 9*sizeof(float));
02328   mesh.n = (float *) calloc(1, numtris * 9*sizeof(float));
02329   mesh.c = (float *) calloc(1, numtris * 12*sizeof(float));
02330   mesh.f = (int *) calloc(1, numtris * 3*sizeof(int));
02331   
02332   float alpha = 1.0f;
02333 //  alpha = materialcache[matindex].opacity;
02334 
02335   int i, ind, ind9, ind12;
02336   for (i=0,ind=0,ind9=0,ind12=0; i<numtris; i++,ind+=27,ind9+=9,ind12+=12) {
02337     // transform to eye coordinates
02338     wtrans.multpoint3d(&vnc[ind    ], (float*) &mesh.v[ind9    ]);
02339     wtrans.multpoint3d(&vnc[ind + 3], (float*) &mesh.v[ind9 + 3]);
02340     wtrans.multpoint3d(&vnc[ind + 6], (float*) &mesh.v[ind9 + 6]);
02341 
02342     wtrans.multnorm3d(&vnc[ind +  9], (float*) &mesh.n[ind9    ]);
02343     wtrans.multnorm3d(&vnc[ind + 12], (float*) &mesh.n[ind9 + 3]);
02344     wtrans.multnorm3d(&vnc[ind + 15], (float*) &mesh.n[ind9 + 6]);
02345 
02346     vec_copy(&mesh.c[ind12    ], &vnc[ind + 18]);
02347     mesh.c[ind12 +  3] = alpha;
02348     vec_copy(&mesh.c[ind12 + 4], &vnc[ind + 21]);
02349     mesh.c[ind12 +  7] = alpha;
02350     vec_copy(&mesh.c[ind12 + 8], &vnc[ind + 24]);
02351     mesh.c[ind12 + 11] = alpha;
02352 
02353     mesh.f[i*3  ] = i*3;
02354     mesh.f[i*3+1] = i*3 + 1;
02355     mesh.f[i*3+2] = i*3 + 2;
02356   }
02357 
02358   append_trimesh_v3f_n3f_c3f(mesh);
02359 }
02360 
02361 
02362 void OSPRayRenderer::trimesh_c4n3v3(Matrix4 & wtrans, int numverts,
02363                                    float *cnv, int numfacets, int * facets,
02364                                    int matindex) {
02365   if (!context_created) return;
02366   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating trimesh_c4n3v3: %d...\n", numfacets);
02367   trimesh_c4u_n3b_v3f_cnt += numfacets;
02368 
02369   // create and fill the OSPRay trimesh memory buffer
02370   osp_trimesh_v3f_n3f_c3f mesh;
02371   memset(&mesh, 0, sizeof(mesh));
02372   mesh.numtris = numfacets;
02373   mesh.numverts = 3L * numfacets;
02374   mesh.matindex = matindex;
02375   mesh.v = (float *) calloc(1, numfacets * 9*sizeof(float));
02376   mesh.n = (float *) calloc(1, numfacets * 9*sizeof(float));
02377   mesh.c = (float *) calloc(1, numfacets * 12*sizeof(float));
02378   mesh.f = (int *) calloc(1, numfacets * 3*sizeof(int));
02379  
02380   float alpha = 1.0f;
02381 //  alpha = materialcache[matindex].opacity;
02382 
02383   // XXX we are currently converting to triangle soup for ease of
02384   // initial implementation, but this is clearly undesirable long-term
02385   int i, ind, ind9, ind12;
02386   for (i=0,ind=0,ind9=0,ind12=0; i<numfacets; i++,ind+=3,ind9+=9,ind12+=12) {
02387     int v0 = facets[ind    ] * 10;
02388     int v1 = facets[ind + 1] * 10;
02389     int v2 = facets[ind + 2] * 10;
02390 
02391     // transform to eye coordinates
02392     wtrans.multpoint3d(cnv + v0 + 7, (float*) &mesh.v[ind9    ]);
02393     wtrans.multpoint3d(cnv + v1 + 7, (float*) &mesh.v[ind9 + 3]);
02394     wtrans.multpoint3d(cnv + v2 + 7, (float*) &mesh.v[ind9 + 6]);
02395 
02396     wtrans.multnorm3d(cnv + v0 + 4, (float*) &mesh.n[ind9    ]);
02397     wtrans.multnorm3d(cnv + v1 + 4, (float*) &mesh.n[ind9 + 3]);
02398     wtrans.multnorm3d(cnv + v2 + 4, (float*) &mesh.n[ind9 + 6]);
02399 
02400     vec_copy(&mesh.c[ind12    ], cnv + v0);
02401     mesh.c[ind12 +  3] = alpha;
02402     vec_copy(&mesh.c[ind12 + 4], cnv + v1);
02403     mesh.c[ind12 +  7] = alpha;
02404     vec_copy(&mesh.c[ind12 + 8], cnv + v2);
02405     mesh.c[ind12 + 11] = alpha;
02406 
02407     mesh.f[i*3  ] = i*3;
02408     mesh.f[i*3+1] = i*3 + 1;
02409     mesh.f[i*3+2] = i*3 + 2;
02410   }
02411 
02412   append_trimesh_v3f_n3f_c3f(mesh);
02413 }
02414 
02415 
02416 
02417 // 
02418 // This implementation translates from the most-compact host representation
02419 // to the best that OSPRay allows
02420 //
02421 void OSPRayRenderer::trimesh_c4u_n3b_v3f(Matrix4 & wtrans, unsigned char *c, 
02422                                          signed char *n, float *v, 
02423                                          int numfacets, int matindex) {
02424   if (!context_created) return;
02425   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating trimesh_c4u_n3b_v3f: %d...\n", numfacets);
02426   trimesh_n3b_v3f_cnt += numfacets;
02427 
02428   // create and fill the OSPRay trimesh memory buffer
02429   osp_trimesh_v3f_n3f_c3f mesh;
02430   memset(&mesh, 0, sizeof(mesh));
02431   mesh.numtris = numfacets;
02432   mesh.numverts = 3L * numfacets;
02433   mesh.matindex = matindex;
02434   mesh.v = (float *) calloc(1, numfacets * 9*sizeof(float));
02435   mesh.n = (float *) calloc(1, numfacets * 9*sizeof(float));
02436   mesh.c = (float *) calloc(1, numfacets * 12*sizeof(float));
02437   mesh.f = (int *) calloc(1, numfacets * 3*sizeof(int));
02438  
02439   float alpha = 1.0f;
02440 //  alpha = materialcache[matindex].opacity;
02441 
02442   // XXX we are currently converting to triangle soup for ease of
02443   // initial implementation, but this is clearly undesirable long-term
02444   int i, ind, ind9, ind12;
02445   const float ci2f = 1.0f / 255.0f;
02446   const float cn2f = 1.0f / 127.5f;
02447   for (i=0,ind=0,ind9=0,ind12=0; i<numfacets; i++,ind+=3,ind9+=9,ind12+=12) {
02448     float norm[9];
02449 
02450     // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
02451     // float = (2c+1)/(2^8-1)
02452     norm[0] = n[ind9    ] * cn2f + ci2f;
02453     norm[1] = n[ind9 + 1] * cn2f + ci2f;
02454     norm[2] = n[ind9 + 2] * cn2f + ci2f;
02455     norm[3] = n[ind9 + 3] * cn2f + ci2f;
02456     norm[4] = n[ind9 + 4] * cn2f + ci2f;
02457     norm[5] = n[ind9 + 5] * cn2f + ci2f;
02458     norm[6] = n[ind9 + 6] * cn2f + ci2f;
02459     norm[7] = n[ind9 + 7] * cn2f + ci2f;
02460     norm[8] = n[ind9 + 8] * cn2f + ci2f;
02461 
02462     // transform to eye coordinates
02463     wtrans.multpoint3d(v + ind9    , (float*) &mesh.v[ind9    ]);
02464     wtrans.multpoint3d(v + ind9 + 3, (float*) &mesh.v[ind9 + 3]);
02465     wtrans.multpoint3d(v + ind9 + 6, (float*) &mesh.v[ind9 + 6]);
02466 
02467     wtrans.multnorm3d(norm    , (float*) &mesh.n[ind9    ]);
02468     wtrans.multnorm3d(norm + 3, (float*) &mesh.n[ind9 + 3]);
02469     wtrans.multnorm3d(norm + 6, (float*) &mesh.n[ind9 + 6]);
02470 
02471     float col[9];
02472 
02473     // conversion from GLubyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
02474     // float = c/(2^8-1)
02475     col[0] = c[ind12     ] * ci2f;
02476     col[1] = c[ind12 +  1] * ci2f;
02477     col[2] = c[ind12 +  2] * ci2f;
02478     col[3] = c[ind12 +  4] * ci2f;
02479     col[4] = c[ind12 +  5] * ci2f;
02480     col[5] = c[ind12 +  6] * ci2f;
02481     col[6] = c[ind12 +  8] * ci2f;
02482     col[7] = c[ind12 +  9] * ci2f;
02483     col[8] = c[ind12 + 10] * ci2f;
02484 
02485     vec_copy(&mesh.c[ind12    ], col    );
02486     mesh.c[ind12 +  3] = alpha;
02487     vec_copy(&mesh.c[ind12 + 4], col + 3);
02488     mesh.c[ind12 +  7] = alpha;
02489     vec_copy(&mesh.c[ind12 + 8], col + 6);
02490     mesh.c[ind12 + 11] = alpha;
02491 
02492     mesh.f[i*3  ] = i*3;
02493     mesh.f[i*3+1] = i*3 + 1;
02494     mesh.f[i*3+2] = i*3 + 2;
02495   }
02496 
02497   append_trimesh_v3f_n3f_c3f(mesh);
02498 }
02499 
02500 
02501 
02502 void OSPRayRenderer::trimesh_c4u_n3f_v3f(Matrix4 & wtrans, unsigned char *c, 
02503                                          float *n, float *v, 
02504                                          int numfacets, int matindex) {
02505   if (!context_created) return;
02506   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating trimesh_c4u_n3f_v3f: %d...\n", numfacets);
02507   tricolor_cnt += numfacets;
02508 
02509   // create and fill the OSPRay trimesh memory buffer
02510   osp_trimesh_v3f_n3f_c3f mesh;
02511   memset(&mesh, 0, sizeof(mesh));
02512   mesh.numtris = numfacets;
02513   mesh.numverts = 3L * numfacets;
02514   mesh.matindex = matindex;
02515   mesh.v = (float *) calloc(1, numfacets * 9*sizeof(float));
02516   mesh.n = (float *) calloc(1, numfacets * 9*sizeof(float));
02517   mesh.c = (float *) calloc(1, numfacets * 12*sizeof(float));
02518   mesh.f = (int *) calloc(1, numfacets * 3*sizeof(int));
02519  
02520   float alpha = 1.0f;
02521 //  alpha = materialcache[matindex].opacity;
02522 
02523   // XXX we are currently converting to triangle soup for ease of
02524   // initial implementation, but this is clearly undesirable long-term
02525   int i, ind, ind9, ind12;
02526   const float ci2f = 1.0f / 255.0f;
02527   for (i=0,ind=0,ind9=0,ind12=0; i<numfacets; i++,ind+=3,ind9+=9,ind12+=12) {
02528     // transform to eye coordinates
02529     wtrans.multpoint3d(v + ind9    , (float*) &mesh.v[ind9    ]);
02530     wtrans.multpoint3d(v + ind9 + 3, (float*) &mesh.v[ind9 + 3]);
02531     wtrans.multpoint3d(v + ind9 + 6, (float*) &mesh.v[ind9 + 6]);
02532 
02533     wtrans.multnorm3d(n + ind9    , &mesh.n[ind9    ]);
02534     wtrans.multnorm3d(n + ind9 + 3, &mesh.n[ind9 + 3]);
02535     wtrans.multnorm3d(n + ind9 + 6, &mesh.n[ind9 + 3]);
02536 
02537     // conversion from GLubyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
02538     // float = c/(2^8-1)
02539     float col[9];
02540     col[0] = c[ind12     ] * ci2f;
02541     col[1] = c[ind12 +  1] * ci2f;
02542     col[2] = c[ind12 +  2] * ci2f;
02543     col[3] = c[ind12 +  4] * ci2f;
02544     col[4] = c[ind12 +  5] * ci2f;
02545     col[5] = c[ind12 +  6] * ci2f;
02546     col[6] = c[ind12 +  8] * ci2f;
02547     col[7] = c[ind12 +  9] * ci2f;
02548     col[8] = c[ind12 + 10] * ci2f;
02549 
02550     vec_copy(&mesh.c[ind12    ], col    );
02551     mesh.c[ind12 +  3] = alpha;
02552     vec_copy(&mesh.c[ind12 + 4], col + 3);
02553     mesh.c[ind12 +  7] = alpha;
02554     vec_copy(&mesh.c[ind12 + 8], col + 6);
02555     mesh.c[ind12 + 11] = alpha;
02556 
02557     mesh.f[i*3  ] = i*3;
02558     mesh.f[i*3+1] = i*3 + 1;
02559     mesh.f[i*3+2] = i*3 + 2;
02560   }
02561 
02562   append_trimesh_v3f_n3f_c3f(mesh);
02563 }
02564 
02565 
02566 void OSPRayRenderer::trimesh_n3b_v3f(Matrix4 & wtrans, float *uniform_color, 
02567                                      signed char *n, float *v, 
02568                                      int numfacets, int matindex) {
02569   if (!context_created) return;
02570   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating trimesh_n3b_v3f: %d...\n", numfacets);
02571   trimesh_n3b_v3f_cnt += numfacets;
02572 
02573   // create and fill the OSPRay trimesh memory buffer
02574   osp_trimesh_v3f_n3f_c3f mesh;
02575   memset(&mesh, 0, sizeof(mesh));
02576   mesh.numtris = numfacets;
02577   mesh.numverts = 3L * numfacets;
02578   mesh.matindex = matindex;
02579   mesh.v = (float *) calloc(1, numfacets * 9*sizeof(float));
02580   mesh.n = (float *) calloc(1, numfacets * 9*sizeof(float));
02581   mesh.c = (float *) calloc(1, numfacets * 12*sizeof(float));
02582   mesh.f = (int *) calloc(1, numfacets * 3*sizeof(int));
02583  
02584   float alpha = 1.0f;
02585 
02586   // XXX we are currently converting to triangle soup for ease of
02587   // initial implementation, but this is clearly undesirable long-term
02588   int i, ind, ind9, ind12;
02589 
02590   const float ci2f = 1.0f / 255.0f;
02591   const float cn2f = 1.0f / 127.5f;
02592   for (i=0,ind=0,ind9=0,ind12=0; i<numfacets; i++,ind+=3,ind9+=9,ind12+=12) {
02593     float norm[9];
02594 
02595     // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1
02596     // float = (2c+1)/(2^8-1)
02597     norm[0] = n[ind9    ] * cn2f + ci2f;
02598     norm[1] = n[ind9 + 1] * cn2f + ci2f;
02599     norm[2] = n[ind9 + 2] * cn2f + ci2f;
02600     norm[3] = n[ind9 + 3] * cn2f + ci2f;
02601     norm[4] = n[ind9 + 4] * cn2f + ci2f;
02602     norm[5] = n[ind9 + 5] * cn2f + ci2f;
02603     norm[6] = n[ind9 + 6] * cn2f + ci2f;
02604     norm[7] = n[ind9 + 7] * cn2f + ci2f;
02605     norm[8] = n[ind9 + 8] * cn2f + ci2f;
02606 
02607     // transform to eye coordinates
02608     wtrans.multpoint3d(v + ind9    , (float*) &mesh.v[ind9    ]);
02609     wtrans.multpoint3d(v + ind9 + 3, (float*) &mesh.v[ind9 + 3]);
02610     wtrans.multpoint3d(v + ind9 + 6, (float*) &mesh.v[ind9 + 6]);
02611 
02612     wtrans.multnorm3d(norm    , (float*) &mesh.n[ind9    ]);
02613     wtrans.multnorm3d(norm + 3, (float*) &mesh.n[ind9 + 3]);
02614     wtrans.multnorm3d(norm + 6, (float*) &mesh.n[ind9 + 6]);
02615 
02616     vec_copy(&mesh.c[ind12    ], uniform_color);
02617     mesh.c[ind12 +  3] = alpha;
02618     vec_copy(&mesh.c[ind12 + 4], uniform_color);
02619     mesh.c[ind12 +  7] = alpha;
02620     vec_copy(&mesh.c[ind12 + 8], uniform_color);
02621     mesh.c[ind12 + 11] = alpha;
02622 
02623     mesh.f[i*3  ] = i*3;
02624     mesh.f[i*3+1] = i*3 + 1;
02625     mesh.f[i*3+2] = i*3 + 2;
02626   }
02627 
02628   append_trimesh_v3f_n3f_c3f(mesh);
02629 }
02630 
02631 
02632 // XXX At present we have to build/populate a per-vertex color arrays,
02633 //     but that should go away as soon as OSPRay allows it.
02634 void OSPRayRenderer::trimesh_n3f_v3f(Matrix4 & wtrans, float *uniform_color, 
02635                                     float *n, float *v, int numfacets, 
02636                                     int matindex) {
02637   DBG();
02638   if (!context_created) return;
02639   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating trimesh_n3f_v3f: %d...\n", numfacets);
02640   trimesh_n3f_v3f_cnt += numfacets;
02641 
02642   // create and fill the OSPRay trimesh memory buffer
02643   osp_trimesh_v3f_n3f_c3f mesh;
02644   memset(&mesh, 0, sizeof(mesh));
02645   mesh.numtris = numfacets;
02646   mesh.numverts = 3L * numfacets;
02647   mesh.matindex = matindex;
02648   mesh.v = (float *) calloc(1, numfacets * 9*sizeof(float));
02649   mesh.n = (float *) calloc(1, numfacets * 9*sizeof(float));
02650   mesh.c = (float *) calloc(1, numfacets * 12*sizeof(float));
02651   mesh.f = (int *) calloc(1, numfacets * 3*sizeof(int));
02652 
02653   float alpha = 1.0f;
02654 
02655   // create and fill the OSPRay trimesh memory buffer
02656   int i, ind, ind9, ind12;
02657   for (i=0,ind=0,ind9=0,ind12=0; i<numfacets; i++,ind+=3,ind9+=9,ind12+=12) {
02658     // transform to eye coordinates
02659     wtrans.multpoint3d(v + ind9    , (float*) &mesh.v[ind9    ]);
02660     wtrans.multpoint3d(v + ind9 + 3, (float*) &mesh.v[ind9 + 3]);
02661     wtrans.multpoint3d(v + ind9 + 6, (float*) &mesh.v[ind9 + 6]);
02662 
02663     wtrans.multnorm3d(n + ind9    , (float*) &mesh.n[ind9    ]);
02664     wtrans.multnorm3d(n + ind9 + 3, (float*) &mesh.n[ind9 + 3]);
02665     wtrans.multnorm3d(n + ind9 + 6, (float*) &mesh.n[ind9 + 6]);
02666 
02667     vec_copy(&mesh.c[ind12    ], uniform_color);
02668     mesh.c[ind12 +  3] = alpha;
02669     vec_copy(&mesh.c[ind12 + 4], uniform_color);
02670     mesh.c[ind12 +  7] = alpha;
02671     vec_copy(&mesh.c[ind12 + 8], uniform_color);
02672     mesh.c[ind12 + 11] = alpha;
02673 
02674     mesh.f[i*3  ] = i*3;
02675     mesh.f[i*3+1] = i*3 + 1;
02676     mesh.f[i*3+2] = i*3 + 2;
02677   }
02678 
02679   append_trimesh_v3f_n3f_c3f(mesh);
02680 }
02681 
02682 
02683 #if 0
02684 void OSPRayRenderer::trimesh_v3f(Matrix4 & wtrans, float *uniform_color, 
02685                                 float *v, int numfacets, int matindex) {
02686   if (!context_created) return;
02687   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating trimesh_v3f: %d...\n", numfacets);
02688   trimesh_v3f_cnt += numfacets;
02689 
02690   set_material(geom, matindex, NULL);
02691   append_objects(buf, geom, instance);
02692 }
02693 
02694 #endif
02695 
02696 void OSPRayRenderer::tristrip(Matrix4 & wtrans, int numverts, const float * cnv,
02697                              int numstrips, const int *vertsperstrip,
02698                              const int *facets, int matindex) {
02699   if (!context_created) return;
02700   int i;
02701   int numfacets = 0;
02702   for (i=0; i<numstrips; i++) 
02703     numfacets += (vertsperstrip[i] - 2);  
02704 
02705   if (verbose == RT_VERB_DEBUG) printf("OSPRayRenderer) creating tristrip: %d...\n", numfacets);
02706   tricolor_cnt += numfacets;
02707 
02708   // create and fill the OSPRay trimesh memory buffer
02709   osp_trimesh_v3f_n3f_c3f mesh;
02710   memset(&mesh, 0, sizeof(mesh));
02711   mesh.numtris = numfacets;
02712   mesh.numverts = 3L * numfacets;
02713   mesh.matindex = matindex;
02714   mesh.v = (float *) calloc(1, numfacets * 9*sizeof(float));
02715   mesh.n = (float *) calloc(1, numfacets * 9*sizeof(float));
02716   mesh.c = (float *) calloc(1, numfacets * 12*sizeof(float));
02717   mesh.f = (int *) calloc(1, numfacets * 3*sizeof(int));
02718 
02719   float alpha = 1.0f;
02720 //  alpha = materialcache[matindex].opacity;
02721 
02722   // XXX we are currently converting to triangle soup for ease of
02723   // initial implementation, but this is clearly undesirable long-term
02724 
02725   // render triangle strips one triangle at a time
02726   // triangle winding order is:
02727   //   v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc.
02728   int strip, t, v = 0;
02729   int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };
02730 
02731   // loop over all of the triangle strips
02732   i=0; // set triangle index to 0
02733   int ind9, ind12;
02734   for (strip=0,ind9=0,ind12=0; strip < numstrips; strip++) {
02735     // loop over all triangles in this triangle strip
02736     for (t = 0; t < (vertsperstrip[strip] - 2); t++) {
02737       // render one triangle, using lookup table to fix winding order
02738       int v0 = facets[v + (stripaddr[t & 0x01][0])] * 10;
02739       int v1 = facets[v + (stripaddr[t & 0x01][1])] * 10;
02740       int v2 = facets[v + (stripaddr[t & 0x01][2])] * 10;
02741 
02742       // transform to eye coordinates
02743       wtrans.multpoint3d(cnv + v0 + 7, (float*) &mesh.v[ind9    ]);
02744       wtrans.multpoint3d(cnv + v1 + 7, (float*) &mesh.v[ind9 + 3]);
02745       wtrans.multpoint3d(cnv + v2 + 7, (float*) &mesh.v[ind9 + 6]);
02746 
02747       wtrans.multnorm3d(cnv + v0 + 4, (float*) &mesh.n[ind9    ]);
02748       wtrans.multnorm3d(cnv + v1 + 4, (float*) &mesh.n[ind9 + 3]);
02749       wtrans.multnorm3d(cnv + v2 + 4, (float*) &mesh.n[ind9 + 6]);
02750 
02751       vec_copy(&mesh.c[ind12    ], cnv + v0);
02752       mesh.c[ind12 +  3] = alpha;
02753       vec_copy(&mesh.c[ind12 + 4], cnv + v1);
02754       mesh.c[ind12 +  7] = alpha;
02755       vec_copy(&mesh.c[ind12 + 8], cnv + v2);
02756       mesh.c[ind12 + 11] = alpha;
02757 
02758       mesh.f[i*3  ] = i*3;
02759       mesh.f[i*3+1] = i*3 + 1;
02760       mesh.f[i*3+2] = i*3 + 2;
02761 
02762       v++; // move on to next vertex
02763       i++; // next triangle
02764       ind9+=9;
02765       ind12+=12;
02766     }
02767     v+=2; // last two vertices are already used by last triangle
02768   }
02769 
02770   append_trimesh_v3f_n3f_c3f(mesh);
02771 }
02772 
02773 
02774 

Generated on Thu Apr 25 02:43:20 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002