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

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