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], ¢ers[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], ¢ers[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(¢ers[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(¢ers[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(¢ers[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