《基于MFC的OpenGL编程》Part 7 Animation

本文介绍如何在太阳系模型中添加动画效果并显示帧率。通过响应WM_TIMER消息改变参数实现星球旋转动画,利用timeGetTime计算帧率,并在窗口标题中展示。
本文中将对 第5篇文章 的太阳系模型进行修改,加入一些动画效果。此外还会加入显示帧速率的代码。

加入动画效果最容易的方法是响应WM_TIMER消息,在其消息处理函数中改变一些参数值,比如每过多少毫秒就旋转一定的角度,并且重绘场景。

Frame Rate

Frame rate is nothing but the number of frames that can be rendered per second. The higher this rate, the smoother the animation. In order to calculate the frame rate we retrieve the system time (using the Windows multimedia API function timeGetTime()) before the rendering is performed and after the buffer is swapped. The difference between the two values is the elapsed time to render one frame. Thus we can calculate the frame rate for a given application.

1,我们需要调用timeGetTime()函数,因此在stdafx.h中加入:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> #include < mmsystem.h > // forMMtimers(you'llneedWINMM.LIB)

并且Link—>Object/library modules中加入winmm.lib

2,为了计算绘制用时,在CCY457OpenGLView.h中加入如下变量:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> // Forelapsedtimingcalculations
DWORDm_StartTime,m_ElapsedTime,m_previousElapsedTime;
CStringm_WindowTitle;
// WindowTitle
int DayOfYear;
int HourOfDay;

并在构造函数中进行初始化:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> CCY457OpenGLView::CCY457OpenGLView()
{
DayOfYear
= 1 ;
HourOfDay
= 1 ;
}

3,为了计算帧速率,修改OnCreate函数,在其中获取窗口标题,从标题中去掉”Untitled”字样,并启动定时器;

4,同样为了计算帧速率,修改OnDraw函数如下,在其中用glPushMatrix glPopMatrixRenderScene函数包裹起来,从而确保动画会正确运行。在SwapBuffers调用后我们调用PostRenderScene来显示帧速率信息到窗口标题。

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> void CCY457OpenGLView::OnDraw(CDC * pDC)
{
CCY457OpenGLDoc
* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// Getthesystemtime,inmilliseconds.
m_ElapsedTime = ::timeGetTime(); // getcurrenttime
if (ElapsedTimeinMSSinceLastRender() < 30 )
return
// Clearoutthecolor&depthbuffers
::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
RenderScene();
glPopMatrix();
// TellOpenGLtoflushitspipeline
::glFinish();
// NowSwapthebuffers
::SwapBuffers(m_pDC -> GetSafeHdc());
// PerformPostDisplayProcessing
// Onlyupdatethetitleevery15redraws(thisisabout
// every1/2second)
PostRenderScene();
// theverylastthingwedoistosave
// theelapsedtime,thisisusedwiththe
// nextelapsedtimetocalculatethe
// elapsedtimesincearenderandtheframerate
m_previousElapsedTime = m_ElapsedTime;
}

4,在CCY457OpenGLView类中加入下述成员函数,用来显示帧速率信息到窗口标题

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> //////////////////////////////////////////////////////////////////////////////
// PostRenderScene
// performpostdisplayprocessing
// ThedefaultPostRenderSceneplacestheframerateinthe
// view'stitle.Replacethiswithyourowntitleifyoulike.
void CCY457OpenGLView::PostRenderScene( void )
{
// Onlyupdatethetitleevery15redraws(thisisabout
// every1/2second)
static int updateFrame = 15 ;
if ( 16 > ++ updateFrame)
return ;
updateFrame
= 0 ;
char string [ 256 ];
_snprintf(
string , 200 , " %s(%dFrames/sec) " ,
(
const char * )m_WindowTitle,FramesPerSecond());
GetParentFrame()
-> SetWindowText( string );
}
//////////////////////////////////////////////////////////////////////////////
// FramesPerSecond
// fetchframeratecalculations
int CCY457OpenGLView::FramesPerSecond( void )
{
double eTime = ElapsedTimeinMSSinceLastRender();
if ( 0 == ( int )eTime)
return 0 ;
return ( int )( 1000 / ( int )eTime);
}
DWORDElapsedTimeinMSSinceLastStartup()
{
return (m_ElapsedTime - m_StartTime);
}
DWORDElapsedTimeinMSSinceLastRender()
{
return (m_ElapsedTime - m_previousElapsedTime);
}

5,在OnTimer函数中,通过增加变量DayOfYear HourOfDay的值来控制地球和月球的位置,并且调用InvalidateRect来刷新界面。

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> void CCY457OpenGLView::OnTimer(UINTnIDEvent)
{
if (DayOfYear < 365 )
DayOfYear
++ ;
else
DayOfYear
= 1 ;
if (HourOfDay < 365 )
HourOfDay
++ ;
else
HourOfDay
= 1 ;
InvalidateRect(NULL,FALSE);
CView::OnTimer(nIDEvent);
}

6,在RenderScene中加入绘制代码:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> void CCY457OpenGLView::RenderScene()
{
// 绘制函数
glTranslatef( 0.0f , 0.0f , - 5.0f );
// DrawtheSun
glutWireSphere( 1.0f , 20 , 20 );
// RotatethePlanetinitsorbit
glRotatef((GLfloat)( 360.0 * DayOfYear) / 365.0 , 0.0f , 1.0f , 0.0f );
glTranslatef(
4.0f , 0.0f , 0.0f );
glPushMatrix();
// RotatethePlanetinitsorbit
glRotatef((GLfloat)( 360 * HourOfDay) / 24.0 , 0.0f , 1.0f , 0.0f );
// DrawthePlanet
glutWireSphere( 0.2f , 20 , 20 );
glPopMatrix();
glRotatef((GLfloat)(
360.0 * 12.5 * DayOfYear) / 365.0 , 0.0f , 1.0f , 0.0f );
glTranslatef(
0.5f , 0.0f , 0.0f );
// DrawtheMoon
glutWireSphere( 0.01f , 20 , 20 );
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值