source: nrEngine/include/Clock.h @ 25

Revision 25, 10.6 KB checked in by art, 12 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#ifndef _NR_C_CLOCK_H_
15#define _NR_C_CLOCK_H_
16
17
18//----------------------------------------------------------------------------------
19// Includes
20//----------------------------------------------------------------------------------
21#include "Prerequisities.h"
22#include "TimeSource.h"
23#include "ITimeObserver.h"
24#include "Timer.h"
25#include "ITask.h"
26#include "TimeSourceVirtual.h"
27#include "ScriptEngine.h"
28
29namespace nrEngine{
30
31        //! Global clock of the engine used to retrieve time or create timers
32        /**
33        * \par
34        * Clock allows you to create timers from it. Clock is always ticks if any
35        * time source is bounded. In contrast to Einstein's relativity theory we have
36        * only one global clock. So your complete application has one time which runs
37        * with the same speed. But to be able to use Einstein's theory you can create
38        * timers from each clock, which allows you to use different time speeds.
39        * Clock can also derive/create timers. But if you want to create the timer by
40        * yourself you can do this.
41        *
42        * @note
43        *               - Our clock works internal with 64Bit float64 values to stay precise.
44        *                       Because using of float32 values is enough for every simulation you will get
45        *                       32Bit float32 values as frame interval time.
46        *               - If you compile the engine on 64Bit systems, so you can change this and use
47        *                       64Bit doubles instead.
48        *               - Each created timer dies when clock dies.
49        *               - You can only destroy timers through the clock interface or it will be
50        *                       deleted automaticly from the memory when clock is deleted
51        *               - Deleting the timer outside from the clock has no effect
52        *
53        * \ingroup time
54        **/
55        class _NRExport Clock : public ITask {
56        public:
57       
58                /**
59                * Set the time source to be used to get current time. Our clock class
60                * is platform independent but the time get code depends mostly on the
61                * platform you using. So just derive your time source from ITimeSource
62                * interface and add this source into our clock.
63                * @param timeSource smart pointer containing to the time source
64                **/
65                void setTimeSource(SharedPtr<TimeSource> timeSource);
66               
67                /**
68                * Returns true if any time source is bounded to our clock.
69                **/
70                bool isAnySourceBounded();
71               
72                /**
73                * Return a smart pointer to the current time source
74                * @return a smart pointer pointing to the current time source or NULL if
75                * no time source is bound at now.
76                **/
77                SharedPtr<TimeSource> getTimeSource() { return timeSource; }
78               
79                /**
80                 * This method will be called by the kernel to start the clock. It is called
81                 * when clock is added to the kernel pipeline.
82                 **/
83                Result onStartTask();
84
85                /**
86                * Updates the clock task by getting time values and calculating of
87                * frame rate and frame interval.
88                * Also each connected time observer will be notified so it can do
89                * own updates. This allows you just to create any observer (like timer)
90                * bind them to the clock and forgett it.
91                **/
92                Result updateTask();
93
94                /**
95                * Stop the clock task and release all used objects.
96                * So all observers will be deleted from the observer list and also
97                * the time source is removed. After this function you still able to access
98                * to the clock and timers (because of smart pointers), but the time will
99                * hold on and no updates of the time will be made.
100                **/
101                Result stopTask();
102
103                /**
104                * Same as taskUpdate(). This name is choosen to separate calls
105                * to the clock by not knowing, that it is a task.
106                * Use this function from somewhere else than a kernel.
107                **/
108                void            Ticks(){ updateTask();}
109               
110                /**
111                * Returns current time since clock start ticking.
112                **/
113                float64         getTime() const;
114               
115       
116                /**
117                * Returns filtered interval time between two or more frames. nrEngine's clock
118                * does not only calculate the interval between two following frames, but it uses
119                * a arithmetic average to compute the frame interval between a lot of frames.
120                * This helps you to ignore some frames if their update time was to big or to less.
121                */
122                float32         getFrameInterval() const;
123       
124                /**
125                * Returns number of frames drawn since clock start ticking
126                **/             
127                int32           getFrameNumber() const;
128                       
129                /**
130                * Returns FPS. Like the frameinterval this value is also computed as average
131                * between a lot of frames. So this value is more smooth.
132                **/
133                float32         getFrameRate() const;
134       
135                /**
136                 * Get the frame interval time of a real time. If you use fix frame rate, so you
137                 * get as an interval a 1.0 / fix frame rate. This method allows you to get
138                 * the time which your frame really need to render.
139                 **/
140                float32 getRealFrameInterval() const;
141
142                /**
143                 * Get real frame rate based on getRealFrameInterval() method
144                 **/
145                float32 getRealFrameRate() const;
146
147                /**
148                 * This method allows you to set the maximal frame rate at which the clock
149                 * shoudl run. It will use this frame rate as an upper bound. If applications
150                 * runs faster than this time, so it will retard to this speed. If app runs
151                 * much slower so nothing happens. At speed above the given boundaries
152                 * the clock runs as for fixed frame rate. So you would retrieve fixed
153                 * frame interval values. Function which retrieves real values are not
154                 * affected by them, so you are still able to get information about the
155                 * real time, which you frame need
156                 **/
157                void setMaxFrameRate(bool set, float32 maxFPS = 60.0);
158
159                /**
160                * Add new time observer to our list of observers. Each observer will
161                * be notified on each frame after clock calculations are done. With this
162                * system we can separate our timers from game loop, but they still be
163                * updated on each frame.
164                * @param timeObserver smart pointers to the observer
165                * @return internal ID of observer to allow of removing them from the list
166                * @note Each observer has to implement the ITimeObserver interface
167                **/
168                int32           addObserver(SharedPtr<ITimeObserver> timeObserver);
169               
170                /**
171                * Removes an observer from the list by given ID
172                * @param observerID id of the observer returned by addObserver()
173                * @return either OK or:
174                *               - CLOCK_OBSERVER_NOT_FOUND if such id is not valid
175                **/
176                Result  removeObserver(int32 observerID);
177               
178                /**
179                * Add an time observer by a name. So you can delete them also by using
180                * this name.
181                * @param obsName name of the observer
182                * @param timeObserver smart pointer pointing to the observer
183                * @return either OK or:
184                *                       - CLOCK_OBSERVER_ALREADY_ADDED if such is already added
185                **/
186                Result  addObserver(const ::std::string& obsName, SharedPtr<ITimeObserver> timeObserver);
187       
188                /**
189                * Removes an observer by using it's name.
190                * @param obsName name of the observer
191                * @return either OK or:
192                *                       - CLOCK_OBSERVER_NOT_FOUND if such an observer not exists
193                **/
194                Result  removeObserver(const ::std::string& obsName);
195               
196                /**
197                * Set the count of frames to be computed to calculate frame rate/interval.
198                * We need this to smooth big peaks on frame rates to allow application
199                * run smoother than without this window. Here we just using averaging
200                * of the frame intervals during certain number of frames.
201                * @param frameCount size of such frame calculation window
202                * @param defaultFrameTime is a frame interval added by default as if there
203                *               was a frame rendered with this speed. This allows us to start smoothly
204                **/
205                void    setFrameWindow(int32 frameCount = 10, float32 defaultFrameTime = 0.03333);
206       
207                /**
208                * If you set this to true so fix frame rate will be used. This helps us
209                * to run our application on console or do internal calculations based
210                * on fix frame rate like Doom3 does.
211                * @param setFixRate if true fix frame rate will be used.
212                * @param fixFrameRate frame rate to be used
213                **/
214                void    setFixFrameRate(bool setFixRate, float32 fixFrameRate = 60.0f);
215
216               
217                /**
218                * Create a new timer which does use this clock as reference.
219                **/
220                SharedPtr<Timer>        createTimer();
221
222                /**
223                * Setup the syncing interval. The clock will be synced with system time
224                * so it helps to prevent timing errors produced by high performance time
225                * counters in addidition to CPU speed stepping functionality of the processor unit.
226                **/
227                void setSyncInterval(uint32 milliseconds);
228               
229                /**
230                 * Reset the clock. The clock time will be resetted to the given time.
231                 * @param resetToTime Reset the clock to the given time value
232                 * @param resetAllObservers if true all registered obseervers would be also resetted
233                 **/
234                void reset(float64 resetToTime = 0.0f, bool resetAllObservers = false);
235               
236                /**
237                 * Script-Function to reset the clock. You can specify in parameters if all timers, which were
238                 * created before should be also reseted.
239                 **/
240                ScriptFunctionDef(scriptResetClock);
241
242
243        private:
244
245                //! Only engine's core object can create instance
246                friend class Engine;
247
248                /**
249                * After the object is created and before it runs the returned value
250                * for the frame rate will be 0.
251                * The value for frame window is set to 7 per default.
252                **/
253                Clock();
254
255                /**
256                * Release all used memory.
257                **/
258                ~Clock();
259
260                // observers
261                typedef ::std::vector< SharedPtr<ITimeObserver> > ObserverList;
262                ::std::map < ::std::string, int32>      observerIDList;
263                ObserverList                            observers;
264               
265                // frame filtering
266                ::std::deque<float64>   frameDurationHistory;
267                float64                 frameDefaultTime;
268                int32                   frameFilteringWindow;
269               
270                // time source
271                SharedPtr<TimeSource>   timeSource;
272                SharedPtr<TimeSource>   realTimeSource;
273                float64         currentTime;
274                float64         frameTime;
275                int32           frameNumber;
276                bool            useFixRate;
277                float32         fixFrameRate;
278
279                float32     maxFrameRate;
280                float64     lastCurrentTime;
281                float64     invMaxFrameRate;
282                bool        useMaxRate;
283
284                // values to hold real frame information if we use fix frame rate
285                float64     realFrameTime;
286
287                // methods
288                void    _addToFrameHistory(float64 duration);
289                float64 _getFilteredFrameDuration() const;
290                float64 _getExactFrameDuration();
291               
292                // helping variables to find out the frame rate
293                float64 sourceStartValue;
294                float64 sourceLastValue;
295                float64 sourceLastRealValue;
296               
297                // Next time when the clock has to be synced with system time
298                float64 nextSyncTime;
299                uint32  syncInterval;
300               
301        };
302       
303}; // end namespace
304#endif
Note: See TracBrowser for help on using the repository browser.