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