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

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