Delta3D源码解析之dtCore::System 类

                                System类解析

欢迎大家一起学习,转载请说明出处

http://blog.csdn.net/zhuyingqingfen/article/details/8096309

1 System类

1.1 System概述:

system是个单例 通过订阅System 实例(即AddSender(&dtCore::GetInstance())可以获得 "preframe"(对应消息是dtCore::System::MESSAGEPREFRAME) , "frame", "postframe", and "configure".四个类型的消息。 要想获得固定的帧率可以用代码这么写

ourSystem.SetFrameRate(60);
ourSystem.SetMaxTimeBetweenDraws(newTime);// The maximum time to wait between frames. Only used when running with
a fixed time step. (Defaults to 0.03 seconds)
ourSystem.SetUseFixedTimeStep(true);

你也可以在你的config文件中这么写

* <Properties>
*    <Property Name="System.SimFrameRate">60</Property>
*    <Property Name="System.MaxTimeBetweenDraws">0.1</Property>
*    <Property Name="System.UseFixedTimeStep">true</Property>
* </Properties>
1.2 System中定义的消息:

System中定义了如下枚举变量

enum SystemStages
     {
        STAGE_NONE                   = 0x00000000, ///<No update loop stages are performed
        STAGE_EVENT_TRAVERSAL        = 0x00000001, ///<"eventtraversal" message is when input and windowing events are picked up, you should not be listening to this message
        STAGE_POST_EVENT_TRAVERSAL   = 0x00000002, ///<"posteventtraversal" message is sent immediately after "eventtraversal" listen to this message for input or windowing related response
        STAGE_PREFRAME               = 0x00000004, ///<"preframe" message
        STAGE_CAMERA_SYNCH           = 0x00000008,
        STAGE_FRAME_SYNCH            = 0x00000010,
        STAGE_FRAME                  = 0x00000020, ///<"frame" message, plus camera rendering
        STAGE_POSTFRAME              = 0x00000040, ///<"postframe" message
        STAGE_CONFIG                 = 0X00000080, ///<"config" message, plus render a camera frame
        STAGES_DEFAULT  = STAGE_EVENT_TRAVERSAL|STAGE_POST_EVENT_TRAVERSAL|STAGE_CAMERA_SYNCH|STAGE_FRAME_SYNCH|STAGE_PREFRAME|STAGE_FRAME|STAGE_POSTFRAME|STAGE_CONFIG,
        STAGES_ALL = STAGES_DEFAULT
     };
const static dtUtil::RefString MESSAGE_EVENT_TRAVERSAL;
const static dtUtil::RefString MESSAGE_POST_EVENT_TRAVERSAL;
const static dtUtil::RefString MESSAGE_PRE_FRAME;
const static dtUtil::RefString MESSAGE_CAMERA_SYNCH;
const static dtUtil::RefString MESSAGE_FRAME_SYNCH;
const static dtUtil::RefString MESSAGE_FRAME;
const static dtUtil::RefString MESSAGE_POST_FRAME;
const static dtUtil::RefString MESSAGE_CONFIG;
const static dtUtil::RefString MESSAGE_PAUSE;
const static dtUtil::RefString MESSAGE_PAUSE_START;
const static dtUtil::RefString MESSAGE_PAUSE_END;
const static dtUtil::RefString MESSAGE_EXIT;

可以用这个函数来控制System发送哪个消息

dtCore::System::GetInstance().SetSystemStages( System::STAGE_PREFRAME|System::STAGE_FRAME ) 

对应的消息都是在SystemImpl(在System的cpp文件中)中实现的(如下:)

void EventTraversal(const double deltaSimTime, const double deltaRealTime);
      void PostEventTraversal(const double deltaSimTime, const double deltaRealTime);
      void PreFrame(const double deltaSimTime, const double deltaRealTime);
      void FrameSynch(const double deltaSimTime, const double deltaRealTime);
      void CameraSynch(const double deltaSimTime, const double deltaRealTime);
      void Frame(const double deltaSimTime, const double deltaRealTime);
      void PostFrame(const double deltaSimTime, const double deltaRealTime);
      void Pause(const double deltaRealTime);
      void SetPause(bool paused);//根据当前System内部变量mPaused发送暂停开始结束消息 

1.1 System中的消息是怎样被发出去的(一步步看下面的函数)

1.1.1 在System类中的Run函数中
void System::Run()
  {
     Start(); ///Automatically start the System when Run.

     while (mSystemImpl->mRunning)//只要程序没退出就一直执行这个函数
     {
        StepWindow();
     }

     LOG_DEBUG("System: Exiting...");
     SendMessage(MESSAGE_EXIT);
     LOG_DEBUG("System: Done Exiting.");
  }
1.1.2 在System类中的StepWindow()函数中
void System::StepWindow()
  {
     if (!mSystemImpl->mRunning)
     {
        return;
     }

     Step();

     // FIXME TODO how to check if GraphicsWindow is always running ??
     // this implementation in really the good way
     if (mSystemImpl->mShutdownOnWindowClose)//当关闭时候做处理
     {
        bool areGraphicsWindow = false;
        for (int i = 0; i < DeltaWin::GetInstanceCount() && !areGraphicsWindow; ++i)
        {
            areGraphicsWindow =
                   areGraphicsWindow || DeltaWin::GetInstance(i)->GetOsgViewerGraphicsWindow()->valid();
        }
        mSystemImpl->mRunning = mSystemImpl->mRunning && areGraphicsWindow;
     }
  }
1.1.3 在System类中的Step()函数中,这个函数中基本上都是SystemImpl中的具体实现
void System::Step()
  {
     static bool first = true;

     if (!mSystemImpl->mRunning)
     {
        return;
     }

     if (first)
     {
        mSystemImpl->InitVars();
        first = false;
     }

     mSystemImpl->SystemStep();
  }
1.1.4 在SystemImpl类中的SystemStep函数中
void SystemImpl::SystemStep()
 {
    const Timer_t lastClockTime  = mTickClockTime;
    mTickClockTime = mClock.Tick();

    const double realDT = mClock.DeltaSec(lastClockTime, mTickClockTime);

    // update real time variable(s)
    mRealClockTime += Timer_t(realDT * 1000000);

    if (mPaused)
    {
       mTotalFrameTime = 0.0;  // reset frame timer for stats
       mWasPaused = true;
       EventTraversal(0.0, realDT);
       PostEventTraversal(0.0, realDT);
       Pause(realDT);
       CameraSynch(0.0, realDT);
       FrameSynch(0.0, realDT);
       Frame(0.0, realDT);
    }
    else
    {
       if (!mUseFixedTimeStep)
       {
          mTotalFrameTime = 0.0;  // reset frame timer for stats
          mWasPaused = false;

          // update simulation time variable(s)
          const double simDT = realDT * mTimeScale;
          mSimulationTime      += simDT;
          mSimTimeSinceStartup += simDT;
          mSimulationClockTime += Timer_t(simDT * 1000000);

          EventTraversal(simDT, realDT);
          PostEventTraversal(simDT, realDT);//下面看下这个函数中的内容,其他函数类似
          PreFrame(simDT, realDT);
          CameraSynch(simDT, realDT);
          FrameSynch(simDT, realDT);
          Frame(simDT, realDT);
          PostFrame(simDT, realDT);
       }
       else
       {
          SystemStepFixed(realDT);
       }
    }

    FinishFrameStats();
 }
1.1.5 在SystemImpl中的PostEventTraversal函数里
void SystemImpl::PostEventTraversal(const double deltaSimTime, const double deltaRealTime)
   {
      if (dtUtil::Bits::Has(mSystemStages, System::STAGE_POST_EVENT_TRAVERSAL))
      {
         StartStatTimer();

         double userData[2] = { deltaSimTime, deltaRealTime };
         SendMessage(System::MESSAGE_POST_EVENT_TRAVERSAL, userData);//消息在这发出

         EndStatTimer(System::MESSAGE_POST_EVENT_TRAVERSAL, System::STAGE_POST_EVENT_TRAVERSAL);
      }
   }
1.1.6 System消息判断中用到的dtUtil::Bits::Has的解释
typedef unsigned int SystemStageFlags;
System::SystemStageFlags mSystemStages;

在SystemImpl::EventTraversal(const double deltaSimTime, const double deltaRealTime)函数中有这样一句话 if (dtUtil::Bits::Has(mSystemStages, System::STAGEEVENTTRAVERSAL))

void SystemImpl::EventTraversal(const double deltaSimTime, const double deltaRealTime)
  {
     if (dtUtil::Bits::Has(mSystemStages, System::STAGE_EVENT_TRAVERSAL))
     {
        StartStatTimer();

        double userData[2] = { deltaSimTime, deltaRealTime };
        SendMessage(System::MESSAGE_EVENT_TRAVERSAL, userData);

        EndStatTimer(System::MESSAGE_EVENT_TRAVERSAL, System::STAGE_EVENT_TRAVERSAL);
     }
  }

看一下这个函数的原型就知道了

template < class N, class B > inline bool Has (N number, B bits)
     {
        return ((number & bits) == (static_cast<N>(bits)));//按位与
     }

dtUtil::Bits::Has函数是个函数模板—采用位来操作,这使detla3D的消息管理变得很简单而且效率很高如0x11 写成二进制就是00010001 如果每一位代表一个消息,一个位为上为1时表示含有此消息的话,则下面的代码就很好理解了

unsigned int accum = 3;
Bits::Has( accum, 1 ); //true
Bits::Has( accum, 7 ); //false

3的二进制为11 和1向与(&)操作后为1 所以 Bits::Has( accum, 1 ); //true

dtUtil::Bits::Add 是按位或(|) unsigned int accum = 1; accum = Bits::Add(accum, 7); //Has(accum, 1) and Has(accum, 7) == true 当执行了 accum= (1 | 7)后acum变成7 如果定义消息postFrame=7 的话,说明accum含有postFrame这个消息

Date: 2012-10-20

Author: Sunday

Org version 7.9.2 with Emacs version 24

Validate XHTML 1.0
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值