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

Last change on this file since 1493 was 1493, checked in by gah, 15 years ago

Changed vector id to name

File size: 23.9 KB
Line 
1
2/*
3 * ----------------------------------------------------------------------
4 * VolumeRenderer.cpp : VolumeRenderer class for volume visualization
5 *
6 * ======================================================================
7 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
8 *           Purdue Rendering and Perceptualization Lab (PURPL)
9 *
10 *  Copyright (c) 2004-2006  Purdue Research Foundation
11 *
12 *  See the file "license.terms" for information on usage and
13 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * ======================================================================
15 */
16
17#include <assert.h>
18#include <time.h>
19#include <sys/time.h>
20#include "nanovis.h"
21#include <R2/R2string.h>
22#include <R2/R2FilePath.h>
23#include "VolumeRenderer.h"
24#include "VolumeInterpolator.h"
25#include "NvStdVertexShader.h"
26#include "Trace.h"
27#include "Grid.h"
28
29#define NUMDIGITS       6
30
31VolumeRenderer::VolumeRenderer():
32    slice_mode(false),
33    volume_mode(true)
34{
35    init_shaders();
36
37    const char *path = R2FilePath::getInstance()->getPath("Font.bmp");
38    if (path == NULL) {
39        fprintf(stderr, "can't find Font.bmp\n");
40        assert(path != NULL);
41    }
42    init_font(path);
43    delete [] path;
44    _volumeInterpolator = new VolumeInterpolator();
45}
46
47VolumeRenderer::~VolumeRenderer()
48{
49    delete _zincBlendeShader;
50    delete _regularVolumeShader;
51    delete _stdVertexShader;
52    delete _volumeInterpolator;
53}
54
55//initialize the volume shaders
56void VolumeRenderer::init_shaders(){
57 
58  //standard vertex program
59  _stdVertexShader = new NvStdVertexShader();
60
61  //volume rendering shader: one cubic volume
62  _regularVolumeShader = new NvRegularVolumeShader();
63
64  //volume rendering shader: one zincblende orbital volume.
65  //This shader renders one orbital of the simulation.
66  //A sim has S, P, D, SS orbitals. thus a full rendering requires 4 zincblende orbital volumes.
67  //A zincblende orbital volume is decomposed into 2 "interlocking" cubic 4-component volumes and passed to the shader.
68  //We render each orbital with a independent transfer functions then blend the result.
69  //
70  //The engine is already capable of rendering multiple volumes and combine them. Thus, we just invoke this shader on
71  //S, P, D and SS orbitals with different transfor functions. The result is a multi-orbital rendering.
72  _zincBlendeShader = new NvZincBlendeVolumeShader();
73}
74
75struct SortElement {
76    float z;
77    int volume_id;
78    int slice_id;
79    SortElement(float _z, int _v, int _s):
80        z(_z), volume_id(_v), slice_id(_s){}
81};
82
83int slice_sort(const void* a, const void* b){
84  if((*((SortElement*)a)).z > (*((SortElement*)b)).z)
85      return 1;
86   else
87      return -1;
88}
89
90
91void
92VolumeRenderer::render_all()
93{
94    size_t total_rendered_slices = 0;
95
96    if (_volumeInterpolator->is_started()) {
97#ifdef notdef
98        ani_vol = _volumeInterpolator->getVolume();
99        ani_tf = ani_vol->transferFunction();
100#endif
101        Trace("VOLUME INTERPOLATOR IS STARTED ----------------------------");
102    }
103    // Determine the volumes that are to be rendered.
104    vector<Volume *> volumes;
105    Tcl_HashEntry *hPtr;
106    Tcl_HashSearch iter;
107    for (hPtr = Tcl_FirstHashEntry(&NanoVis::volumeTable, &iter); hPtr != NULL;
108         hPtr = Tcl_NextHashEntry(&iter)) {
109        Volume* volPtr;
110        volPtr = (Volume *)Tcl_GetHashValue(hPtr);
111        Trace("volume %s addr=%x\n", volPtr->name(), volPtr);
112        if(!volPtr->visible()) {
113            continue;                   // Skip this volume
114        }
115        // BE CAREFUL: Set the number of slices to something slightly
116        // different for each volume.  If we have identical volumes at exactly
117        // the same position with exactly the same number of slices, the
118        // second volume will overwrite the first, so the first won't appear
119        // at all.
120        volumes.push_back(volPtr);
121        volPtr->n_slices(256 - volumes.size());
122    }
123
124    //two dimension pointer array
125    ConvexPolygon*** polys = new ConvexPolygon**[volumes.size()];       
126    //number of actual slices for each volume
127    size_t* actual_slices = new size_t[volumes.size()];
128
129    Trace("start loop %d\n", volumes.size());
130    for (size_t i = 0; i < volumes.size(); i++) {
131        Volume* volPtr;
132
133        polys[i] = NULL;
134        actual_slices[i] = 0;
135        volPtr = volumes[i];
136
137        int n_slices = volPtr->n_slices();
138        if (volPtr->isosurface()) {
139            // double the number of slices
140            n_slices <<= 1;
141        }
142       
143        //volume start location
144        Vector3 loc = volPtr->location();
145        Vector4 shift_4d(loc.x, loc.y, loc.z, 0);
146       
147        double x0 = 0;
148        double y0 = 0;
149        double z0 = 0;
150       
151        Mat4x4 model_view_no_trans, model_view_trans;
152        Mat4x4 model_view_no_trans_inverse, model_view_trans_inverse;
153       
154        double zNear, zFar;
155       
156        //initialize volume plane with world coordinates
157        Plane volume_planes[6];
158        volume_planes[0].set_coeffs( 1,  0,  0, -x0);
159        volume_planes[1].set_coeffs(-1,  0,  0,  x0+1);
160        volume_planes[2].set_coeffs( 0,  1,  0, -y0);
161        volume_planes[3].set_coeffs( 0, -1,  0,  y0+1);
162        volume_planes[4].set_coeffs( 0,  0,  1, -z0);
163        volume_planes[5].set_coeffs( 0,  0, -1,  z0+1);
164       
165        //get modelview matrix with no translation
166        glPushMatrix();
167        glScalef(volPtr->aspect_ratio_width,
168                 volPtr->aspect_ratio_height,
169                 volPtr->aspect_ratio_depth);
170       
171        glEnable(GL_DEPTH_TEST);
172       
173        GLfloat mv_no_trans[16];
174        glGetFloatv(GL_MODELVIEW_MATRIX, mv_no_trans);
175       
176        model_view_no_trans = Mat4x4(mv_no_trans);
177        model_view_no_trans_inverse = model_view_no_trans.inverse();
178       
179        glPopMatrix();
180       
181        //get modelview matrix with translation
182        glPushMatrix();
183        glTranslatef(shift_4d.x, shift_4d.y, shift_4d.z);
184        glScalef(volPtr->aspect_ratio_width,
185                 volPtr->aspect_ratio_height,
186                 volPtr->aspect_ratio_depth);
187        GLfloat mv_trans[16];
188        glGetFloatv(GL_MODELVIEW_MATRIX, mv_trans);
189       
190        model_view_trans = Mat4x4(mv_trans);
191        model_view_trans_inverse = model_view_trans.inverse();
192       
193        //draw volume bounding box with translation (the correct location in
194        //space)
195        if (volPtr->outline()) {
196            float olcolor[3];
197            volPtr->get_outline_color(olcolor);
198            draw_bounding_box(x0, y0, z0, x0+1, y0+1, z0+1,
199                (double)olcolor[0], (double)olcolor[1], (double)olcolor[2],
200                1.5);
201        }
202        glPopMatrix();
203       
204        //draw labels
205        glPushMatrix();
206        glTranslatef(shift_4d.x, shift_4d.y, shift_4d.z);
207        if(volPtr->outline()) {
208            //draw_label(i);
209        }
210        glPopMatrix();
211       
212        //transform volume_planes to eye coordinates.
213        for(size_t j = 0; j < 6; j++) {
214            volume_planes[j].transform(model_view_no_trans);
215        }
216        get_near_far_z(mv_no_trans, zNear, zFar);
217       
218        //compute actual rendering slices
219        float z_step = fabs(zNear-zFar)/n_slices;               
220        size_t n_actual_slices;
221       
222        if (volPtr->data_enabled()) {
223            n_actual_slices = (int)(fabs(zNear-zFar)/z_step + 1);
224            polys[i] = new ConvexPolygon*[n_actual_slices];
225        } else {
226            n_actual_slices = 0;
227            polys[i] = NULL;
228        }
229        actual_slices[i] = n_actual_slices;
230       
231        Vector4 vert1 = (Vector4(-10, -10, -0.5, 1));
232        Vector4 vert2 = (Vector4(-10, +10, -0.5, 1));
233        Vector4 vert3 = (Vector4(+10, +10, -0.5, 1));
234        Vector4 vert4 = (Vector4(+10, -10, -0.5, 1));
235       
236       
237        // Render cutplanes first with depth test enabled.  They will mark the
238        // image with their depth values.  Then we render other volume slices.
239        // These volume slices will be occluded correctly by the cutplanes and
240        // vice versa.
241       
242        ConvexPolygon static_poly;
243        for(int j = 0; j < volPtr->get_cutplane_count(); j++) {
244            if(!volPtr->cutplane_is_enabled(j))
245                continue;
246           
247            float offset = volPtr->get_cutplane(j)->offset;
248            int axis = volPtr->get_cutplane(j)->orient;
249           
250            if(axis==3){
251                vert1 = Vector4(-10, -10, offset, 1);
252                vert2 = Vector4(-10, +10, offset, 1);
253                vert3 = Vector4(+10, +10, offset, 1);
254                vert4 = Vector4(+10, -10, offset, 1);
255                //continue;
256            } else if(axis==1){
257                vert1 = Vector4(offset, -10, -10, 1);
258                vert2 = Vector4(offset, +10, -10, 1);
259                vert3 = Vector4(offset, +10, +10, 1);
260                vert4 = Vector4(offset, -10, +10, 1);
261                //continue;
262            } else if(axis==2){
263                vert1 = Vector4(-10, offset, -10, 1);
264                vert2 = Vector4(+10, offset, -10, 1);
265                vert3 = Vector4(+10, offset, +10, 1);
266                vert4 = Vector4(-10, offset, +10, 1);
267                //continue;
268            }
269           
270            vert1 = model_view_no_trans.transform(vert1);
271            vert2 = model_view_no_trans.transform(vert2);
272            vert3 = model_view_no_trans.transform(vert3);
273            vert4 = model_view_no_trans.transform(vert4);
274           
275            ConvexPolygon* p = &static_poly;
276            p->vertices.clear();
277           
278            p->append_vertex(vert1);
279            p->append_vertex(vert2);
280            p->append_vertex(vert3);
281            p->append_vertex(vert4);
282           
283            for(size_t k = 0; k < 6; k++){
284                p->clip(volume_planes[k], true);
285            }
286           
287            p->transform(model_view_no_trans_inverse);
288            p->transform(model_view_trans);
289           
290            glPushMatrix();
291            glScalef(volPtr->aspect_ratio_width, volPtr->aspect_ratio_height,
292                     volPtr->aspect_ratio_depth);
293           
294            activate_volume_shader(volPtr, true);
295            glPopMatrix();
296           
297            glEnable(GL_DEPTH_TEST);
298            glDisable(GL_BLEND);
299           
300            glBegin(GL_POLYGON);
301            p->Emit(true);
302            glEnd();
303            glDisable(GL_DEPTH_TEST);
304           
305            deactivate_volume_shader();
306        } //done cutplanes
307       
308       
309        //Now do volume rendering
310       
311        vert1 = (Vector4(-10, -10, -0.5, 1));
312        vert2 = (Vector4(-10, +10, -0.5, 1));
313        vert3 = (Vector4(+10, +10, -0.5, 1));
314        vert4 = (Vector4(+10, -10, -0.5, 1));
315       
316        size_t counter = 0;
317       
318        //transform slices and store them
319        float slice_z;
320        for (size_t j = 0; j < n_actual_slices; j++) {
321            slice_z = zFar + j * z_step;        //back to front
322           
323            ConvexPolygon *poly = new ConvexPolygon();
324            polys[i][counter] = poly;
325            counter++;
326           
327            poly->vertices.clear();
328            poly->set_id(i);
329           
330            //Setting Z-coordinate
331            vert1.z = slice_z;
332            vert2.z = slice_z;
333            vert3.z = slice_z;
334            vert4.z = slice_z;
335           
336            poly->append_vertex(vert1);
337            poly->append_vertex(vert2);
338            poly->append_vertex(vert3);
339            poly->append_vertex(vert4);
340           
341            for(size_t k = 0; k < 6; k++) {
342                poly->clip(volume_planes[k], true);
343            }
344           
345            poly->transform(model_view_no_trans_inverse);
346            poly->transform(model_view_trans);
347           
348            if(poly->vertices.size()>=3)
349                total_rendered_slices++;
350        }
351       
352    } //iterate all volumes
353    fprintf(stderr, "total slices: %d\n", total_rendered_slices);
354    Trace("end loop\n");
355   
356    // We sort all the polygons according to their eye-space depth, from
357    // farthest to the closest.  This step is critical for correct blending
358   
359    SortElement* slices = (SortElement*)
360        malloc(sizeof(SortElement) * total_rendered_slices);
361   
362    size_t counter = 0;
363    for (size_t i = 0; i < volumes.size(); i++){
364        for (size_t j = 0; j < actual_slices[i]; j++){
365            if(polys[i][j]->vertices.size() >= 3){
366                slices[counter] = SortElement(polys[i][j]->vertices[0].z, i, j);
367                counter++;
368            }
369        }
370    }
371   
372    //sort them
373    qsort(slices, total_rendered_slices, sizeof(SortElement), slice_sort);
374   
375    //Now we are ready to render all the slices from back to front
376    glEnable(GL_DEPTH_TEST);
377    glEnable(GL_BLEND);
378   
379    for(size_t i = 0; i < total_rendered_slices; i++){
380        Volume* volPtr;
381
382        int volume_index = slices[i].volume_id;
383        int slice_index = slices[i].slice_id;
384        ConvexPolygon* cur = polys[volume_index][slice_index];
385       
386        volPtr = volumes[volume_index];
387        glPushMatrix();
388        glScalef(volPtr->aspect_ratio_width, volPtr->aspect_ratio_height,
389                 volPtr->aspect_ratio_depth);
390       
391#ifdef notdef
392        Trace("shading slice: volume %s addr=%x slice=%d, volume=%d\n",
393              volPtr->name(), volPtr, slice_index, volume_index);
394#endif
395        activate_volume_shader(volPtr, false);
396        glPopMatrix();
397       
398        glBegin(GL_POLYGON);
399        cur->Emit(true);
400        glEnd();
401
402        deactivate_volume_shader();
403    }
404   
405    glDisable(GL_DEPTH_TEST);
406    glDisable(GL_BLEND);
407   
408    //Deallocate all the memory used
409    for(size_t i = 0; i < volumes.size(); i++){
410        for(size_t j=0; j <actual_slices[i]; j++){
411            delete polys[i][j];
412        }
413        if (polys[i]) {
414            delete[] polys[i];
415        }
416    }
417    delete[] polys;
418    delete[] actual_slices;
419    free(slices);
420}
421
422void
423VolumeRenderer::draw_bounding_box(float x0, float y0, float z0,
424                                  float x1, float y1, float z1,
425                                  float r, float g, float b,
426                                  float line_width)
427{
428    glPushMatrix();
429    glEnable(GL_DEPTH_TEST);
430    glDisable(GL_TEXTURE_2D);
431    glEnable(GL_BLEND);
432
433    glColor4d(r, g, b, 1.0);
434    glLineWidth(line_width);
435   
436    glBegin(GL_LINE_LOOP);
437    {
438        glVertex3d(x0, y0, z0);
439        glVertex3d(x1, y0, z0);
440        glVertex3d(x1, y1, z0);
441        glVertex3d(x0, y1, z0);
442    }
443    glEnd();
444   
445    glBegin(GL_LINE_LOOP);
446    {
447        glVertex3d(x0, y0, z1);
448        glVertex3d(x1, y0, z1);
449        glVertex3d(x1, y1, z1);
450        glVertex3d(x0, y1, z1);
451    }
452    glEnd();
453   
454   
455    glBegin(GL_LINE_LOOP);
456    {
457        glVertex3d(x0, y0, z0);
458        glVertex3d(x0, y0, z1);
459        glVertex3d(x0, y1, z1);
460        glVertex3d(x0, y1, z0);
461    }
462    glEnd();
463   
464    glBegin(GL_LINE_LOOP);
465    {
466        glVertex3d(x1, y0, z0);
467        glVertex3d(x1, y0, z1);
468        glVertex3d(x1, y1, z1);
469        glVertex3d(x1, y1, z0);
470    }
471    glEnd();
472
473#ifdef notdef
474    /* Rappture doesn't supply axis units yet. So turn labeling off until we
475     * can display the proper units with the distance of each bounding box
476     * dimension.
477     */
478    glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
479
480    if (NanoVis::fonts != NULL) {
481        double mv[16], prjm[16];
482        int viewport[4];
483        double wx, wy, wz;
484        double dx, dy, dz;
485
486        glGetDoublev(GL_MODELVIEW_MATRIX, mv);
487        glGetDoublev(GL_PROJECTION_MATRIX, prjm);
488        glGetIntegerv(GL_VIEWPORT, viewport);
489       
490        NanoVis::fonts->begin();
491        dx = x1 - x0;
492        dy = y1 - y0;
493        dz = z1 - z0;
494        if (gluProject((x0 + x1) * 0.5, y0, z0, mv, prjm, viewport,
495                       &wx, &wy, &wz)) {
496            char buff[20];
497            double min, max;
498
499            NanoVis::grid->xAxis.GetDataLimits(min, max);
500            glLoadIdentity();
501            glTranslatef((int)wx, viewport[3] - (int) wy, 0.0f);
502            const char *units;
503            units = NanoVis::grid->xAxis.GetUnits();
504            sprintf(buff, "%.*g %s", NUMDIGITS, max - min, units);
505            NanoVis::fonts->draw(buff);
506        }
507        if (gluProject(x0, (y0 + y1) * 0.5, z0, mv, prjm, viewport, &
508                       wx, &wy, &wz)) {
509            char buff[20];
510            double min, max;
511
512            NanoVis::grid->yAxis.GetDataLimits(min, max);
513            glLoadIdentity();
514            glTranslatef((int)wx, viewport[3] - (int) wy, 0.0f);
515            const char *units;
516            units = NanoVis::grid->yAxis.GetUnits();
517            sprintf(buff, "%.*g %s", NUMDIGITS, max - min, units);
518            NanoVis::fonts->draw(buff);
519        }
520        if (gluProject(x0, y0, (z0 + z1) * 0.5, mv, prjm, viewport,
521                       &wx, &wy, &wz)) {
522            glLoadIdentity();
523            glTranslatef((int)wx, viewport[3] - (int) wy, 0.0f);
524
525            double min, max;
526            NanoVis::grid->zAxis.GetDataLimits(min, max);
527            const char *units;
528            units = NanoVis::grid->zAxis.GetUnits();
529            char buff[20];
530            sprintf(buff, "%.*g %s", NUMDIGITS, max - min, units);
531            NanoVis::fonts->draw(buff);
532        }
533        NanoVis::fonts->end();
534    };
535#endif
536    glPopMatrix();
537    glDisable(GL_DEPTH_TEST);
538    glDisable(GL_BLEND);
539    glEnable(GL_TEXTURE_2D);
540}
541
542
543
544void
545VolumeRenderer::activate_volume_shader(Volume* volPtr, bool slice_mode)
546{
547    //vertex shader
548    _stdVertexShader->bind();
549    TransferFunction *tfPtr  = volPtr->transferFunction();
550    if (volPtr->volume_type() == Volume::CUBIC) {
551        Trace("regular volume shader: volume=%s tf=%s slice_mode=%d\n",
552              volPtr->name(), tfPtr->name(), slice_mode);
553        _regularVolumeShader->bind(tfPtr->id(), volPtr, slice_mode);
554    } else if (volPtr->volume_type() == Volume::ZINCBLENDE) {
555        Trace("zincblende volume shader: volume=%s tf=%s slice_mode=%d\n",
556              volPtr->name(), tfPtr->name(), slice_mode);
557        _zincBlendeShader->bind(tfPtr->id(), volPtr, slice_mode);
558    }
559}
560 
561
562void VolumeRenderer::deactivate_volume_shader()
563{
564    _stdVertexShader->unbind();
565    _regularVolumeShader->unbind();
566    _zincBlendeShader->unbind();
567}
568
569
570void VolumeRenderer::get_near_far_z(Mat4x4 mv, double &zNear, double &zFar)
571{
572
573  double x0 = 0;
574  double y0 = 0;
575  double z0 = 0;
576  double x1 = 1;
577  double y1 = 1;
578  double z1 = 1;
579
580  double zMin, zMax;
581  zMin =  10000;
582  zMax = -10000;
583
584  double vertex[8][4];
585
586  vertex[0][0]=x0; vertex[0][1]=y0; vertex[0][2]=z0; vertex[0][3]=1.0;
587  vertex[1][0]=x1; vertex[1][1]=y0; vertex[1][2]=z0; vertex[1][3]=1.0;
588  vertex[2][0]=x0; vertex[2][1]=y1; vertex[2][2]=z0; vertex[2][3]=1.0;
589  vertex[3][0]=x0; vertex[3][1]=y0; vertex[3][2]=z1; vertex[3][3]=1.0;
590  vertex[4][0]=x1; vertex[4][1]=y1; vertex[4][2]=z0; vertex[4][3]=1.0;
591  vertex[5][0]=x1; vertex[5][1]=y0; vertex[5][2]=z1; vertex[5][3]=1.0;
592  vertex[6][0]=x0; vertex[6][1]=y1; vertex[6][2]=z1; vertex[6][3]=1.0;
593  vertex[7][0]=x1; vertex[7][1]=y1; vertex[7][2]=z1; vertex[7][3]=1.0;
594
595  for(int i=0;i<8;i++) {
596    Vector4 tmp = mv.transform(Vector4(vertex[i][0], vertex[i][1], vertex[i][2], vertex[i][3]));
597    tmp.perspective_devide();
598    vertex[i][2] = tmp.z;
599    if (vertex[i][2]<zMin) zMin = vertex[i][2];
600    if (vertex[i][2]>zMax) zMax = vertex[i][2];
601  }
602
603  zNear = zMax;
604  zFar = zMin;
605}
606
607void VolumeRenderer::set_slice_mode(bool val) { slice_mode = val; }
608void VolumeRenderer::set_volume_mode(bool val) { volume_mode = val; }
609void VolumeRenderer::switch_slice_mode() { slice_mode = (!slice_mode); }
610void VolumeRenderer::switch_volume_mode() { volume_mode = (!volume_mode); }
611
612
613bool
614VolumeRenderer::init_font(const char* filename)
615{
616    FILE *f;
617    unsigned short int bfType;
618    int bfOffBits;
619    short int biPlanes;
620    short int biBitCount;
621    int biSizeImage;
622    int width, height;
623    int i;
624    unsigned char temp;
625    unsigned char* data;
626    /* make sure the file is there and open it read-only (binary) */
627    f = fopen(filename, "rb");
628    if (f == NULL) {
629        fprintf(stderr, "can't open font file \"%s\"\n", filename);
630        return false;
631    }
632   
633    if (fread(&bfType, sizeof(short int), 1, f) != 1) {
634        fprintf(stderr, "can't read %lu bytes from font file \"%s\"\n",
635                (unsigned long)sizeof(short int), filename);
636        goto error;
637    }
638   
639    /* check if file is a bitmap */
640    if (bfType != 19778) {
641        fprintf(stderr, "not a bmp file.\n");
642        goto error;
643    }
644   
645    /* get the file size */
646    /* skip file size and reserved fields of bitmap file header */
647    fseek(f, 8, SEEK_CUR);
648   
649    /* get the position of the actual bitmap data */
650    if (fread(&bfOffBits, sizeof(int), 1, f) != 1) {
651        fprintf(stderr, "error reading file.\n");
652        goto error;
653    }
654    //printf("Data at Offset: %ld\n", bfOffBits);
655   
656    /* skip size of bitmap info header */
657    fseek(f, 4, SEEK_CUR);
658   
659    /* get the width of the bitmap */
660    if (fread(&width, sizeof(int), 1, f) != 1) {
661        fprintf(stderr, "error reading file.\n");
662        goto error;
663    }
664    //printf("Width of Bitmap: %d\n", texture->width);
665   
666    /* get the height of the bitmap */
667    if (fread(&height, sizeof(int), 1, f) != 1) {
668        fprintf(stderr, "error reading file.\n");
669        goto error;
670    }
671    //printf("Height of Bitmap: %d\n", texture->height);
672   
673    /* get the number of planes (must be set to 1) */
674    if (fread(&biPlanes, sizeof(short int), 1, f) != 1) {
675        fprintf(stderr, "error reading file.\n");
676        goto error;
677    }
678    if (biPlanes != 1) {
679        fprintf(stderr, "Error: number of Planes not 1!\n");
680        goto error;
681    }
682   
683    /* get the number of bits per pixel */
684    if (fread(&biBitCount, sizeof(short int), 1, f) != 1) {
685        fprintf(stderr, "error reading file.\n");
686        goto error;
687    }
688   
689    //printf("Bits per Pixel: %d\n", biBitCount);
690    if (biBitCount != 24) {
691        fprintf(stderr, "Bits per Pixel not 24\n");
692        goto error;
693    }
694
695
696    /* calculate the size of the image in bytes */
697    biSizeImage = width * height * 3 * sizeof(unsigned char);
698    data = (unsigned char*) malloc(biSizeImage);
699    if (data == NULL) {
700        fprintf(stderr, "Can't allocate memory for image\n");
701        goto error;
702    }
703
704    /* seek to the actual data */
705    fseek(f, bfOffBits, SEEK_SET);
706    if (fread(data, biSizeImage, 1, f) != 1) {
707        fprintf(stderr, "Error loading file!\n");
708        goto error;
709    }
710    fclose(f);
711
712    /* swap red and blue (bgr -> rgb) */
713    for (i = 0; i < biSizeImage; i += 3) {
714       temp = data[i];
715       data[i] = data[i + 2];
716       data[i + 2] = temp;
717    }
718
719    //insert alpha channel
720    unsigned char* data_with_alpha;
721    data_with_alpha = (unsigned char*)
722        malloc(width*height*4*sizeof(unsigned char));
723    for(int i=0; i<height; i++){
724        for(int j=0; j<width; j++){
725            unsigned char r, g, b, a;
726            r = data[3*(i*width+j)];
727            g = data[3*(i*width+j)+1];
728            b = data[3*(i*width+j)+2];
729           
730            if(r==0 && g==0 && b==0)
731                a = 0;
732            else
733                a = 255;
734           
735            data_with_alpha[4*(i*width+j)] = r;
736            data_with_alpha[4*(i*width+j) + 1] = g;
737            data_with_alpha[4*(i*width+j) + 2] = b;
738            data_with_alpha[4*(i*width+j) + 3] = a;
739           
740        }
741    }
742    free(data);
743   
744    //create opengl texture
745    glGenTextures(1, &font_texture);
746    glBindTexture(GL_TEXTURE_2D, font_texture);
747    //glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
748    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_with_alpha);
749    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
750    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
751    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
752
753    free(data_with_alpha);
754
755    build_font();
756    return (glGetError()==0);
757
758 error:
759    fclose(f);
760    return false;
761}
762
763
764
765void
766VolumeRenderer::draw_label(Volume* vol)
767{
768
769    //glEnable(GL_TEXTURE_2D);
770    glDisable(GL_TEXTURE_2D);
771    glEnable(GL_DEPTH_TEST);
772   
773    //x
774    glColor3f(0.5, 0.5, 0.5);
775   
776    int length = vol->label[0].size();
777    glPushMatrix();
778   
779    glTranslatef(.5*vol->aspect_ratio_width, vol->aspect_ratio_height,
780                 -0.1*vol->aspect_ratio_depth);
781    glRotatef(180, 0, 0, 1);
782    glRotatef(90, 1, 0, 0);
783   
784    glScalef(0.0008, 0.0008, 0.0008);
785    for(int i=0; i<length; i++){
786        glutStrokeCharacter(GLUT_STROKE_ROMAN, vol->label[0].c_str()[i]);
787        glTranslatef(0.04, 0., 0.);
788    }
789    glPopMatrix();
790   
791    //y
792    length = vol->label[1].size();
793    glPushMatrix();
794    glTranslatef(vol->aspect_ratio_width, 0.5*vol->aspect_ratio_height, -0.1*vol->aspect_ratio_depth);
795    glRotatef(90, 0, 1, 0);
796    glRotatef(90, 0, 0, 1);
797   
798    glScalef(0.0008, 0.0008, 0.0008);
799    for(int i=0; i<length; i++){
800        glutStrokeCharacter(GLUT_STROKE_ROMAN, vol->label[1].c_str()[i]);
801        glTranslatef(0.04, 0., 0.);
802    }
803    glPopMatrix();
804   
805   
806    //z
807    length = vol->label[2].size();
808    glPushMatrix();
809    glTranslatef(0., 1.*vol->aspect_ratio_height, 0.5*vol->aspect_ratio_depth);
810    glRotatef(90, 0, 1, 0);
811   
812    glScalef(0.0008, 0.0008, 0.0008);
813    for(int i=0; i<length; i++){
814        glutStrokeCharacter(GLUT_STROKE_ROMAN, vol->label[2].c_str()[i]);
815        glTranslatef(0.04, 0., 0.);
816    }
817    glPopMatrix();
818   
819    glDisable(GL_TEXTURE_2D);
820}
821 
822 
823
824void
825VolumeRenderer::build_font()
826{
827    GLfloat cx, cy;         /* the character coordinates in our texture */
828    font_base = glGenLists(256);
829    glBindTexture(GL_TEXTURE_2D, font_texture);
830    for (int loop = 0; loop < 256; loop++) {
831        cx = (float) (loop % 16) / 16.0f;
832        cy = (float) (loop / 16) / 16.0f;
833        glNewList(font_base + loop, GL_COMPILE);
834        glBegin(GL_QUADS);
835        glTexCoord2f(cx, 1 - cy - 0.0625f);
836        glVertex3f(0, 0, 0);
837        glTexCoord2f(cx + 0.0625f, 1 - cy - 0.0625f);
838        glVertex3f(0.04, 0, 0);
839        glTexCoord2f(cx + 0.0625f, 1 - cy);
840        glVertex3f(0.04, 0.04, 0);
841        glTexCoord2f(cx, 1 - cy);
842        glVertex3f(0, 0.04, 0);
843        glEnd();
844        glTranslated(0.04, 0, 0);
845        glEndList();
846    }
847}
848
849void
850VolumeRenderer::glPrint(char* string, int set)
851{
852    if(set>1) {
853        set=1;
854    }
855    glBindTexture(GL_TEXTURE_2D, font_texture);
856    glListBase(font_base - 32 + (128 * set));
857    glCallLists(strlen(string), GL_BYTE, string);
858}
859
Note: See TracBrowser for help on using the repository browser.