00001
00008 #include "../common/standard.h"
00009 #include "stdafx.h"
00010
00011 #include <windows.h>
00012 #include <GL/glu.h>
00013 #include "GLutils.h"
00014 #include "Archimedes.h"
00015 #include "MainFrm.h"
00016 #include "ChildView.h"
00017 #include "VoxelParamDialog.h"
00018
00019 #ifdef _DEBUG
00020 #define new DEBUG_NEW
00021 #undef THIS_FILE
00022 static char THIS_FILE[] = __FILE__;
00023 #endif
00024
00026
00027
00028 CChildView::CChildView()
00029 {
00030 m_bFileLoaded = false;
00031 m_hglrc = NULL;
00032 m_bShowSmooth = false;
00033 }
00034
00035 CChildView::~CChildView()
00036 {
00037 }
00038
00039
00040 BEGIN_MESSAGE_MAP(CChildView,CWnd )
00041
00042 ON_WM_PAINT()
00043 ON_UPDATE_COMMAND_UI(ID_FILE_OPEN, OnUpdateFileOpen)
00044 ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
00045 ON_WM_SIZE()
00046 ON_WM_ERASEBKGND()
00047 ON_WM_LBUTTONDOWN()
00048 ON_WM_LBUTTONUP()
00049 ON_WM_MOUSEMOVE()
00050 ON_BN_CLICKED(IDC_SNAPSHOT_BUTTON, OnSnapshotButton)
00051 ON_CBN_SELCHANGE(IDC_VOXELSMOOTH_COMBO, OnSelchangeVoxelsmoothCombo)
00052
00053 END_MESSAGE_MAP()
00054
00055
00057
00058
00059 BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
00060 {
00061 if (!CWnd::PreCreateWindow(cs))
00062 return FALSE;
00063
00064 cs.dwExStyle |= WS_EX_CLIENTEDGE;
00065 cs.style &= ~WS_BORDER;
00066 cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
00067 ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);
00068
00069 return TRUE;
00070 }
00071
00072
00074 BOOL InitPixelFormat(CDC *pDC)
00075 {
00076
00077 static PIXELFORMATDESCRIPTOR pfd =
00078 {
00079 sizeof(PIXELFORMATDESCRIPTOR),
00080 1,
00081 PFD_DRAW_TO_WINDOW |
00082 PFD_SUPPORT_OPENGL |
00083 PFD_DOUBLEBUFFER,
00084 PFD_TYPE_RGBA,
00085 24,
00086 0, 0, 0, 0, 0, 0,
00087 0,
00088 0,
00089 0,
00090 0, 0, 0, 0,
00091 32,
00092 0,
00093 0,
00094 PFD_MAIN_PLANE,
00095 0,
00096 0, 0, 0
00097 };
00098
00099 int pixelformat;
00100
00101 if ( (pixelformat = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd)) == 0 )
00102 {
00103 AfxMessageBox("ChoosePixelFormat failed");
00104 return FALSE;
00105 }
00106
00107
00108 if (SetPixelFormat(pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE)
00109 {
00110 AfxMessageBox("SetPixelFormat failed");
00111 return FALSE;
00112 }
00113
00114 return TRUE;
00115 }
00116
00118 static HGLRC InitOpenGL(CDC *pDC, const CRect &clientRect)
00119 {
00120 HGLRC hrc;
00121
00122
00123 ASSERT(pDC != NULL);
00124 if (!InitPixelFormat(pDC))
00125 {
00126 AfxMessageBox("InitOpenGL couldn't initialize the pixel format, bailing...");
00127 assert(0);
00128
00129 exit(0);
00130 }
00131
00132
00133 hrc = wglCreateContext(pDC->GetSafeHdc());
00134 wglMakeCurrent(pDC->GetSafeHdc(), hrc);
00135
00136 return hrc;
00137 }
00138
00140 void CChildView::OnPaint()
00141 {
00142
00143 Draw();
00144 }
00145
00146
00147 void CChildView::OnUpdateFileOpen(CCmdUI* pCmdUI)
00148 {
00149 pCmdUI->Enable();
00150 }
00151
00152
00153
00154
00155
00156
00157
00158 static float
00159 tb_project_to_sphere(float r, float x, float y)
00160 {
00161 float d, t, z;
00162
00163 d = sqrt(x*x + y*y);
00164 if (d < r * 0.70710678118654752440) {
00165 z = sqrt(r*r - d*d);
00166 } else {
00167 t = r / 1.41421356237309504880;
00168 z = t*t / d;
00169 }
00170 return z;
00171 }
00172
00173
00174 #define TRACKBALLSIZE (0.6)
00175
00183 void getRotation(ColVector2d mouseOld, ColVector2d mouseNew, float &phi, ColVector3 &a)
00184 {
00185 float t;
00186
00187 if (mouseOld == mouseNew)
00188 return;
00189
00190
00191
00192
00193
00194
00195 ColVector3d p1 (mouseOld[0], mouseOld[1], tb_project_to_sphere(TRACKBALLSIZE,mouseOld[0],mouseOld[1]));
00196 ColVector3d p2 (mouseNew[0], mouseNew[1], tb_project_to_sphere(TRACKBALLSIZE,mouseNew[0],mouseNew[1]));
00197
00198
00199
00200
00201
00202 a = p2.crossProduct(p1);
00203
00204
00205
00206
00207 ColVector3 d = p1 - p2;
00208 t = d.getLength() / (2.0*TRACKBALLSIZE);
00209
00210
00211
00212
00213 if (t > 1.0) t = 1.0;
00214 if (t < -1.0) t = -1.0;
00215 phi = 2.0 * asin(t);
00216 }
00217
00218
00226 static void doResize (int w, int h)
00227 {
00228
00229 if (h == 0 || w == 0)
00230 return;
00231
00232 glViewport(0, 0, w, h);
00233
00234 glMatrixMode(GL_PROJECTION);
00235 glLoadIdentity();
00236
00237 if (w > h)
00238 gluPerspective(30, (float)w/h, 0.5f, 200);
00239 else
00240 gluPerspective(30*h/w, (float)w/h, 0.5f, 200);
00241
00242 glMatrixMode(GL_MODELVIEW);
00243 }
00244
00245 void CChildView::Draw()
00246 {
00247 CPaintDC dc(this);
00248
00249
00250
00251 CRect clientRect;
00252 GetClientRect(&clientRect);
00253
00254 static bool bInit = false;
00255 if (!bInit)
00256 {
00257 m_hglrc = InitOpenGL(&dc, clientRect);
00258 bInit = true;
00259 }
00260
00261 wglMakeCurrent (dc.m_hDC, m_hglrc);
00262
00263 glClearColor (0,0,1,1);;
00264 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00265
00266 if (m_bFileLoaded)
00267 {
00268 glEnable(GL_DEPTH_TEST);
00269
00270 glMatrixMode (GL_PROJECTION);
00271 glLoadIdentity();
00272
00273 doResize(clientRect.Width(), clientRect.Height());
00274 glMatrixMode (GL_MODELVIEW);
00275 glLoadIdentity();
00276 gluLookAt(0,0,-1, 0,0,0, 0,1,0);
00277
00278 CRect r;
00279 this->GetClientRect(r);
00280
00281 ColVector2d oldPos (
00282 RESCALE (m_oldMousePos.x, 0, r.Width(), -1., 1.),
00283 RESCALE (m_oldMousePos.y, 0, r.Height(), -1., 1.));
00284 ColVector2d newPos (
00285 RESCALE (m_newMousePos.x, 0, r.Width(), -1., 1.),
00286 RESCALE (m_newMousePos.y, 0, r.Height(), -1., 1.));
00287
00288 float phi=0;
00289 ColVector3d amt(0,0,0);
00290 getRotation(oldPos, newPos, phi, amt);
00291
00292 if (m_bShowSmooth)
00293 glDisable (GL_CULL_FACE);
00294 else
00295 glEnable (GL_CULL_FACE);
00296
00297 m_scanner.drawWithAngle(m_bShowSmooth, (180.)*newPos[1], -(180.)*newPos[0]);
00298 }
00299
00300 if (stringToDraw.GetLength() > 0)
00301 {
00302 try
00303 {
00304 printBitmapString(stringToDraw.GetBuffer(0), dc.m_hDC);
00305 }
00306 catch (exception &e)
00307 {
00308 Message(e.what());
00309 }
00310 }
00311
00312 assert(!glGetError());
00313
00314 SwapBuffers(wglGetCurrentDC());
00315 }
00316
00317
00318 void updateCallback (char *str, float pct, void *data)
00319 {
00320 CChildView *_this = (CChildView *)data;
00321
00322 if (strlen(str) > 0)
00323 {
00324 char stringWithPct[256];
00325 sprintf (stringWithPct, "%s (%.1f%% of voxels carved)", str, pct*100);
00326 _this->stringToDraw = stringWithPct;
00327 }
00328 else
00329 _this->stringToDraw="";
00330
00331 _this->Invalidate();
00332 _this->UpdateWindow();
00333 }
00334
00335 bool CChildView::openFile(const char *filename)
00336 {
00337 try {
00338 m_scanner.loadImages(filename,
00339 25,
00340 30);
00341 }
00342 catch (exception &e)
00343 {
00344 Message("Unable to load file %s: %s", filename, e.what());
00345 return false;
00346 }
00347
00348 AfxGetApp()->AddToRecentFileList(filename);
00349
00350 char *ext = strrchr (filename, '.');
00351 if (!ext) throw RuntimeError ("OnOpenDocument(): Your file must have a .scn or a .col extension.");
00352
00353 Vertex center;
00354 int voxelsPerSide;
00355 double voxelCubeSize;
00356
00357 if (0 == _stricmp(ext, ".scn"))
00358 {
00359 m_scanner.getVoxelParamsFromScnFile (filename, center, voxelsPerSide, voxelCubeSize);
00360 }
00361 else
00362 {
00363 voxelsPerSide = 25;
00364 voxelCubeSize = 30;
00365 center = m_scanner.guessVoxelcubeCenter();
00366 }
00367
00368 VoxelParamDialog d;
00369
00370 d.m_voxelcubeWidth = voxelCubeSize;
00371 d.m_voxelsPerSide = voxelsPerSide;
00372 d.m_threshold = 50;
00373 d.m_bEnableSilhouetteCheckbox = m_scanner.hasSilhouettes();
00374
00375 m_scanner.setProgressCallback (updateCallback, 1, this);
00376 if (IDOK == d.DoModal ())
00377 {
00378 VoxelCube &cube = m_scanner.voxelCube;
00379 cube.setVoxelSize (d.m_voxelcubeWidth / d.m_voxelsPerSide);
00380 cube.setVoxelsPerSide (d.m_voxelsPerSide);
00381 cube.setCenter (center);
00382
00383 m_bFileLoaded = true;
00384 m_scanner.carveVoxels (d.m_threshold, d.m_bUseSilhouettes?true:false);
00385 m_scanner.setProgressCallback (NULL, 0, NULL);
00386
00387 Invalidate(false);
00388 CMainFrame *mf = (CMainFrame *)GetParentFrame();
00389 mf->m_wndStatusBar.SetPaneText(
00390 1, fmtString("%d voxels (cube view), %d polygons (smooth mesh view)", m_scanner.voxelCube.svl.size(), m_scanner.mesh.getNumFacesVisible()),
00391 TRUE);
00392 return true;
00393 }
00394 else
00395 {
00396 m_scanner.setProgressCallback (NULL, 0, NULL);
00397 return false;
00398 }
00399 }
00400
00401 void CChildView::OnFileOpen()
00402 {
00403 CFileDialog f(
00404 TRUE,
00405 ".scn",
00406 NULL,
00407 OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
00408 "All Files (*.col, *.scn)|*.col;*.scn|Archimedes XML files (*.scn)|*.scn|MERL files (*.col)|*.col||");
00409
00410 if (IDOK != f.DoModal())
00411 return;
00412
00413 CString filename = f.GetPathName();
00414
00415 if (!openFile (filename))
00416 return;
00417 }
00418
00419 void CChildView::OnSize(UINT nType, int cx, int cy)
00420 {
00421 CWnd ::OnSize(nType, cx, cy);
00422
00423 doResize(cx, cy);
00424 }
00425
00427 BOOL CChildView::OnEraseBkgnd(CDC* pDC) { return true; }
00428
00429 void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
00430 {
00431 m_bMouseDown = true;
00432 m_oldMousePos = point;
00433
00434 SetCapture();
00435
00436 CWnd::OnLButtonDown(nFlags, point);
00437 }
00438
00439 void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
00440 {
00441 ReleaseCapture();
00442 m_bMouseDown = false;
00443
00444 CWnd::OnLButtonUp(nFlags, point);
00445 }
00446
00447 void CChildView::OnMouseMove(UINT nFlags, CPoint point)
00448 {
00449 if (!m_bMouseDown)
00450 return;
00451
00452 m_newMousePos = point;
00453 Invalidate();
00454
00455 CWnd::OnMouseMove(nFlags, point);
00456 }
00457 #ifndef BIF_NEWDIALOGSTYLE
00458 #define BIF_NEWDIALOGSTYLE 0x0040
00459 #endif
00460
00468 bool getDirectoryNameFromDialog(HWND hwnd, const char *messageToDisplay, std::string &dirName)
00469 {
00470 bool rtn = false;
00471 CoInitialize(NULL);
00472 LPMALLOC pMalloc;
00473
00474 if (::SHGetMalloc(&pMalloc) == NOERROR)
00475 {
00476 BROWSEINFO info;
00477 char pszBuffer[MAX_PATH];
00478 LPITEMIDLIST pidl;
00479
00480 memset (&info, 0, sizeof(BROWSEINFO));
00481
00482 info.hwndOwner = hwnd;
00483 info.pszDisplayName = pszBuffer;
00484 info.lpszTitle = _T(messageToDisplay);
00485 info.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
00486
00488 if ((pidl = ::SHBrowseForFolder(&info)) != NULL)
00489 {
00490 if (::SHGetPathFromIDList(pidl, pszBuffer))
00491 {
00492 dirName = pszBuffer;
00493 rtn = true;
00494 }
00495 else
00496 {
00497 dirName = "";
00498 }
00499
00500 pMalloc->Free(pidl);
00501 }
00502
00503 pMalloc->Release();
00504 }
00505
00506 return rtn;
00507 }
00508
00509 void CChildView::OnSnapshotButton()
00510 {
00511 if (!m_bFileLoaded)
00512 {
00513 Message("Can't take snapshots (no file loaded yet!)");
00514 return;
00515 }
00516
00517 std::string dirName;
00518 if (getDirectoryNameFromDialog (this->m_hWnd, "Where would you like to save your snapshots?", dirName))
00519 {
00520 try
00521 {
00522 m_scanner.takeSnapshots(dirName.c_str());
00523 }
00524 catch (exception &e)
00525 {
00526 Message(e.what());
00527 }
00528 }
00529 }
00530
00532 void CChildView::OnSelchangeVoxelsmoothCombo()
00533 {
00534 CMainFrame *mf = (CMainFrame *)GetParentFrame();
00535 CComboBox *bSmooth = (CComboBox *)mf->m_wndDlgBar.GetDlgItem(IDC_VOXELSMOOTH_COMBO);
00536
00537 if (bSmooth->GetCurSel() == 1)
00538 m_bShowSmooth = true;
00539 else
00540 m_bShowSmooth = false;
00541 Invalidate();
00542 }