source: nrEngine/include/Clock.h @ 22

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