Panda3D
|
00001 // Filename: clockObject.h 00002 // Created by: drose (19Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef CLOCKOBJECT_H 00016 #define CLOCKOBJECT_H 00017 00018 #include "pandabase.h" 00019 00020 #include "trueClock.h" 00021 #include "pdeque.h" 00022 #include "cycleData.h" 00023 #include "cycleDataReader.h" 00024 #include "cycleDataWriter.h" 00025 #include "cycleDataStageReader.h" 00026 #include "pipelineCycler.h" 00027 #include "thread.h" 00028 #include "referenceCount.h" 00029 #include "pointerTo.h" 00030 #include "vector_double.h" // needed to see exported allocators for pdeque 00031 00032 class EXPCL_PANDA_PUTIL TimeVal { 00033 PUBLISHED: 00034 INLINE TimeVal(); 00035 INLINE ulong get_sec() const; 00036 INLINE ulong get_usec() const; 00037 ulong tv[2]; 00038 }; 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Class : ClockObject 00042 // Description : A ClockObject keeps track of elapsed real time and 00043 // discrete time. In normal mode, get_frame_time() 00044 // returns the time as of the last time tick() was 00045 // called. This is the "discrete" time, and is usually 00046 // used to get the time as of, for instance, the 00047 // beginning of the current frame. 00048 // 00049 // In other modes, as set by set_mode() or the 00050 // clock-mode config variable, get_frame_time() may 00051 // return other values to simulate different timing 00052 // effects, for instance to perform non-real-time 00053 // animation. See set_mode(). 00054 // 00055 // In all modes, get_real_time() always returns the 00056 // elapsed real time in seconds since the ClockObject 00057 // was constructed, or since it was last reset. 00058 // 00059 // You can create your own ClockObject whenever you want 00060 // to have your own local timer. There is also a 00061 // default, global ClockObject intended to represent 00062 // global time for the application; this is normally set 00063 // up to tick every frame so that its get_frame_time() 00064 // will return the time for the current frame. 00065 //////////////////////////////////////////////////////////////////// 00066 class EXPCL_PANDA_PUTIL ClockObject : public ReferenceCount { 00067 PUBLISHED: 00068 enum Mode { 00069 M_normal, 00070 M_non_real_time, 00071 M_forced, 00072 M_degrade, 00073 M_slave, 00074 M_limited, 00075 M_integer, 00076 M_integer_limited, 00077 }; 00078 00079 ClockObject(); 00080 ClockObject(const ClockObject ©); 00081 INLINE ~ClockObject(); 00082 00083 void set_mode(Mode mode); 00084 INLINE Mode get_mode() const; 00085 00086 INLINE double get_frame_time(Thread *current_thread = Thread::get_current_thread()) const; 00087 INLINE double get_real_time() const; 00088 INLINE double get_long_time() const; 00089 00090 INLINE void reset(); 00091 void set_real_time(double time); 00092 void set_frame_time(double time, Thread *current_thread = Thread::get_current_thread()); 00093 void set_frame_count(int frame_count, Thread *current_thread = Thread::get_current_thread()); 00094 00095 INLINE int get_frame_count(Thread *current_thread = Thread::get_current_thread()) const; 00096 INLINE double get_net_frame_rate(Thread *current_thread = Thread::get_current_thread()) const; 00097 00098 INLINE double get_dt(Thread *current_thread = Thread::get_current_thread()) const; 00099 void set_dt(double dt); 00100 void set_frame_rate(double frame_rate); 00101 00102 INLINE double get_max_dt() const; 00103 INLINE void set_max_dt(double max_dt); 00104 00105 INLINE double get_degrade_factor() const; 00106 INLINE void set_degrade_factor(double degrade_factor); 00107 00108 INLINE void set_average_frame_rate_interval(double time); 00109 INLINE double get_average_frame_rate_interval() const; 00110 double get_average_frame_rate(Thread *current_thread = Thread::get_current_thread()) const; 00111 double get_max_frame_duration(Thread *current_thread = Thread::get_current_thread()) const; 00112 double calc_frame_rate_deviation(Thread *current_thread = Thread::get_current_thread()) const; 00113 00114 void tick(Thread *current_thread = Thread::get_current_thread()); 00115 void sync_frame_time(Thread *current_thread = Thread::get_current_thread()); 00116 00117 INLINE bool check_errors(Thread *current_thread); 00118 00119 INLINE static ClockObject *get_global_clock(); 00120 00121 public: 00122 static void (*_start_clock_wait)(); 00123 static void (*_start_clock_busy_wait)(); 00124 static void (*_stop_clock_wait)(); 00125 00126 private: 00127 void wait_until(double want_time); 00128 static void make_global_clock(); 00129 static void dummy_clock_wait(); 00130 00131 TrueClock *_true_clock; 00132 Mode _mode; 00133 double _start_short_time; 00134 double _start_long_time; 00135 double _actual_frame_time; 00136 double _max_dt; 00137 double _user_frame_rate; 00138 double _degrade_factor; 00139 int _error_count; 00140 00141 // For tracking the average frame rate over a certain interval of 00142 // time. 00143 double _average_frame_rate_interval; 00144 typedef pdeque<double> Ticks; 00145 Ticks _ticks; 00146 00147 // This is the data that needs to be cycled each frame. 00148 class EXPCL_PANDA_PUTIL CData : public CycleData { 00149 public: 00150 CData(); 00151 INLINE CData(const CData ©); 00152 00153 virtual CycleData *make_copy() const; 00154 virtual TypeHandle get_parent_type() const { 00155 return ClockObject::get_class_type(); 00156 } 00157 00158 int _frame_count; 00159 double _reported_frame_time; 00160 double _reported_frame_time_epoch; 00161 double _dt; 00162 }; 00163 00164 PipelineCycler<CData> _cycler; 00165 typedef CycleDataReader<CData> CDReader; 00166 typedef CycleDataWriter<CData> CDWriter; 00167 typedef CycleDataStageReader<CData> CDStageReader; 00168 00169 static PT(ClockObject) _global_clock; 00170 00171 public: 00172 static TypeHandle get_class_type() { 00173 return _type_handle; 00174 } 00175 static void init_type() { 00176 ReferenceCount::init_type(); 00177 register_type(_type_handle, "ClockObject", 00178 ReferenceCount::get_class_type()); 00179 } 00180 00181 private: 00182 static TypeHandle _type_handle; 00183 }; 00184 00185 EXPCL_PANDA_PUTIL ostream & 00186 operator << (ostream &out, ClockObject::Mode mode); 00187 EXPCL_PANDA_PUTIL istream & 00188 operator >> (istream &in, ClockObject::Mode &mode); 00189 00190 #include "clockObject.I" 00191 00192 #endif 00193