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

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

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