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

ANARIRenderer.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr 
00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 
00004 *cr University of Illinois 
00005 *cr All Rights Reserved 
00006 *cr 
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010 * RCS INFORMATION:
00011 *
00012 * $RCSfile: 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], &centers[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], &centers[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(&centers[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(&centers[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(&centers[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 

Generated on Mon Nov 17 02:45:28 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /