source: trunk/vizservers/nanovis/VolumeRenderer.cpp @ 837

Last change on this file since 837 was 825, checked in by vrinside, 17 years ago

Image Loader initialization

  • Add BMP loader in Nv.cpp

Point Renderer code added..

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