• 【转】《基于MFC的OpenGL编程》Part 7 Animation


    本文中将对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中加入:

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

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

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

        //For elapsed timing calculations
         DWORD m_StartTime, m_ElapsedTime, m_previousElapsedTime;    
         CString m_WindowTitle;    
    //Window Title
        int DayOfYear;
        
    int HourOfDay;

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

    CCY457OpenGLView::CCY457OpenGLView()
    {
         DayOfYear
    = 1;
         HourOfDay
    = 1;
    }

    3,为了计算帧速率,修改OnCreate函数,在其中获取窗口标题,从标题中去掉"Untitled”字样,并启动定时器。同样为了计算帧速率,修改OnDraw函数如下,在其中用glPushMatrix glPopMatrixRenderScene函数包裹起来,从而确保动画会正确运行。在SwapBuffers调用后我们调用PostRenderScene来显示帧速率信息到窗口标题。

    void CCY457OpenGLView::OnDraw(CDC* pDC)
    {
         CCY457OpenGLDoc
    * pDoc = GetDocument();
         ASSERT_VALID(pDoc);
        
    // Get the system time, in milliseconds.
         m_ElapsedTime = ::timeGetTime(); // get current time
        if ( ElapsedTimeinMSSinceLastRender() < 30 )
            
    return
        
    // Clear out the color & depth buffers
         ::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
         glPushMatrix();
             RenderScene();
         glPopMatrix();
        
    // Tell OpenGL to flush its pipeline
         ::glFinish();
        
    // Now Swap the buffers
         ::SwapBuffers( m_pDC->GetSafeHdc() );
        
    //Perform Post Display Processing
        
    // Only update the title every 15 redraws (this is about
        
    // every 1/2 second)
         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;
    }

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

    //////////////////////////////////////////////////////////////////////////////
    // 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 CCY457OpenGLView::PostRenderScene( void )
    {
        
    // Only update the title every 15 redraws (this is about
        
    // every 1/2 second)
        static int updateFrame = 15;
        
    if (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 CCY457OpenGLView::FramesPerSecond( void )
    {
        
    double eTime = ElapsedTimeinMSSinceLastRender();
        
    if ( 0 == (int)eTime )
            
    return 0;
        
    return (int)(1000/(int)eTime);
    }
    DWORD ElapsedTimeinMSSinceLastStartup()
    {
        
    return(m_ElapsedTime - m_StartTime);
    }
    DWORD ElapsedTimeinMSSinceLastRender()
    {
        
    return(m_ElapsedTime - m_previousElapsedTime);
    }

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

    void CCY457OpenGLView::OnTimer(UINT nIDEvent)
    {
        
    if(DayOfYear < 365)
             DayOfYear
    ++;
        
    else
             DayOfYear
    = 1;
        
    if(HourOfDay < 365)
             HourOfDay
    ++;
        
    else
             HourOfDay
    = 1;
         InvalidateRect(NULL, FALSE);    
         CView::OnTimer(nIDEvent);
    }

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

    void CCY457OpenGLView::RenderScene ()
    {
    //绘制函数
         glTranslatef(0.0f,0.0f,-5.0f);
        
    //Draw the Sun
         glutWireSphere(1.0f,20,20);
        
    //Rotate the Planet in its orbit
         glRotatef((GLfloat) (360.0*DayOfYear)/365.0, 0.0f, 1.0f, 0.0f);
         glTranslatef(
    4.0f,0.0f,0.0f);
         glPushMatrix();
            
    //Rotate the Planet in its orbit
             glRotatef((GLfloat)(360*HourOfDay)/24.0, 0.0f,1.0f,0.0f);
            
    //Draw the Planet
             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);
        
    //Draw the Moon
         glutWireSphere(0.01f,20,20);
    }
  • 相关阅读:
    select_tag in rails about selected not change and onchange()
    debian7 请把标有“Debian GNU/Linux 7.1.0 _Wheezy_
    rails关于utf8问题-------------------utf8申明必须置顶
    ruby 删除文件
    svn conflict
    40亿个有序不同的数的文件中找一个缺失的数
    马云语录
    语音识别概率问题,一段在数学之美了看到的话
    两个有序数组的中位数
    磁盘文件排序-编程珠玑
  • 原文地址:https://www.cnblogs.com/lcxu2/p/2004061.html
Copyright © 2020-2023  润新知