C:/Users/thebigMuh/Documents/Visual Studio 2005/Projects/Volumizer/Volumizer/RayEngine.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 #include "Volumizer.h"
00008 
00009 unsigned short *rawdat, rawmax;         
00010 float *voldat;                                          
00011 unsigned int volx, voly, volz;          
00012 
00013 extern HWND wnd_main;
00014 extern camera cam;
00015 extern HDC rayHdc;
00016 extern HGLRC rayHglrc;
00017 extern vect ldir;
00018 
00022 INT_PTR CALLBACK ProgressProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
00023 {
00024         return FALSE;
00025 }
00026 
00031 void ShovelData()
00032 {
00033         if (rawdat)
00034         {
00035 
00037                 HWND wnd_progress = CreateDialog(hInst, 
00038                         MAKEINTRESOURCE(IDD_PROGRESS), 
00039                         wnd_main, 
00040                         ProgressProc);
00041 
00043                 ShowWindow(wnd_progress, SW_SHOW);
00044 
00046                 HWND progressbar = GetDlgItem(wnd_progress, IDC_PROGRESS);
00047 
00049                 SendMessage(progressbar, PBM_SETRANGE, 0, MAKELPARAM(0, volx));
00050         
00051                 unsigned int i = 0;
00052 
00053                 for (unsigned int x = 0; x < volx; x++)
00054                 {
00055                         for (unsigned int y = 0; y < voly; y++)
00056                         {
00057                                 for (unsigned int z = 0; z < volz; z++)
00058                                 {
00059                                         voldat[i] = OogleVal((float)rawdat[i] / (float)rawmax);
00060                                         i++;
00061                                 }
00062                         }
00063                         SendMessage(progressbar, PBM_SETPOS, x, 0);
00064                 }
00065 
00067                 BuildOrthoSlice(wnd_front);
00068                 BuildOrthoSlice(wnd_left);
00069                 BuildOrthoSlice(wnd_top);
00070 
00072                 DestroyWindow(wnd_progress);
00073 
00074                 DrawOrtho(wnd_front);
00075                 DrawOrtho(wnd_left);
00076                 DrawOrtho(wnd_top);
00077 
00079                 CalcHistogram();
00080 
00081                 DrawHistogram(wnd_histogram);
00082 
00084                 RayRender();
00085         }
00086 }
00087 
00091 void LoadDataFile(wchar_t *fileName)
00092 {
00094         int infile;
00095         _wsopen_s(&infile, fileName, _O_BINARY | _O_SEQUENTIAL, _SH_DENYNO, 0);
00096 
00098         _read(infile, &volx, 2);
00099         _read(infile, &voly, 2);
00100         _read(infile, &volz, 2);
00101 
00103         delete [] voldat;
00104 
00106         voldat = new float[volx*voly*volz];
00107 
00109         delete [] rawdat;
00110 
00111         rawdat = new unsigned short[volx*voly*volz];
00112 
00114         _read(infile, rawdat, volx*voly*volz*2);
00115 
00117         rawmax = 0;
00118 
00119         for (unsigned int i = 0; i < volx * voly * volz; i++)
00120         {
00121                 if (rawdat[i] > rawmax)
00122                         rawmax = rawdat[i];
00123         }
00124 
00126         _close(infile);
00127 
00129         xslice = volx / 2;
00130         yslice = voly / 2;
00131         zslice = volz / 2;
00132 
00134         InitCam();
00135         InitLight();
00136 
00138         ShovelData();
00139 }
00140 
00144 float bias(float _val, float _bias)
00145 {
00146         return _val / ((1.0f / _bias - 2.0f) * (1.0f - _val) + 1.0f);
00147 }
00148 
00152 float gain(float _val, float _gain)
00153 {
00154         if (_val < 0.5f)
00155         {
00156                 return _val / ((1.0f / _gain - 2.0f) * (1.0f - 2.0f * _val) + 1.0f);
00157         }
00158         else
00159         {
00160                 return ((1.0f / _gain - 2.0f) * (1.0f - 2.0f * _val) - _val) / ((1.0f / _gain - 2.0f) * (1.0f - 2.0f * _val) - 1.0f);
00161         }
00162 }
00163 
00167 static __inline float OogleVal(float inp)
00168 {
00169         float tmp = bias(inp, brightness);
00170 
00171         tmp = gain(tmp, contrast);
00172 
00173         return (gamma == 0.0f)?0.0f:pow(tmp, 1.0f/gamma);
00174 }
00175 
00179 static __inline float GetSample(int x, int y, int z)
00180 {
00181         return voldat[x + volx * y + voly * volx * z];
00182 }
00183 
00187 static __inline float GetInterpolatedSample(vect pos)
00188 {
00189         float s1, s2, s3, s4;
00190 
00191         float intx, inty, intz;
00192 
00194         intx = fmod(pos.x, 1.0f);
00195         inty = fmod(pos.y, 1.0f);
00196         intz = fmod(pos.z, 1.0f);
00197 
00198         unsigned int basex, basey, basez;
00199 
00201         basex = (unsigned int)pos.x;
00202         basey = (unsigned int)pos.y;
00203         basez = (unsigned int)pos.z;
00204 
00206         if (basex > volx - 2)
00207                 basex = volx - 2;
00208 
00209         if (basey > voly - 2)
00210                 basey = voly - 2;
00211 
00212         if (basez > volz - 2)
00213                 basez = volz - 2;
00214 
00216         s1 = GetSample(basex, basey, basez) * (1.0f - intz) + GetSample(basex, basey, basez + 1) * intz;
00217         s2 = GetSample(basex, basey+1, basez) * (1.0f - intz) + GetSample(basex, basey+1, basez + 1) * intz;
00218         s3 = GetSample(basex+1, basey, basez) * (1.0f - intz) + GetSample(basex+1, basey, basez + 1) * intz;
00219         s4 = GetSample(basex+1, basey+1, basez) * (1.0f - intz) + GetSample(basex+1, basey+1, basez + 1) * intz;
00220 
00222         s1 = s1 * (1.0f - inty) + s2 * inty;
00223         s2 = s3 * (1.0f - inty) + s4 * inty;
00224 
00226         s1 = s1 * (1.0f - intx) + s2 * intx;
00227 
00228         return s1;
00229 }
00230 
00236 static __inline
00237 int GetBoxIntersection(vect &vnear, 
00238                                            vect &vfar,  
00239                                            vect &org,   
00240                                            vect &dir    
00241                                            )
00242 {
00243         vect sect;
00244         float dist_near, dist_far, dist;
00245         int nsect = 0;
00246         int vx = volx - 1;
00247         int vy = voly - 1;
00248         int vz = volz - 1;
00249 
00251         dist_near = dist_far = 100000000.0f;
00252 
00256         if (fabs(dir.x) > 0.001f)
00257         {
00258                 // 0-plane
00259                 dist = -org.x / dir.x;
00260 
00261                 sect.x = 0.0f;
00262                 sect.y = org.y + dir.y * dist;
00263                 sect.z = org.z + dir.z * dist;
00264 
00265                 if (sect.y >= 0.0f && sect.y <= vy &&
00266                         sect.z >= 0.0f && sect.z <= vz &&
00267                         dist > 0.0f)
00268                 {
00269                         // valid intersection - find if closer or farther than existing
00270                         nsect++;
00271 
00272                         if (dist < dist_near)
00273                         {
00274                                 vfar = vnear;
00275                                 dist_far = dist_near;
00276 
00277                                 vnear = sect;
00278                                 dist_near = dist;
00279                         }
00280                         else
00281                         {
00282                                 vfar = sect;
00283                                 dist_far = dist;
00284                         }
00285                 }
00286 
00287                 // volx-plane
00288                 dist = (vx - org.x) / dir.x;
00289 
00290                 sect.x = (float)vx;
00291                 sect.y = org.y + dir.y * dist;
00292                 sect.z = org.z + dir.z * dist;
00293 
00294                 if (sect.y >= 0.0f && sect.y <= vy &&
00295                         sect.z >= 0.0f && sect.z <= vz &&
00296                         dist > 0.0f)
00297                 {
00298                         // valid intersection - find if closer or farther than existing
00299                         nsect++;
00300 
00301                         if (dist < dist_near)
00302                         {
00303                                 vfar = vnear;
00304                                 dist_far = dist_near;
00305 
00306                                 vnear = sect;
00307                                 dist_near = dist;
00308                         }
00309                         else
00310                         {
00311                                 vfar = sect;
00312                                 dist_far = dist;
00313                         }
00314                 }
00315         }
00316 
00317         // intersect with y-planes
00318         if (fabs(dir.y) > 0.001f)
00319         {
00320                 // 0-plane
00321                 dist = -org.y / dir.y;
00322 
00323                 sect.x = org.x + dir.x * dist;
00324                 sect.y = 0.0f;
00325                 sect.z = org.z + dir.z * dist;
00326 
00327                 if (sect.x >= 0.0f && sect.x <= vx &&
00328                         sect.z >= 0.0f && sect.z <= vz &&
00329                         dist > 0.0f)
00330                 {
00331                         // valid intersection - find if closer or farther than existing
00332                         nsect++;
00333 
00334                         if (dist < dist_near)
00335                         {
00336                                 vfar = vnear;
00337                                 dist_far = dist_near;
00338 
00339                                 vnear = sect;
00340                                 dist_near = dist;
00341                         }
00342                         else
00343                         {
00344                                 vfar = sect;
00345                                 dist_far = dist;
00346                         }
00347                 }
00348 
00349                 // voly-plane
00350                 dist = (vy - org.y) / dir.y;
00351 
00352                 sect.x = org.x + dir.x * dist;
00353                 sect.y = (float)vy;
00354                 sect.z = org.z + dir.z * dist;
00355 
00356                 if (sect.x >= 0.0f && sect.x <= vx &&
00357                         sect.z >= 0.0f && sect.z <= vz &&
00358                         dist > 0.0f)
00359                 {
00360                         // valid intersection - find if closer or farther than existing
00361                         nsect++;
00362 
00363                         if (dist < dist_near)
00364                         {
00365                                 vfar = vnear;
00366                                 dist_far = dist_near;
00367 
00368                                 vnear = sect;
00369                                 dist_near = dist;
00370                         }
00371                         else
00372                         {
00373                                 vfar = sect;
00374                                 dist_far = dist;
00375                         }
00376                 }
00377         }
00378 
00379         // intersect with z-planes
00380         if (fabs(dir.z) > 0.001f)
00381         {
00382                 // 0-plane
00383                 dist = -org.z / dir.z;
00384 
00385                 sect.x = org.x + dir.x * dist;
00386                 sect.y = org.y + dir.y * dist;
00387                 sect.z = 0.0f;
00388 
00389                 if (sect.x >= 0.0f && sect.x <= vx &&
00390                         sect.y >= 0.0f && sect.y <= vy &&
00391                         dist > 0.0f)
00392                 {
00393                         // valid intersection - find if closer or farther than existing
00394                         nsect++;
00395 
00396                         if (dist < dist_near)
00397                         {
00398                                 vfar = vnear;
00399                                 dist_far = dist_near;
00400 
00401                                 vnear = sect;
00402                                 dist_near = dist;
00403                         }
00404                         else
00405                         {
00406                                 vfar = sect;
00407                                 dist_far = dist;
00408                         }
00409                 }
00410 
00411                 // volz-plane
00412                 dist = (vz - org.z) / dir.z;
00413 
00414                 sect.x = org.x + dir.x * dist;
00415                 sect.y = org.y + dir.y * dist;
00416                 sect.z = (float)vz;
00417 
00418                 if (sect.x >= 0.0f && sect.x <= vx &&
00419                         sect.y >= 0.0f && sect.y <= vy &&
00420                         dist > 0.0f)
00421                 {
00422                         // valid intersection - find if closer or farther than existing
00423                         nsect++;
00424 
00425                         if (dist < dist_near)
00426                         {
00427                                 vfar = vnear;
00428                                 dist_far = dist_near;
00429 
00430                                 vnear = sect;
00431                                 dist_near = dist;
00432                         }
00433                         else
00434                         {
00435                                 vfar = sect;
00436                                 dist_far = dist;
00437                         }
00438                 }
00439         }
00440 
00441         return nsect;
00442 }
00443 
00447 static __inline float GetRand01()
00448 {
00449         return (float)rand() / (float)RAND_MAX;
00450 }
00451 
00456 static __inline vect GetGradient(vect pos,              
00457                                                                  float base             
00458                                                                  )
00459 {
00460         vect gradient;
00461 
00462         pos.x += vol_opts.gradstep;
00463         gradient.x = GetInterpolatedSample(pos) - base;
00464 
00465         pos.x -= vol_opts.gradstep;
00466         pos.y += vol_opts.gradstep;
00467         gradient.y = GetInterpolatedSample(pos) - base;
00468 
00469         pos.y -= vol_opts.gradstep;
00470         pos.z += vol_opts.gradstep;
00471         gradient.z = GetInterpolatedSample(pos) - base;
00472 
00473         return gradient;
00474 }
00475 
00479 bool ShadeStep(vect &dir,                       
00480                            vect &pos,                   
00481                            color &col,                  
00482                            float steplen                
00483                            )
00484 {
00486         if (col.a > 0.99f)
00487                 return false;
00488 
00490         float val = GetInterpolatedSample(pos);
00491 
00493         vect grad = GetGradient(pos, val);
00494 
00496         float len = norm(grad);
00497 
00498         if (len > 0.0f)
00499         {
00500                 grad.x /= len;
00501                 grad.y /= len;
00502                 grad.z /= len;
00503         }
00504 
00506         histo_handle    hh;
00507 
00508         CreateInterpolatedHandle(hh, val);
00509 
00512         len = 1.0f * (1.0f - hh.gradient) + len * hh.gradient;
00513         hh.out_alpha *= len;
00514 
00515         hh.out_alpha *= steplen;
00516 
00517         hh.out_alpha = clamp(hh.out_alpha, 0.0f, 1.0f);
00518 
00520         color end;
00521 
00522         end.r = hh.col_ambient[0];
00523         end.g = hh.col_ambient[1];
00524         end.b = hh.col_ambient[2];
00525 
00527         float kd = dot(ldir, grad);
00528 
00529         if (kd < 0.0f)
00530                 kd = 0.0f;
00531 
00532         end.r += kd * hh.col_diffuse[0];
00533         end.g += kd * hh.col_diffuse[1];
00534         end.b += kd * hh.col_diffuse[2];
00535 
00537         vect half;
00538 
00539         half.x = dir.x + ldir.x;
00540         half.y = dir.y + ldir.y;
00541         half.z = dir.z + ldir.z;
00542 
00543         float half_len = norm(half);
00544 
00545         if (half_len > 0.0f)
00546         {
00547                 half.x /= half_len;
00548                 half.y /= half_len;
00549                 half.z /= half_len;
00550         }
00551 
00552         float ks = dot(half, grad);
00553 
00554         if (ks < 0.0f)
00555                 ks = 0.0f;
00556 
00557         ks = pow(ks, 1.0f / hh.spec_exponent);
00558 
00559         end.r += ks * hh.col_specular[0];
00560         end.g += ks * hh.col_specular[1];
00561         end.b += ks * hh.col_specular[2];
00562 
00564 
00565         float newweight = (1.0f - col.a) * hh.out_alpha;
00566 
00567         col.r += end.r * newweight;
00568         col.g += end.g * newweight;
00569         col.b += end.b * newweight;
00570         col.a += newweight;
00571 
00572         return true;
00573 }
00574 
00578 color ShootRay(vect org,                
00579                            vect dir                     
00580                            )
00581 {
00582         color col;
00583         col.r = col.g = col.b = col.a = 0.0f;
00584 
00585         vect sect1, sect2, pos;
00586 
00587         int nsects = GetBoxIntersection(sect1, sect2, org, dir);
00588 
00590         if (nsects > 0)
00591         {
00593                 if (nsects == 1)
00594                 {
00595                         sect2 = sect1;
00596                         sect1 = org;
00597                 }
00598                 
00599                 vect dist;
00600 
00601                 dist.x = sect1.x - sect2.x;
00602                 dist.y = sect1.y - sect2.y;
00603                 dist.z = sect1.z - sect2.z;
00604 
00605                 float range = norm(dist);
00606                 float travelled = 0.0f;
00607 
00608                 pos = sect1;
00609 
00611                 if (vol_opts.rendermode == MODE_FULL)
00612                 {
00613                         while (travelled < range)
00614                         {
00615                                 float rnd = (GetRand01() * 2.0f - 1.0f) * vol_opts.jitter * vol_opts.stepsize + vol_opts.stepsize;
00616 
00617                                 if (!ShadeStep(dir, pos, col, rnd))
00618                                 {
00619                                         travelled = range;
00620                                 }
00621 
00622                                 pos.x += dir.x * rnd;
00623                                 pos.y += dir.y * rnd;
00624                                 pos.z += dir.z * rnd;
00625 
00626                                 travelled += rnd;
00627                         }
00628                 }
00629                 else
00630                 {
00632                         float maxval = 0.0f;
00633 
00634                         while (travelled < range)
00635                         {
00636                                 float rnd = (GetRand01() * 2.0f - 1.0f) * vol_opts.jitter * vol_opts.stepsize + vol_opts.stepsize;
00637 
00638                                 float val = GetInterpolatedSample(pos);
00639 
00640                                 if (val > maxval)
00641                                 {
00642                                         maxval = val;
00643                                 }
00644 
00645                                 if (maxval >= 0.999f)
00646                                         break;
00647 
00648                                 pos.x += dir.x * rnd;
00649                                 pos.y += dir.y * rnd;
00650                                 pos.z += dir.z * rnd;
00651 
00652                                 travelled += rnd;
00653                         }
00654 
00655                         histo_handle hh;
00656                         CreateInterpolatedHandle(hh, maxval);
00657 
00658                         col.r = hh.col_diffuse[0];
00659                         col.g = hh.col_diffuse[1];
00660                         col.b = hh.col_diffuse[2];
00661                         col.a = 1.0f;
00662                 }
00663         }
00664 
00665         return col;
00666 }
00667 
00671 void DrawRect(int x, int y,                             
00672                           int height, int width,        
00673                           color c, int size,            
00674                           color *fbuffer)                       
00675 
00676 {
00677         for (int j = y; j < (y+size >= height?height-1:y+size); j++)
00678         {
00679                 for (int i = x; i < (x+size >= width?width-1:x+size); i++)
00680                 {
00681                         fbuffer[j * width + i] = c;
00682                 }
00683         }
00684 }
00685 
00689 void RayRender()
00690 {
00691         color *fbuffer;
00692         RECT crect;
00693         MSG msg;
00694 
00696         GetClientRect(wnd_3d, &crect);
00697 
00698         int width = crect.right;
00699         int height = crect.bottom;
00700 
00701         fbuffer = new color[width * height];
00702 
00704         vect dir;
00705         dir.x = cam.org.x - cam.pos.x;
00706         dir.y = cam.org.y - cam.pos.y;
00707         dir.z = cam.org.z - cam.pos.z;
00708 
00709         normalize(dir);
00710 
00711         vect up = cam.up;
00712 
00713         vect right = cross(dir, up);
00714         normalize(right);
00715 
00716         vect raydir;
00717         
00718         float aspect = (float)width / (float)height;
00719         float vert_open = atan((float)M_PI / 6.0f); // vertical FOV of 60 deg
00720         float horz_open = vert_open * aspect;
00721 
00722         wglMakeCurrent(rayHdc, rayHglrc);
00723 
00724         RECT clientRect;
00725         GetClientRect(wnd_3d, &clientRect);
00726 
00727         glViewport(0, 0, clientRect.right, clientRect.bottom);
00728 
00729         glMatrixMode(GL_PROJECTION);
00730         glLoadIdentity();
00731 
00732         gluOrtho2D(0, clientRect.right, clientRect.bottom, 0.0f);
00733 
00734         glMatrixMode(GL_MODELVIEW);
00735 
00736         glDisable(GL_BLEND);
00737         glDisable(GL_DEPTH_TEST);
00738         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00739 
00741         for (int n = MAX_ITERATION; n >= 0; n--)
00742         {
00743                 for (int y = 0; y < height; y += (1 << n))
00744                 {
00745                         for (int x = 0; x < width; x += (1 << n))
00746                         {
00749                                 if (n == MAX_ITERATION || 
00750                                         !(x % (1 << (n+1)) == 0 &&
00751                                          y % (1 << (n+1)) == 0))
00752                                 {
00754                                         float xpart = (float)(x * 2 - width) / (float)width * horz_open;
00755                                         float ypart = (float)(y * 2 - height) / (float)height * vert_open;
00756 
00757                                         raydir.x = dir.x + right.x * xpart;
00758                                         raydir.y = dir.y + right.y * xpart;
00759                                         raydir.z = dir.z + right.z * xpart;
00760 
00761                                         raydir.x = raydir.x + up.x * ypart;
00762                                         raydir.y = raydir.y + up.y * ypart;
00763                                         raydir.z = raydir.z + up.z * ypart;
00764 
00765                                         normalize(raydir);
00766 
00768                                         DrawRect(x, y, height, width, 
00769                                                 ShootRay(cam.pos, raydir), 1 << n, fbuffer);
00770                                 }
00771                         }
00772                         
00774                         if (y % (1 << (n + 5)) == 0)
00775                         {
00776                                 glDrawPixels(width, height, GL_RGBA, GL_FLOAT, fbuffer);
00777 
00778                                 glBegin(GL_LINES);
00779                                         glColor3f(0.0f, 0.0f, 1.0f);
00780                                         glVertex2i(0, height - y);
00781                                         glVertex2i(width, height - y);
00782                                 glEnd();
00783 
00784                                 glFinish();
00785 
00786                                 SwapBuffers(rayHdc);
00787                         }
00788 
00790                         while (PeekMessage(&msg, wnd_main, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
00791                         {
00792                                 switch(msg.message)
00793                                 {
00794                                 case WM_LBUTTONDOWN:
00795                                 case WM_MBUTTONDOWN:
00796                                 case WM_RBUTTONDOWN:
00797                                         glEnable(GL_DEPTH_TEST);
00798                                         glEnable(GL_BLEND);
00799 
00800                                         delete [] fbuffer;
00801 
00802                                         PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
00803 
00804                                         return;
00805                                 }
00806                         }
00807 
00808                         if (PeekMessage(&msg, wnd_main, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))
00809                         {
00810                                 switch(msg.message)
00811                                 {
00812                                 case WM_KEYDOWN:
00813                                         glEnable(GL_DEPTH_TEST);
00814                                         glEnable(GL_BLEND);
00815 
00816                                         delete [] fbuffer;
00817 
00818                                         return;
00819                                 }
00820                         }
00821                 }
00822         }
00823 
00825         glDrawPixels(width, height, GL_RGBA, GL_FLOAT, fbuffer);
00826 
00827         glFinish();
00828 
00829         SwapBuffers(rayHdc);
00830 
00831         glEnable(GL_DEPTH_TEST);
00832         glEnable(GL_BLEND);
00833 
00834         delete [] fbuffer;
00835 }

Generated on Wed Dec 5 12:07:30 2007 for Volumizer by  doxygen 1.5.4