source: trunk/packages/vizservers/nanovis/VolumeRenderer.cpp @ 1156

Last change on this file since 1156 was 1111, checked in by gah, 16 years ago

nanovis/heightmap update

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