资源描述
外部图形的加载、旋转和平移
1、 实验目的和要求
外部图形的的加载、旋转和平移
2、 实验内容
用MFC方法和OpengL知识来实现位图和.cur格式图形文件的的加载、旋转和平移。
3、 实验步骤
1) 程序设计
Camera.cpp 实现照相机模型与变换。
CoordinateAxis.cpp 实现图中的向量绘制和标注。
MFCGL.cpp 实现的功能相当于主函数调用的功能。
MFCGLView.cpp 主干文件,对图形的编辑的具体实现。
2) 程序调试、测试与运行结果分析
(1) X视图
Y视图
Z视图
旋转功能
平移共能
功能选择键,依次为选择、旋转、平移和三种视图。
(2) 功能上实现的感觉还可以,基本上已经达到要求,但由于图形文件是从网上下来的,不是自己编辑设计的,而且也不是cad文件,是没有达到题目要求,Win7不能安装CAD软件,这是我自己考虑不周,实验结果还是比较满意的。
4、 实验总结
此次课程设计,对我的很有挑战。在课上对文件加载这部分知识没有过多的领会,导致我在网上找了很长时间的加载函数。后来网上有了个用MFC加载图形的例子,根据它的截图和关键算法的代码实现,再加上以前对MFC稍微有点了解,知道函数该添加在什么位置,花了将近一个下午的时间将在RES文件夹中的文件进行了加载、旋转和平移,代码看的不是特别懂,有点糊里糊涂,而且可能对MFC了解的也不是特别深,致使我在编译时错误不断,有时甚至达到了115个错误。后来原因只是因为一个符号错了,看来还得再细节上多多注意,还有头一次用MFC实现OpengL方法的编程,感觉还好,最起码有结果出来了。MFC的优点就是框架已经搭建好了,不用在费事去做过多与需求功能无关的事,很多文件都是直接生成的,只需加几个头文件就行了,还有就是添加功能函数。总体讲收获很大,对自己的编程能力又多了一点自信。
5、 附录
res/rc2:包含项目使用的附加资源的脚本文件。
1)MFCGLView.cpp文件代码:
// MFCGLView.cpp : implementation of the CMFCGLView class
//
#include "stdafx.h"
#include "MFCGL.h"
#include "MainFrm.h"
#include "MFCGLDoc.h"
#include "MFCGLView.h"
#include "CoordinateAxis.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
GLfloat ambientLight[] = { 0.3f, 0.3f,0.3f, 1.0f };
GLfloat diffuseLight[] = { 0.7f, 0.7f,0.7f, 1.0f };
GLfloat lightPos[] = {-50.0f, 50.0f,100.0f, 1.0f };
/////////////////////////////////////////////////////////////////////////////
// CMFCGLView
IMPLEMENT_DYNCREATE(CMFCGLView, CView)
BEGIN_MESSAGE_MAP(CMFCGLView, CView)
//{{AFX_MSG_MAP(CMFCGLView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_ERASEBKGND()
ON_COMMAND(C_PAN, OnCameraPan)
ON_UPDATE_COMMAND_UI(C_PAN, OnUpdateCameraPan)
ON_COMMAND(SELECTMODE, OnSELECTMODE)
ON_UPDATE_COMMAND_UI(SELECTMODE, OnUpdateSELECTMODE)
ON_WM_MOUSEMOVE()
ON_WM_KEYDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_COMMAND(C_ROTATE, OnSceneRotate)
ON_UPDATE_COMMAND_UI(C_ROTATE, OnUpdateSceneRotate)
ON_WM_PAINT()
ON_COMMAND(ID_ORTHO, OnOrtho)
ON_UPDATE_COMMAND_UI(ID_ORTHO, OnUpdateOrtho)
ON_COMMAND(ID_PERSPECTIVE, OnPerspective)
ON_UPDATE_COMMAND_UI(ID_PERSPECTIVE, OnUpdatePerspective)
ON_COMMAND(ID_X_VIEW, OnXView)
ON_COMMAND(ID_Y_VIEW, OnYView)
ON_COMMAND(ID_Z_VIEW, OnZView)
ON_COMMAND(ID_FREE_VIEW, OnFreeView)
ON_UPDATE_COMMAND_UI(ID_X_VIEW, OnUpdateXView)
ON_UPDATE_COMMAND_UI(ID_Y_VIEW, OnUpdateYView)
ON_UPDATE_COMMAND_UI(ID_Z_VIEW, OnUpdateZView)
ON_UPDATE_COMMAND_UI(ID_FREE_VIEW, OnUpdateFreeView)
ON_COMMAND(ID_SHOW_COORDINATE_AXIS, OnShowCoordinateAxis)
ON_UPDATE_COMMAND_UI(ID_SHOW_COORDINATE_AXIS, OnUpdateShowCoordinateAxis)
ON_COMMAND(ID_DRAWMODE_SOLID, OnDrawmodeSolid)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SOLID, OnUpdateDrawmodeSolid)
ON_COMMAND(ID_DRAWMODE_WIRE, OnDrawmodeWire)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_WIRE, OnUpdateDrawmodeWire)
ON_WM_SETCURSOR()
ON_COMMAND(ID_DRAWMODE_POINTS, OnDrawmodePoints)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_POINTS, OnUpdateDrawmodePoints)
ON_COMMAND(ID_DRAWMODE_SILHOUETTE, OnDrawmodeSilhouette)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SILHOUETTE, OnUpdateDrawmodeSilhouette)
ON_COMMAND(ID_DRAWMODE_ORIENTATION_INSIDE, OnDrawmodeOrientationInside)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_ORIENTATION_INSIDE, OnUpdateDrawmodeOrientationInside)
ON_COMMAND(ID_DRAWMODE_ORIENTATION_OUTSIDE, OnDrawmodeOrientationOutside)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_ORIENTATION_OUTSIDE, OnUpdateDrawmodeOrientationOutside)
ON_COMMAND(ID_DRAWMODE_SHADING_FLAT, OnDrawmodeShadingFlat)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SHADING_FLAT, OnUpdateDrawmodeShadingFlat)
ON_COMMAND(ID_DRAWMODE_SHADING_NONE, OnDrawmodeShadingNone)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SHADING_NONE, OnUpdateDrawmodeShadingNone)
ON_COMMAND(ID_DRAWMODE_SHADING_SMOOTH, OnDrawmodeShadingSmooth)
ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SHADING_SMOOTH, OnUpdateDrawmodeShadingSmooth)
//}}AFX_MSG_MAP
// 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)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMFCGLView construction/destruction
CMFCGLView::CMFCGLView()
{
// TODO: add construction code here
m_pShape = gluNewQuadric();
m_fLineWidth = 0.05;
m_hGLContext = NULL;
m_GLPixelIndex = 0;
m_Action = SELECT;
m_RotateAxis = AXIS_Z;
m_bBuildList = FALSE;
m_bOrtho = FALSE;
m_ViewMode = FREE_VIEW;
m_bShowAxis = TRUE;
m_bSelection = FALSE;
m_nDrawMode = SOLID;
m_nDrawOrient = OUTSIDE;
m_nShading = SMOOTH;
}
CMFCGLView::~CMFCGLView()
{
gluDeleteQuadric(m_pShape);
}
BOOL CMFCGLView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CMFCGLView drawing
void CMFCGLView::OnDraw(CDC* pDC)
{
CMFCGLDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CMFCGLView printing
BOOL CMFCGLView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CMFCGLView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CMFCGLView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CMFCGLView diagnostics
#ifdef _DEBUG
void CMFCGLView::AssertValid() const
{
CView::AssertValid();
}
void CMFCGLView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMFCGLDoc* CMFCGLView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCGLDoc)));
return (CMFCGLDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMFCGLView message handlers
BOOL CMFCGLView::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc;
pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixelDesc.nVersion = 1;
pixelDesc.dwFlags =PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_STEREO_DONTCARE|
PFD_DOUBLEBUFFER;
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)
{
m_GLPixelIndex = 1;
if (DescribePixelFormat(hDC,
m_GLPixelIndex,
sizeof(PIXELFORMATDESCRIPTOR),
&pixelDesc)==0)
{
return FALSE;
}
}
if (SetPixelFormat( hDC,
m_GLPixelIndex,
&pixelDesc)==FALSE)
{
return FALSE;
}
return TRUE;
}
int CMFCGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);
if (SetWindowPixelFormat(hDC)==FALSE)
return 0;
if (CreateViewGLContext(hDC)==FALSE)
return 0;
SetTimer(0,100,NULL);
return 0;
}
BOOL CMFCGLView::CreateViewGLContext(HDC hDC)
{
m_hGLContext = wglCreateContext(hDC);
if (m_hGLContext == NULL)
{
return FALSE;
}
if (wglMakeCurrent(hDC, m_hGLContext)==FALSE)
{
return FALSE;
}
return TRUE;
}
void CMFCGLView::OnDestroy()
{
if(wglGetCurrentContext()!=NULL)
{
wglMakeCurrent(NULL, NULL) ;
}
if (m_hGLContext!=NULL)
{
wglDeleteContext(m_hGLContext);
m_hGLContext = NULL;
}
CView::OnDestroy();
}
void CMFCGLView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
GLsizei width, height;
GLdouble aspect;
width = cx;
height = cy;
if (cy==0)
aspect = (GLdouble)width;
else
aspect = (GLdouble)width/(GLdouble)height;
m_WHRatio=aspect;
glViewport(0, 0, width, height);
InitOpenGL();
}
void CMFCGLView::OnTimer(UINT nIDEvent)
{
CView::OnTimer(nIDEvent);
}
//override the virtual function to prevent the window redraw the window client
BOOL CMFCGLView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
void CMFCGLView::OnCameraPan()
{
m_Action = CAMERA_PAN;
m_bSelection = FALSE;
}
void CMFCGLView::OnUpdateCameraPan(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_Action==CAMERA_PAN);
pCmdUI->Enable(m_ViewMode==FREE_VIEW);
}
void CMFCGLView::OnSELECTMODE()
{
m_Action = SELECT;
m_bSelection = TRUE;
}
void CMFCGLView::OnUpdateSELECTMODE(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_Action==SELECT);
pCmdUI->Enable(m_ViewMode==FREE_VIEW);
}
void CMFCGLView::OnMouseMove(UINT nFlags, CPoint point)
{
DisplayWorldCoord(point);
if(nFlags==MK_LBUTTON)
{
int rx = point.x-m_OldPoint.x;
int ry = point.y-m_OldPoint.y;
switch(m_Action)
{
case CAMERA_PAN:
m_Camera.Offset(rx/100.0,-ry/100.0,0);
break;
case SCENE_ROTATE:
m_Scene.RotateRoundAxis(rx/10,m_RotateAxis);
break;
}
m_OldPoint=point;
Invalidate();
}
if(nFlags==MK_RBUTTON)
{
int rx=point.x-m_OldPoint.x;
switch(m_Action)
{
case CAMERA_PAN:
m_Camera.Offset(0,0,rx/100.0);
HCURSOR hCursor = NULL;
CWinApp *cWinApp = AfxGetApp ();
hCursor = cWinApp->LoadCursor (IDC_CUR_ZOOM);
::SetCursor(hCursor);
break;
}
m_OldPoint=point;
Invalidate();
}
//DisplayWorldCoord(point);
CView::OnMouseMove(nFlags, point);
}
void CMFCGLView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(nChar == VK_TAB && m_Action == SCENE_ROTATE)
m_RotateAxis = (m_RotateAxis+1) %3;
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CMFCGLView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_OldPoint = point;
UINT xPos = point.x;
WORD yPos = point.y;
if(m_bSelection == TRUE)
{
ProcessSelection(xPos, yPos);
}
CView::OnLButtonDown(nFlags, point);
}
void CMFCGLView::OnRButtonDown(UINT nFlags, CPoint point)
{
m_OldPoint = point;
HCURSOR hCursor = NULL;
CWinApp *cWinApp = AfxGetApp ();
if(m_Action == CAMERA_PAN){
hCursor = cWinApp->LoadCursor (IDC_CUR_ZOOM);
::SetCursor(hCursor);
}
CView::OnRButtonDown(nFlags, point);
}
void CMFCGLView::OnSceneRotate()
{
m_Action = SCENE_ROTATE;
m_bSelection = FALSE;
}
void CMFCGLView::OnUpdateSceneRotate(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_Action == SCENE_ROTATE);
pCmdUI->Enable(m_ViewMode==FREE_VIEW);
}
void CMFCGLView::OnPaint()
{
CPaintDC dc(this);
glLoadIdentity();
glClearColor(0.0,0.0,0.0,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
CheckOrtho();
SetViewMode();
if(m_bShowAxis)
{
glDisable(GL_DEPTH_TEST);
CCoordinateAxis(2,2,2).Display();
glEnable(GL_DEPTH_TEST);
}
RenderScene();
SwapBuffers(dc.m_ps.hdc);
}
void CMFCGLView::OnOrtho()
{
if(m_bOrtho)
return;
else
{
m_bOrtho=TRUE;
Invalidate();
}
}
void CMFCGLView::OnUpdateOrtho(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_bOrtho);
}
void CMFCGLView::OnPerspective()
{
if(!m_bOrtho)
return;
else
{
m_bOrtho=FALSE;
Invalidate();
}
}
void CMFCGLView::OnUpdatePerspective(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(!m_bOrtho);
}
void CMFCGLView::InitOpenGL()
{
glLineWidth(m_fLineWidth);
glEnable(GL_LINE_SMOOTH);
glFrontFace(GL_CW);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
}
void CMFCGLView::OnXView()
{
m_ViewMode = X_VIEW;
m_bOrtho = TRUE;
Invalidate();
}
void CMFCGLView::OnYView()
{
m_ViewMode = Y_VIEW;
m_bOrtho = TRUE;
Invalidate();
}
void CMFCGLView::OnZView()
{
m_ViewMode = Z_VIEW;
m_bOrtho = TRUE;
Invalidate();
}
void CMFCGLView::OnFreeView()
{
m_ViewMode = FREE_VIEW;
m_bOrtho = FALSE;
Invalidate();
}
void CMFCGLView::OnUpdateXView(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_ViewMode == X_VIEW);
}
void CMFCGLView::OnUpdateYView(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_ViewMode == Y_VIEW);
}
void CMFCGLView::OnUpdateZView(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_ViewMode == Z_VIEW);
}
void CMFCGLView::OnUpdateFreeView(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_ViewMode == FREE_VIEW);
}
void CMFCGLView::SetViewMode()
{
glMatrixMode(GL_MODELVIEW);
switch(m_ViewMode)
{
case X_VIEW:
gluLookAt(100,0,0,0,0,0,0,0,1);
break;
case Y_VIEW:
gluLookAt(0,100,0,0,0,0,0,0,1);
break;
case Z_VIEW:
gluLookAt(0,0,100,0,0,0,0,1,0);
break;
case FREE_VIEW:
m_Camera.Apply();
gluLookAt(5,5,2,0,0,0,0,0,1);
m_Scene.Apply();
break;
}
}
void CMFCGLView::CheckOrtho()
{
if(!m_bOrtho)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(35,m_WHRatio,1,1000);
glMatrixMode(GL_MODELVIEW);
}
else
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-3*m_WHRatio,3*m_WHRatio,-3,3,-1000,1000);
glMatrixMode(GL_MODELVIEW);
}
}
void CMFCGLView::OnShowCoordinateAxis()
{
m_bShowAxis =! m_bShowAxis;
Invalidate();
}
void CMFCGLView::OnUpdateShowCoordinateAxis(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_bShowAxis);
}
void CMFCGLView::OnDrawmodeSolid()
{
// TODO: Add your command handler code here
m_nDrawMode = SOLID;
InvalidateRect(NULL);
}
void CMFCGLView::OnUpdateDrawmodeSolid(CCmdUI* pCmdUI)
{
// TODO: A
展开阅读全文