Panda3D
frameRateMeter.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file frameRateMeter.cxx
10  * @author drose
11  * @date 2003-12-23
12  */
13 
14 #include "frameRateMeter.h"
15 #include "camera.h"
16 #include "displayRegion.h"
17 #include "orthographicLens.h"
18 #include "clockObject.h"
19 #include "config_grutil.h"
20 #include "depthTestAttrib.h"
21 #include "depthWriteAttrib.h"
22 #include "pStatTimer.h"
23 #include "omniBoundingVolume.h"
24 #include <stdio.h> // For sprintf/snprintf
25 
26 PStatCollector FrameRateMeter::_show_fps_pcollector("*:Show fps");
27 
28 TypeHandle FrameRateMeter::_type_handle;
29 
30 /**
31  *
32  */
33 FrameRateMeter::
34 FrameRateMeter(const std::string &name) :
35  TextNode(name),
36  _last_aspect_ratio(-1) {
37 
38  set_cull_callback();
39 
40  // Don't do frustum culling, as the text will always be in view.
41  set_bounds(new OmniBoundingVolume());
42  set_final(true);
43 
44  Thread *current_thread = Thread::get_current_thread();
45 
46  _show_milliseconds = frame_rate_meter_milliseconds;
47  if (_show_milliseconds) {
48  _text_pattern = frame_rate_meter_ms_text_pattern;
49  } else {
50  _text_pattern = frame_rate_meter_text_pattern;
51  }
52 
53  _update_interval = frame_rate_meter_update_interval;
54  _last_update = 0.0f;
55  _clock_object = ClockObject::get_global_clock();
56 
57  // The top of the visible frame is 80% of the line height, based on the
58  // calculation within TextAssembler.
59  PN_stdfloat height = 1.0f;
60  TextFont *font = get_font();
61  if (font != nullptr){
62  height = font->get_line_height() * 0.8;
63  }
64 
65  set_align(A_right);
66  set_transform(LMatrix4::scale_mat(frame_rate_meter_scale) *
67  LMatrix4::translate_mat(LVector3::rfu(-frame_rate_meter_side_margins * frame_rate_meter_scale, 0.0f, -frame_rate_meter_scale * height)));
68  set_card_color(0.0f, 0.0f, 0.0f, 0.4);
69  set_card_as_margin(frame_rate_meter_side_margins, frame_rate_meter_side_margins, 0.1f, 0.0f);
70  // set_usage_hint(Geom::UH_client);
71 
72  do_update(current_thread);
73 }
74 
75 /**
76  *
77  */
78 FrameRateMeter::
79 ~FrameRateMeter() {
80  clear_window();
81 }
82 
83 /**
84  * Sets up the frame rate meter to create a DisplayRegion to render itself
85  * into the indicated window.
86  */
89  clear_window();
90 
91  _window = window;
92 
93  _root = NodePath("frame_rate_root");
94  _root.attach_new_node(this);
95 
96  CPT(RenderAttrib) dt = DepthTestAttrib::make(DepthTestAttrib::M_none);
97  CPT(RenderAttrib) dw = DepthWriteAttrib::make(DepthWriteAttrib::M_off);
98  _root.node()->set_attrib(dt, 1);
99  _root.node()->set_attrib(dw, 1);
100  _root.set_material_off(1);
101  _root.set_two_sided(1, 1);
102 
103  // If we don't set this explicitly, Panda will cause it to be rendered in a
104  // back-to-front cull bin, which will cause the bounding volume to be
105  // computed unnecessarily. Saves a little bit of overhead.
106  _root.set_bin("unsorted", 0);
107 
108  // Create a display region that covers the entire window.
109  _display_region = _window->make_mono_display_region();
110  _display_region->set_sort(frame_rate_meter_layer_sort);
111 
112  // Finally, we need a camera to associate with the display region.
113  PT(Camera) camera = new Camera("frame_rate_camera");
114  NodePath camera_np = _root.attach_new_node(camera);
115 
116  PT(Lens) lens = new OrthographicLens;
117 
118  // We choose these values such that we can place the text against (0, 0).
119  static const PN_stdfloat left = -2.0f;
120  static const PN_stdfloat right = 0.0f;
121  static const PN_stdfloat bottom = -2.0f;
122  static const PN_stdfloat top = 0.0f;
123  lens->set_film_size(right - left, top - bottom);
124  lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
125  lens->set_near_far(-1000, 1000);
126 
127  camera->set_lens(lens);
128  camera->set_scene(_root);
129  _display_region->set_camera(camera_np);
130 }
131 
132 /**
133  * Undoes the effect of a previous call to setup_window().
134  */
135 void FrameRateMeter::
137  if (_window != nullptr) {
138  _window->remove_display_region(_display_region);
139  _window = nullptr;
140  _display_region = nullptr;
141  }
142  _root = NodePath();
143 }
144 
145 /**
146  * This function will be called during the cull traversal to perform any
147  * additional operations that should be performed at cull time. This may
148  * include additional manipulation of render state or additional
149  * visible/invisible decisions, or any other arbitrary operation.
150  *
151  * Note that this function will *not* be called unless set_cull_callback() is
152  * called in the constructor of the derived class. It is necessary to call
153  * set_cull_callback() to indicated that we require cull_callback() to be
154  * called.
155  *
156  * By the time this function is called, the node has already passed the
157  * bounding-volume test for the viewing frustum, and the node's transform and
158  * state have already been applied to the indicated CullTraverserData object.
159  *
160  * The return value is true if this node should be visible, or false if it
161  * should be culled.
162  */
163 bool FrameRateMeter::
164 cull_callback(CullTraverser *trav, CullTraverserData &data) {
165  // This triggers when you try to parent a frame rate meter into the scene
166  // graph yourself. Instead, use setup_window().
167  nassertr(_display_region != nullptr, false);
168 
169  Thread *current_thread = trav->get_current_thread();
170 
171  // Statistics
172  PStatTimer timer(_show_fps_pcollector, current_thread);
173 
174  // This is probably a good time to check if the aspect ratio on the window
175  // has changed.
176  int width = _display_region->get_pixel_width();
177  int height = _display_region->get_pixel_height();
178  PN_stdfloat aspect_ratio = 1;
179  if (width != 0 && height != 0) {
180  aspect_ratio = (PN_stdfloat)height / (PN_stdfloat)width;
181  }
182 
183  // Scale the transform by the calculated aspect ratio.
184  if (aspect_ratio != _last_aspect_ratio) {
185  _aspect_ratio_transform = TransformState::make_scale(LVecBase3(aspect_ratio, 1, 1));
186  _last_aspect_ratio = aspect_ratio;
187  }
188  data._net_transform = data._net_transform->compose(_aspect_ratio_transform);
189 
190  // Check to see if it's time to update.
191  double now = _clock_object->get_frame_time(current_thread);
192  double elapsed = now - _last_update;
193  if (elapsed < 0.0 || elapsed >= _update_interval) {
194  do_update(current_thread);
195  }
196 
197  return TextNode::cull_callback(trav, data);
198 }
199 
200 /**
201  * Resets the text according to the current frame rate.
202  */
203 void FrameRateMeter::
204 do_update(Thread *current_thread) {
205  _last_update = _clock_object->get_frame_time(current_thread);
206 
207  double value = _clock_object->get_average_frame_rate(current_thread);
208  double deviation = _clock_object->calc_frame_rate_deviation(current_thread);
209 
210  if (_show_milliseconds) {
211  value = 1000.0 / value;
212  deviation = 1000.0 / deviation;
213  }
214 
215  static const size_t buffer_size = 1024;
216  char buffer[buffer_size];
217 #if defined(WIN32_VC) || defined(WIN64_VC)
218  // Windows doesn't define snprintf(). Hope we don't overflow.
219  sprintf(buffer, _text_pattern.c_str(), value, deviation);
220 #else
221  snprintf(buffer, buffer_size, _text_pattern.c_str(), value, deviation);
222 #endif
223  nassertv(strlen(buffer) < buffer_size);
224 
225  if (get_text() == buffer) {
226  // Never mind; the frame rate hasn't changed.
227  return;
228  }
229 
230  set_text(buffer);
231 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
get_average_frame_rate
Returns the average frame rate in number of frames per second over the last get_average_frame_rate_in...
Definition: clockObject.h:118
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
double calc_frame_rate_deviation(Thread *current_thread=Thread::get_current_thread()) const
Returns the standard deviation of the frame times of the frames rendered over the past get_average_fr...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear_window()
Undoes the effect of a previous call to setup_window().
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_bin(const std::string &bin_name, int draw_order, int priority=0)
Assigns the geometry at this level and below to the named rendering bin.
Definition: nodePath.cxx:2801
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An encapsulation of a font; i.e.
Definition: textFont.h:32
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
void setup_window(GraphicsOutput *window)
Sets up the frame rate meter to create a DisplayRegion to render itself into the indicated window.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that represents a single element that may be timed and/or counted via stats.
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
set_film_size
Sets the horizontal size of the film without changing its shape.
Definition: lens.h:82
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.h:91
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:563
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_text
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.h:124
This is a base class for the various different classes that represent the result of a frame of render...
void set_attrib(const RenderAttrib *attrib, int override=0)
Adds the indicated render attribute to the scene graph on this node.
Definition: pandaNode.cxx:944
get_line_height
Returns the number of units high each line of text is.
Definition: textFont.h:69
An orthographic lens.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
A thread; that is, a lightweight process.
Definition: thread.h:46
void set_material_off(int priority=0)
Sets the geometry at this level and below to render using no material.
Definition: nodePath.cxx:4113
The primary interface to this module.
Definition: textNode.h:48
This is a special kind of GeometricBoundingVolume that fills all of space.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
void set_two_sided(bool two_sided, int priority=0)
Specifically sets or disables two-sided rendering mode on this particular node.
Definition: nodePath.cxx:4430
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.