00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "frameRateMeter.h"
00016 #include "camera.h"
00017 #include "displayRegion.h"
00018 #include "orthographicLens.h"
00019 #include "clockObject.h"
00020 #include "config_grutil.h"
00021 #include "depthTestAttrib.h"
00022 #include "depthWriteAttrib.h"
00023 #include "pStatTimer.h"
00024 #include <stdio.h>
00025
00026 PStatCollector FrameRateMeter::_show_fps_pcollector("*:Show fps");
00027
00028 TypeHandle FrameRateMeter::_type_handle;
00029
00030
00031
00032
00033
00034
00035 FrameRateMeter::
00036 FrameRateMeter(const string &name) : TextNode(name) {
00037 set_cull_callback();
00038
00039 Thread *current_thread = Thread::get_current_thread();
00040
00041 _update_interval = frame_rate_meter_update_interval;
00042 _last_update = 0.0f;
00043 _text_pattern = frame_rate_meter_text_pattern;
00044 _clock_object = ClockObject::get_global_clock();
00045
00046
00047
00048 PN_stdfloat height = 1.0f;
00049 TextFont *font = get_font();
00050 if (font != NULL){
00051 height = font->get_line_height() * 0.8;
00052 }
00053
00054 set_align(A_right);
00055 set_transform(LMatrix4::scale_mat(frame_rate_meter_scale) *
00056 LMatrix4::translate_mat(LVector3::rfu(1.0f - frame_rate_meter_side_margins * frame_rate_meter_scale, 0.0f, 1.0f - frame_rate_meter_scale * height)));
00057 set_card_color(0.0f, 0.0f, 0.0f, 0.4);
00058 set_card_as_margin(frame_rate_meter_side_margins, frame_rate_meter_side_margins, 0.1f, 0.0f);
00059
00060
00061 do_update(current_thread);
00062 }
00063
00064
00065
00066
00067
00068
00069 FrameRateMeter::
00070 ~FrameRateMeter() {
00071 clear_window();
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081 void FrameRateMeter::
00082 setup_window(GraphicsOutput *window) {
00083 clear_window();
00084
00085 _window = window;
00086
00087 _root = NodePath("frame_rate_root");
00088 _root.attach_new_node(this);
00089
00090 CPT(RenderAttrib) dt = DepthTestAttrib::make(DepthTestAttrib::M_none);
00091 CPT(RenderAttrib) dw = DepthWriteAttrib::make(DepthWriteAttrib::M_off);
00092 _root.node()->set_attrib(dt, 1);
00093 _root.node()->set_attrib(dw, 1);
00094 _root.set_material_off(1);
00095 _root.set_two_sided(1, 1);
00096
00097
00098 _display_region = _window->make_mono_display_region();
00099 _display_region->set_sort(frame_rate_meter_layer_sort);
00100
00101
00102 PT(Camera) camera = new Camera("frame_rate_camera");
00103 NodePath camera_np = _root.attach_new_node(camera);
00104
00105 PT(Lens) lens = new OrthographicLens;
00106
00107 static const PN_stdfloat left = -1.0f;
00108 static const PN_stdfloat right = 1.0f;
00109 static const PN_stdfloat bottom = -1.0f;
00110 static const PN_stdfloat top = 1.0f;
00111 lens->set_film_size(right - left, top - bottom);
00112 lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
00113 lens->set_near_far(-1000, 1000);
00114
00115 camera->set_lens(lens);
00116 camera->set_scene(_root);
00117 _display_region->set_camera(camera_np);
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 void FrameRateMeter::
00127 clear_window() {
00128 if (_window != (GraphicsOutput *)NULL) {
00129 _window->remove_display_region(_display_region);
00130 _window = (GraphicsOutput *)NULL;
00131 _display_region = (DisplayRegion *)NULL;
00132 }
00133 _root = NodePath();
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 bool FrameRateMeter::
00162 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00163 Thread *current_thread = trav->get_current_thread();
00164
00165
00166 PStatTimer timer(_show_fps_pcollector, current_thread);
00167
00168
00169 double now = _clock_object->get_frame_time(current_thread);
00170 double elapsed = now - _last_update;
00171 if (elapsed < 0.0 || elapsed >= _update_interval) {
00172 do_update(current_thread);
00173 }
00174
00175 return TextNode::cull_callback(trav, data);
00176 }
00177
00178
00179
00180
00181
00182
00183 void FrameRateMeter::
00184 do_update(Thread *current_thread) {
00185 _last_update = _clock_object->get_frame_time(current_thread);
00186
00187 double frame_rate = _clock_object->get_average_frame_rate(current_thread);
00188 double deviation = _clock_object->calc_frame_rate_deviation(current_thread);
00189
00190 static const size_t buffer_size = 1024;
00191 char buffer[buffer_size];
00192 #if defined(WIN32_VC) || defined(WIN64_VC)
00193
00194 sprintf(buffer, _text_pattern.c_str(), frame_rate, deviation);
00195 #else
00196 snprintf(buffer, buffer_size, _text_pattern.c_str(), frame_rate, deviation);
00197 #endif
00198 nassertv(strlen(buffer) < buffer_size);
00199
00200 if (get_text() == buffer) {
00201
00202 return;
00203 }
00204
00205 set_text(buffer);
00206 }