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