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

Last change on this file since 927 was 927, checked in by gah, 13 years ago

collect limits for axes

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