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
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
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
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
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
00318 if (fabs(dir.y) > 0.001f)
00319 {
00320
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
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
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
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
00380 if (fabs(dir.z) > 0.001f)
00381 {
00382
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
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
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
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);
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 }