⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copenglview.cpp

📁 本文以数字图像处理、压缩技术和MATLAB应用为基础
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
//
// COpenGLView.cpp : implementation of the COpenGLView class
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

//#include "resource.h"       // main symbols

#include "COpenGLView.h"

#include <mmsystem.h> // for MM timers (you'll need WINMM.LIB)

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif



// add support for OpenGL 1.1 if we're using an old header
// These are new PIXELFORMATDESCRIPTOR flags for OpenGL 1.1

#ifndef PFD_GENERIC_ACCELERATED
#define PFD_GENERIC_ACCELERATED		0x00001000
#endif

#ifndef PFD_DEPTH_DONTCARE
#define PFD_DEPTH_DONTCARE			0x20000000
#endif

#define INSTALLABLE_DRIVER_TYPE_MASK  (PFD_GENERIC_ACCELERATED|PFD_GENERIC_FORMAT)


/////////////////////////////////////////////////////////////////////////////

const char* const COpenGLView::_ErrorStrings[]= {
				{"No Error"},					// 0
				{"Unable to get a DC"},			// 1
				{"ChoosePixelFormat failed"},	// 2
				{"SelectPixelFormat failed"},	// 3
				{"wglCreateContext failed"},	// 4
				{"wglMakeCurrent failed"},		// 5
				{"wglDeleteContext failed"},	// 6
				{"SwapBuffers failed"},			// 7

		};

/////////////////////////////////////////////////////////////////////////////
// COpenGLView

IMPLEMENT_DYNCREATE(COpenGLView, CView)

BEGIN_MESSAGE_MAP(COpenGLView, CView)
	//{{AFX_MSG_MAP(COpenGLView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_WM_SIZE()
	// If you don't have an ID_ANIMATE, you can either add one
	// to your menu (Add an Animate command) or comment out the
	// references
#if defined ID_ANIMATE
	ON_COMMAND(ID_ANIMATE, OnAnimate)
	ON_UPDATE_COMMAND_UI(ID_ANIMATE, OnUpdateAnimate)
#else
	#pragma message( "No Animation Accelerator Interface Defined in COpenGLView" )
#endif
	ON_WM_KEYDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// COpenGLView construction/destruction

COpenGLView::COpenGLView() 
	: m_StockSceneListIndex(0), m_DefaultTextID(0),
	m_DefaultFlatTextID(0),
	m_SelectedStockScene( eStockSceneCheckerboard ),
	m_bAnimationRunning(FALSE),
	m_PixelFormat(0),m_hRC(0), m_pDC(0),
	m_ErrorString(_ErrorStrings[0]),
	m_deltaX(0), m_deltaY(0), m_deltaZ(0),
	m_accelX(0), m_accelY(0), m_accelZ(0), 
	m_rotdeltaX(0), m_rotdeltaY(0), m_rotdeltaZ(0), 
	m_rotaccelX(0), m_rotaccelY(0), m_rotaccelZ(0),
	m_rotX(0), m_rotY(0), m_rotZ(0),
	m_X(0), m_Y(0), m_Z(0),
	m_MaxVelocity(5.0),	m_MaxRotation(90.0), // in units/sec
	m_ElapsedTime( ~(DWORD)0 ), // initialize to a big number
	m_eCurrentDriver(eGeneric)	// driver for current pixel format

{
	// TODO: add construction code here

}

/////////////////////////////////////////////////////////////////////////////
COpenGLView::~COpenGLView()
{
	// clean up the extensions array
	if ( m_ExtensionPtr )
		{
		m_ExtensionArray.RemoveAll();
		delete[] m_ExtensionPtr;
		}
}

/////////////////////////////////////////////////////////////////////////////
BOOL COpenGLView::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized code here and/or call the base class

	// An OpenGL window must be created with the following flags and must not
    // include CS_PARENTDC for the class style. Refer to SetPixelFormat
    // documentation in the "Comments" section for further information.
    cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

	return CView::PreCreateWindow(cs);
}


/////////////////////////////////////////////////////////////////////////////
// COpenGLView drawing

void COpenGLView::OnDraw(CDC* pDC)
{

	CDocument* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	if ( m_bAnimationRunning )
		{
		// Get the system time, in milliseconds.
		// The system time is the time elapsed since Windows was started.
		// NOTE: This value wraps about every 50 days, not that I worry
		// about it.

		// The accuracy depends upon the OS that you're running
		// Win95 has accuracy to 1 ms, while WinNT will average about
		// 5 ms or more (fine for our purposes). If you're running NT you can
		// set the accuracy to a finer value. See the documentation.
		// (However, this runs fine under NT as it is...)
		m_ElapsedTime = ::timeGetTime(); // get current time

		// Now invalidate the rect and post the message to repaint.
		// Note that posting merely places the message in the queue.
		// We HAVE to do this before we short circut the animation code
		// since we'd never get called again if we didn't.
		InvalidateRect( 0, FALSE );
		GetParent()->PostMessage(WM_PAINT);

		// this statement will limit the refresh rate of the
		// window to 1000/30 frames/sec (about 33).
		// Comment it out or modify it if you really want
		// faster rates. See if you can tell the difference between a
		// limited animation and an unlimited one. Resize the window
		// and watch the rates change. With a tiny window you can easily get
		// it over 150 frames/sec (with a simple scene).
		if ( ElapsedTimeinMSSinceLastRender() < 30 )
			return;

		// Now do the time-based dynamic calculations for things like
		// accelerations, velocity, rotations, etc...
		CalculateDynamics();

		}

	// Clear out the color & depth buffers
	::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	PreRenderScene();

	::glPushMatrix();
	RenderStockScene();
 	::glPopMatrix();

	::glPushMatrix();
	RenderScene();
	::glPopMatrix();

	// Tell OpenGL to flush its pipeline
	::glFinish();

	// Now Swap the buffers
	if ( FALSE == ::SwapBuffers( m_pDC->GetSafeHdc() ) )
		{
		SetError(7);
		}

	PostRenderScene();

	// the very last thing we do is to save
	// the elapsed time, this is used with the
	// next elapsed time to calculate the
	// elapsed time since a render and the frame rate
	m_previousElapsedTime = m_ElapsedTime;

}

//////////////////////////////////////////////////////////////////////////////
// PostRenderScene
// perform post display processing
//
// The default PostRenderScene places the framerate in the
// view's title. Replace this with your own title if you like.
void COpenGLView::PostRenderScene( void )
{
	// Only update the title every 15 redraws (this is about
	// every 1/2 second)
	static int updateFrame = 15;

	if ( !m_bAnimationRunning || 16 > ++updateFrame )
		return;

	updateFrame = 0;

	char string[256];
	_snprintf( string, 200, "%s ( %d Frames/sec )",
		(const char*)m_WindowTitle, FramesPerSecond() );

	GetParentFrame()->SetWindowText( string );

}

//////////////////////////////////////////////////////////////////////////////
// FramesPerSecond
// fetch frame rate calculations
int COpenGLView::FramesPerSecond( void )
{
	double eTime = ElapsedTimeinMSSinceLastRender();

	if ( 0 == (int)eTime )
		return 0;

	return (int)(1000/(int)eTime);
}



/////////////////////////////////////////////////////////////////////////////
// COpenGLView diagnostics

#ifdef _DEBUG
/////////////////////////////////////////////////////////////////////////////
void COpenGLView::AssertValid() const
{
	CView::AssertValid();
}

/////////////////////////////////////////////////////////////////////////////
void COpenGLView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
CDocument* COpenGLView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDocument)));
	return (CDocument*)m_pDocument;
}

/////////////////////////////////////////////////////////////////////////////

int COpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	GetParentFrame()->GetWindowText( m_WindowTitle );

	// get rid of that " - Untitled" stuff
	GetParentFrame()->ModifyStyle(FWS_ADDTOTITLE,0);

	InitializeOpenGL();

	// Now we initialize the animation code

	m_StartTime = ::timeGetTime(); // get time in ms

	// need a previous time if we start off animated
	if ( m_bAnimationRunning )
		{
		m_previousElapsedTime = m_StartTime;
		}

	m_HomeX = m_X;	// initialize dynamic starting values
	m_HomeY = m_Y;
	m_HomeZ = m_Z;
	m_HomerotX = m_rotX;
	m_HomerotY = m_rotY;
	m_HomerotZ = m_rotZ;

	return 0;
}


/////////////////////////////////////////////////////////////////////////////
void COpenGLView::OnDestroy() 
{
	CView::OnDestroy();
	
	// TODO: Add your message handler code here

//	NOTE:wglDeleteContext makes the RC non-current, so this step is unnecessary
//	(but you can do it if it makes you feel secure)
//    if ( FALSE ==  ::wglMakeCurrent( 0, 0 ) )
//		{
//		SetError(2);
//        return FALSE;
//		}


    if ( FALSE == ::wglDeleteContext( m_hRC ) )
		{
		SetError(6);
 		}

//	For Color-Index mode, you should reset the palette to the original here

    if ( m_pDC )
		{
        delete m_pDC;
		}
}


/////////////////////////////////////////////////////////////////////////////
// OnEraseBkgnd
// OpenGL has its own routine to erase the background. Here we tell MFC
// not to do it, that we'll take care of it. If we didn't the scene might
// flash.	
BOOL COpenGLView::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	
	//	return CView::OnEraseBkgnd(pDC);
	return TRUE; // tell Windows not to erase the background
}

/////////////////////////////////////////////////////////////////////////////
// OnSize
// We need to set up the viewport when the size changes, and this is the best
// place for it, as long as you don't need to render more than one scene, in which
// case you'd have to do it just before each scene gets rendered.
// We also set up the viewing volumn here since we're using perspective mode. For
// Orthographic you could do it anywhere since you don't need the aspect ratio.
// Finally we also set up the default veiwing transform. For an animated scene you'd
// have to do it just before the scene was rendered.

void COpenGLView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
	GLdouble aspect_ratio; // width/height ratio
	
	if ( 0 >= cx || 0 >= cy )
		{
		return;
		}

	SetupViewport( cx, cy );

	// compute the aspect ratio
	// this will keep all dimension scales equal
	aspect_ratio = (GLdouble)cx/(GLdouble)cy;

	// select the projection matrix and clear it
    ::glMatrixMode(GL_PROJECTION);
    ::glLoadIdentity();

	// select the viewing volumn
	SetupViewingFrustum( aspect_ratio );
	
	// switch back to the modelview matrix and clear it
    ::glMatrixMode(GL_MODELVIEW);
    ::glLoadIdentity();
  
	// now perform any viewing transformations
	SetupViewingTransform();
}


//////////////////////////////////////////////////////////////////////////////
// SetError-error string manipulation

/////////////////////////////////////////////////////////////////////////////
void COpenGLView::SetError( int e )
{
	// if there was no previous error,
	// then save this one
	if ( _ErrorStrings[0] == m_ErrorString ) 
		{
		m_ErrorString = _ErrorStrings[e];
		}
}


//////////////////////////////////////////////////////////////////////////////
// InitializeOpenGL
// - just that. This is set up for RGB mode, though I've indicated
// where you would add code for color-index mode.
BOOL COpenGLView::InitializeOpenGL()
{
	// Can we put this in the constructor?
    m_pDC = new CClientDC(this);

    if ( NULL == m_pDC ) // failure to get DC
		{
		SetError(1);
		return FALSE;
		}

	if (!SetupPixelFormat())
		{
        return FALSE;
		}

//	For Color-Index mode, you'd probably create your palette here, right
//	after you select the pixel format

    if ( 0 == (m_hRC = ::wglCreateContext( m_pDC->GetSafeHdc() ) ) )
		{
		SetError(4);
		return FALSE;
		}

    if ( FALSE == ::wglMakeCurrent( m_pDC->GetSafeHdc(), m_hRC ) )
		{
		SetError(5);
		return FALSE;
		}	

	// get the extended information about the currently running
	// OpenGL implementation
    FetchExtendedInformation();

	// select our default display fonts
	// (this may take a while....)
	SetDefaultFonts();

	// specify black as clear color
    ::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	// specify the back of the buffer as clear depth
    ::glClearDepth(1.0f);
	// enable depth testing
    ::glEnable(GL_DEPTH_TEST);

	// Save the initial positions and rotations
	m_HomeX = m_X;
	m_HomeY = m_Y;
	m_HomeZ = m_Y;
	m_HomerotX = m_rotX;
	m_HomerotY = m_rotY;
	m_HomerotZ = m_rotY;

	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
BOOL COpenGLView::SetupPixelFormat()
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -