00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00037 #include <math.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <string.h>
00041
00042 #include "VMDApp.h"
00043 #include "QuickSurf.h"
00044
00045 #include "DispCmds.h"
00046 #include "ANARIDisplayDevice.h"
00047 #include "ANARIRenderer.h"
00048 #include "config.h"
00049 #include "Hershey.h"
00050
00051
00052
00053
00054 #define DEFAULT_RADIUS 0.0025f
00055
00056
00057
00058 void ANARIDisplayDevice::ANARI_Global_Init(void) {
00059 ANARIRender::ANARI_Global_Init();
00060 }
00061
00062
00063 void ANARIDisplayDevice::ANARI_Global_Shutdown(void) {
00064 ANARIRender::ANARI_Global_Shutdown();
00065 }
00066
00067
00069 ANARIDisplayDevice::ANARIDisplayDevice(VMDApp *app, int interactive) : FileRenderer((interactive) ?
00070 "ANARIInteractive" : "ANARIInternal",
00071 (interactive) ?
00072 "ANARI (interactive)" : "ANARI (internal, in-memory)",
00073 "vmdscene.ppm", DEF_VMDIMAGEVIEWER) {
00074 vmdapp = app;
00075
00076 reset_vars();
00077
00078
00079 isinteractive = interactive;
00080
00081
00082 formats.add_name("PPM", 0);
00083
00084
00085 curformat = 0;
00086
00087
00088 has_aa = TRUE;
00089 aasamples = 12;
00090 aosamples = 12;
00091
00092 ort = new ANARIRender();
00093 ort_timer = wkf_timer_create();
00094 }
00095
00097 ANARIDisplayDevice::~ANARIDisplayDevice(void) {
00098 delete ort;
00099 ort = NULL;
00100 wkf_timer_destroy(ort_timer);
00101 }
00102
00103 void ANARIDisplayDevice::add_material(void) {
00104 ort->add_material(materialIndex,
00105 mat_ambient, mat_diffuse, mat_specular, mat_shininess,
00106 mat_mirror, mat_opacity, mat_outline, mat_outlinewidth,
00107 mat_transmode > 0.5f);
00108 }
00109
00110
00112 void ANARIDisplayDevice::reset_vars(void) {
00113
00114 reset_triangle_buffer();
00115 }
00116
00117
00118 void ANARIDisplayDevice::comment(const char *s) {
00119 ort->comment(s);
00120 }
00121
00122
00123 #if 0
00124
00125 void ANARIDisplayDevice::send_cylinder_buffer() {
00126 if (cylinder_vert_buffer.num() > 0) {
00127
00128 ort->cylinder_array_color(*cylinder_xform, cylinder_radius_scalefactor,
00129 cylinder_vert_buffer.num()/6,
00130 &cylinder_vert_buffer[0],
00131 &cylinder_radii_buffer[0],
00132 &cylinder_color_buffer[0],
00133 cylinder_matindex);
00134
00135 #if 0
00136
00137 if (cylcap_vert_buffer.num() > 0) {
00138 ort->ring_array_color(*cylinder_xform, cylinder_radius_scalefactor,
00139 cylcap_vert_buffer.num()/3,
00140 &cylcap_vert_buffer[0],
00141 &cylcap_norm_buffer[0],
00142 &cylcap_radii_buffer[0],
00143 &cylcap_color_buffer[0],
00144 cylinder_matindex);
00145 }
00146 #endif
00147
00148 delete cylinder_xform;
00149 cylinder_xform=NULL;
00150 }
00151
00152 }
00153
00154
00155
00156 void ANARIDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
00157
00158
00159 if (cylinder_xform != NULL && ((cylinder_matindex != materialIndex) || (memcmp(cylinder_xform->mat, transMat.top().mat, sizeof(cylinder_xform->mat))))) {
00160 send_cylinder_buffer();
00161 }
00162
00163
00164 if (cylinder_xform == NULL) {
00165
00166 cylinder_matindex = materialIndex;
00167 cylinder_xform = new Matrix4(transMat.top());
00168 cylinder_radius_scalefactor = scale_factor();
00169 add_material();
00170 }
00171
00172
00173 cylinder_vert_buffer.append2x3(&a[0], &b[0]);
00174 cylinder_radii_buffer.append(r);
00175 cylinder_color_buffer.append3(&matData[colorIndex][0]);
00176
00177 #if 0
00178
00179
00180 if (filled) {
00181 float norm[3];
00182 norm[0] = b[0] - a[0];
00183 norm[1] = b[1] - a[1];
00184 norm[2] = b[2] - a[2];
00185
00186 float div = 1.0f / sqrtf(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
00187 norm[0] *= div;
00188 norm[1] *= div;
00189 norm[2] *= div;
00190
00191 if (filled & CYLINDER_TRAILINGCAP) {
00192 cylcap_vert_buffer.append3(&a[0]);
00193 cylcap_norm_buffer.append3(&norm[0]);
00194 cylcap_radii_buffer.append2(0.0f, r);
00195 cylcap_color_buffer.append3(&matData[colorIndex][0]);
00196 }
00197
00198 if (filled & CYLINDER_LEADINGCAP) {
00199 cylcap_vert_buffer.append3(&b[0]);
00200 norm[0] *= -1;
00201 norm[1] *= -1;
00202 norm[2] *= -1;
00203 cylcap_norm_buffer.append3(&norm[0]);
00204 cylcap_radii_buffer.append2(0.0f, r);
00205 cylcap_color_buffer.append3(&matData[colorIndex][0]);
00206 }
00207 }
00208 #endif
00209 }
00210
00211 #endif
00212
00213
00214
00215 void ANARIDisplayDevice::sphere_array(int spnum, int spres, float *centers,
00216 float *radii, float *colors) {
00217 add_material();
00218 ort->sphere_array_color(transMat.top(), scale_factor(), spnum,
00219 centers, radii, colors, materialIndex);
00220
00221
00222 int ind=(spnum-1)*3;
00223 super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
00224 }
00225
00226
00227 #if 0
00228
00229
00230
00231
00232 void ANARIDisplayDevice::text(float *pos, float size, float thickness,
00233 const char *str) {
00234 float textpos[3];
00235 float textsize, textthickness;
00236 hersheyhandle hh;
00237
00238
00239 (transMat.top()).multpoint3d(pos, textpos);
00240 textsize = size * 1.5f;
00241 textthickness = thickness*DEFAULT_RADIUS;
00242
00243 ResizeArray<float> text_spheres;
00244 ResizeArray<float> text_cylinders;
00245
00246 while (*str != '\0') {
00247 float lm, rm, x, y, ox, oy;
00248 int draw, odraw;
00249 ox=oy=x=y=0.0f;
00250 draw=odraw=0;
00251
00252 hersheyDrawInitLetter(&hh, *str, &lm, &rm);
00253 textpos[0] -= lm * textsize;
00254
00255 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
00256 float oldpt[3], newpt[3];
00257 if (draw) {
00258 newpt[0] = textpos[0] + textsize * x;
00259 newpt[1] = textpos[1] + textsize * y;
00260 newpt[2] = textpos[2];
00261
00262 if (odraw) {
00263
00264 oldpt[0] = textpos[0] + textsize * ox;
00265 oldpt[1] = textpos[1] + textsize * oy;
00266 oldpt[2] = textpos[2];
00267
00268 text_cylinders.append2x3(&oldpt[0], &newpt[0]);
00269 text_spheres.append3(&newpt[0]);
00270 } else {
00271
00272 text_spheres.append3(&newpt[0]);
00273 }
00274 }
00275
00276 ox=x;
00277 oy=y;
00278 odraw=draw;
00279 }
00280 textpos[0] += rm * textsize;
00281
00282 str++;
00283 }
00284
00285 add_material();
00286
00287 if (text_cylinders.num() > 0) {
00288 ort->cylinder_array(NULL, textthickness, matData[colorIndex],
00289 text_cylinders.num() / 6, &text_cylinders[0],
00290 materialIndex);
00291 }
00292 if (text_spheres.num() > 0) {
00293 ort->sphere_array(NULL, textthickness, matData[colorIndex],
00294 text_spheres.num() / 3, &text_spheres[0], NULL,
00295 materialIndex);
00296 }
00297 }
00298
00299 #endif
00300
00301
00302 void ANARIDisplayDevice::send_triangle_buffer() {
00303 if (triangle_vert_buffer.num() > 0) {
00304 ort->trimesh_n3f_v3f(*triangle_xform,
00305 matData[triangle_cindex],
00306 &triangle_norm_buffer[0],
00307 &triangle_vert_buffer[0],
00308 triangle_vert_buffer.num()/9,
00309 triangle_matindex);
00310 delete triangle_xform;
00311 triangle_xform=NULL;
00312 }
00313 reset_triangle_buffer();
00314 }
00315
00316
00317
00318 void ANARIDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
00319
00320
00321 if (triangle_xform != NULL && ((triangle_cindex != colorIndex) || (triangle_matindex != materialIndex) || (memcmp(triangle_xform->mat, transMat.top().mat, sizeof(triangle_xform->mat))))) {
00322 send_triangle_buffer();
00323 }
00324
00325
00326 if (triangle_xform == NULL) {
00327
00328 triangle_cindex = colorIndex;
00329 triangle_matindex = materialIndex;
00330 triangle_xform = new Matrix4(transMat.top());
00331 add_material();
00332 }
00333
00334
00335 triangle_vert_buffer.append3x3(&a[0], &b[0], &c[0]);
00336
00337
00338 triangle_norm_buffer.append3x3(&n1[0], &n2[0], &n3[0]);
00339 }
00340
00341
00342
00343 void ANARIDisplayDevice::tricolor(const float *a, const float *b, const float *c,
00344 const float *n1, const float *n2, const float *n3,
00345 const float *c1, const float *c2, const float *c3) {
00346 add_material();
00347
00348 float vnc[27];
00349 vec_copy(&vnc[ 0], a);
00350 vec_copy(&vnc[ 3], b);
00351 vec_copy(&vnc[ 6], c);
00352
00353 vec_copy(&vnc[ 9], n1);
00354 vec_copy(&vnc[12], n2);
00355 vec_copy(&vnc[15], n3);
00356
00357 vec_copy(&vnc[18], c1);
00358 vec_copy(&vnc[21], c2);
00359 vec_copy(&vnc[24], c3);
00360
00361 ort->tricolor_list(transMat.top(), 1, vnc, materialIndex);
00362 }
00363
00364
00365 void ANARIDisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, signed char *n,
00366 float *v, int numfacets) {
00367 add_material();
00368 ort->trimesh_c4u_n3b_v3f(transMat.top(), c, n, v, numfacets, materialIndex);
00369 }
00370
00371
00372 void ANARIDisplayDevice::trimesh_c4u_n3f_v3f(unsigned char *c, float *n,
00373 float *v, int numfacets) {
00374 add_material();
00375 ort->trimesh_c4u_n3f_v3f(transMat.top(), c, n, v, numfacets, materialIndex);
00376 }
00377
00378 void ANARIDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
00379 int numfacets, int * facets) {
00380 add_material();
00381 ort->trimesh_c4n3v3(transMat.top(), numverts, cnv, numfacets, facets,
00382 materialIndex);
00383 }
00384
00385 void ANARIDisplayDevice::trimesh_n3b_v3f(signed char *n, float *v, int numfacets) {
00386 add_material();
00387 ort->trimesh_n3b_v3f(transMat.top(), matData[colorIndex], n, v, numfacets, materialIndex);
00388 }
00389
00390 void ANARIDisplayDevice::trimesh_n3f_v3f(float *n, float *v, int numfacets) {
00391 add_material();
00392 ort->trimesh_n3f_v3f(transMat.top(), matData[colorIndex], n, v, numfacets, materialIndex);
00393 }
00394
00395
00396 #if 0
00397 void ANARIDisplayDevice::trimesh_n3fopt_v3f(float *n, float *v, int numfacets) {
00398 add_material();
00399 ort->trimesh_v3f(transMat.top(), matData[colorIndex], v, numfacets, materialIndex);
00400 }
00401
00402 #endif
00403
00404 void ANARIDisplayDevice::tristrip(int numverts, const float * cnv,
00405 int numstrips, const int *vertsperstrip,
00406 const int *facets) {
00407 add_material();
00408 ort->tristrip(transMat.top(), numverts, cnv, numstrips, vertsperstrip,
00409 facets, materialIndex);
00410 }
00411
00412
00413
00414 void ANARIDisplayDevice::write_lights() {
00415 int i;
00416 int lightcount = 0;
00417
00418
00419
00420 ort->clear_all_lights();
00421
00422
00423 for (i=0; i<DISP_LIGHTS; i++) {
00424 if (lightState[i].on) {
00425 ort->add_directional_light(lightState[i].pos, lightState[i].color);
00426 lightcount++;
00427 }
00428 }
00429
00430 #if 0
00431
00432 for (i=0; i<DISP_LIGHTS; i++) {
00433 if (advLightState[i].on) {
00434 float pos[3];
00435
00436
00437 vec_copy(pos, advLightState[i].pos);
00438
00439 if (advLightState[i].spoton) {
00440 printf("ANARIDisplayDevice) SpotLight not implemented yet ...\n");
00441 } else {
00442 apitexture tex;
00443 memset(&tex, 0, sizeof(apitexture));
00444
00445 tex.col.r=advLightState[i].color[0];
00446 tex.col.g=advLightState[i].color[1];
00447 tex.col.b=advLightState[i].color[2];
00448
00449 void *l = rt_light(rtscene,
00450 rt_texture(rtscene, &tex),
00451
00452 rt_vector(pos[0], pos[1], -pos[2]), 0.0f);
00453
00454
00455 if (advLightState[i].constfactor != 1.0f ||
00456 advLightState[i].linearfactor != 0.0f ||
00457 advLightState[i].quadfactor != 0.0f) {
00458 rt_light_attenuation(l,
00459 advLightState[i].constfactor,
00460 advLightState[i].linearfactor,
00461 advLightState[i].quadfactor);
00462 }
00463 }
00464
00465 lightcount++;
00466 }
00467 }
00468 #endif
00469
00470 if (lightcount < 1) {
00471 msgWarn << "No lights defined in molecular scene!!" << sendmsg;
00472 }
00473 }
00474
00475
00476 void ANARIDisplayDevice::write_materials() {
00477 ort->set_bg_color(backColor);
00478
00479
00480
00481 if (backgroundmode == 1) {
00482 float bspheremag = 0.5f;
00483
00484
00485 switch (projection()) {
00486 case DisplayDevice::ORTHOGRAPHIC:
00487
00488
00489
00490
00491 bspheremag = vSize / 4.0f;
00492 break;
00493
00494 case DisplayDevice::PERSPECTIVE:
00495 default:
00496
00497
00498
00499
00500 bspheremag = (vSize / 2.0f) / (eyePos[2] - zDist);
00501 if (bspheremag > 1.0f)
00502 bspheremag = 1.0f;
00503 break;
00504 }
00505
00506 if (projection() == DisplayDevice::ORTHOGRAPHIC)
00507 ort->set_bg_mode(ANARIRender::RT_BACKGROUND_TEXTURE_SKY_ORTHO_PLANE);
00508 else
00509 ort->set_bg_mode(ANARIRender::RT_BACKGROUND_TEXTURE_SKY_SPHERE);
00510
00511 float updir[3] = { 0.0f, 1.0f, 0.0f };
00512 ort->set_bg_color_grad_top(backgradienttopcolor);
00513 ort->set_bg_color_grad_bot(backgradientbotcolor);
00514 ort->set_bg_gradient(updir);
00515 ort->set_bg_gradient_topval(bspheremag);
00516 ort->set_bg_gradient_botval(-bspheremag);
00517 } else {
00518 ort->set_bg_mode(ANARIRender::RT_BACKGROUND_TEXTURE_SOLID);
00519 }
00520 }
00521
00522
00524
00525 void ANARIDisplayDevice::write_header() {
00526 wkf_timer_start(ort_timer);
00527
00528 ort->setup_context(xSize, ySize);
00529 write_materials();
00530 write_lights();
00531
00532 ort->set_aa_samples(aasamples);
00533
00534
00535 if (shadows_enabled() || ao_enabled()) {
00536 if (shadows_enabled() && !ao_enabled())
00537 msgInfo << "Shadow rendering enabled." << sendmsg;
00538
00539 ort->shadows_on(1);
00540 } else {
00541 ort->shadows_on(0);
00542 }
00543
00544
00545 if (ao_enabled()) {
00546 msgInfo << "Ambient occlusion enabled." << sendmsg;
00547 msgInfo << "Shadow rendering enabled." << sendmsg;
00548 ort->set_ao_samples(aosamples);
00549 } else {
00550 ort->set_ao_samples(0);
00551 }
00552
00553
00554
00555 ort->set_ao_ambient(get_ao_ambient());
00556 ort->set_ao_direct(get_ao_direct());
00557
00558
00559 if (dof_enabled()) {
00560 msgInfo << "DoF focal blur enabled." << sendmsg;
00561 ort->dof_on(1);
00562 ort->set_camera_dof_fnumber(get_dof_fnumber());
00563 ort->set_camera_dof_focal_dist(get_dof_focal_dist());
00564 } else {
00565 ort->dof_on(0);
00566 }
00567
00568
00569 float start = get_cue_start();
00570 float end = get_cue_end();
00571 float density = get_cue_density();
00572 if (cueingEnabled) {
00573 switch (cueMode) {
00574 case CUE_LINEAR:
00575 ort->set_cue_mode(ANARIRender::RT_FOG_LINEAR, start, end, density);
00576 break;
00577
00578 case CUE_EXP:
00579 ort->set_cue_mode(ANARIRender::RT_FOG_EXP, start, end, density);
00580 break;
00581
00582 case CUE_EXP2:
00583 ort->set_cue_mode(ANARIRender::RT_FOG_EXP2, start, end, density);
00584 break;
00585
00586 case NUM_CUE_MODES:
00587
00588 break;
00589 }
00590 } else {
00591 ort->set_cue_mode(ANARIRender::RT_FOG_NONE, start, end, density);
00592 }
00593 }
00594
00595
00596 void ANARIDisplayDevice::write_trailer(void){
00597
00598 send_triangle_buffer();
00599
00600 #if 0
00601 printf("ANARI: z: %f zDist: %f vSize %f\n", eyePos[2], zDist, vSize);
00602 #endif
00603 switch (projection()) {
00604 case DisplayDevice::ORTHOGRAPHIC:
00605 ort->set_camera_projection(ANARIRender::RT_ORTHOGRAPHIC);
00606 ort->set_camera_zoom(0.5f / (1.0 / (vSize / 2.0)));
00607 break;
00608
00609 case DisplayDevice::PERSPECTIVE:
00610 default:
00611 ort->set_camera_projection(ANARIRender::RT_PERSPECTIVE);
00612
00613 ort->set_camera_zoom(0.5f * vSize / (eyePos[2] - zDist));
00614 }
00615
00616
00617 ort->set_camera_stereo_eyesep(eyeSep);
00618 ort->set_camera_stereo_convergence_dist(eyeDist);
00619
00620 char *verbstr = getenv("VMDANARIVERBOSE");
00621 if (verbstr != NULL) {
00622 if (!strupcmp(verbstr, "TIMING") || !strupcmp(verbstr, "DEBUG")) {
00623 double time_scene_graph = wkf_timer_timenow(ort_timer);
00624 printf("ANARIDisplayDevice) scene graph construction time %.2f\n",
00625 time_scene_graph);
00626 }
00627 }
00628
00629 #if defined(VMDANARI_INTERACTIVE_OPENGL)
00630 if (isinteractive)
00631 ort->render_to_glwin(my_filename);
00632 else
00633 #endif
00634 ort->render_to_file(my_filename);
00635
00636 reset_vars();
00637
00638 if (getenv("VMDANARINODESTROYCONTEXT") == NULL) {
00639
00640
00641 delete ort;
00642
00643
00644 ort = new ANARIRender();
00645 } else {
00646
00647
00648 ort->destroy_scene();
00649 }
00650
00651 wkf_timer_stop(ort_timer);
00652 printf("ANARIDisplayDevice) Total rendering time: %.2f sec\n", wkf_timer_time(ort_timer));
00653 }
00654
00655
00656
00657
00658