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