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


#include <stdlib.h> 
#include <math.h> 
#include "ray.h" 
 
 
//---- abstract class Ray ------------------------------------------- 
 
Ray::Ray(Volume *vol, TransferFunction *tf) 
{ 
   m_volume = vol; 
   m_tf = tf; 
   m_usetf = false; 
   m_step_length = 1.0f; 
} 
 
Ray::~Ray() 
{ 
} 
 
void  
Ray::UseTransFunc(bool use) 
{ 
   m_usetf = use; 
} 
 
void  
Ray::UseHighlights(bool use) 
{ 
   m_usehighlights = use; 
} 
 
void 
Ray::SetStepLength(float steplength) 
{ 
   m_step_length = steplength; 
} 
 
void  
Ray::Cast(coord3 pos, coord3 dir,  rgba &color) 
{ 
} 
 
//----- "First Hit" -------------------------------------------------------- 
 
void 
RayFirstHitNN::SetThreshold(int threshold) 
{ 
   m_threshold = threshold; 
} 
 
void  
RayFirstHitNN::Cast(coord3 pos, coord3 dir, rgba &color) 
{ 
   coord3 start; 
   coord3 end; 
   float dist; 
   if (m_volume->GetRayEnds(start, end, pos, dir, dist)) 
   { 
      data_t data; 
      grad_t grad; 
      coord3 ndir; 
      coord3 pt = start; 
      vec_normalize(&ndir, &dir); 
      coord3 sdir; 
      vec_scale(&sdir, &ndir, m_step_length); 
      while (dist > 0) 
      { 
         if (m_volume->GetData(pt, data)) 
            if (data > m_threshold)  
            { 
               m_volume->GetGradient(pt, grad); 
               double k = fabs(grad.x*ndir.x + grad.y*ndir.y + grad.z*ndir.z); 
               if (m_usetf) m_tf->GetColor(data, color); else white(color); 
               if (m_usehighlights) 
               { 
                  double h = pow(k, 16); 
                  int r = (int)(color.r * k + 255 * h); 
                  int g = (int)(color.g * k + 255 * h); 
                  int b = (int)(color.b * k + 255 * h); 
                  if (r > 255) color.r = 255; else color.r = r; 
                  if (g > 255) color.g = 255; else color.g = g; 
                  if (b > 255) color.b = 255; else color.b = b; 
                  color.a = 255; 
               } 
               else 
               { 
                  color.r = (unsigned char)(color.r * k); 
                  color.g = (unsigned char)(color.g * k); 
                  color.b = (unsigned char)(color.b * k); 
                  color.a = 255; 
               } 
               return; 
            } 
         dist -= m_step_length; 
         vec_add(&pt, &pt, &sdir); 
      } 
   } 
   anycolor(color, 0, 0, 100); 
} 
 
void  
RayFirstHitTL::Cast(coord3 pos, coord3 dir, rgba &color) 
{ 
   coord3 start; 
   coord3 end; 
   float dist; 
   if (m_volume->GetRayEnds(start, end, pos, dir, dist)) 
   { 
      data_t data; 
      data_t prevdata = -1; 
      grad_t grad; 
      coord3 ndir; 
      coord3 pt = start; 
      vec_normalize(&ndir, &dir); 
      coord3 sdir; 
      vec_scale(&sdir, &ndir, m_step_length); 
      while (dist > 0) 
      { 
         if (m_volume->GetDataTL(pt, data)) 
            if (data > m_threshold)  
            { 
               if (prevdata > 0) 
               { 
                  vec_scale(&sdir, &sdir, ((float)(m_threshold-data))/(data-prevdata)); 
                  vec_add(&pt, &pt, &sdir); 
               } 
               m_volume->GetGradientTL(pt, grad); 
               double k = fabs(grad.x*ndir.x + grad.y*ndir.y + grad.z*ndir.z); 
               if (m_usetf) m_tf->GetColor(data, color); else white(color); 
               if (m_usehighlights) 
               { 
                  double h = pow(k, 16); 
                  int r = (int)(color.r * k + 255 * h); 
                  int g = (int)(color.g * k + 255 * h); 
                  int b = (int)(color.b * k + 255 * h); 
                  if (r > 255) color.r = 255; else color.r = r; 
                  if (g > 255) color.g = 255; else color.g = g; 
                  if (b > 255) color.b = 255; else color.b = b; 
                  color.a = 255; 
               } 
               else 
               { 
                  color.r = (unsigned char)(color.r * k); 
                  color.g = (unsigned char)(color.g * k); 
                  color.b = (unsigned char)(color.b * k); 
                  color.a = 255; 
               } 
               return; 
            } 
         prevdata = data; 
         dist -= m_step_length; 
         vec_add(&pt, &pt, &sdir); 
      } 
   } 
   anycolor(color, 0, 0, 100); 
} 
 
//----- Max. Intensity -------------------------------------------------------- 
 
void  
RayMaxIntensityNN::Cast(coord3 pos, coord3 dir, rgba &color) 
{ 
   coord3 start; 
   coord3 end; 
   float dist; 
   int max = 0; 
   if (m_volume->GetRayEnds(start, end, pos, dir, dist)) 
   { 
      data_t data; 
      coord3 ndir; 
      coord3 pt = start; 
      vec_normalize(&ndir, &dir); 
      coord3 sdir; 
      vec_scale(&sdir, &ndir, m_step_length); 
      while (dist > 0) 
      { 
         if (m_volume->GetData(pt, data)) 
         { 
            if (data > max) max = data; 
         } 
         dist -= m_step_length; 
         vec_add(&pt, &pt, &sdir); 
      } 
      if (m_usetf) m_tf->GetColor(max, color); else gray(color, max >> 4); 
      return; 
   } 
   anycolor(color, 0, 0, 100); 
} 
 
void  
RayMaxIntensityTL::Cast(coord3 pos, coord3 dir, rgba &color) 
{ 
   coord3 start; 
   coord3 end; 
   float dist; 
   int max = 0; 
   if (m_volume->GetRayEnds(start, end, pos, dir, dist)) 
   { 
      data_t data; 
      coord3 ndir; 
      coord3 pt = start; 
      vec_normalize(&ndir, &dir); 
      coord3 sdir; 
      vec_scale(&sdir, &ndir, m_step_length); 
      while (dist > 0) 
      { 
         if (m_volume->GetDataTL(pt, data)) 
         { 
            if (data > max) max = data; 
         } 
         dist -= m_step_length; 
         vec_add(&pt, &pt, &sdir); 
      } 
      if (m_usetf) m_tf->GetColor(max, color); else gray(color, max >> 4); 
      return; 
   } 
   anycolor(color, 0, 0, 100); 
} 
 
//----- Transparency ---------------------------------------------------- 
 
void  
RayTransparencyNN::SetTransFuncVolume(TransferFunctionVolume *tfv) 
{ 
   m_tfv = tfv; 
} 
 
void  
RayTransparencyNN::Cast(coord3 pos, coord3 dir, rgba &color) 
{ 
   m_step_length = 1.0f; 
   coord3 start; 
   coord3 end; 
   float dist; 
   if (m_volume->GetRayEnds(start, end, pos, dir, dist)) 
   { 
      data_t data; 
      grad_t grad; 
      float transparency; 
      rgba col; 
 
      coord3 ndir; 
      coord3 pt = start; 
      vec_normalize(&ndir, &dir); 
      coord3 sdir; 
      vec_scale(&sdir, &ndir, m_step_length); 
      float alpha = 1.0f; 
      float Ir = 0.0f; 
      float Ig = 0.0f; 
      float Ib = 0.0f; 
      float k, mul; 
      while ((dist > 0) && (alpha > TRANSPARENCYLIMIT)) 
      { 
         if (m_volume->GetData(pt, data)) 
         { 
            m_volume->GetGradient(pt, grad); 
            m_tf->GetTransparency(data, transparency); 
            if (m_usetf) m_tf->GetColor(data, col); else white(col); 
            k = (float)fabs(grad.x*ndir.x + grad.y*ndir.y + grad.z*ndir.z); 
            mul = alpha * (1.0f-transparency) * k; 
            if (m_usehighlights) 
            { 
               float i = (float)(255 * pow(k, 16)); 
               Ir = Ir + (mul * (col.r + i)); 
               Ig = Ig + (mul * (col.g + i)); 
               Ib = Ib + (mul * (col.b + i)); 
            } 
            else 
            { 
               Ir = Ir + (mul * col.r); 
               Ig = Ig + (mul * col.g); 
               Ib = Ib + (mul * col.b); 
            } 
            alpha = alpha * transparency;  
         } 
         dist -= m_step_length; 
         vec_add(&pt, &pt, &sdir); 
      } 
      if (alpha > TRANSPARENCYLIMIT) 
      { 
         rgba bcol; 
         m_tf->GetBackgroundColor(bcol); 
         Ir = Ir + (alpha * bcol.r); 
         Ig = Ig + (alpha * bcol.g); 
         Ib = Ib + (alpha * bcol.b); 
      } 
      if (Ir > 255) Ir = 255; 
      if (Ig > 255) Ig = 255; 
      if (Ib > 255) Ib = 255; 
      color.r = (unsigned char)(Ir); 
      color.g = (unsigned char)(Ig); 
      color.b = (unsigned char)(Ib); 
      color.a = 255; 
      return; 
   } 
   m_tf->GetBackgroundColor(color); 
} 
 
void  
RayTransparencyTL::Cast(coord3 pos, coord3 dir, rgba &color) 
{ 
   m_step_length = 1.0f; 
   coord3 start; 
   coord3 end; 
   float dist; 
   if (m_volume->GetRayEnds(start, end, pos, dir, dist)) 
   { 
      data_t data; 
      grad_t grad; 
      float transparency; 
      rgba col; 
 
      coord3 ndir; 
      coord3 pt = start; 
      vec_normalize(&ndir, &dir); 
      coord3 sdir; 
      vec_scale(&sdir, &ndir, m_step_length); 
      float alpha = 1.0f; 
      float Ir = 0.0f; 
      float Ig = 0.0f; 
      float Ib = 0.0f; 
      float k, mul; 
      while ((dist > 0) && (alpha > TRANSPARENCYLIMIT)) 
      { 
         if (m_volume->GetDataTL(pt, data)) 
         { 
            m_volume->GetGradientTL(pt, grad); 
            m_tfv->GetTransparencyTL(pt, transparency); 
            if (m_usetf) m_tfv->GetColor(pt, col); else white(col); 
            k = (float)fabs(grad.x*ndir.x + grad.y*ndir.y + grad.z*ndir.z); 
            mul = alpha * (1.0f-transparency) * k; 
            if (m_usehighlights) 
            { 
               float i = (float)(255 * pow(k, 16)); 
               Ir = Ir + (mul * (col.r + i)); 
               Ig = Ig + (mul * (col.g + i)); 
               Ib = Ib + (mul * (col.b + i)); 
            } 
            else 
            { 
               Ir = Ir + (mul * col.r); 
               Ig = Ig + (mul * col.g); 
               Ib = Ib + (mul * col.b); 
            } 
            alpha = alpha * transparency;  
         } 
         dist -= m_step_length; 
         vec_add(&pt, &pt, &sdir); 
      } 
      if (alpha > TRANSPARENCYLIMIT) 
      { 
         rgba bcol; 
         m_tf->GetBackgroundColor(bcol); 
         Ir = Ir + (alpha * bcol.r); 
         Ig = Ig + (alpha * bcol.g); 
         Ib = Ib + (alpha * bcol.b); 
      } 
      if (Ir > 255) Ir = 255; 
      if (Ig > 255) Ig = 255; 
      if (Ib > 255) Ib = 255; 
      color.r = (unsigned char)(Ir); 
      color.g = (unsigned char)(Ig); 
      color.b = (unsigned char)(Ib); 
      color.a = 255; 
      return; 
   } 
   m_tf->GetBackgroundColor(color); 
}