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  */
136 clear_window() {
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 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
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
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
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...
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
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
void setup_window(GraphicsOutput *window)
Sets up the frame rate meter to create a DisplayRegion to render itself into the indicated window.
void clear_window()
Undoes the effect of a previous call to setup_window().
This is a base class for the various different classes that represent the result of a frame of render...
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
set_film_size
Sets the horizontal size of the film without changing its shape.
Definition: lens.h:82
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
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:600
void set_material_off(int priority=0)
Sets the geometry at this level and below to render using no material.
Definition: nodePath.cxx:4195
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:2868
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:4514
This is a special kind of GeometricBoundingVolume that fills all of space.
An orthographic lens.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
void set_attrib(const RenderAttrib *attrib, int override=0)
Adds the indicated render attribute to the scene graph on this node.
Definition: pandaNode.cxx:938
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
get_text
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.h:124
An encapsulation of a font; i.e.
Definition: textFont.h:32
get_line_height
Returns the number of units high each line of text is.
Definition: textFont.h:69
The primary interface to this module.
Definition: textNode.h:48
A thread; that is, a lightweight process.
Definition: thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.