source: trunk/gui/vizservers/nanovis/VolumeRenderer.cpp @ 524

Last change on this file since 524 was 524, checked in by qiaow, 18 years ago

Added ZincBlendeVolume? as a subclass of Volume.
Added shader to render zincblende volume.
Modified nanovis.cpp to handle render zincblende volume.

Need transfer protocle to actually pass two cubic volumes to create a ZincBlendeVolume?

File size: 29.9 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 * VolumeRenderer.cpp : VolumeRenderer class for volume visualization
4 *
5 * ======================================================================
6 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
7 *           Purdue Rendering and Perceptualization Lab (PURPL)
8 *
9 *  Copyright (c) 2004-2006  Purdue Research Foundation
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15
16#include "VolumeRenderer.h"
17
18
19VolumeRenderer::VolumeRenderer(CGcontext _context):
20  n_volumes(0),
21  g_context(_context),
22  slice_mode(false),
23  volume_mode(true)
24{
25  volume.clear();
26  tf.clear();
27
28  init_shaders();
29  init_font("/opt/nanovis/lib/font/Font.bmp");
30}
31
32
33VolumeRenderer::~VolumeRenderer(){}
34
35//initialize the volume shaders
36void VolumeRenderer::init_shaders(){
37 
38  //standard vertex program
39  m_vert_std_vprog = loadProgram(g_context, CG_PROFILE_VP30, CG_SOURCE, "/opt/nanovis/lib/shaders/vertex_std.cg");
40  m_mvp_vert_std_param = cgGetNamedParameter(m_vert_std_vprog, "modelViewProjMatrix");
41  m_mvi_vert_std_param = cgGetNamedParameter(m_vert_std_vprog, "modelViewInv");
42
43
44  //volume rendering shader: one cubic volume
45  m_one_volume_fprog = loadProgram(g_context, CG_PROFILE_FP30, CG_SOURCE, "/opt/nanovis/lib/shaders/one_volume.cg");
46  m_vol_one_volume_param = cgGetNamedParameter(m_one_volume_fprog, "volume");
47  //cgGLSetTextureParameter(m_vol_one_volume_param, _vol->id);
48  m_tf_one_volume_param = cgGetNamedParameter(m_one_volume_fprog, "tf");
49  //m_tf_cut_one_volume_param = cgGetNamedParameter(m_one_volume_fprog, "tf_cutplane");
50  //cgGLSetTextureParameter(m_tf_one_volume_param, _tf->id);
51  m_mvi_one_volume_param = cgGetNamedParameter(m_one_volume_fprog, "modelViewInv");
52  m_mv_one_volume_param = cgGetNamedParameter(m_one_volume_fprog, "modelView");
53  m_render_param_one_volume_param = cgGetNamedParameter(m_one_volume_fprog, "renderParameters");
54
55
56
57  //volume rendering shader: one zincblende orbital volume.
58  //This shader renders one orbital of the simulation.
59  //A sim has S, P, D, SS orbitals. thus a full rendering requires 4 zincblende orbital volumes.
60  //A zincblende orbital volume is decomposed into 2 "interlocking" cubic 4-component volumes and passed to the shader.
61  //We render each orbital with a independent transfer functions then blend the result.
62  //
63  //The engine is already capable of rendering multiple volumes and combine them. Thus, we just invoke this shader on
64  //S, P, D and SS orbitals with different transfor functions. The result is a multi-orbital rendering.
65  m_zincblende_volume_fprog = loadProgram(g_context, CG_PROFILE_FP30, CG_SOURCE,
66                                        "/opt/nanovis/lib/shaders/zincblende_volume.cg");
67
68  m_zincblende_tf_param = cgGetNamedParameter(m_zincblende_volume_fprog, "tf");
69  m_zincblende_volume_a_param = cgGetNamedParameter(m_zincblende_volume_fprog, "volumeA");
70  m_zincblende_volume_b_param = cgGetNamedParameter(m_zincblende_volume_fprog, "volumeB");
71  m_zincblende_cell_size_param = cgGetNamedParameter(m_zincblende_volume_fprog, "cellSize");
72  m_zincblende_mvi_param = cgGetNamedParameter(m_zincblende_volume_fprog, "modelViewInv");
73  m_zincblende_render_param = cgGetNamedParameter(m_zincblende_volume_fprog, "renderParameters");
74
75}
76
77
78int VolumeRenderer::add_volume(Volume* _vol, TransferFunction* _tf){
79
80  int ret = n_volumes;
81
82  volume.push_back(_vol);
83  tf.push_back(_tf);
84
85  n_volumes++;
86
87  return ret;
88}
89
90void
91VolumeRenderer::shade_volume(Volume* _vol, TransferFunction* _tf)
92{
93  for (int i=0; i < volume.size(); i++) {
94    if (volume[i] == _vol) {
95      tf[i] = _tf;
96    }
97  }
98}
99
100TransferFunction*
101VolumeRenderer::get_volume_shading(Volume* _vol)
102{
103  for (int i=0; i < volume.size(); i++) {
104    if (volume[i] == _vol) {
105      return tf[i];
106    }
107  }
108  return NULL;
109}
110
111typedef struct SortElement{
112  float z;
113  int volume_id;
114  int slice_id;
115  SortElement(float _z, int _v, int _s):
116          z(_z), volume_id(_v), slice_id(_s){}
117};
118
119int slice_sort(const void* a, const void* b){
120  if((*((SortElement*)a)).z > (*((SortElement*)b)).z)
121      return 1;
122   else
123      return -1;
124}
125
126
127void VolumeRenderer::render_all(){
128  int total_rendered_slices = 0;
129
130  ConvexPolygon*** polys = new ConvexPolygon**[n_volumes];      //two dimension pointer array
131                                                                        //storing the slices
132  int* actual_slices = new int[n_volumes]; //number of actual slices for each volume
133
134  for(int i=0; i<n_volumes; i++){
135    polys[i] = NULL;
136    actual_slices[i] = 0;
137
138    if(!volume[i]->is_enabled())
139      continue; //skip this volume
140
141    int volume_index = i;
142    int n_slices = volume[volume_index]->get_n_slice();
143
144    //volume start location
145    Vector3* location = volume[volume_index]->get_location();
146    Vector4 shift_4d(location->x, location->y, location->z, 0);
147
148    double x0 = 0;
149    double y0 = 0;
150    double z0 = 0;
151
152    Mat4x4 model_view_no_trans, model_view_trans;
153    Mat4x4 model_view_no_trans_inverse, model_view_trans_inverse;
154
155    double zNear, zFar;
156
157    //initialize volume plane with world coordinates
158    Plane volume_planes[6];
159    volume_planes[0].set_coeffs(1, 0, 0, -x0);
160    volume_planes[1].set_coeffs(-1, 0, 0, x0+1);
161    volume_planes[2].set_coeffs(0, 1, 0, -y0);
162    volume_planes[3].set_coeffs(0, -1, 0, y0+1);
163    volume_planes[4].set_coeffs(0, 0, 1, -z0);
164    volume_planes[5].set_coeffs(0, 0, -1, z0+1);
165 
166    //get modelview matrix with no translation
167    glPushMatrix();
168    glScalef(volume[volume_index]->aspect_ratio_width,
169          volume[volume_index]->aspect_ratio_height,
170          volume[volume_index]->aspect_ratio_depth);
171
172    glEnable(GL_DEPTH_TEST);
173
174    GLfloat mv_no_trans[16];
175    glGetFloatv(GL_MODELVIEW_MATRIX, mv_no_trans);
176
177    model_view_no_trans = Mat4x4(mv_no_trans);
178    model_view_no_trans_inverse = model_view_no_trans.inverse();
179
180    glPopMatrix();
181
182    //get modelview matrix with translation
183    glPushMatrix();
184    glTranslatef(shift_4d.x, shift_4d.y, shift_4d.z);
185    glScalef(volume[volume_index]->aspect_ratio_width,
186          volume[volume_index]->aspect_ratio_height,
187          volume[volume_index]->aspect_ratio_depth);
188    GLfloat mv_trans[16];
189    glGetFloatv(GL_MODELVIEW_MATRIX, mv_trans);
190
191    model_view_trans = Mat4x4(mv_trans);
192    model_view_trans_inverse = model_view_trans.inverse();
193
194    //draw volume bounding box with translation (the correct location in space)
195    if (volume[volume_index]->outline_is_enabled()) {
196        float olcolor[3];
197        volume[volume_index]->get_outline_color(olcolor);
198        draw_bounding_box(x0, y0, z0, x0+1, y0+1, z0+1,
199            (double)olcolor[0], (double)olcolor[1], (double)olcolor[2],
200            1.5);
201    }
202    glPopMatrix();
203
204    //draw labels
205    glPushMatrix();
206    glTranslatef(shift_4d.x, shift_4d.y, shift_4d.z);
207    if(volume[i]->outline_is_enabled()) {
208       draw_label(i);
209    }
210    glPopMatrix();
211
212    //transform volume_planes to eye coordinates.
213    for(int i=0; i<6; i++)
214      volume_planes[i].transform(model_view_no_trans);
215    get_near_far_z(mv_no_trans, zNear, zFar);
216
217    //compute actual rendering slices
218    float z_step = fabs(zNear-zFar)/n_slices;           
219    int n_actual_slices;
220
221    if (volume[volume_index]->data_is_enabled()) {
222        n_actual_slices = (int)(fabs(zNear-zFar)/z_step + 1);
223        polys[volume_index] = new ConvexPolygon*[n_actual_slices];
224    } else {
225        n_actual_slices = 0;
226        polys[volume_index] = NULL;
227    }
228    actual_slices[volume_index] = n_actual_slices;
229
230    Vector4 vert1 = (Vector4(-10, -10, -0.5, 1));
231    Vector4 vert2 = (Vector4(-10, +10, -0.5, 1));
232    Vector4 vert3 = (Vector4(+10, +10, -0.5, 1));
233    Vector4 vert4 = (Vector4(+10, -10, -0.5, 1));
234
235   
236    //Render cutplanes first with depth test enabled.
237    //They will mark the image with their depth values. Then we render other volume slices.
238    //These volume slices will be occluded correctly by the cutplanes and vice versa.
239
240    ConvexPolygon static_poly;
241    for(int i=0; i<volume[volume_index]->get_cutplane_count(); i++){
242      if(!volume[volume_index]->cutplane_is_enabled(i))
243        continue;
244
245      float offset = volume[volume_index]->get_cutplane(i)->offset;
246      int axis = volume[volume_index]->get_cutplane(i)->orient;
247
248      if(axis==3){
249        vert1 = Vector4(-10, -10, offset, 1);
250        vert2 = Vector4(-10, +10, offset, 1);
251        vert3 = Vector4(+10, +10, offset, 1);
252        vert4 = Vector4(+10, -10, offset, 1);
253        //continue;
254      }
255      else if(axis==1){
256        vert1 = Vector4(offset, -10, -10, 1);
257        vert2 = Vector4(offset, +10, -10, 1);
258        vert3 = Vector4(offset, +10, +10, 1);
259        vert4 = Vector4(offset, -10, +10, 1);
260        //continue;
261      }
262      else if(axis==2){
263        vert1 = Vector4(-10, offset, -10, 1);
264        vert2 = Vector4(+10, offset, -10, 1);
265        vert3 = Vector4(+10, offset, +10, 1);
266        vert4 = Vector4(-10, offset, +10, 1);
267        //continue;
268      }
269
270      vert1 = model_view_no_trans.transform(vert1);
271      vert2 = model_view_no_trans.transform(vert2);
272      vert3 = model_view_no_trans.transform(vert3);
273      vert4 = model_view_no_trans.transform(vert4);
274
275      ConvexPolygon* p = &static_poly;
276      p->vertices.clear();
277
278      p->append_vertex(vert1);
279      p->append_vertex(vert2);
280      p->append_vertex(vert3);
281      p->append_vertex(vert4);
282
283      for(int k=0; k<6; k++){
284        p->clip(volume_planes[k], true);
285      }
286
287      p->transform(model_view_no_trans_inverse);
288      p->transform(model_view_trans);
289
290      glPushMatrix();
291      glScalef(volume[volume_index]->aspect_ratio_width, volume[volume_index]->aspect_ratio_height, volume[volume_index]->aspect_ratio_depth);
292
293      activate_volume_shader(volume_index, true);
294      glPopMatrix();
295
296      glEnable(GL_DEPTH_TEST);
297      glDisable(GL_BLEND);
298
299      glBegin(GL_POLYGON);
300        p->Emit(true);
301      glEnd();
302      glDisable(GL_DEPTH_TEST);
303
304      deactivate_volume_shader();
305    } //done cutplanes
306
307   
308    //Now do volume rendering
309
310    vert1 = (Vector4(-10, -10, -0.5, 1));
311    vert2 = (Vector4(-10, +10, -0.5, 1));
312    vert3 = (Vector4(+10, +10, -0.5, 1));
313    vert4 = (Vector4(+10, -10, -0.5, 1));
314
315    int counter = 0;
316   
317    //transform slices and store them
318    float slice_z;
319    for (int i=0; i<n_actual_slices; i++){
320      slice_z = zFar + i * z_step;      //back to front
321
322      ConvexPolygon *poly = new ConvexPolygon();
323      polys[volume_index][counter] = poly;
324      counter++;
325
326      poly->vertices.clear();
327      poly->set_id(volume_index);
328
329      //Setting Z-coordinate
330      vert1.z = slice_z;
331      vert2.z = slice_z;
332      vert3.z = slice_z;
333      vert4.z = slice_z;
334               
335      poly->append_vertex(vert1);
336      poly->append_vertex(vert2);
337      poly->append_vertex(vert3);
338      poly->append_vertex(vert4);
339       
340      for(int k=0; k<6; k++){
341        poly->clip(volume_planes[k], true);
342      }
343
344      poly->transform(model_view_no_trans_inverse);
345      poly->transform(model_view_trans);
346
347      if(poly->vertices.size()>=3)
348        total_rendered_slices++;
349    }
350   
351  } //iterate all volumes
352  //fprintf(stderr, "total slices: %d\n", total_rendered_slices);
353
354  //We sort all the polygons according to their eye-space depth, from farthest to the closest.
355  //This step is critical for correct blending
356
357  SortElement* slices = (SortElement*) malloc(sizeof(SortElement)*total_rendered_slices);
358
359  int counter = 0;
360  for(int i=0; i<n_volumes; i++){
361    for(int j=0; j<actual_slices[i]; j++){
362      if(polys[i][j]->vertices.size() >= 3){
363        slices[counter] = SortElement(polys[i][j]->vertices[0].z, i, j);
364        counter++;
365      }
366    }
367  }
368
369  //sort them
370  qsort(slices, total_rendered_slices, sizeof(SortElement), slice_sort);
371
372  /*
373  //debug
374  for(int i=0; i<total_rendered_slices; i++){
375    fprintf(stderr, "%f ", slices[i].z);
376  }
377  fprintf(stderr, "\n\n");
378  */
379
380  //Now we are ready to render all the slices from back to front
381  glEnable(GL_DEPTH_TEST);
382  glEnable(GL_BLEND);
383
384  for(int i=0; i<total_rendered_slices; i++){
385    int volume_index = slices[i].volume_id;
386    int slice_index = slices[i].slice_id;
387    ConvexPolygon* cur = polys[volume_index][slice_index];
388
389    glPushMatrix();
390    glScalef(volume[volume_index]->aspect_ratio_width, volume[volume_index]->aspect_ratio_height, volume[volume_index]->aspect_ratio_depth);
391   
392    activate_volume_shader(volume_index, false);
393    glPopMatrix();
394
395    glBegin(GL_POLYGON);
396      cur->Emit(true);
397    glEnd();
398
399    deactivate_volume_shader();
400  }
401
402
403  glDisable(GL_DEPTH_TEST);
404  glDisable(GL_BLEND);
405
406  //Deallocate all the memory used
407  for(int i=0; i<n_volumes; i++){
408    for(int j=0; j<actual_slices[i]; j++){
409      delete polys[i][j];
410    }
411    if (polys[i]) {
412      delete[] polys[i];
413    }
414  }
415  delete[] polys;
416  delete[] actual_slices;
417  free(slices);
418}
419
420
421void VolumeRenderer::render(int volume_index){
422  int n_slices = volume[volume_index]->get_n_slice();
423
424  //volume start location
425  Vector4 shift_4d(volume[volume_index]->location.x, volume[volume_index]->location.y, volume[volume_index]->location.z, 0);
426
427  double x0 = 0;
428  double y0 = 0;
429  double z0 = 0;
430
431  Mat4x4 model_view_no_trans, model_view_trans;
432  Mat4x4 model_view_no_trans_inverse, model_view_trans_inverse;
433
434  double zNear, zFar;
435
436  //initialize volume plane with world coordinates
437  Plane volume_planes[6];
438  volume_planes[0].set_coeffs(1, 0, 0, -x0);
439  volume_planes[1].set_coeffs(-1, 0, 0, x0+1);
440  volume_planes[2].set_coeffs(0, 1, 0, -y0);
441  volume_planes[3].set_coeffs(0, -1, 0, y0+1);
442  volume_planes[4].set_coeffs(0, 0, 1, -z0);
443  volume_planes[5].set_coeffs(0, 0, -1, z0+1);
444 
445  glPushMatrix();
446
447  glScalef(volume[volume_index]->aspect_ratio_width,
448          volume[volume_index]->aspect_ratio_height,
449          volume[volume_index]->aspect_ratio_depth);
450
451  glEnable(GL_DEPTH_TEST);
452
453  GLfloat mv_no_trans[16];
454  glGetFloatv(GL_MODELVIEW_MATRIX, mv_no_trans);
455
456  model_view_no_trans = Mat4x4(mv_no_trans);
457  model_view_no_trans_inverse = model_view_no_trans.inverse();
458
459  glPopMatrix();
460
461  //get modelview matrix with translation
462  glPushMatrix();
463  glTranslatef(shift_4d.x, shift_4d.y, shift_4d.z);
464  glScalef(volume[volume_index]->aspect_ratio_width,
465          volume[volume_index]->aspect_ratio_height,
466          volume[volume_index]->aspect_ratio_depth);
467  GLfloat mv_trans[16];
468  glGetFloatv(GL_MODELVIEW_MATRIX, mv_trans);
469
470  model_view_trans = Mat4x4(mv_trans);
471  model_view_trans_inverse = model_view_trans.inverse();
472
473  //draw volume bounding box
474  draw_bounding_box(x0, y0, z0, x0+1, y0+1, z0+1, 0.8, 0.1, 0.1, 1.5);
475  glPopMatrix();
476
477  //transform volume_planes to eye coordinates.
478  for(int i=0; i<6; i++)
479    volume_planes[i].transform(model_view_no_trans);
480
481  get_near_far_z(mv_no_trans, zNear, zFar);
482  //fprintf(stderr, "zNear:%f, zFar:%f\n", zNear, zFar);
483  //fflush(stderr);
484
485  //compute actual rendering slices
486  float z_step = fabs(zNear-zFar)/n_slices;             
487  int n_actual_slices = (int)(fabs(zNear-zFar)/z_step + 1);
488  //fprintf(stderr, "slices: %d\n", n_actual_slices);
489  //fflush(stderr);
490
491  static ConvexPolygon staticPoly;     
492  float slice_z;
493
494  Vector4 vert1 = (Vector4(-10, -10, -0.5, 1));
495  Vector4 vert2 = (Vector4(-10, +10, -0.5, 1));
496  Vector4 vert3 = (Vector4(+10, +10, -0.5, 1));
497  Vector4 vert4 = (Vector4(+10, -10, -0.5, 1));
498
499  glEnable(GL_BLEND);
500
501  if(slice_mode){
502    glEnable(GL_DEPTH_TEST);
503
504  //render the cut planes
505  for(int i=0; i<volume[volume_index]->get_cutplane_count(); i++){
506    float offset = volume[volume_index]->get_cutplane(i)->offset;
507    int axis = volume[volume_index]->get_cutplane(i)->orient;
508
509    if(axis==1){
510      vert1 = Vector4(-10, -10, offset, 1);
511      vert2 = Vector4(-10, +10, offset, 1);
512      vert3 = Vector4(+10, +10, offset, 1);
513      vert4 = Vector4(+10, -10, offset, 1);
514    }
515    else if(axis==2){
516      vert1 = Vector4(offset, -10, -10, 1);
517      vert2 = Vector4(offset, +10, -10, 1);
518      vert3 = Vector4(offset, +10, +10, 1);
519      vert4 = Vector4(offset, -10, +10, 1);
520    }
521    else if(axis==3){
522      vert1 = Vector4(-10, offset, -10, 1);
523      vert2 = Vector4(+10, offset, -10, 1);
524      vert3 = Vector4(+10, offset, +10, 1);
525      vert4 = Vector4(-10, offset, +10, 1);
526    }
527
528    vert1 = model_view_no_trans.transform(vert1);
529    vert2 = model_view_no_trans.transform(vert2);
530    vert3 = model_view_no_trans.transform(vert3);
531    vert4 = model_view_no_trans.transform(vert4);
532
533    ConvexPolygon *poly;
534    poly = &staticPoly;
535    poly->vertices.clear();
536
537    poly->append_vertex(vert1);
538    poly->append_vertex(vert2);
539    poly->append_vertex(vert3);
540    poly->append_vertex(vert4);
541
542    for(int k=0; k<6; k++){
543      poly->clip(volume_planes[k], true);
544    }
545
546    //poly->transform(model_view_inverse);
547    //poly->translate(shift_4d);
548    //poly->transform(model_view);
549    poly->transform(model_view_no_trans_inverse);
550    poly->transform(model_view_trans);
551
552    glPushMatrix();
553    glScalef(volume[volume_index]->aspect_ratio_width, volume[volume_index]->aspect_ratio_height, volume[volume_index]->aspect_ratio_depth);
554
555    activate_volume_shader(volume_index, true);
556    glPopMatrix();
557
558    glBegin(GL_POLYGON);
559      poly->Emit(true);
560    glEnd();
561
562    deactivate_volume_shader();
563  }
564  } //slice_mode
565
566
567  if(volume_mode){
568  glEnable(GL_DEPTH_TEST);
569
570  for (int i=0; i<n_actual_slices; i++){
571    slice_z = zFar + i * z_step;        //back to front
572       
573    ConvexPolygon *poly;
574    poly = &staticPoly;
575    poly->vertices.clear();
576
577    //Setting Z-coordinate
578    vert1.z = slice_z;
579    vert2.z = slice_z;
580    vert3.z = slice_z;
581    vert4.z = slice_z;
582               
583    poly->append_vertex(vert1);
584    poly->append_vertex(vert2);
585    poly->append_vertex(vert3);
586    poly->append_vertex(vert4);
587       
588    for(int k=0; k<6; k++){
589      poly->clip(volume_planes[k], true);
590    }
591
592    //move the volume to the proper location
593    //poly->transform(model_view_inverse);
594    //poly->translate(shift_4d);
595    //poly->transform(model_view);
596
597    poly->transform(model_view_no_trans_inverse);
598    poly->transform(model_view_trans);
599
600    glPushMatrix();
601    glScalef(volume[volume_index]->aspect_ratio_width, volume[volume_index]->aspect_ratio_height, volume[volume_index]->aspect_ratio_depth);
602   
603   /*
604    //draw slice lines only
605    glDisable(GL_BLEND);
606    glDisable(GL_TEXTURE_3D);
607    glDisable(GL_TEXTURE_2D);
608    glLineWidth(1.0);
609    glColor3f(1,1,1);
610    glBegin(GL_LINE_LOOP);
611      poly->Emit(false);
612    glEnd();
613    */
614   
615    activate_volume_shader(volume_index, false);
616    glPopMatrix();
617
618    glBegin(GL_POLYGON);
619      poly->Emit(true);
620    glEnd();
621
622    deactivate_volume_shader();
623               
624  }
625  } //volume_mode
626
627  glDisable(GL_BLEND);
628  glDisable(GL_DEPTH_TEST);
629}
630
631void VolumeRenderer::draw_bounding_box(float x0, float y0, float z0,
632                float x1, float y1, float z1,
633                float r, float g, float b, float line_width)
634{
635        glDisable(GL_TEXTURE_2D);
636
637        glColor4d(r, g, b, 1.0);
638        glLineWidth(line_width);
639       
640        glBegin(GL_LINE_LOOP);
641
642                glVertex3d(x0, y0, z0);
643                glVertex3d(x1, y0, z0);
644                glVertex3d(x1, y1, z0);
645                glVertex3d(x0, y1, z0);
646               
647        glEnd();
648
649        glBegin(GL_LINE_LOOP);
650
651                glVertex3d(x0, y0, z1);
652                glVertex3d(x1, y0, z1);
653                glVertex3d(x1, y1, z1);
654                glVertex3d(x0, y1, z1);
655               
656        glEnd();
657
658
659        glBegin(GL_LINE_LOOP);
660
661                glVertex3d(x0, y0, z0);
662                glVertex3d(x0, y0, z1);
663                glVertex3d(x0, y1, z1);
664                glVertex3d(x0, y1, z0);
665               
666        glEnd();
667
668        glBegin(GL_LINE_LOOP);
669
670                glVertex3d(x1, y0, z0);
671                glVertex3d(x1, y0, z1);
672                glVertex3d(x1, y1, z1);
673                glVertex3d(x1, y1, z0);
674               
675        glEnd();
676
677        glEnable(GL_TEXTURE_2D);
678}
679
680
681
682void VolumeRenderer::activate_volume_shader(int volume_index, bool slice_mode){
683
684  //vertex shader
685  cgGLSetStateMatrixParameter(m_mvp_vert_std_param, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
686  cgGLSetStateMatrixParameter(m_mvi_vert_std_param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE);
687  cgGLBindProgram(m_vert_std_vprog);
688  cgGLEnableProfile(CG_PROFILE_VP30);
689
690
691  if (volume[volume_index]->volume_type == CUBIC)
692  {
693    //regular cubic volume
694    //
695
696    cgGLSetStateMatrixParameter(m_mvi_one_volume_param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE);
697    cgGLSetStateMatrixParameter(m_mv_one_volume_param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_IDENTITY);
698    cgGLSetTextureParameter(m_vol_one_volume_param, volume[volume_index]->id);
699    cgGLSetTextureParameter(m_tf_one_volume_param, tf[volume_index]->id);
700    //cgGLSetTextureParameter(m_tf_cut_one_volume_param, tf_cut[volume_index]->id);
701    cgGLEnableTextureParameter(m_vol_one_volume_param);
702    cgGLEnableTextureParameter(m_tf_one_volume_param);
703    //cgGLEnableTextureParameter(m_tf_cut_one_volume_param);
704
705    if(!slice_mode)
706      cgGLSetParameter4f(m_render_param_one_volume_param,
707                  volume[volume_index]->get_n_slice(),
708                  volume[volume_index]->get_opacity_scale(),
709                  volume[volume_index]->get_diffuse(),
710                  volume[volume_index]->get_specular());
711    else
712      cgGLSetParameter4f(m_render_param_one_volume_param,
713                  0.,
714                  volume[volume_index]->get_opacity_scale(),
715                  volume[volume_index]->get_diffuse(),
716                  volume[volume_index]->get_specular());
717
718    cgGLBindProgram(m_one_volume_fprog);
719    cgGLEnableProfile(CG_PROFILE_FP30);
720  }
721
722  else if (volume[volume_index]->volume_type == ZINCBLENDE)
723  {
724    //zinc blende volume
725    ZincBlendeVolume* vol = (ZincBlendeVolume*) volume[volume_index];
726
727    cgGLSetStateMatrixParameter(m_zincblende_mvi_param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE);
728    cgGLSetTextureParameter(m_zincblende_tf_param, tf[volume_index]->id);
729    cgGLSetParameter4f(m_zincblende_cell_size_param, vol->cell_size.x, vol->cell_size.y, vol->cell_size.z, 0.);
730
731    cgGLSetTextureParameter(m_zincblende_volume_a_param, vol->zincblende_tex[0]->id);
732    cgGLSetTextureParameter(m_zincblende_volume_b_param, vol->zincblende_tex[1]->id);
733    cgGLEnableTextureParameter(m_zincblende_volume_a_param);
734    cgGLEnableTextureParameter(m_zincblende_volume_b_param);
735
736    if(!slice_mode)
737      cgGLSetParameter4f(m_zincblende_render_param,
738                  vol->get_n_slice(),
739                  vol->get_opacity_scale(),
740                  vol->get_diffuse(),
741                  vol->get_specular());
742    else
743      cgGLSetParameter4f(m_zincblende_render_param,
744                  0.,
745                  vol->get_opacity_scale(),
746                  vol->get_diffuse(),
747                  vol->get_specular());
748
749    cgGLBindProgram(m_zincblende_volume_fprog);
750    cgGLEnableProfile(CG_PROFILE_FP30);
751
752  }
753}
754
755
756void VolumeRenderer::deactivate_volume_shader(){
757  cgGLDisableProfile(CG_PROFILE_VP30);
758  cgGLDisableProfile(CG_PROFILE_FP30);
759
760  cgGLDisableTextureParameter(m_vol_one_volume_param);
761  cgGLDisableTextureParameter(m_tf_one_volume_param);
762
763  cgGLDisableTextureParameter(m_zincblende_volume_a_param);
764  cgGLDisableTextureParameter(m_zincblende_volume_b_param);
765  cgGLDisableTextureParameter(m_zincblende_tf_param);
766}
767
768
769void VolumeRenderer::get_near_far_z(Mat4x4 mv, double &zNear, double &zFar)
770{
771
772  double x0 = 0;
773  double y0 = 0;
774  double z0 = 0;
775  double x1 = 1;
776  double y1 = 1;
777  double z1 = 1;
778
779  double zMin, zMax;
780  zMin =  10000;
781  zMax = -10000;
782
783  double vertex[8][4];
784
785  vertex[0][0]=x0; vertex[0][1]=y0; vertex[0][2]=z0; vertex[0][3]=1.0;
786  vertex[1][0]=x1; vertex[1][1]=y0; vertex[1][2]=z0; vertex[1][3]=1.0;
787  vertex[2][0]=x0; vertex[2][1]=y1; vertex[2][2]=z0; vertex[2][3]=1.0;
788  vertex[3][0]=x0; vertex[3][1]=y0; vertex[3][2]=z1; vertex[3][3]=1.0;
789  vertex[4][0]=x1; vertex[4][1]=y1; vertex[4][2]=z0; vertex[4][3]=1.0;
790  vertex[5][0]=x1; vertex[5][1]=y0; vertex[5][2]=z1; vertex[5][3]=1.0;
791  vertex[6][0]=x0; vertex[6][1]=y1; vertex[6][2]=z1; vertex[6][3]=1.0;
792  vertex[7][0]=x1; vertex[7][1]=y1; vertex[7][2]=z1; vertex[7][3]=1.0;
793
794  for(int i=0;i<8;i++)
795  {
796    Vector4 tmp = mv.transform(Vector4(vertex[i][0], vertex[i][1], vertex[i][2], vertex[i][3]));
797    tmp.perspective_devide();
798    vertex[i][2] = tmp.z;
799    if (vertex[i][2]<zMin) zMin = vertex[i][2];
800    if (vertex[i][2]>zMax) zMax = vertex[i][2];
801  }
802
803  zNear = zMax;
804  zFar = zMin;
805}
806
807void VolumeRenderer::set_slice_mode(bool val) { slice_mode = val; }
808void VolumeRenderer::set_volume_mode(bool val) { volume_mode = val; }
809void VolumeRenderer::switch_slice_mode() { slice_mode = (!slice_mode); }
810void VolumeRenderer::switch_volume_mode() { volume_mode = (!volume_mode); }
811
812void VolumeRenderer::enable_volume(int index){
813  volume[index]->enable();
814}
815
816void VolumeRenderer::disable_volume(int index){
817  volume[index]->disable();
818}
819
820
821void VolumeRenderer::init_font(char* filename) {
822
823    FILE *file;
824    unsigned short int bfType;
825    long int bfOffBits;
826    short int biPlanes;
827    short int biBitCount;
828    long int biSizeImage;
829    int width, height;
830    int i;
831    unsigned char temp;
832
833
834    /* make sure the file is there and open it read-only (binary) */
835    if ((file = fopen(filename, "rb")) == NULL)
836    {
837      assert(false);
838    }
839   
840    if(!fread(&bfType, sizeof(short int), 1, file))
841    {
842      assert(false);
843      //printf("Error reading file!\n");
844    }
845   
846    /* check if file is a bitmap */
847    if (bfType != 19778)
848    {
849      assert(false);
850      //printf("Not a Bitmap-File!\n");
851    }
852   
853    /* get the file size */
854    /* skip file size and reserved fields of bitmap file header */
855    fseek(file, 8, SEEK_CUR);
856   
857    /* get the position of the actual bitmap data */
858    if (!fread(&bfOffBits, sizeof(long int), 1, file))
859    {
860      assert(false);
861      //printf("Error reading file!\n");
862    }
863    //printf("Data at Offset: %ld\n", bfOffBits);
864   
865    /* skip size of bitmap info header */
866    fseek(file, 4, SEEK_CUR);
867   
868    /* get the width of the bitmap */
869    fread(&width, sizeof(int), 1, file);
870    //printf("Width of Bitmap: %d\n", texture->width);
871   
872    /* get the height of the bitmap */
873    fread(&height, sizeof(int), 1, file);
874    //printf("Height of Bitmap: %d\n", texture->height);
875   
876    /* get the number of planes (must be set to 1) */
877    fread(&biPlanes, sizeof(short int), 1, file);
878    if (biPlanes != 1)
879    {
880      assert(false);
881      //printf("Error: number of Planes not 1!\n");
882    }
883   
884    /* get the number of bits per pixel */
885    if (!fread(&biBitCount, sizeof(short int), 1, file))
886    {
887      assert(false);
888      //printf("Error reading file!\n");
889      //return 0;
890    }
891   
892    //printf("Bits per Pixel: %d\n", biBitCount);
893    if (biBitCount != 24)
894    {
895      assert(false);
896      //printf("Bits per Pixel not 24\n");
897      //return 0;
898    }
899
900
901    /* calculate the size of the image in bytes */
902    biSizeImage = width * height * 3 * sizeof(unsigned char);
903    unsigned char* data = (unsigned char*) malloc(biSizeImage);
904
905
906    /* seek to the actual data */
907    fseek(file, bfOffBits, SEEK_SET);
908    if (!fread(data, biSizeImage, 1, file))
909    {
910       assert(false);
911       //printf("Error loading file!\n");
912    }
913
914    /* swap red and blue (bgr -> rgb) */
915    for (i = 0; i < biSizeImage; i += 3)
916    {
917       temp = data[i];
918       data[i] = data[i + 2];
919       data[i + 2] = temp;
920    }
921
922    //insert alpha channel
923    unsigned char* data_with_alpha = (unsigned char*) malloc(width*height*4*sizeof(unsigned char));
924    for(int i=0; i<height; i++){
925      for(int j=0; j<width; j++){
926        unsigned char r, g, b, a;
927        r = data[3*(i*width+j)];
928        g = data[3*(i*width+j)+1];
929        b = data[3*(i*width+j)+2];
930
931        if(r==0 && g==0 && b==0)
932          a = 0;
933        else
934          a = 255;
935
936        data_with_alpha[4*(i*width+j)] = r;
937        data_with_alpha[4*(i*width+j) + 1] = g;
938        data_with_alpha[4*(i*width+j) + 2] = b;
939        data_with_alpha[4*(i*width+j) + 3] = a;
940
941      }
942    }
943    free(data);
944
945    //create opengl texture
946    glGenTextures(1, &font_texture);
947    glBindTexture(GL_TEXTURE_2D, font_texture);
948    //glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
949    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_with_alpha);
950    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
951    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
952    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
953
954    free(data_with_alpha);
955
956    build_font();
957    assert(glGetError()==0);
958}
959
960
961
962void VolumeRenderer::draw_label(int volume_index){
963
964  Volume* vol = volume[volume_index];
965 
966  //glEnable(GL_TEXTURE_2D);
967  glDisable(GL_TEXTURE_2D);
968  glEnable(GL_DEPTH_TEST);
969
970  //x
971  glColor3f(0.5, 0.5, 0.5);
972
973  int length = vol->label[0].size();
974  glPushMatrix();
975 
976    glTranslatef(.5*vol->aspect_ratio_width, vol->aspect_ratio_height, -0.1*vol->aspect_ratio_depth);
977    glRotatef(180, 0, 0, 1);
978    glRotatef(90, 1, 0, 0);
979
980    glScalef(0.0008, 0.0008, 0.0008);
981    for(int i=0; i<length; i++){
982      glutStrokeCharacter(GLUT_STROKE_ROMAN, vol->label[0].c_str()[i]);
983      glTranslatef(0.04, 0., 0.);
984    }
985  glPopMatrix();
986
987  //y
988  length = vol->label[1].size();
989  glPushMatrix();
990    glTranslatef(vol->aspect_ratio_width, 0.5*vol->aspect_ratio_height, -0.1*vol->aspect_ratio_depth);
991    glRotatef(90, 0, 1, 0);
992    glRotatef(90, 0, 0, 1);
993
994    glScalef(0.0008, 0.0008, 0.0008);
995    for(int i=0; i<length; i++){
996      glutStrokeCharacter(GLUT_STROKE_ROMAN, vol->label[1].c_str()[i]);
997      glTranslatef(0.04, 0., 0.);
998    }
999  glPopMatrix();
1000
1001
1002  //z
1003  length = vol->label[2].size();
1004  glPushMatrix();
1005    glTranslatef(0., 1.*vol->aspect_ratio_height, 0.5*vol->aspect_ratio_depth);
1006    glRotatef(90, 0, 1, 0);
1007
1008    glScalef(0.0008, 0.0008, 0.0008);
1009    for(int i=0; i<length; i++){
1010      glutStrokeCharacter(GLUT_STROKE_ROMAN, vol->label[2].c_str()[i]);
1011      glTranslatef(0.04, 0., 0.);
1012    }
1013  glPopMatrix();
1014
1015  glDisable(GL_TEXTURE_2D);
1016}
1017
1018
1019
1020void VolumeRenderer::build_font() {
1021
1022    GLfloat cx, cy;         /* the character coordinates in our texture */
1023    font_base = glGenLists(256);
1024    glBindTexture(GL_TEXTURE_2D, font_texture);
1025    for (int loop = 0; loop < 256; loop++)
1026    {
1027        cx = (float) (loop % 16) / 16.0f;
1028        cy = (float) (loop / 16) / 16.0f;
1029        glNewList(font_base + loop, GL_COMPILE);
1030            glBegin(GL_QUADS);
1031                glTexCoord2f(cx, 1 - cy - 0.0625f);
1032                glVertex3f(0, 0, 0);
1033                glTexCoord2f(cx + 0.0625f, 1 - cy - 0.0625f);
1034                glVertex3f(0.04, 0, 0);
1035                glTexCoord2f(cx + 0.0625f, 1 - cy);
1036                glVertex3f(0.04, 0.04, 0);
1037                glTexCoord2f(cx, 1 - cy);
1038                glVertex3f(0, 0.04, 0);
1039            glEnd();
1040            glTranslated(0.04, 0, 0);
1041        glEndList();
1042    }
1043}
1044
1045
1046   
1047void VolumeRenderer::glPrint(char* string, int set){
1048
1049    if(set>1) set=1;
1050
1051    glBindTexture(GL_TEXTURE_2D, font_texture);
1052
1053    glListBase(font_base - 32 + (128 * set));
1054    glCallLists(strlen(string), GL_BYTE, string);
1055
1056}
1057
Note: See TracBrowser for help on using the repository browser.