System类解析
欢迎大家一起学习,转载请说明出处
http://blog.youkuaiyun.com/zhuyingqingfen/article/details/8096309
Table of Contents
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这个消息