source: nrEngine/include/Clock.h @ 1

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