www.pudn.com > 法线示例程序.zip > NormalsView.cpp


// objviewerView.cpp : implementation of the CNormalsView class 
// 
 
#include "stdafx.h" 
#include "glincludes.h" 
#include "Normals.h" 
 
#include "NormalsDoc.h" 
#include "NormalsView.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CNormalsView 
 
IMPLEMENT_DYNCREATE(CNormalsView, CView) 
 
BEGIN_MESSAGE_MAP(CNormalsView, CView) 
	//{{AFX_MSG_MAP(CNormalsView) 
	ON_WM_TIMER() 
	ON_WM_DESTROY() 
	ON_WM_CHAR() 
	ON_WM_KEYDOWN() 
	ON_WM_SIZE() 
	ON_COMMAND(ID_DISP_FLAT, OnDispFlat) 
	ON_COMMAND(ID_DISP_SMOOTH, OnDispSmooth) 
	ON_UPDATE_COMMAND_UI(ID_DISP_FLAT, OnUpdateDispFlat) 
	ON_UPDATE_COMMAND_UI(ID_DISP_SMOOTH, OnUpdateDispSmooth) 
	ON_COMMAND(ID_DISP_NONE, OnDispNone) 
	ON_UPDATE_COMMAND_UI(ID_DISP_NONE, OnUpdateDispNone) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CNormalsView construction/destruction 
 
CNormalsView::CNormalsView() :  
	m_pGLDC(NULL), 
	m_nTimerID (0),	 
	m_shading (SHADING_NONE) 
{ 
	m_center.x = m_center.y = m_center.z = 0; 
	m_oyAngle = (float)_PI/3; 
	m_radius = 400; 
} 
 
 
CNormalsView::~CNormalsView() 
{ 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CNormalsView drawing 
void CNormalsView::OnDraw(CDC* pDC) 
{ 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CNormalsView diagnostics 
 
#ifdef _DEBUG 
void CNormalsView::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
 
void CNormalsView::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
CNormalsDoc* CNormalsView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CNormalsDoc))); 
	return (CNormalsDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CNormalsView message handlers 
 
void CNormalsView::OnInitialUpdate()  
{ 
	CView::OnInitialUpdate(); 
	 
	ModifyStyle(0, WS_CLIPCHILDREN|WS_CLIPSIBLINGS); 
 
	m_pGLDC = new CClientDC(this); 
 
	PIXELFORMATDESCRIPTOR pfd = {  
		sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd 
		1,                              // version number 
		PFD_DRAW_TO_WINDOW |            // support window 
		  PFD_SUPPORT_OPENGL |          // support OpenGL 
		  PFD_DOUBLEBUFFER,             // double buffered 
		PFD_TYPE_RGBA,                  // RGBA type 
		24,                             // 24-bit color depth 
		0, 0, 0, 0, 0, 0,               // color bits ignored 
		0,                              // no alpha buffer 
		0,                              // shift bit ignored 
		0,                              // no accumulation buffer 
		0, 0, 0, 0,                     // accum bits ignored 
		16,                             // 16-bit z-buffer 
		0,                              // no stencil buffer 
		0,                              // no auxiliary buffer 
		PFD_MAIN_PLANE,                 // main layer 
		0,                              // reserved 
		0, 0, 0                         // layer masks ignored 
	}; 
 
	// get the best available match of pixel format for the device context   
	int iPixelFormat = ChoosePixelFormat(m_pGLDC->GetSafeHdc(), &pfd);   
 
	// make that the pixel format of the device context  
	SetPixelFormat(m_pGLDC->GetSafeHdc(), iPixelFormat, &pfd); 
	 
	// Get the pixel format 
	iPixelFormat = ::GetPixelFormat(m_pGLDC->GetSafeHdc()); 
	::DescribePixelFormat(m_pGLDC->GetSafeHdc(), iPixelFormat, sizeof(pfd), &pfd); 
 
	HGLRC hglrc = wglCreateContext(m_pGLDC->GetSafeHdc()); 
	ASSERT(hglrc); 
 
	if (hglrc) 
	{ 
		VERIFY(wglMakeCurrent(m_pGLDC->GetSafeHdc(), hglrc)); 
 
		GL_VERIFY(glMatrixMode(GL_PROJECTION)); 
		RECT r; 
		GetClientRect(&r); 
 
		// Compute the field of view angle for the perspective matrix 
		#define EYE_TO_SCREEN	(13.5)	// Distance from eye to screen in inches 
		double yinch = (double)r.bottom / m_pGLDC->GetDeviceCaps(LOGPIXELSY); 
		m_fovAngle = asin(yinch / EYE_TO_SCREEN); 
		m_aspectRatio = (GLdouble)r.right / r.bottom; 
		gluPerspective(RAD2DEG(m_fovAngle), m_aspectRatio, 100, 10000); 
 
		GL_VERIFY(glClearColor(0, 0, 0, 0)); 
		GL_VERIFY(glEnable(GL_DEPTH_TEST)); 
		GL_VERIFY(glShadeModel(GL_FLAT)); 
		GL_VERIFY(glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); 
 
		// Set a default lightning 
		GL_VERIFY(glEnable(GL_LIGHTING)); 
		GL_VERIFY(glEnable(GL_LIGHT0)); 
		float ld[4] = { 1, 1, 1, 0 }; 
		GL_VERIFY(glLightfv(GL_LIGHT0, GL_AMBIENT, ld)); 
		GL_VERIFY(glLightfv(GL_LIGHT0, GL_DIFFUSE, ld)); 
		GL_VERIFY(glLightfv(GL_LIGHT0, GL_SPECULAR, ld)); 
 
		// Set a default model view matrix 
		SetEyePos(); 
 
		// Set a default material 
		GLfloat a[4] = { 0, 0, 0, 1 }; 
		glMaterialfv(GL_FRONT, GL_AMBIENT, a); 
		GLfloat d[4] = { 1, 0, 0, 1 }; 
		glMaterialfv(GL_FRONT, GL_DIFFUSE, d); 
		glMaterialfv(GL_FRONT, GL_SPECULAR, d); 
		glMaterialf(GL_FRONT, GL_SHININESS, 128); 
 
		// Start redraw timer 
		m_nTimerID = SetTimer(1, 10, NULL); 
	} 
} 
 
void CNormalsView::OnTimer(UINT nIDEvent)  
{ 
	// Redraw scene 
	DrawScene();	 
	 
	CView::OnTimer(nIDEvent); 
} 
 
 
static void glDrawAxis () 
{ 
	GLboolean bLightning = glIsEnabled(GL_LIGHTING); 
	glDisable(GL_LIGHTING); 
 
	glBegin(GL_LINES ); 
		glColor3f(1, 0, 0); 
		glVertex3f(-1000, 0,  0); 
		glVertex3f(1000, 0,  0); 
	glEnd(); 
	glBegin(GL_LINES ); 
		glColor3f(0, 1, 0); 
		glVertex3f(0, -1000,  0); 
		glVertex3f(0, 1000,  0); 
	glEnd(); 
	glBegin(GL_LINES ); 
		glColor3f(0, 0, 1); 
		glVertex3f(0, 0,  -1000); 
		glVertex3f(0, 0,  1000); 
	glEnd(); 
 
	if (bLightning) 
		glEnable(GL_LIGHTING); 
} 
 
 
void CNormalsView::DrawScene() 
{ 
	// Protect ourself against reentrance calls 
    static bool bBusy = false; 
    if (bBusy) 
		return; 
    bBusy = true; 
 
    GL_VERIFY(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); 
 
	// Draw the static object 
	WORD wFlags = 0; 
	switch (m_shading) 
	{ 
		case SHADING_FLAT: wFlags |= DF_FLAT; break; 
		case SHADING_SMOOTH: wFlags |= DF_SMOOTH; break; 
	} 
	m_object.Draw(wFlags); 
 
	// Draw axis if the shift key is down 
	if (GetAsyncKeyState(VK_SHIFT) < 0) 
		glDrawAxis(); 
 
	glFlush(); 
    SwapBuffers(wglGetCurrentDC()); 
 
    bBusy = false; 
} 
 
 
void CNormalsView::OnDestroy()  
{ 
	CView::OnDestroy(); 
	 
	if (m_nTimerID) 
		KillTimer(m_nTimerID); 
 
	HGLRC hglrc = wglGetCurrentContext(); 
	if (hglrc) 
	{ 
		wglMakeCurrent(NULL,  NULL); 
		VERIFY(wglDeleteContext(hglrc)); 
	} 
 
	if (m_pGLDC) 
		delete m_pGLDC;	 
} 
 
 
void CNormalsView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	float f = 10; 
	switch (nChar) 
	{ 
		case '+': m_radius -= f; break; 
		case '-': m_radius += f; break; 
	} 
	SetEyePos(); 
	 
	CView::OnChar(nChar, nRepCnt, nFlags); 
} 
 
 
void CNormalsView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	float f = (float)DEG2RAD(5); 
	switch (nChar) 
	{ 
		case VK_LEFT: m_oyAngle -= f; break; 
		case VK_RIGHT: m_oyAngle += f; break; 
	} 
	SetEyePos(); 
	 
	CView::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
 
void CNormalsView::SetEyePos() 
{ 
	GL_VERIFY(glMatrixMode(GL_MODELVIEW)); 
    glLoadIdentity(); 
 
	// Set camera position 
	GLpoint eyePos = m_center; 
	eyePos.y = (float)(m_radius * cos(m_oyAngle)); 
	eyePos.x = (float)(m_radius * -sin(m_oyAngle)); 
	eyePos.z = m_radius; 
	gluLookAt(eyePos.x, eyePos.y, eyePos.z, m_center.x, m_center.y, m_center.z, 0, 0, 1); 
 
	// Set light position 
	GLfloat f[4]; 
	f[0] = eyePos.x; 
	f[1] = eyePos.y; 
	f[2] = eyePos.z; 
	f[3] = 1; 
	glLightfv(GL_LIGHT0, GL_POSITION, f); 
} 
 
 
void CNormalsView::OnSize(UINT nType, int cx, int cy)  
{ 
	CView::OnSize(nType, cx, cy); 
		 
	if (cx && m_pGLDC) 
	{ 
		glMatrixMode(GL_PROJECTION); 
		glLoadIdentity(); 
 
		glViewport(0, 0, cx, cy); 
 
		// Compute the field of view angle for the perspective matrix 
		#define EYE_TO_SCREEN	(13.5)	// Distance from eye to screen in inches 
		double yinch = (double)cy / m_pGLDC->GetDeviceCaps(LOGPIXELSY); 
		m_fovAngle = asin(yinch / EYE_TO_SCREEN); 
		m_aspectRatio = (GLdouble)cx / cy; 
		gluPerspective(RAD2DEG(m_fovAngle), m_aspectRatio, 1, 10000); 
 
		// Set the default model view matrix 
		SetEyePos(); 
	} 
} 
 
 
void CNormalsView::OnDispFlat()  
{ 
	m_shading = SHADING_FLAT; 
	GL_VERIFY(glShadeModel(GL_FLAT)); 
} 
 
 
void CNormalsView::OnDispSmooth()  
{ 
	m_shading = SHADING_SMOOTH; 
	GL_VERIFY(glShadeModel(GL_SMOOTH)); 
} 
 
 
void CNormalsView::OnDispNone()  
{ 
	m_shading = SHADING_NONE; 
	GL_VERIFY(glShadeModel(GL_FLAT)); 
} 
 
 
void CNormalsView::OnUpdateDispFlat(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_shading == SHADING_FLAT); 
} 
 
 
void CNormalsView::OnUpdateDispSmooth(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_shading == SHADING_SMOOTH); 
} 
 
 
void CNormalsView::OnUpdateDispNone(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_shading == SHADING_NONE); 
}