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

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

various cleanups

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