ChildView.cpp

Go to the documentation of this file.
00001 
00008 #include "../common/standard.h"
00009 #include "stdafx.h"
00010 
00011 #include <windows.h>
00012 #include <GL/glu.h>
00013 #include "GLutils.h" // printBitmapString
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 // CChildView
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         //{{AFX_MSG_MAP(CChildView)
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         //}}AFX_MSG_MAP
00053 END_MESSAGE_MAP()
00054 
00055 
00057 // CChildView message handlers
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),      // size of this pfd
00080             1,                              // version number
00081             PFD_DRAW_TO_WINDOW |            // support window
00082             PFD_SUPPORT_OPENGL |            // support OpenGL
00083             PFD_DOUBLEBUFFER,               // double buffered
00084             PFD_TYPE_RGBA,                  // RGBA type
00085             24,                             // 24-bit color depth
00086             0, 0, 0, 0, 0, 0,               // color bits ignored
00087             0,                              // no alpha buffer
00088             0,                              // shift bit ignored
00089             0,                              // no accumulation buffer
00090             0, 0, 0, 0,                     // accum bits ignored
00091             32,                             // 32-bit z-buffer
00092             0,                              // no stencil buffer
00093             0,                              // no auxiliary buffer
00094             PFD_MAIN_PLANE,                 // main layer
00095             0,                              // reserved
00096             0, 0, 0                         // layer masks ignored
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         // Set up DC
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         // Set up GL context
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  * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
00154  * if we are away from the center of the sphere.
00155  *
00156  * @author Gavin Bell
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) {    /* Inside sphere */
00165         z = sqrt(r*r - d*d);
00166     } else {           /* On hyperbola */
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      * First, figure out z-coordinates for projection of P1 and P2 to
00192      * deformed sphere
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      *  Now, we want the cross product of P1 and P2
00200      */
00201     // axis of rotation
00202     a = p2.crossProduct(p1);
00203 
00204     /*
00205      *  Figure out how much to rotate around that axis.
00206      */
00207     ColVector3 d = p1 - p2;
00208     t = d.getLength() / (2.0*TRACKBALLSIZE);
00209 
00210     /*
00211      * Avoid problems with out-of-control values...
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         // don't divide by zero
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); // device context for painting       
00248 /*
00249  * Initialize OpenGL, if it hasn't been already
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,   // default # voxels/side
00340             30);  // default width of the whole cube of voxels
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,           // open file dialog
00405                 ".scn",         // default extension
00406                 NULL,           // initial filename
00407                 OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, // flags
00408                 "All Files (*.col, *.scn)|*.col;*.scn|Archimedes XML files (*.scn)|*.scn|MERL files (*.col)|*.col||");  // extension filter                     
00409 
00410         if (IDOK != f.DoModal()) // user cancelled
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 }

Generated on Tue May 21 03:34:51 2002 for Archimedes by doxygen1.2.15