source: nrEngine/src/Clock.cpp @ 1

Revision 1, 9.4 KB checked in by art, 13 years ago (diff)
Line 
1/***************************************************************************
2 *                                                                         *
3 *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
4 *       mailto: <tevs@mpi-sb.mpg.de>                                      *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 ***************************************************************************/
12
13//----------------------------------------------------------------------------------
14// Includes
15//----------------------------------------------------------------------------------
16#include "Clock.h"
17#include "Log.h"
18
19//----------------------------------------------------------------------------------
20// Defines
21//----------------------------------------------------------------------------------
22#define DEFAULT_OBSERVER_NAME "__no_name__"
23
24
25namespace nrEngine{
26       
27        //------------------------------------------------------------------------
28        Clock::Clock() : ITask(){
29               
30                setTaskName("SystemClock");
31                currentTime = 0;
32                frameTime = 0;
33                frameNumber = 0;
34               
35                sourceStartValue = 0;
36                sourceLastValue = 0;
37               
38                useFixRate = false;
39                fixFrameRate = 0;
40                useMaxRate = false;
41                maxFrameRate = 0;
42                lastCurrentTime = 0;
43
44                // add default frame time       
45                setFrameWindow (7);
46                frameTime = _getFilteredFrameDuration();
47               
48                timeSource.reset();
49
50                // setup some other values
51                nextSyncTime = 0;
52                syncInterval = 0;
53               
54        }
55               
56        //------------------------------------------------------------------------
57        Clock::~Clock(){
58                stopTask();
59        }
60       
61        //------------------------------------------------------------------------     
62        void Clock::setTimeSource(SharedPtr<TimeSource> timeSource)
63        {               
64                this->timeSource = timeSource;
65       
66                if (timeSource != NULL){
67                        timeSource->reset();
68                        sourceStartValue = timeSource->getTime();
69                        sourceLastValue = sourceStartValue;
70                }
71        }
72       
73        //------------------------------------------------------------------------     
74        void Clock::setSyncInterval(uint32 milliseconds)
75        {
76                this->syncInterval = milliseconds;
77        }
78       
79        //------------------------------------------------------------------------
80        bool Clock::isAnySourceBounded(){
81                return (timeSource != NULL);
82        }
83       
84        //------------------------------------------------------------------------
85        SharedPtr<Timer> Clock::createTimer(){
86       
87                // create timer as observer
88                SharedPtr<ITimeObserver> timer(
89                                        new Timer(*this));
90               
91                // add him to the list
92                int32 id = addObserver(timer);
93               
94                if (id == 0){
95                        NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "Clock::createTimer(): Can not add timer to the observer list");
96                }
97               
98                // set the id of the timer
99                timer->_observerID = id;
100               
101                // return created timer
102                return ::boost::dynamic_pointer_cast<Timer, ITimeObserver>(timer);
103               
104        }
105       
106        //------------------------------------------------------------------------
107        Result Clock::stopTask(){
108                timeSource.reset();
109               
110                for (uint32 i=0; i < observers.size(); i++){
111                        observers[i].reset();
112                }
113                observers.clear();
114               
115                return OK;
116        }
117       
118        //------------------------------------------------------------------------
119        Result Clock::updateTask(){
120
121                // check whenever a time source is bound
122                if (timeSource == NULL) return CLOCK_NO_TIME_SOURCE;
123               
124                // calculate exact frame duration time
125                float64 exactFrameDuration = _getExactFrameDuration();
126                _addToFrameHistory(exactFrameDuration);
127               
128                // get filtered frame time
129                frameTime = _getFilteredFrameDuration();
130                frameNumber ++;
131
132                // check if we use frame bounder
133                do {
134                        currentTime = timeSource->getTime();
135
136                        // get through the list of connected observers and notify them
137                        ObserverList::iterator it;
138                        for (it = observers.begin(); it != observers.end(); ++it){
139                                (*it)->notifyTimeObserver();
140                        }
141
142                        // check if we need to sync the clock
143                        if (syncInterval > 0 && nextSyncTime < currentTime)
144                        {
145                                timeSource->sync();
146                                nextSyncTime = currentTime + static_cast<float64>(syncInterval) / 1000.0;
147                        }
148
149                } while (useMaxRate && (currentTime - lastCurrentTime) < invMaxFrameRate);
150
151                // set the last current time we used to the current time
152                lastCurrentTime = currentTime;
153
154                // OK
155                return OK;
156        }
157
158        //------------------------------------------------------------------------
159        float64 Clock::getTime() const{
160                return currentTime;
161        }
162       
163        //------------------------------------------------------------------------
164        float32 Clock::getFrameInterval() const{
165                return (float32)frameTime;
166        }
167       
168        //------------------------------------------------------------------------
169        float32 Clock::getRealFrameInterval() const
170        {
171                return (float32)realFrameTime;
172        }
173
174        //------------------------------------------------------------------------
175        float32 Clock::getRealFrameRate() const
176        {
177                return 1.0f / getRealFrameInterval();
178        }
179
180        //------------------------------------------------------------------------
181        int32 Clock::getFrameNumber() const{
182                return frameNumber;
183        }
184       
185        //------------------------------------------------------------------------
186        float32 Clock::getFrameRate() const{
187                return 1.0f / getFrameInterval();
188        }
189               
190        //------------------------------------------------------------------------
191        int32 Clock::addObserver(SharedPtr<ITimeObserver> timeObserver){
192               
193                int32 id = 0;
194               
195                if (timeObserver != NULL){
196                        observers.push_back (timeObserver);
197                        id = observers.size();
198                        observerIDList[::std::string(DEFAULT_OBSERVER_NAME) 
199                                                                                + ::boost::lexical_cast< ::std::string >(id)] = id;
200                        observers[observers.size()-1]->_observerID = id;
201                }
202               
203                return id;
204        }
205       
206        //------------------------------------------------------------------------
207        Result Clock::removeObserver(int32 observerID){
208               
209                int32 id = observerID - 1;
210                if (id <= 0 || id+1 >= static_cast<int32>(observers.size())
211                                || observerIDList.find(::std::string(DEFAULT_OBSERVER_NAME) + 
212                                                        ::boost::lexical_cast< ::std::string >(observerID)) == observerIDList.end()){
213                        return CLOCK_OBSERVER_NOT_FOUND;
214                }
215               
216                // remove it from the list
217                observers.erase(observers.begin() + id);
218               
219                // also clean the map enty for this id
220                observerIDList.erase(observerIDList.find( ::std::string(DEFAULT_OBSERVER_NAME) + 
221                                ::boost::lexical_cast< ::std::string >(observerID) ));
222                               
223                // OK
224                return OK;
225        }
226               
227        //------------------------------------------------------------------------
228        Result Clock::addObserver(const ::std::string& obsName,
229                                                                                                SharedPtr<ITimeObserver> timeObserver){
230                                                               
231       
232                // check whenever such an observer already exists
233                if (observerIDList[obsName]){
234                        return CLOCK_OBSERVER_ALREADY_ADDED;
235                }
236               
237                // add observer
238                if (timeObserver != NULL && obsName.length() > 0){
239                        observers.push_back (timeObserver);
240                        observerIDList[obsName] = observers.size(); 
241                        observers[observers.size()-1]->_observerID = observers.size();
242                }
243               
244                return OK;
245                                       
246        }
247       
248        //------------------------------------------------------------------------
249        Result Clock::removeObserver(const ::std::string& obsName){
250       
251                if (observerIDList[obsName]){
252                        int32 id = observerIDList[obsName] - 1;
253                        observers.erase(observers.begin() + id);
254                }else{
255                        return CLOCK_OBSERVER_NOT_FOUND;
256                }
257               
258                return OK;
259        }
260       
261        //------------------------------------------------------------------------
262        void Clock::setFrameWindow(int32 frameCount, float32 defaultFrameTime){
263               
264                frameFilteringWindow = frameCount > 1 ? frameCount : 1;
265                frameDefaultTime = defaultFrameTime;
266                frameDurationHistory.clear ();
267                frameDurationHistory.push_back(frameDefaultTime);
268        }
269       
270        //------------------------------------------------------------------------
271        void Clock::setFixFrameRate(bool setFixRate, float32 fixFrameRate){
272                useFixRate = setFixRate;
273                this->fixFrameRate = fixFrameRate;
274        }
275               
276        //------------------------------------------------------------------------
277        void Clock::setMaxFrameRate(bool set, float32 maxFPS)
278        {
279                useMaxRate = set;
280                this->maxFrameRate = maxFPS;
281                invMaxFrameRate = 1.0 / (float64)(maxFPS);
282        }
283
284        //------------------------------------------------------------------------
285        float64 Clock::_getExactFrameDuration (){
286               
287               
288                float64 sourceTime = timeSource->getTime();
289                realFrameTime = sourceTime - sourceLastValue;
290               
291                /*if (frameDuration > 0.200){
292                        frameDuration = frameDurationHistory.back();
293                }else if (frameDuration < 0){
294                        frameDuration = 0;
295                }*/
296
297                if (useFixRate || timeSource == NULL){
298                        return 1.0f / (fixFrameRate);
299                }
300
301                sourceLastValue = sourceTime;
302                return realFrameTime;
303               
304        }
305       
306        //------------------------------------------------------------------------
307        void Clock::_addToFrameHistory (float64 exactFrameDuration){
308                frameDurationHistory.push_back (exactFrameDuration);
309                if (frameDurationHistory.size () > (uint32) frameFilteringWindow)
310                        frameDurationHistory.pop_front ();
311        }
312       
313        //------------------------------------------------------------------------
314        float64 Clock::_getFilteredFrameDuration () const{
315               
316                if (useFixRate){
317                        return 1.0f/(fixFrameRate);
318                }
319               
320                float64 totalFrameTime = 0;
321       
322                ::std::deque<float64>::const_iterator it;
323                for (it=frameDurationHistory.begin();it != frameDurationHistory.end(); ++it){
324                        totalFrameTime += *it;
325                }
326               
327                return totalFrameTime/static_cast<float64>(frameDurationHistory.size());
328        }
329       
330}; // end namespace
331
332#undef DEFAULT_OBSERVER_NAME
Note: See TracBrowser for help on using the repository browser.