// MeshView.cpp : implementation of the CMeshView class // #include "stdafx.h" #include "Mesh.h" #include "MeshDoc.h" #include "MeshView.h" #include "Lib/dump_eps.h" #include "Lib/texture.h" #include "DialogRenderingMode.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMeshView IMPLEMENT_DYNCREATE(CMeshView, CView) BEGIN_MESSAGE_MAP(CMeshView, CView) // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) ON_WM_CREATE() ON_WM_PAINT() ON_WM_SIZE() ON_WM_ACTIVATE() ON_WM_ERASEBKGND() ON_WM_DESTROY() ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_COMMAND(ID_RENDER_LIGHT, OnRenderLight) ON_UPDATE_COMMAND_UI(ID_RENDER_LIGHT, OnUpdateRenderLight) ON_COMMAND(ID_RENDER_CULLING, OnRenderCulling) ON_UPDATE_COMMAND_UI(ID_RENDER_CULLING, OnUpdateRenderCulling) ON_COMMAND(ID_RENDER_BACKCOLOR, OnRenderBackcolor) ON_COMMAND(ID_EDIT_COPY, OnEditCopy) ON_COMMAND(ID_MODE_FILL, OnModeFill) ON_UPDATE_COMMAND_UI(ID_MODE_FILL, OnUpdateModeFill) ON_COMMAND(ID_MODE_WIREFRAME, OnModeWireframe) ON_UPDATE_COMMAND_UI(ID_MODE_WIREFRAME, OnUpdateModeWireframe) ON_COMMAND(ID_MODE_POINT, OnModePoint) ON_UPDATE_COMMAND_UI(ID_MODE_POINT, OnUpdateModePoint) ON_COMMAND(ID_RENDER_SMOOTH, OnRenderSmooth) ON_UPDATE_COMMAND_UI(ID_RENDER_SMOOTH, OnUpdateRenderSmooth) ON_COMMAND(ID_VIEW_ALL, OnViewAll) ON_COMMAND(ID_RENDER_SUPERIMPOSE_EDGES, OnRenderSuperimposeEdges) ON_UPDATE_COMMAND_UI(ID_RENDER_SUPERIMPOSE_EDGES, OnUpdateRenderSuperimposeEdges) ON_COMMAND(ID_COLORS_MESH, OnColorsMesh) ON_COMMAND(ID_COLORS_SUPERIMPOSEDEDGES, OnColorsSuperimposededges) ON_COMMAND(ID_RENDER_ANTIALIASING, OnRenderAntialiasing) ON_UPDATE_COMMAND_UI(ID_RENDER_ANTIALIASING, OnUpdateRenderAntialiasing) ON_COMMAND(ID_PREDEFINED_MESH, OnPredefinedmodesMesh) ON_UPDATE_COMMAND_UI(ID_PREDEFINED_MESH, OnUpdatePredefinedmodesMesh) ON_COMMAND(ID_PREDEFINED_CONTROLMESH, OnPredefinedControlmesh) ON_UPDATE_COMMAND_UI(ID_PREDEFINED_CONTROLMESH, OnUpdatePredefinedControlmesh) ON_COMMAND(ID_PREDEFINED_THICK, OnPredefinedMesh) ON_UPDATE_COMMAND_UI(ID_PREDEFINED_THICK, OnUpdatePredefinedMesh) ON_COMMAND(ID_COLORS_THICKEDGES, OnColorsThickedges) ON_COMMAND(ID_RENDER_VISUALCHOOSER, OnRenderVisualchooser) ON_COMMAND(ID_SUPERIMPOSE_VERTICES, OnSuperimposeVertices) ON_UPDATE_COMMAND_UI(ID_SUPERIMPOSE_VERTICES, OnUpdateSuperimposeVertices) ON_COMMAND(ID_COLORS_VERTICES, OnColorsVertices) ON_COMMAND(ID_MATERIAL_PEARL, OnMaterialPearl) ON_COMMAND(ID_MATERIAL_BRASS, OnMaterialBrass) ON_COMMAND(ID_MATERIAL_BLACKPLASTIC, OnMaterialBlackplastic) ON_COMMAND(ID_MATERIAL_GOLD, OnMaterialGold) ON_COMMAND(ID_MATERIAL_SILVER, OnMaterialSilver) ON_COMMAND(ID_MATERIAL_JADE, OnMaterialJade) ON_COMMAND(ID_MATERIAL_RUBY, OnMaterialRuby) ON_COMMAND(ID_FILE_DUMPTOPS, OnFileDumptops) ON_UPDATE_COMMAND_UI(ID_FILE_DUMPTOPS, OnUpdateFileDumptops) ON_COMMAND(ID_BOUNDIXBOX_SHOW, OnBoundixboxShow) ON_UPDATE_COMMAND_UI(ID_BOUNDIXBOX_SHOW, OnUpdateBoundixboxShow) ON_COMMAND(ID_BOUNDIXBOX_SHOWWHENMOVING, OnBoundixboxShowwhenmoving) ON_UPDATE_COMMAND_UI(ID_BOUNDIXBOX_SHOWWHENMOVING, OnUpdateBoundixboxShowwhenmoving) ON_COMMAND(ID_SPECIAL_DRAWVORONOIEDGES, OnSpecialDrawvoronoiedges) ON_UPDATE_COMMAND_UI(ID_SPECIAL_DRAWVORONOIEDGES, OnUpdateSpecialDrawvoronoiedges) END_MESSAGE_MAP() // CMeshView construction/destruction CMeshView::CMeshView() { // OpenGL m_hGLContext = NULL; m_GLPixelIndex = 0; // rendering options m_Lighting = true; m_Culling = false; m_FirstView = true; m_UseNormals = true; m_Antialiasing = false; m_SmoothShading = true; m_PolygonMode = GL_FILL; m_SuperimposeEdges = true; m_DrawVoronoiEdges = false; m_DrawBoundingBox = false; m_SuperimposeVertices = false; m_ThickerControlEdges = false; m_ThicknessControlEdges = 3.0f; m_DrawBoundingBoxWhenMoving = false; m_SuperimposeOnlyControlMesh = true; // other options m_PointSize = 3.0f; m_BackColor[0] = m_BackColor[1] = m_BackColor[2] = 0.0f; m_MeshColor[0] = m_MeshColor[1] = m_MeshColor[2] = 1.0f; m_EdgeColor[0] = m_EdgeColor[1] = m_EdgeColor[2] = 0.0f; m_VertexColor[0] = m_VertexColor[1] = m_VertexColor[2] = 0.0; m_ControlEdgeColor[0] = m_ControlEdgeColor[1] = m_ControlEdgeColor[2] = 0.0f; // mouse m_LeftButtonDown = false; m_RightButtonDown = false; m_Moving = false; } CMeshView::~CMeshView() { } BOOL CMeshView::PreCreateWindow(CREATESTRUCT& cs) { return CView::PreCreateWindow(cs); } // CMeshView drawing // OnPaint message is preferred void CMeshView::OnDraw(CDC* /*pDC*/) { } // CMeshView printing BOOL CMeshView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMeshView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { } void CMeshView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { } // CMeshView diagnostics #ifdef _DEBUG void CMeshView::AssertValid() const { CView::AssertValid(); } void CMeshView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMeshDoc* CMeshView::GetDocument() const // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMeshDoc))); return (CMeshDoc*)m_pDocument; } #endif //_DEBUG ////////////////////////////////////////////// // OPENGL ////////////////////////////////////////////// //******************************************** // SetWindowPixelFormat //******************************************** BOOL CMeshView::SetWindowPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pixelDesc; pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); pixelDesc.nVersion = 1; pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE; pixelDesc.iPixelType = PFD_TYPE_RGBA; pixelDesc.cColorBits = 32; pixelDesc.cRedBits = 8; pixelDesc.cRedShift = 16; pixelDesc.cGreenBits = 8; pixelDesc.cGreenShift = 8; pixelDesc.cBlueBits = 8; pixelDesc.cBlueShift = 0; pixelDesc.cAlphaBits = 0; pixelDesc.cAlphaShift = 0; pixelDesc.cAccumBits = 64; pixelDesc.cAccumRedBits = 16; pixelDesc.cAccumGreenBits = 16; pixelDesc.cAccumBlueBits = 16; pixelDesc.cAccumAlphaBits = 0; pixelDesc.cDepthBits = 32; pixelDesc.cStencilBits = 8; pixelDesc.cAuxBuffers = 0; pixelDesc.iLayerType = PFD_MAIN_PLANE; pixelDesc.bReserved = 0; pixelDesc.dwLayerMask = 0; pixelDesc.dwVisibleMask = 0; pixelDesc.dwDamageMask = 0; m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc); if(m_GLPixelIndex == 0) // Choose default { m_GLPixelIndex = 1; if(DescribePixelFormat(hDC,m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) return FALSE; } if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc)) return FALSE; return TRUE; } //******************************************** // CreateViewGLContext // Create an OpenGL rendering context //******************************************** BOOL CMeshView::CreateViewGLContext(HDC hDC) { m_hGLContext = wglCreateContext(hDC); if(m_hGLContext==NULL) return FALSE; if(wglMakeCurrent(hDC,m_hGLContext)==FALSE) return FALSE; return TRUE; } //******************************************** // Create an OpenGL framework //******************************************** int CMeshView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CView::OnCreate(lpCreateStruct) == -1) return -1; HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); if(SetWindowPixelFormat(hDC)==FALSE) return -1; if(CreateViewGLContext(hDC)==FALSE) return -1; // Default mode glEnable(GL_DEPTH_TEST); glClearColor(m_BackColor[0], m_BackColor[1], m_BackColor[2], 1.0f); // lighting glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); float lpos[4] = { -.2f, .2f, .9797958971f, 0.0f }; glLightfv(GL_LIGHT0,GL_POSITION,lpos); glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0f); // back material float MatAmbientBack[] = {0.0f, 1.0f, 0.0f, 1.0f}; glMaterialfv(GL_BACK,GL_AMBIENT,MatAmbientBack); ChangeMaterial(CString("Silver"),false); // init camera InitCamera(); return 0; } void CMeshView::OnPaint() { // device context for painting CPaintDC dc(this); // model is stored in Document CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); if(pDoc->m_pMesh == NULL) return; // setup camera (only once) ViewAll(); // useful in multidoc templates HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); //wglMakeCurrent(hDC,m_hGLContext); wglMakeCurrent(dc.m_ps.hdc,m_hGLContext); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // shading option if(m_SmoothShading) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); // culling option if(m_Culling) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); // polygon mode (point, line or fill) glPolygonMode(GL_FRONT_AND_BACK,m_PolygonMode); // set mesh color glColor3f(m_MeshColor[0],m_MeshColor[1],m_MeshColor[2]); // antialiasing if(m_Antialiasing) { glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT,GL_NICEST); glLineWidth(1.5f); } else { glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); glLineWidth(1.0f); } // drawing glPushMatrix(); // setup viewpoint from current arcball m_Arcball.glDraw(); if(m_SuperimposeEdges || m_SuperimposeVertices) { // enable polygon offset glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(3.0f,1.0f); } // draw the mesh if((m_Moving && m_DrawBoundingBoxWhenMoving) || m_DrawBoundingBox) { glColor3f(1.0f,0.0f,0.0f); glDisable(GL_LIGHTING); pDoc->m_pMesh->gl_draw_bounding_box(); } // lighting option if(m_Lighting) { m_UseNormals = true; glEnable(GL_LIGHTING); } else { m_UseNormals = false; glDisable(GL_LIGHTING); } if(!m_Moving || !m_DrawBoundingBoxWhenMoving) pDoc->m_pMesh->gl_draw(m_SmoothShading, m_UseNormals); // disable lighting if(m_SuperimposeEdges || m_SuperimposeVertices) glDisable(GL_LIGHTING); // draw the mesh once again with a few // options desactivated if(m_SuperimposeEdges && !(m_Moving && m_DrawBoundingBoxWhenMoving)) { // set line mode glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); // edge color glColor3f(m_EdgeColor[0],m_EdgeColor[1],m_EdgeColor[2]); // superimpose edges on the mesh bool skip_ordinary_edges = m_SuperimposeOnlyControlMesh; bool skip_control_edges = m_ThickerControlEdges; pDoc->m_pMesh->superimpose_edges(skip_ordinary_edges, skip_control_edges, m_DrawVoronoiEdges); if(m_ThickerControlEdges) { glLineWidth(m_ThicknessControlEdges); // thick edge color glColor3f(m_ControlEdgeColor[0], m_ControlEdgeColor[1], m_ControlEdgeColor[2]); skip_ordinary_edges = true; skip_control_edges = false; pDoc->m_pMesh->superimpose_edges(skip_ordinary_edges, skip_control_edges, m_DrawVoronoiEdges); } } // end superimpose edges // superimpose vertices if(m_SuperimposeVertices && !(m_Moving && m_DrawBoundingBoxWhenMoving)) { glColor3f(m_VertexColor[0],m_VertexColor[1],m_VertexColor[2]); pDoc->m_pMesh->superimpose_spheres(0.1); } // end superimpose vertices // disable polygon offset if(m_SuperimposeEdges || m_SuperimposeVertices) glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); // Double buffer SwapBuffers(dc.m_ps.hdc); glFlush(); // release ::ReleaseDC(hWnd,hDC); } // resize client void CMeshView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); wglMakeCurrent(hDC,m_hGLContext); // set OpenGL viewport and perspective glMatrixMode(GL_MODELVIEW); glLoadIdentity(); m_Viewport.SetSize(cx,cy); m_Viewport.glDraw(); m_Camera.glDraw(m_Viewport); glDrawBuffer(GL_BACK); ::ReleaseDC(hWnd,hDC); } void CMeshView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); wglMakeCurrent(hDC,m_hGLContext); ::ReleaseDC(hWnd,hDC); CView::OnActivateView(bActivate, pActivateView, pDeactiveView); } // avoid flickering BOOL CMeshView::OnEraseBkgnd(CDC*) { return TRUE; } // destroy rendering context void CMeshView::OnDestroy() { if(wglGetCurrentContext() != NULL) wglMakeCurrent(NULL,NULL); if(m_hGLContext != NULL) { wglDeleteContext(m_hGLContext); m_hGLContext = NULL; } } // handle mouse button void CMeshView::HandleMouseButton(int x, int y) { CVector3d vec = m_Arcball.Intersect(x,m_Viewport.yRes()-y, m_Camera,m_Viewport); m_Arcball.EndDrag(vec); m_Arcball.SetMode(m_LeftButtonDown+2*m_RightButtonDown); vec = m_Arcball.Intersect(x,m_Viewport.yRes()-y,m_Camera,m_Viewport); m_Arcball.BeginDrag(vec); } // mouse move void CMeshView::OnMouseMove(UINT nFlags, CPoint point) { if(m_LeftButtonDown || m_RightButtonDown) { CVector3d vec = m_Arcball.Intersect(point.x,m_Viewport.yRes()-point.y, m_Camera,m_Viewport); m_Arcball.Motion(vec); m_Moving = true; InvalidateRect(NULL,FALSE); } else m_Moving = false; } void CMeshView::OnLButtonDown(UINT nFlags, CPoint point) { SetCapture(); m_LeftButtonDown = TRUE; HandleMouseButton(point.x,point.y); CView::OnLButtonDown(nFlags, point); } void CMeshView::OnLButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); m_LeftButtonDown = FALSE; m_Moving = false; HandleMouseButton(point.x,point.y); CView::OnLButtonUp(nFlags, point); InvalidateRect(NULL,FALSE); } void CMeshView::OnRButtonDown(UINT nFlags, CPoint point) { SetCapture(); m_RightButtonDown = TRUE; HandleMouseButton(point.x,point.y); CView::OnRButtonDown(nFlags, point); } void CMeshView::OnRButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); m_RightButtonDown = FALSE; m_Moving = false; HandleMouseButton(point.x,point.y); CView::OnRButtonUp(nFlags, point); InvalidateRect(NULL,FALSE); } void CMeshView::OnEditCopy() { // Clean clipboard of contents, and copy the DIB. if(OpenClipboard()) { CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); pDoc->StatusMessage("Bmp output..."); BeginWaitCursor(); // Snap CRect rect; GetClientRect(&rect); CSize size(rect.Width(),rect.Height()); pDoc->StatusMessage("Bmp output...snap..."); unsigned char *pixel = new unsigned char[3*size.cx*size.cy]; if(pixel == NULL) { AfxMessageBox("insufficient memory"); return; } glPixelStorei(GL_PACK_ALIGNMENT,1) ; glPixelStorei(GL_PACK_ROW_LENGTH, size.cx) ; glReadPixels(0,0,size.cx,size.cy,GL_RGB,GL_UNSIGNED_BYTE,pixel); glPixelStorei(GL_PACK_ROW_LENGTH, 0) ; // Link image - buffer CTexture image; pDoc->StatusMessage("Bmp output...snap...read buffer..."); VERIFY(image.ReadBuffer(pixel,size.cx,size.cy,24)); image.BGRtoRGB(); // Cleanup memory delete [] pixel; pDoc->StatusMessage("Bmp output...snap...read buffer...fill clipboard..."); VERIFY(EmptyClipboard()); VERIFY(SetClipboardData(CF_DIB,image.ExportHandle())); VERIFY(CloseClipboard()); EndWaitCursor(); pDoc->StatusMessage("Ready"); } } void CMeshView::OnInitialUpdate() { CView::OnInitialUpdate(); } ////////////////////////////////////////////// // OPENGL OPTIONS ////////////////////////////////////////////// // ligthing void CMeshView::OnRenderLight() { m_Lighting = !m_Lighting; CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateRenderLight(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_Lighting); } // culling void CMeshView::OnRenderCulling() { m_Culling = !m_Culling; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateRenderCulling(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_Culling); } // fill rendering mode void CMeshView::OnModeFill() { m_PolygonMode = GL_FILL; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateModeFill(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_PolygonMode == GL_FILL); } // line rendering mode void CMeshView::OnModeWireframe() { m_PolygonMode = GL_LINE; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateModeWireframe(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_PolygonMode == GL_LINE); } // point rendering mode void CMeshView::OnModePoint() { m_PolygonMode = GL_POINT; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateModePoint(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_PolygonMode == GL_POINT); } // smooth vs flat shading void CMeshView::OnRenderSmooth() { m_SmoothShading = !m_SmoothShading; CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateRenderSmooth(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_SmoothShading); } // superimpose edges void CMeshView::OnRenderSuperimposeEdges() { m_SuperimposeEdges = !m_SuperimposeEdges; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateRenderSuperimposeEdges(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_SuperimposeEdges); } // superimpose vertices void CMeshView::OnSuperimposeVertices() { m_SuperimposeVertices = !m_SuperimposeVertices; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateSuperimposeVertices(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_SuperimposeVertices); } void CMeshView::OnPredefinedmodesMesh() { m_SuperimposeEdges = true; m_ThickerControlEdges = false; m_SuperimposeOnlyControlMesh = false; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdatePredefinedmodesMesh(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_SuperimposeEdges && !m_ThickerControlEdges && !m_SuperimposeOnlyControlMesh); } void CMeshView::OnPredefinedControlmesh() { m_SuperimposeEdges = true; m_ThickerControlEdges = false; m_SuperimposeOnlyControlMesh = true; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdatePredefinedControlmesh(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_SuperimposeEdges && !m_ThickerControlEdges && m_SuperimposeOnlyControlMesh); } void CMeshView::OnPredefinedMesh() { m_SuperimposeEdges = true; m_ThickerControlEdges = true; m_SuperimposeOnlyControlMesh = false; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdatePredefinedMesh(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_SuperimposeEdges && m_ThickerControlEdges && !m_SuperimposeOnlyControlMesh); } void CMeshView::OnRenderAntialiasing() { m_Antialiasing = !m_Antialiasing; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateRenderAntialiasing(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_Antialiasing); } ////////////////////////////////////////////// // CAMERA ////////////////////////////////////////////// // view all the current object void CMeshView::ViewAll(bool check_first) { // make it only once if(!m_FirstView && check_first) return; CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); ASSERT(pDoc != NULL); if(pDoc->m_pMesh == NULL) return; m_FirstView = false; // set up the camera to visualize the whole object TRACE("setup camera."); pDoc->m_pMesh->compute_bounding_box(); CMatrix44 ArcballMatrix = m_Arcball.GetMatrix(); CVector3d minBound, maxBound; minBound.Set(pDoc->m_pMesh->xmin(), pDoc->m_pMesh->ymin(), pDoc->m_pMesh->zmin()); maxBound.Set(pDoc->m_pMesh->xmax(), pDoc->m_pMesh->ymax(), pDoc->m_pMesh->zmax()); minBound = ArcballMatrix * minBound; maxBound = ArcballMatrix * maxBound; m_Camera.ViewAll(minBound[0], maxBound[0], minBound[1], maxBound[1], minBound[2], maxBound[2], m_Viewport); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); m_Camera.glDraw(m_Viewport); glMatrixMode(GL_MODELVIEW); TRACE("..ok\n"); } // init camera parameters void CMeshView::InitCamera() { // perspective CRect rect; GetClientRect(&rect); HWND hWnd = GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); wglMakeCurrent(hDC,m_hGLContext); // set viewport and camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); m_Viewport.SetOrigin(0,0); m_Viewport.SetSize(rect.Width(),rect.Height()); m_Camera.SetHeightAngle(45.); m_Camera.SetPosition(0.,0.,5.); m_Camera.SetOrientation(0.,1.,0.,0); m_Camera.SetNearDistance(.1); m_Camera.SetFarDistance(1000.); m_Viewport.glDraw(); m_Camera.glDraw(m_Viewport); glDrawBuffer(GL_BACK); ::ReleaseDC(hWnd,hDC); } void CMeshView::OnViewAll() { ViewAll(false); InvalidateRect(NULL,FALSE); } bool CMeshView::EditColor(float pColor[3]) { unsigned char r = (unsigned char)(pColor[0]*255); unsigned char g = (unsigned char)(pColor[1]*255); unsigned char b = (unsigned char)(pColor[2]*255); COLORREF color = RGB(r,g,b); CColorDialog dlg(color); if(dlg.DoModal() == IDOK) { color = dlg.GetColor(); pColor[0] = (float)GetRValue(color)/255.0f; pColor[1] = (float)GetGValue(color)/255.0f; pColor[2] = (float)GetBValue(color)/255.0f; return true; } return false; } ////////////////////////////////////////////// // COLORS ////////////////////////////////////////////// void CMeshView::OnRenderBackcolor() { if(EditColor(m_BackColor)) { glClearColor(m_BackColor[0], m_BackColor[1], m_BackColor[2], 1.0f); InvalidateRect(NULL,FALSE); } } void CMeshView::OnColorsMesh() { if(EditColor(m_MeshColor)) InvalidateRect(NULL,FALSE); } void CMeshView::OnColorsSuperimposededges() { if(EditColor(m_EdgeColor)) InvalidateRect(NULL,FALSE); } void CMeshView::OnColorsThickedges() { if(EditColor(m_ControlEdgeColor)) InvalidateRect(NULL,FALSE); } void CMeshView::OnColorsVertices() { if(EditColor(m_VertexColor)) InvalidateRect(NULL,FALSE); } void CMeshView::OnRenderVisualchooser() { CDialogRenderingMode dlg; if(dlg.DoModal()) { int mode = dlg.m_Mode; switch(mode) { case 0: m_Lighting = false; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = false; m_ThickerControlEdges = false; m_PolygonMode = GL_LINE; m_Culling = false; break; case 1: m_Lighting = false; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = false; m_ThickerControlEdges = false; m_PolygonMode = GL_LINE; m_Culling = true; break; case 2: m_Lighting = true; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = false; m_ThickerControlEdges = false; m_PolygonMode = GL_FILL; m_Culling = false; break; case 3: m_Lighting = true; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = true; m_ThickerControlEdges = false; m_PolygonMode = GL_FILL; m_Culling = false; break; case 4: m_Lighting = true; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = true; m_ThickerControlEdges = true; m_PolygonMode = GL_FILL; m_Culling = false; break; case 5: m_Lighting = true; m_SuperimposeOnlyControlMesh = true; m_SuperimposeEdges = true; m_ThickerControlEdges = false; m_PolygonMode = GL_FILL; m_Culling = false; break; case 6: m_Lighting = false; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = true; m_ThickerControlEdges = false; m_PolygonMode = GL_FILL; m_Culling = false; break; case 7: m_Lighting = false; m_SuperimposeOnlyControlMesh = false; m_SuperimposeEdges = true; m_ThickerControlEdges = true; m_PolygonMode = GL_FILL; m_Culling = false; break; case 8: m_Lighting = false; m_SuperimposeOnlyControlMesh = true; m_SuperimposeEdges = true; m_ThickerControlEdges = false; m_PolygonMode = GL_FILL; m_Culling = false; } CMeshDoc *pDoc = (CMeshDoc *)GetDocument(); InvalidateRect(NULL,FALSE); } } // change material void CMeshView::ChangeMaterial(CString &string, bool update) { float ambient[] = {0.0f,0.0f,0.0f,1.0f}; float diffuse[] = {0.0f,0.0f,0.0f,1.0f}; float specular[] = {0.0f,0.0f,0.0f,1.0f}; float emission[] = {0.3f,0.3f,0.3f,1.0f}; float shininess[] = {0.0f}; // Change if(string == "Silver") { // Ambient ambient[0] = 0.19225f; ambient[1] = 0.19225f; ambient[2] = 0.19225f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.50754f; diffuse[1] = 0.50754f; diffuse[2] = 0.50754f; diffuse[3] = 1.0f; // Specular specular[0] = 0.508273f; specular[1] = 0.508273f; specular[2] = 0.508273f; specular[3] = 1.0f; // Shininess shininess[0] = 51.2f; } else // Change if(string == "Gold") { // Ambient ambient[0] = 0.24725f; ambient[1] = 0.1995f; ambient[2] = 0.0745f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.75164f; diffuse[1] = 0.60648f; diffuse[2] = 0.22648f; diffuse[3] = 1.0f; // Specular specular[0] = 0.928281f; specular[1] = 0.855802f; specular[2] = 0.666065f; specular[3] = 1.0f; // Shininess shininess[0] = 51.2f; } else // Change if(string == "Jade") { // Ambient ambient[0] = 0.135f; ambient[1] = 0.2225f; ambient[2] = 0.1575f; ambient[3] = 0.95f; // Diffuse diffuse[0] = 0.54f; diffuse[1] = 0.89f; diffuse[2] = 0.63f; diffuse[3] = 0.95f; // Specular specular[0] = 0.316228f; specular[1] = 0.316228f; specular[2] = 0.316228f; specular[3] = 0.95f; // Shininess shininess[0] = 12.8f; } else // Change if(string == "Light blue") { // Ambient ambient[0] = 0.0f; ambient[1] = 0.5f; ambient[2] = 0.75f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.0f; diffuse[1] = 0.5f; diffuse[2] = 1.0f; diffuse[3] = 1.0f; // Specular specular[0] = 0.75f; specular[1] = 0.75f; specular[2] = 0.75f; specular[3] = 1.0f; // Shininess shininess[0] = 64.0f; } else // Change if(string == "Emerald") { // Ambient ambient[0] = 0.0215f; ambient[1] = 0.1745f; ambient[2] = 0.0215f; ambient[3] = 0.55f; // Diffuse diffuse[0] = 0.07568f; diffuse[1] = 0.61424f; diffuse[2] = 0.07568f; diffuse[3] = 0.55f; // Specular specular[0] = 0.633f; specular[1] = 0.727811f; specular[2] = 0.633f; specular[3] = 0.55f; // Shininess shininess[0] = 76.8f; } else // Change if(string == "Polished silver") { // Ambient ambient[0] = 0.23125f; ambient[1] = 0.23125f; ambient[2] = 0.23125f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.2775f; diffuse[1] = 0.2775f; diffuse[2] = 0.2775f; diffuse[3] = 1.0f; // Specular specular[0] = 0.773911f; specular[1] = 0.773911f; specular[2] = 0.773911f; specular[3] = 1.0f; // Shininess shininess[0] = 89.6f; } else // Change if(string == "Chrome") { // Ambient ambient[0] = 0.25f; ambient[1] = 0.25f; ambient[2] = 0.25f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.4f; diffuse[1] = 0.4f; diffuse[2] = 0.4f; diffuse[3] = 1.0f; // Specular specular[0] = 0.774597f; specular[1] = 0.774597f; specular[2] = 0.774597f; specular[3] = 1.0f; // Shininess shininess[0] = 76.8f; } else // Change if(string == "Copper") { // Ambient ambient[0] = 0.19125f; ambient[1] = 0.0735f; ambient[2] = 0.0225f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.7038f; diffuse[1] = 0.27048f; diffuse[2] = 0.0828f; diffuse[3] = 1.0f; // Specular specular[0] = 0.256777f; specular[1] = 0.137622f; specular[2] = 0.086014f; specular[3] = 1.0f; // Shininess shininess[0] = 12.8f; } else // Change if(string == "Polished gold") { // Ambient ambient[0] = 0.24725f; ambient[1] = 0.2245f; ambient[2] = 0.0645f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.34615f; diffuse[1] = 0.3143f; diffuse[2] = 0.0903f; diffuse[3] = 1.0f; // Specular specular[0] = 0.797357f; specular[1] = 0.723991f; specular[2] = 0.208006f; specular[3] = 1.0f; // Shininess shininess[0] = 83.2f; } else // Change if(string == "Pewter") { // Ambient ambient[0] = 0.105882f; ambient[1] = 0.058824f; ambient[2] = 0.113725f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.427451f; diffuse[1] = 0.470588f; diffuse[2] = 0.541176f; diffuse[3] = 1.0f; // Specular specular[0] = 0.333333f; specular[1] = 0.333333f; specular[2] = 0.521569f; specular[3] = 1.0f; // Shininess shininess[0] = 9.84615f; } else // Change if(string == "Obsidian") { // Ambient ambient[0] = 0.05375f; ambient[1] = 0.05f; ambient[2] = 0.06625f; ambient[3] = 0.82f; // Diffuse diffuse[0] = 0.18275f; diffuse[1] = 0.17f; diffuse[2] = 0.22525f; diffuse[3] = 0.82f; // Specular specular[0] = 0.332741f; specular[1] = 0.328634f; specular[2] = 0.346435f; specular[3] = 0.82f; // Shininess shininess[0] = 38.4f; } else // Change if(string == "Black plastic") { // Ambient ambient[0] = 0.0f; ambient[1] = 0.0f; ambient[2] = 0.0f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.01f; diffuse[1] = 0.01f; diffuse[2] = 0.01f; diffuse[3] = 1.0f; // Specular specular[0] = 0.5f; specular[1] = 0.5f; specular[2] = 0.5f; specular[3] = 1.0f; // Shininess shininess[0] = 32.0f; } else // Change if(string == "Polished bronze") { // Ambient ambient[0] = 0.25f; ambient[1] = 0.148f; ambient[2] = 0.006475f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.4f; diffuse[1] = 0.2368f; diffuse[2] = 0.1036f; diffuse[3] = 1.0f; // Specular specular[0] = 0.774597f; specular[1] = 0.458561f; specular[2] = 0.200621f; specular[3] = 1.0f; // Shininess shininess[0] = 76.8f; } else // Change if(string == "Polished copper") { // Ambient ambient[0] = 0.2295f; ambient[1] = 0.08825f; ambient[2] = 0.0275f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.5508f; diffuse[1] = 0.2118f; diffuse[2] = 0.066f; diffuse[3] = 1.0f; // Specular specular[0] = 0.580594f; specular[1] = 0.223257f; specular[2] = 0.0695701f; specular[3] = 1.0f; // Shininess shininess[0] = 51.2f; } else // Change if(string == "Pearl") { // Ambient ambient[0] = 0.25f; ambient[1] = 0.20725f; ambient[2] = 0.20725f; ambient[3] = 0.922f; // Diffuse diffuse[0] = 1.0f; diffuse[1] = 0.829f; diffuse[2] = 0.829f; diffuse[3] = 0.922f; // Specular specular[0] = 0.296648f; specular[1] = 0.296648f; specular[2] = 0.296648f; specular[3] = 0.922f; // Shininess shininess[0] = 11.264f; } else // Change if(string == "Ruby") { // Ambient ambient[0] = 0.1745f; ambient[1] = 0.01175f; ambient[2] = 0.01175f; ambient[3] = 0.55f; // Diffuse diffuse[0] = 0.61424f; diffuse[1] = 0.04136f; diffuse[2] = 0.04136f; diffuse[3] = 0.55f; // Specular specular[0] = 0.727811f; specular[1] = 0.626959f; specular[2] = 0.626959f; specular[3] = 0.55f; // Shininess shininess[0] = 76.8f; } else // Change if(string == "Turquoise") { // Ambient ambient[0] = 0.1f; ambient[1] = 0.18725f; ambient[2] = 0.1745f; ambient[3] = 0.8f; // Diffuse diffuse[0] = 0.396f; diffuse[1] = 0.74151f; diffuse[2] = 0.69102f; diffuse[3] = 0.8f; // Specular specular[0] = 0.297254f; specular[1] = 0.30829f; specular[2] = 0.306678f; specular[3] = 0.8f; // Shininess shininess[0] = 12.8f; } else // Change if(string == "Brass") { // Ambient ambient[0] = 0.329412f; ambient[1] = 0.223529f; ambient[2] = 0.027451f; ambient[3] = 1.0f; // Diffuse diffuse[0] = 0.780392f; diffuse[1] = 0.268627f; diffuse[2] = 0.113725f; diffuse[3] = 1.0f; // Specular specular[0] = 0.992157f; specular[1] = 0.741176f; specular[2] = 0.807843f; specular[3] = 1.0f; // Shininess shininess[0] = 27.8974f; } // apply glMaterialfv( GL_FRONT, GL_AMBIENT, ambient); glMaterialfv( GL_FRONT, GL_DIFFUSE, diffuse); glMaterialfv( GL_FRONT, GL_SPECULAR, specular); glMaterialfv( GL_FRONT, GL_SHININESS, shininess); glMaterialfv( GL_FRONT, GL_EMISSION, emission); if(update) InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialPearl() { ChangeMaterial(CString("Pearl"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialBrass() { ChangeMaterial(CString("Brass"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialBlackplastic() { ChangeMaterial(CString("Black plastic"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialGold() { ChangeMaterial(CString("Gold"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialSilver() { ChangeMaterial(CString("Silver"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialJade() { ChangeMaterial(CString("Jade"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnMaterialRuby() { ChangeMaterial(CString("Ruby"),false); InvalidateRect(NULL,FALSE); } void CMeshView::OnFileDumptops() { static char BASED_CODE filter[] = "EPS Files (*.eps)|*.eps"; CFileDialog SaveDlg(FALSE,"*.eps","mesh.eps", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,filter); if(SaveDlg.DoModal() == IDOK) { CString string = SaveDlg.GetPathName(); char *pFilename = string.GetBuffer(MAX_PATH); // drawing glPushMatrix(); // setup viewpoint from current arcball m_Arcball.glDraw(); // get camera GLint viewport[4]; GLdouble modelMatrix[16]; GLdouble projMatrix[16]; glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix); glGetDoublev(GL_PROJECTION_MATRIX,projMatrix); glGetIntegerv(GL_VIEWPORT,viewport); glPopMatrix(); CMeshDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); Dumper_eps,Enriched_kernel> dumper; dumper.dump(pDoc->m_pMesh, pFilename, modelMatrix, projMatrix, viewport, false); string.ReleaseBuffer(); } } void CMeshView::OnUpdateFileDumptops(CCmdUI *pCmdUI) { } // bounding box void CMeshView::OnBoundixboxShow() { m_DrawBoundingBox = !m_DrawBoundingBox; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateBoundixboxShow(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_DrawBoundingBox); } // show bounding box void CMeshView::OnBoundixboxShowwhenmoving() { m_DrawBoundingBoxWhenMoving = !m_DrawBoundingBoxWhenMoving; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateBoundixboxShowwhenmoving(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_DrawBoundingBoxWhenMoving); } // draw Voronoi edges void CMeshView::OnSpecialDrawvoronoiedges() { m_DrawVoronoiEdges = !m_DrawVoronoiEdges; InvalidateRect(NULL,FALSE); } void CMeshView::OnUpdateSpecialDrawvoronoiedges(CCmdUI *pCmdUI) { pCmdUI->SetCheck(m_DrawVoronoiEdges); }