www.pudn.com > Ì廿֯Âë.rar > volume.cpp, change:2001-12-12,size:24956b


#include <stdio.h> 
#include <math.h> 
#include "stdafx.h" 
#include "openglsupport.h" 
#include "vecmath.h" 
#include "volume.h" 
#include "progress.h" 
#include "color.h" 
 
//-------------------------------------------------------------- 
 
grad_t operator * (grad_t g1, float s) 
{ 
   grad_t g; 
   g.x = g1.x * s; 
   g.y = g1.y * s; 
   g.z = g1.z * s; 
   return g; 
} 
 
grad_t operator + (grad_t g1, grad_t g2) 
{ 
   grad_t g; 
   g.x = g1.x + g2.x; 
   g.y = g1.y + g2.y; 
   g.z = g1.z + g2.z; 
   return g; 
} 
 
bool norm(grad_t &g) 
{ 
   float l = (float)sqrt(g.x*g.x + g.y*g.y + g.z*g.z); 
   if (l > 0) 
   { 
      float il = (1.0f/l); 
      g.x *= il; 
      g.y *= il; 
      g.z *= il; 
      return true; 
   } 
   return false; 
} 
 
float normlen(grad_t &g) 
{ 
   float l = (float)sqrt(g.x*g.x + g.y*g.y + g.z*g.z); 
   if (l > 0) 
   { 
      float il = (1.0f/l); 
      g.x *= il; 
      g.y *= il; 
      g.z *= il; 
   } 
   return l; 
} 
 
float length(grad_t g) 
{ 
   return (float)(sqrt(g.x*g.x + g.y*g.y + g.z*g.z)); 
} 
 
//-------------------------------------------------------------- 
 
void swap4(void *p) 
{ 
   char *c = (char *)p; 
   char h; 
   h = c[0]; c[0] = c[3]; c[3] = h; 
   h = c[1]; c[1] = c[2]; c[2] = h; 
} 
 
//===== class Volume ============================================= 
 
Volume::Volume() 
{ 
   m_data = NULL; 
   m_grad = NULL; 
//   m_gradlen = NULL; 
   m_overview_xtex = NULL; 
   m_overview_ytex = NULL; 
   m_overview_ztex = NULL; 
   m_view_matrix = IDENTITY_MATRIX; 
   m_view_matrix_inv = IDENTITY_MATRIX; 
   m_overview_gllist = 0; 
   for (int i=0; i=MAXDENSITY; i++) m_histogram[i] = 0.0f; 
} 
 
Volume::~Volume() 
{ 
   if (m_data != NULL) delete []m_data; 
   if (m_grad != NULL) delete []m_grad; 
//   if (m_gradlen != NULL) delete []m_gradlen; 
   if (m_overview_xtex != NULL) glDeleteTextures(m_overview_texsize, m_overview_xtex); 
   if (m_overview_ytex != NULL) glDeleteTextures(m_overview_texsize, m_overview_ytex); 
   if (m_overview_ztex != NULL) glDeleteTextures(m_overview_texsize, m_overview_ztex); 
   if (m_overview_xtex != NULL) delete []m_overview_xtex; 
   if (m_overview_ytex != NULL) delete []m_overview_ytex; 
   if (m_overview_ztex != NULL) delete []m_overview_ztex; 
   if (m_overview_gllist != 0) glDeleteLists(m_overview_gllist, 1); 
} 
 
void  
Volume::CalcGradient() 
{ 
   ProgressWin pw; 
 
   // ===== gradienten berechnen ===== 
   pw.SetText("Calculating Gradient Data ..."); 
   pw.SetRange(0, m_zz); 
 
   grad_t g;  
//   float len; 
   int x,y,z; 
   int ix,iy,iz; 
   m_grad = new grad_t[m_size]; 
//   m_gradlen = new float[m_size]; 
   iz = 0; 
   for (z=0; z<m_z; z++) 
   { 
      iy = 0; 
      for (y=0; y<m_y; y++) 
      { 
         ix = 0; 
         for (x=0; x<m_x; x++) 
         { 
            g.x = (float)(GetDataI(ix+1,iy,    iz     ) - GetDataI(ix-1,iy    ,iz     )); 
            g.y = (float)(GetDataI(ix,  iy+m_x,iz     ) - GetDataI(ix,  iy-m_x,iz     )); 
            g.z = (float)(GetDataI(ix,  iy,    iz+m_xy) - GetDataI(ix,  iy    ,iz-m_xy)); 
//            len = normlen(g); 
            norm(g); 
            m_grad[DATAI(ix,iy,iz)] = g;  
//            m_gradlen[DATAI(ix,iy,iz)] = len; 
            ix++; 
         } 
         iy += m_x; 
      } 
      pw.SetPos(z); 
      iz += m_xy; 
   } 
} 
 
void  
Volume::CalcHistogram() 
{ 
   ProgressWin pw; 
 
   // ===== histogram berechnen 
 
   pw.SetText("Calculating Histogram ..."); 
   pw.SetRange(0, m_zz); 
 
   int x,y,z; 
   int i; 
   for (i=0; i=MAXDENSITY; i++) m_histogram[i] = 0.0f; 
   for (z=0; z<m_z; z++) 
   { 
      for (y=0; y<m_y; y++) 
         for (x=0; x<m_x; x++) 
         { 
            m_histogram[m_data[DATA(x,y,z)]] += 1.0f; 
         } 
      pw.SetPos(z); 
   } 
   // suche maximum 
   float max = 0.0f; 
   for (i=0; i=MAXDENSITY; i++) if (m_histogram[i] > max) max = m_histogram[i]; 
   max *= 0.25f; 
   // normalisieren 
   for (i=0; i=MAXDENSITY; i++) m_histogram[i] /= ((float)max); 
} 
 
void  
Volume::Initialise() 
{ 
   m_max = m_x; 
   if (m_max  m_y) m_max = m_y; 
   if (m_max  m_z) m_max = m_z; 
} 
 
bool 
Volume::LoadDataDAT(const char *filename) 
{ 
   FILE *f; 
   f = fopen(filename, "r+b"); 
   if (f != NULL) 
   { 
      ProgressWin pw; 
 
      // ===== daten laden ===== 
      unsigned short sx,sy,sz; 
      fread(&sx, 2, 1, f);  
      fread(&sy, 2, 1, f);  
      fread(&sz, 2, 1, f);  
 
      pw.SetText("Loading Volume Data ..."); 
 
      m_x = (int)sx; 
      m_y = (int)sy; 
      m_z = (int)sz; 
      m_xx = m_x-1; 
      m_yy = m_y-1; 
      m_zz = m_z-1; 
      m_xy = m_x * m_y; 
      m_xyz = m_xy * m_z; 
      m_size = m_x * m_y * m_z; 
      m_data = new data_t[m_size]; 
      fread(m_data, 2, m_size, f); 
      fclose(f); 
 
      int x, y, z; 
 
      // daten maskieren mit 12bit maske 
 
      pw.SetText("Preparing Volume Data ..."); 
      pw.SetRange(0, m_zz); 
       
      for (z=0; z<m_z; z++) 
      { 
         for (y=0; y<m_y; y++) 
            for (x=0; x<m_x; x++) 
               m_data[DATA(x,y,z)] &= 0x0fff; 
         pw.SetPos(z); 
      } 
 
      //------------- 
 
      CalcGradient(); 
      CalcHistogram(); 
      Initialise(); 
      return true; 
   } 
   return false; 
} 
 
bool 
Volume::LoadDataVOL(const char *filename) 
{ 
    struct VolHeader 
    { 
      long magic; 
      long headerlength; 
      long width;  
      long height;  
      long images;  
      long bitspervoxel; 
      long indexbits; 
      float scaleX; 
      float scaleY; 
      float scaleZ; 
      float rotX; 
      float rotY; 
      float rotZ; 
   }; 
 
   FILE *f; 
   f = fopen(filename, "r+b"); 
   if (f != NULL) 
   { 
      ProgressWin pw; 
      VolHeader vh; 
      int x, y, z; 
 
      // ===== daten laden ===== 
 
      fread(&(vh.magic), 4, 1, f);  
      fread(&(vh.headerlength), 4, 1, f);  
      fread(&(vh.width), 4, 1, f);  
      fread(&(vh.height), 4, 1, f);  
      fread(&(vh.images), 4, 1, f);  
      fread(&(vh.bitspervoxel), 4, 1, f);  
      fread(&(vh.indexbits), 4, 1, f);  
      fread(&(vh.scaleX), 4, 1, f);  
      fread(&(vh.scaleY), 4, 1, f);  
      fread(&(vh.scaleZ), 4, 1, f);  
 
      swap4(&(vh.magic));  
      swap4(&(vh.headerlength));  
      swap4(&(vh.width));  
      swap4(&(vh.height));  
      swap4(&(vh.images));  
      swap4(&(vh.bitspervoxel));  
      swap4(&(vh.indexbits));  
      swap4(&(vh.scaleX));  
      swap4(&(vh.scaleY));  
      swap4(&(vh.scaleZ));  
 
      fseek(f, vh.headerlength, SEEK_SET); 
 
      int voxbits = vh.bitspervoxel + vh.indexbits; 
 
      if (voxbits > 32)  
      { 
         fclose(f); 
         return false; 
      } 
      int voxbytes = vh.bitspervoxel >> 3; 
 
      m_x = vh.width; 
      m_y = vh.height; 
      m_z = vh.images; 
      m_xx = m_x-1; 
      m_yy = m_y-1; 
      m_zz = m_z-1; 
      m_xy = m_x * m_y; 
      m_xyz = m_xy * m_z; 
      m_size = m_x * m_y * m_z; 
      m_data = new data_t[m_size]; 
 
      int shift = 32 - vh.bitspervoxel; 
      int mask = ((1 < (vh.bitspervoxel - vh.indexbits)) - 1) < vh.indexbits; 
 
      pw.SetText("Loading Volume Data ..."); 
      pw.SetRange(0, m_zz); 
 
      if (voxbytes == 3) voxbytes = 4; 
      for (z=0; z<m_z; z++) 
      { 
         for (y=0; y<m_y; y++) 
            for (x=0; x<m_x; x++) 
            { 
               long l; 
               fread(&l, voxbytes, 1, f); 
               m_data[DATA(x,y,z)] = ((((l & mask) < shift) >> 20) & 0x0fff); 
            } 
         pw.SetPos(z); 
      } 
 
      fclose(f); 
 
      // ===== daten resamplen ===== 
      if (vh.magic == 192837466) // C_VR_MAGIC_NUMBER 
      { 
         int t_x = (int)(m_x * vh.scaleX); 
         int t_y = (int)(m_y * vh.scaleY); 
         int t_z = (int)(m_z * vh.scaleZ); 
         int t_size = t_x * t_y * t_z; 
         data_t *t_data = new data_t[t_size]; 
         memset(t_data, 0, t_size); 
         float sx = ((float)m_x) / t_x;  
         float sy = ((float)m_y) / t_y;  
         float sz = ((float)m_z) / t_z;  
 
         pw.SetText("Resampling Volume Data ..."); 
         pw.SetRange(0, t_z-1); 
 
         coord3 pos; 
         pos.z = 0; 
         for (z=0; z<t_z; z++) 
         { 
            pos.y = 0; 
            for (y=0; y<t_y; y++) 
            { 
               pos.x = 0; 
               for (x=0; x<t_x; x++) 
               { 
                  data_t d; 
                  GetDataTL(pos, d); 
                  t_data[DATA(x,y,z)] = (d & 0xfff); 
                  pos.x += sx; 
               } 
               pos.y += sy; 
            } 
            pos.z += sz; 
            pw.SetPos(z); 
         } 
 
         delete []m_data; 
 
         m_x = t_x; 
         m_y = t_y; 
         m_z = t_z; 
         m_xx = m_x-1; 
         m_yy = m_y-1; 
         m_zz = m_z-1; 
         m_xy = m_x * m_y; 
         m_xyz = m_xy * m_z; 
         m_size = m_x * m_y * m_z; 
         m_data = t_data; 
      } 
 
      //------------- 
 
      CalcGradient(); 
      CalcHistogram(); 
      Initialise(); 
      return true; 
   } 
   return false; 
} 
 
bool 
Volume::GetData(int x, int y, int z, data_t &data) 
{ 
   data = m_data[DATA(x,y,z)]; 
   return true; 
} 
 
data_t 
Volume::GetData(int x, int y, int z) 
{ 
   if ((x<0) || (x>=m_x) || (y<0) || (y>=m_y) || (z<0) || (z>=m_z)) return 0; 
   return m_data[DATA(x,y,z)]; 
} 
 
data_t 
Volume::GetDataI(int x, int y, int z) 
{ 
   if ((x<0) || (x>=m_x) || (y<0) || (y>=m_xy) || (z<0) || (z>=m_xyz)) return 0; 
   return m_data[DATAI(x,y,z)]; 
} 
 
bool 
Volume::GetData(coord3 &pos, data_t &data) 
{ 
   data = m_data[DATA((int)(pos.x),(int)(pos.y),(int)(pos.z))]; 
   return true; 
} 
 
bool 
Volume::GetDataTL(coord3 &pos, data_t &data) 
{ 
   int x0 = (int)(pos.x); 
   int y0 = (int)(pos.y); 
   int z0 = (int)(pos.z); 
   if ((x0 >= m_xx) || (y0 >= m_yy) || (z0 >= m_zz)) return false; 
   int x1 = x0+1; 
   int y1 = y0+1; 
   int z1 = z0+1; 
 
   float fx = pos.x - x0; 
   float fy = pos.y - y0; 
   float fz = pos.z - z0; 
   float dm00 = m_data[DATA(x0,y0,z0)]*(1-fx) + m_data[DATA(x1,y0,z0)]*fx; 
   float dm10 = m_data[DATA(x0,y1,z0)]*(1-fx) + m_data[DATA(x1,y1,z0)]*fx; 
   float dm01 = m_data[DATA(x0,y0,z1)]*(1-fx) + m_data[DATA(x1,y0,z1)]*fx; 
   float dm11 = m_data[DATA(x0,y1,z1)]*(1-fx) + m_data[DATA(x1,y1,z1)]*fx; 
   float dmm0 = dm00*(1-fy) + dm10*fy; 
   float dmm1 = dm01*(1-fy) + dm11*fy; 
   float dmmm = dmm0*(1-fz) + dmm1*fz; 
   data = (data_t)dmmm; 
   return true; 
/* 
   int fx = ((int)(pos.x*FPMUL)) & FPMASK; 
   int fy = ((int)(pos.y*FPMUL)) & FPMASK; 
   int fz = ((int)(pos.z*FPMUL)) & FPMASK; 
   int dx00 = ((int)m_data[DATA(x0,y0,z0)])*(FPMUL-fx) + ((int)m_data[DATA(x1,y0,z0)])*fx; 
   int dx10 = ((int)m_data[DATA(x0,y1,z0)])*(FPMUL-fx) + ((int)m_data[DATA(x1,y1,z0)])*fx; 
   int dx01 = ((int)m_data[DATA(x0,y0,z1)])*(FPMUL-fx) + ((int)m_data[DATA(x1,y0,z1)])*fx; 
   int dx11 = ((int)m_data[DATA(x0,y1,z1)])*(FPMUL-fx) + ((int)m_data[DATA(x1,y1,z1)])*fx; 
   int dy0 = (dx00>>FPSH)*(FPMUL-fy) + (dx10>>FPSH)*fy; 
   int dy1 = (dx01>>FPSH)*(FPMUL-fy) + (dx11>>FPSH)*fy; 
   int dz = (dy0>>FPSH)*(FPMUL-fz) + (dy1>>FPSH)*fz; 
   data = (data_t)(dz>>FPSH); 
   return true;  
*/ 
} 
 
bool 
Volume::GetGradient(int x, int y, int z, grad_t &grad) 
{ 
   grad = m_grad[DATA(x,y,z)]; 
   return true; 
} 
 
bool 
Volume::GetGradient(coord3 &pos, grad_t &grad) 
{ 
   grad = m_grad[DATA((int)(pos.x),(int)(pos.y),(int)(pos.z))]; 
   return true; 
} 
 
bool 
Volume::GetGradientTL(coord3 &pos, grad_t &grad) 
{ 
 
   int x0 = (int)(pos.x); 
   int y0 = (int)(pos.y); 
   int z0 = (int)(pos.z); 
   if ((x0 >= m_xx) || (y0 >= m_yy) || (z0 >= m_zz)) return false; 
   int x1 = x0+1; 
   int y1 = y0+1; 
   int z1 = z0+1; 
 
   float fx = pos.x - x0; 
   float fy = pos.y - y0; 
   float fz = pos.z - z0; 
 
   grad_t gm00 = (m_grad[DATA(x0,y0,z0)]*(1-fx) + m_grad[DATA(x1,y0,z0)]*fx); 
   grad_t gm10 = (m_grad[DATA(x0,y1,z0)]*(1-fx) + m_grad[DATA(x1,y1,z0)]*fx); 
   grad_t gm01 = (m_grad[DATA(x0,y0,z1)]*(1-fx) + m_grad[DATA(x1,y0,z1)]*fx); 
   grad_t gm11 = (m_grad[DATA(x0,y1,z1)]*(1-fx) + m_grad[DATA(x1,y1,z1)]*fx); 
   norm(gm00); 
   norm(gm10); 
   norm(gm01); 
   norm(gm11); 
   grad_t gmm0 = (gm00*(1-fy) + gm10*fy); 
   grad_t gmm1 = (gm01*(1-fy) + gm11*fy); 
   norm(gmm0); 
   norm(gmm1); 
   grad_t gmmm = (gmm0*(1-fz) + gmm1*fz); 
   norm(gmmm); 
   grad = gmmm; 
   return true; 
} 
 
/* 
 
float 
Volume::GetGradientLength(coord3 &pos) 
{ 
   return m_gradlen[DATA((int)(pos.x),(int)(pos.y),(int)(pos.z))]; 
} 
 
float 
Volume::GetGradientLengthTL(coord3 &pos) 
{ 
   int x0 = (int)(pos.x); 
   int y0 = (int)(pos.y); 
   int z0 = (int)(pos.z); 
   if ((x0 >= m_xx) || (y0 >= m_yy) || (z0 >= m_zz)) return 0.0; 
   int x1 = x0+1; 
   int y1 = y0+1; 
   int z1 = z0+1; 
 
   float fx = pos.x - x0; 
   float fy = pos.y - y0; 
   float fz = pos.z - z0; 
   float dm00 = m_gradlen[DATA(x0,y0,z0)]*(1-fx) + m_gradlen[DATA(x1,y0,z0)]*fx; 
   float dm10 = m_gradlen[DATA(x0,y1,z0)]*(1-fx) + m_gradlen[DATA(x1,y1,z0)]*fx; 
   float dm01 = m_gradlen[DATA(x0,y0,z1)]*(1-fx) + m_gradlen[DATA(x1,y0,z1)]*fx; 
   float dm11 = m_gradlen[DATA(x0,y1,z1)]*(1-fx) + m_gradlen[DATA(x1,y1,z1)]*fx; 
   float dmm0 = dm00*(1-fy) + dm10*fy; 
   float dmm1 = dm01*(1-fy) + dm11*fy; 
   float dmmm = dmm0*(1-fz) + dmm1*fz; 
   return dmmm; 
} 
 
*/ 
 
//------------------------------------------------------------------- 
 
int  
Volume::GetDimX() 
{ 
   return m_x; 
} 
 
int  
Volume::GetDimY() 
{ 
   return m_y; 
} 
 
int  
Volume::GetDimZ() 
{ 
   return m_z; 
} 
 
int  
Volume::GetMaxWidth() 
{ 
   return m_max; 
} 
 
//------------------------------------------------------------------- 
 
float  
Volume::GetHistogramValue(int i) 
{ 
   if ((i  0) || (i > MAXDENSITY)) return 0.0f; 
   return m_histogram[i]; 
} 
 
float  
Volume::GetHistogramRange(int min, int max) 
{ 
   int h; 
   if (max  min)  
   { 
      h = max; 
      max = min; 
      min = h; 
   } 
   if ((max  0) || (min > MAXDENSITY)) return 0.0f; 
   if (max > MAXDENSITY) max = MAXDENSITY; 
   if (min  0) min = 0; 
 
   float val = 0; 
   for (h=min; h=max; h++) val += m_histogram[h]; 
   return val; 
} 
 
 
//------------------------------------------------------------------- 
 
bool  
Volume::GetRayEnds(coord3 &nearpos, coord3 &farpos, coord3 &pos, coord3 &dir, float &dist) 
{ 
   // intersect ray with the volume cube from (0,0,0) to (m_x,m_y,m_z); 
   float nearscale = -1000000; 
   float farscale = +1000000; 
   float scale1, scale2; 
 
   // intersect with x planes   
   if (dir.x != 0) 
   { 
      scale1 = (0 - pos.x) / dir.x; 
      scale2 = (m_xx - pos.x) / dir.x; 
      if (scale1  scale2)  
      { 
         if (scale1 > nearscale) nearscale = scale1; 
         if (scale2  farscale) farscale = scale2; 
      } 
      else 
      { 
         if (scale2 > nearscale) nearscale = scale2; 
         if (scale1  farscale) farscale = scale1; 
      } 
   } 
 
   // intersect with y planes   
   if (dir.y != 0) 
   { 
      scale1 = (0 - pos.y) / dir.y; 
      scale2 = (m_yy - pos.y) / dir.y; 
      if (scale1  scale2)  
      { 
         if (scale1 > nearscale) nearscale = scale1; 
         if (scale2  farscale) farscale = scale2; 
      } 
      else 
      { 
         if (scale2 > nearscale) nearscale = scale2; 
         if (scale1  farscale) farscale = scale1; 
      } 
   } 
 
   // intersect with z planes  
   if (dir.z != 0) 
   { 
      scale1 = (0 - pos.z) / dir.z; 
      scale2 = (m_zz - pos.z) / dir.z; 
      if (scale1  scale2)  
      { 
         if (scale1 > nearscale) nearscale = scale1; 
         if (scale2  farscale) farscale = scale2; 
      } 
      else 
      { 
         if (scale2 > nearscale) nearscale = scale2; 
         if (scale1  farscale) farscale = scale1; 
      } 
   } 
   nearpos.x = pos.x + nearscale * dir.x + 0.5f; 
   nearpos.y = pos.y + nearscale * dir.y + 0.5f; 
   nearpos.z = pos.z + nearscale * dir.z + 0.5f; 
 
   if (nearpos.x  0) return false; 
   if (nearpos.x >= m_x) return false; 
   if (nearpos.y  0) return false; 
   if (nearpos.y >= m_y) return false; 
   if (nearpos.z  0) return false; 
   if (nearpos.z >= m_z) return false; 
 
   farpos.x = pos.x + farscale * dir.x + 0.5f; 
   farpos.y = pos.y + farscale * dir.y + 0.5f; 
   farpos.z = pos.z + farscale * dir.z + 0.5f; 
 
   if (farpos.x  0) return false; 
   if (farpos.x >= m_x) return false; 
   if (farpos.y  0) return false; 
   if (farpos.y >= m_y) return false; 
   if (farpos.z  0) return false; 
   if (farpos.z >= m_z) return false; 
 
   coord3 tmp; 
   vec_subtract(&tmp, &farpos, &nearpos); 
   dist = vec_length(&tmp); 
   return true; 
} 
 
 
//------------------------------------------------------------------- 
 
void  
Volume::CreateOverview(int ts) 
{ 
   int texsize = 1 < ts; 
   rgba *texture = new rgba[texsize*texsize];   
   data_t *voldata = new data_t[texsize*texsize*texsize]; 
   m_overview_texsize = texsize; 
 
   int x,y,z,i,j; 
 
   ProgressWin pw; 
   pw.SetText("Generating Overview Textures: Preparing Textures ..."); 
   pw.SetRange(0,texsize-1); 
 
   float sx = ((float)m_x)/((float)texsize); 
   float sy = ((float)m_y)/((float)texsize); 
   float sz = ((float)m_z)/((float)texsize); 
   for (z=0; z<texsize; z++) 
   { 
      for (y=0; y<texsize; y++) 
         for (x=0; x<texsize; x++) 
         { 
            coord3 pos; 
            data_t d; 
            pos.x = x * sx; 
            pos.y = y * sy; 
            pos.z = z * sz; 
            GetData(pos, d); 
            voldata[(z*texsize+y)*texsize+x] = d; 
         } 
      pw.SetPos(z); 
   } 
 
   glEnable(GL_TEXTURE_2D); 
   GLint neighbour = GL_NEAREST; 
 
   // ----- Z axis ----- 
   pw.SetText("Generating Overview Textures: Z axis ..."); 
   pw.SetRange(0,texsize-1); 
   m_overview_ztex = new GLuint[texsize]; 
   glGenTextures(texsize, m_overview_ztex); 
   for (i=0; i<texsize; i++) 
   { 
      for (y=0; y<texsize; y++) 
         for (x=0; x<texsize; x++) 
         { 
            data_t d = voldata[(i*texsize+y)*texsize+x]; 
            unsigned char uc = d >> 4; 
            texture[y*texsize+x].r = 128+uc/2; 
            texture[y*texsize+x].g = 128+uc/2; 
            texture[y*texsize+x].b = 128+uc/2; 
            texture[y*texsize+x].a = uc; 
         } 
      glBindTexture(GL_TEXTURE_2D, m_overview_ztex[i]); 
   	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    	glTexImage2D(GL_TEXTURE_2D, 0, 4, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, neighbour); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, neighbour); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
      pw.SetPos(i); 
   } 
 
   // ----- Y axis ----- 
   pw.SetText("Generating Overview Textures: Y axis ..."); 
   pw.SetRange(0,texsize-1); 
   m_overview_ytex = new GLuint[texsize]; 
   glGenTextures(texsize, m_overview_ytex); 
   for (i=0; i<texsize; i++) 
   { 
      for (y=0; y<texsize; y++) 
         for (x=0; x<texsize; x++) 
         { 
            data_t d = voldata[(y*texsize+i)*texsize+x]; 
            unsigned char uc = d >> 4; 
            texture[y*texsize+x].r = 128+uc/2; 
            texture[y*texsize+x].g = 128+uc/2; 
            texture[y*texsize+x].b = 128+uc/2; 
            texture[y*texsize+x].a = uc; 
         } 
      glBindTexture(GL_TEXTURE_2D, m_overview_ytex[i]); 
   	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    	glTexImage2D(GL_TEXTURE_2D, 0, 4, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, neighbour); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, neighbour); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
      pw.SetPos(i); 
   } 
 
   // ----- X axis ----- 
   pw.SetText("Generating Overview Textures: X axis ..."); 
   pw.SetRange(0,texsize-1); 
   m_overview_xtex = new GLuint[texsize]; 
   glGenTextures(texsize, m_overview_xtex); 
   for (i=0; i<texsize; i++) 
   { 
      for (y=0; y<texsize; y++) 
         for (x=0; x<texsize; x++) 
         { 
            data_t d = voldata[(y*texsize+x)*texsize+i]; 
            unsigned char uc = d >> 4; 
            texture[y*texsize+x].r = 128+uc/2; 
            texture[y*texsize+x].g = 128+uc/2; 
            texture[y*texsize+x].b = 128+uc/2; 
            texture[y*texsize+x].a = uc; 
         } 
      glBindTexture(GL_TEXTURE_2D, m_overview_xtex[i]); 
   	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    	glTexImage2D(GL_TEXTURE_2D, 0, 4, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, neighbour); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, neighbour); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
      pw.SetPos(i); 
   } 
 
 
   // create display list 
   m_overview_gllist = glGenLists(1); 
   glNewList(m_overview_gllist, GL_COMPILE); 
 
   float mx = (float)m_x; 
   float my = (float)m_y; 
   float mz = (float)m_z; 
/*   float sx = mx/m_overview_texsize; 
   float sy = my/m_overview_texsize; 
   float sz = mz/m_overview_texsize; */ 
 
   GLfloat LightAmbient[]= { 0.6f, 0.6f, 0.6f, 1.0f }; 
   GLfloat LightDiffuse[]=	{ 0.8f, 0.8f, 0.8f, 1.0f }; 
    
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, LightDiffuse); 
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, LightAmbient); 
 
   for (i=0; i<m_overview_texsize; i++) 
   { 
      glBindTexture(GL_TEXTURE_2D, m_overview_ztex[i]); 
      glBegin(GL_QUADS); 
      for (j=0; j<2; j++) 
      { 
         glNormal3f(0, 0, 1); 
         glTexCoord2f(0, 0); 
         glVertex3f(0, 0, (i+j)*sz); 
         glTexCoord2f(1, 0); 
         glVertex3f(mx, 0, (i+j)*sz); 
         glTexCoord2f(1, 1); 
         glVertex3f(mx,my, (i+j)*sz); 
         glTexCoord2f(0, 1); 
         glVertex3f(0,my, (i+j)*sz); 
      } 
      glEnd(); 
   } 
 
   for (i=0; i<m_overview_texsize; i++) 
   { 
      glBindTexture(GL_TEXTURE_2D, m_overview_ytex[i]); 
      glBegin(GL_QUADS); 
      for (j=0; j<2; j++) 
      { 
         glNormal3f(0, -1, 0); 
         glTexCoord2f(0, 0); 
         glVertex3f(0, (i+j)*sy, 0); 
         glTexCoord2f(1, 0); 
         glVertex3f(mx, (i+j)*sy, 0); 
         glTexCoord2f(1, 1); 
         glVertex3f(mx, (i+j)*sy, mz); 
         glTexCoord2f(0, 1); 
         glVertex3f(0, (i+j)*sy, mz); 
      } 
      glEnd(); 
   } 
 
   for (i=0; i<m_overview_texsize; i++) 
   { 
      glBindTexture(GL_TEXTURE_2D, m_overview_xtex[i]); 
      glBegin(GL_QUADS); 
      for (j=0; j<2; j++) 
      { 
         glNormal3f(1, 0, 0); 
         glTexCoord2f(0, 0); 
         glVertex3f((i+j)*sx, 0, 0); 
         glTexCoord2f(1, 0); 
         glVertex3f((i+j)*sx,my, 0); 
         glTexCoord2f(1, 1); 
         glVertex3f((i+j)*sx,my, mz); 
         glTexCoord2f(0, 1); 
         glVertex3f((i+j)*sx, 0, mz); 
      } 
      glEnd(); 
   } 
 
   glEndList(); 
   glFlush(); 
 
 
   glDisable(GL_TEXTURE_2D); 
 
   delete []texture; 
   delete []voldata; 
} 
 
void  
Volume::SetOverviewDrawSize(int width, int height) 
{ 
   m_overview_draw_width = width; 
   m_overview_draw_height = height; 
} 
 
//------------------------------------------------------------------- 
 
void  
Volume::GetViewMatrix(matrix44 &m) 
{ 
   m = m_view_matrix; 
} 
 
void  
Volume::GetViewMatrixInv(matrix44 &m) 
{ 
   m = m_view_matrix_inv; 
} 
 
void  
Volume::ViewRotate(float angle, float x, float y, float z) 
{ 
   matrix44 m,tmp; 
 
   matrix_rotate(&m, x, y, z, angle); 
   tmp = m_view_matrix; 
   matrix_matrixmul(&m_view_matrix, &m, &tmp);  
 
   matrix_rotate(&m, x, y, z, -angle); 
   tmp = m_view_matrix_inv; 
   matrix_matrixmul(&m_view_matrix_inv, &tmp, &m);  
} 
 
//------------------------------------------------------------------- 
 
void  
Volume::glOverviewDraw(int threshold) 
{ 
   glClearColor(0.0f, 0.0f, 0.4f, 1.0f); 
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
   glEnable(GL_TEXTURE_2D); 
   glEnable(GL_ALPHA_TEST); 
   glAlphaFunc(GL_GEQUAL, ((float)threshold)/MAXDENSITY); 
 
	glMatrixMode(GL_PROJECTION);	 
	glLoadIdentity();					 
   float w = ((GLfloat)m_overview_draw_width/(GLfloat)m_overview_draw_height) * 0.5f; 
   glOrtho(-w, +w, -0.5, +0.5, -2, +2); 
	glMatrixMode(GL_MODELVIEW);	 
	glLoadIdentity();					 
 
   float mx = (float)m_x; 
   float my = (float)m_y; 
   float mz = (float)m_z; 
 
   glMultMatrixf((const float *)m_view_matrix.matrix); 
   glScalef(1.0f/m_max, 1.0f/m_max, 1.0f/m_max); 
   glTranslatef(-mx/2, -my/2, -mz/2); 
 
   glCallList(m_overview_gllist); 
   glFlush(); 
 
   glDisable(GL_ALPHA_TEST); 
   glDisable(GL_TEXTURE_2D); 
 
}