Browse Source

new FrameRateMeter

David Rose 22 years ago
parent
commit
212e00c3e9

+ 2 - 0
panda/src/framework/config_framework.cxx

@@ -35,6 +35,8 @@ const bool undecorated = config_framework.GetBool("undecorated", false);
 const bool cursor_hidden = config_framework.GetBool("cursor-hidden", false);
 const bool cursor_hidden = config_framework.GetBool("cursor-hidden", false);
 const float aspect_ratio = config_framework.GetFloat("aspect-ratio", 0.0f);
 const float aspect_ratio = config_framework.GetFloat("aspect-ratio", 0.0f);
 
 
+const bool show_frame_rate_meter = config_framework.GetBool("show-frame-rate-meter", false);
+
 // The default window background color.
 // The default window background color.
 const float win_background_r = config_framework.GetFloat("win-background-r", 0.41);
 const float win_background_r = config_framework.GetFloat("win-background-r", 0.41);
 const float win_background_g = config_framework.GetFloat("win-background-g", 0.41);
 const float win_background_g = config_framework.GetFloat("win-background-g", 0.41);

+ 2 - 0
panda/src/framework/config_framework.h

@@ -32,6 +32,8 @@ extern const bool undecorated;
 extern const bool cursor_hidden;
 extern const bool cursor_hidden;
 extern const float aspect_ratio;
 extern const float aspect_ratio;
 
 
+extern const bool show_frame_rate_meter;
+
 extern const float win_background_r;
 extern const float win_background_r;
 extern const float win_background_g;
 extern const float win_background_g;
 extern const float win_background_b;
 extern const float win_background_b;

+ 8 - 0
panda/src/framework/windowFramework.cxx

@@ -118,6 +118,12 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
 
 
   // Set up a 3-d camera for the window by default.
   // Set up a 3-d camera for the window by default.
   make_camera();
   make_camera();
+
+  if (show_frame_rate_meter) {
+    _frame_rate_meter = new FrameRateMeter("frame_rate_meter");
+    _frame_rate_meter->setup_layer(_window);
+  }
+
   return _window;
   return _window;
 }
 }
 
 
@@ -146,6 +152,8 @@ close_window() {
   _two_sided_enabled = false;
   _two_sided_enabled = false;
   _one_sided_reverse_enabled = false;
   _one_sided_reverse_enabled = false;
   _lighting_enabled = false;
   _lighting_enabled = false;
+
+  _frame_rate_meter == (FrameRateMeter *)NULL;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/framework/windowFramework.h

@@ -26,6 +26,7 @@
 #include "animControlCollection.h"
 #include "animControlCollection.h"
 #include "trackball.h"
 #include "trackball.h"
 #include "filename.h"
 #include "filename.h"
+#include "frameRateMeter.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "pvector.h"
 #include "pvector.h"
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
@@ -136,6 +137,8 @@ private:
   bool _one_sided_reverse_enabled;
   bool _one_sided_reverse_enabled;
   bool _lighting_enabled;
   bool _lighting_enabled;
 
 
+  PT(FrameRateMeter) _frame_rate_meter;
+
   BackgroundType _background_type;
   BackgroundType _background_type;
 
 
 public:
 public:

+ 4 - 1
panda/src/grutil/Sources.pp

@@ -4,22 +4,25 @@
 #begin lib_target
 #begin lib_target
   #define TARGET grutil
   #define TARGET grutil
   #define LOCAL_LIBS \
   #define LOCAL_LIBS \
-    pgraph gobj linmath putil
+    display text pgraph gobj linmath putil
     
     
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx 
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx 
 
 
   #define SOURCES \
   #define SOURCES \
     cardMaker.I cardMaker.h \
     cardMaker.I cardMaker.h \
     config_grutil.h \
     config_grutil.h \
+    frameRateMeter.I frameRateMeter.h \
     lineSegs.I lineSegs.h
     lineSegs.I lineSegs.h
     
     
   #define INCLUDED_SOURCES \
   #define INCLUDED_SOURCES \
     cardMaker.cxx \
     cardMaker.cxx \
     config_grutil.cxx \
     config_grutil.cxx \
+    frameRateMeter.cxx \
     lineSegs.cxx
     lineSegs.cxx
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
     cardMaker.I cardMaker.h \
     cardMaker.I cardMaker.h \
+    frameRateMeter.I frameRateMeter.h \
     lineSegs.I lineSegs.h
     lineSegs.I lineSegs.h
 
 
   #define IGATESCAN all
   #define IGATESCAN all

+ 29 - 1
panda/src/grutil/config_grutil.cxx

@@ -17,12 +17,40 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "config_grutil.h"
 #include "config_grutil.h"
+#include "frameRateMeter.h"
 
 
-#include <dconfig.h>
+#include "dconfig.h"
 
 
 Configure(config_grutil);
 Configure(config_grutil);
 NotifyCategoryDef(grutil, "");
 NotifyCategoryDef(grutil, "");
 
 
 ConfigureFn(config_grutil) {
 ConfigureFn(config_grutil) {
+  init_libgrutil();
+}
+
+const double frame_rate_meter_update_interval = config_grutil.GetDouble("frame-rate-meter-update-interval", 1.0);
+const string frame_rate_meter_text_pattern = config_grutil.GetString("frame-rate-meter-text-pattern", "%0.1f fps");
+const int frame_rate_meter_layer_sort = config_grutil.GetInt("frame-rate-meter-layer-sort", 1000);
+const float frame_rate_meter_scale = config_grutil.GetFloat("frame-rate-meter-scale", 0.05f);
+const float frame_rate_meter_side_margins = config_grutil.GetFloat("frame-rate-meter-side-margins", 0.5f);
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libgrutil
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libgrutil() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  FrameRateMeter::init_type();
 }
 }
 
 

+ 9 - 1
panda/src/grutil/config_grutil.h

@@ -20,10 +20,18 @@
 #define CONFIG_GRUTIL_H
 #define CONFIG_GRUTIL_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
-#include <notifyCategoryProxy.h>
+#include "notifyCategoryProxy.h"
 
 
 NotifyCategoryDecl(grutil, EXPCL_PANDA, EXPTP_PANDA);
 NotifyCategoryDecl(grutil, EXPCL_PANDA, EXPTP_PANDA);
 
 
+extern const double frame_rate_meter_update_interval;
+extern const string frame_rate_meter_text_pattern;
+extern const int frame_rate_meter_layer_sort;
+extern const float frame_rate_meter_scale;
+extern const float frame_rate_meter_side_margins;
+
+extern EXPCL_PANDA void init_libgrutil();
+
 #endif
 #endif
 
 
 
 

+ 115 - 0
panda/src/grutil/frameRateMeter.I

@@ -0,0 +1,115 @@
+// Filename: frameRateMeter.I
+// Created by:  drose (23Dec03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::setup_layer
+//       Access: Published
+//  Description: Sets up the frame rate meter to create a layer to
+//               render itself into the indicated window.
+////////////////////////////////////////////////////////////////////
+INLINE void FrameRateMeter::
+setup_layer(GraphicsWindow *window) {
+  setup_layer(window->get_channel(0));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::get_layer
+//       Access: Published
+//  Description: Returns the GraphicsLayer that the meter has created
+//               to render itself into the window or channel supplied
+//               to setup_layer(), or NULL if setup_layer() has not
+//               been called.
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsLayer *FrameRateMeter::
+get_layer() const {
+  return _layer;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::set_update_interval
+//       Access: Published
+//  Description: Specifies the number of seconds that should elapse
+//               between updates to the frame rate indication.  This
+//               should be reasonably slow (e.g. 0.2 to 1.0) so that
+//               the calculation of the frame rate text does not
+//               itself dominate the frame rate.
+////////////////////////////////////////////////////////////////////
+INLINE void FrameRateMeter::
+set_update_interval(double update_interval) {
+  _update_interval = update_interval;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::get_update_interval
+//       Access: Published
+//  Description: Returns the number of seconds that will elapse
+//               between updates to the frame rate indication.
+////////////////////////////////////////////////////////////////////
+INLINE double FrameRateMeter::
+get_update_interval() const {
+  return _update_interval;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::set_text_pattern
+//       Access: Published
+//  Description: Sets the sprintf() pattern that is used to format the
+//               text.  The string "%f" or some variant will be
+//               replaced with the current frame rate in frames per
+//               second.
+////////////////////////////////////////////////////////////////////
+INLINE void FrameRateMeter::
+set_text_pattern(const string &text_pattern) {
+  _text_pattern = text_pattern;
+  do_update();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::get_text_pattern
+//       Access: Published
+//  Description: Returns the sprintf() pattern that is used to format the
+//               text.
+////////////////////////////////////////////////////////////////////
+INLINE const string &FrameRateMeter::
+get_text_pattern() const {
+  return _text_pattern;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::set_clock_object
+//       Access: Published
+//  Description: Sets the clock that is used to determine the frame
+//               rate.  The default is the application's global clock
+//               (ClockObject::get_global_clock()).
+////////////////////////////////////////////////////////////////////
+INLINE void FrameRateMeter::
+set_clock_object(ClockObject *clock_object) {
+  _clock_object = clock_object;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::get_clock_object
+//       Access: Published
+//  Description: Returns the clock that is used to determine the frame
+//               rate.
+////////////////////////////////////////////////////////////////////
+INLINE ClockObject *FrameRateMeter::
+get_clock_object() const {
+  return _clock_object;
+}

+ 183 - 0
panda/src/grutil/frameRateMeter.cxx

@@ -0,0 +1,183 @@
+// Filename: frameRateMeter.cxx
+// Created by:  drose (23Dec03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "frameRateMeter.h"
+#include "camera.h"
+#include "displayRegion.h"
+#include "orthographicLens.h"
+#include "graphicsChannel.h"
+#include "clockObject.h"
+#include "config_grutil.h"
+#include "depthTestAttrib.h"
+#include "depthWriteAttrib.h"
+
+TypeHandle FrameRateMeter::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+FrameRateMeter::
+FrameRateMeter(const string &name) : TextNode(name) {
+  _update_interval = frame_rate_meter_update_interval;
+  _text_pattern = frame_rate_meter_text_pattern;
+  _clock_object = ClockObject::get_global_clock();
+
+  set_align(A_right);
+  set_transform(LMatrix4f::scale_mat(frame_rate_meter_scale) * 
+                LMatrix4f::translate_mat(1.0f - frame_rate_meter_side_margins * frame_rate_meter_scale, 0.0f, 1.0f - frame_rate_meter_scale));
+  set_card_color(0.0f, 0.0f, 0.0f, 0.4f);
+  set_card_as_margin(frame_rate_meter_side_margins, frame_rate_meter_side_margins, 0.1f, 0.0f);
+
+  do_update();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::Destructor
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+FrameRateMeter::
+~FrameRateMeter() {
+  clear_layer();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::setup_layer
+//       Access: Published
+//  Description: Sets up the frame rate meter to create a layer to
+//               render itself into the indicated channel.
+////////////////////////////////////////////////////////////////////
+void FrameRateMeter::
+setup_layer(GraphicsChannel *channel) {
+  clear_layer();
+
+  _root = NodePath("frame_rate_root");
+  _root.attach_new_node(this);
+
+  CPT(RenderAttrib) dt = DepthTestAttrib::make(DepthTestAttrib::M_none);
+  CPT(RenderAttrib) dw = DepthWriteAttrib::make(DepthWriteAttrib::M_off);
+  _root.node()->set_attrib(dt, 1);
+  _root.node()->set_attrib(dw, 1);
+  _root.set_material_off(1);
+  _root.set_two_sided(1, 1);
+
+  // Make a layer on the channel to hold our display region.
+  _layer = channel->make_layer(frame_rate_meter_layer_sort);
+    
+  // And create a display region that covers the entire window.
+  PT(DisplayRegion) dr = _layer->make_display_region();
+    
+  // Finally, we need a camera to associate with the display region.
+  PT(Camera) camera = new Camera("frame_rate_camera");
+  NodePath camera_np = _root.attach_new_node(camera);
+    
+  PT(Lens) lens = new OrthographicLens;
+  
+  static const float left = -1.0f;
+  static const float right = 1.0f;
+  static const float bottom = -1.0f;
+  static const float top = 1.0f;
+  lens->set_film_size(right - left, top - bottom);
+  lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
+  lens->set_near_far(-1000, 1000);
+  
+  camera->set_lens(lens);
+  camera->set_scene(_root);
+  dr->set_camera(camera_np);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::clear_layer
+//       Access: Published
+//  Description: Undoes the effect of a previous call to
+//               setup_layer().
+////////////////////////////////////////////////////////////////////
+void FrameRateMeter::
+clear_layer() {
+  if (_layer != (GraphicsLayer *)NULL) {
+    GraphicsChannel *channel = _layer->get_channel();
+    if (channel != (GraphicsChannel *)NULL) {
+      channel->remove_layer(_layer);
+    }
+    _layer = (GraphicsLayer *)NULL;
+  }
+
+  _root = NodePath();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::cull_callback
+//       Access: Protected, Virtual
+//  Description: If has_cull_callback() returns true, this function
+//               will be called during the cull traversal to perform
+//               any additional operations that should be performed at
+//               cull time.  This may include additional manipulation
+//               of render state or additional visible/invisible
+//               decisions, or any other arbitrary operation.
+//
+//               By the time this function is called, the node has
+//               already passed the bounding-volume test for the
+//               viewing frustum, and the node's transform and state
+//               have already been applied to the indicated
+//               CullTraverserData object.
+//
+//               The return value is true if this node should be
+//               visible, or false if it should be culled.
+////////////////////////////////////////////////////////////////////
+bool FrameRateMeter::
+cull_callback(CullTraverser *trav, CullTraverserData &data) {
+  // Check to see if it's time to update.
+  double now = _clock_object->get_frame_time();
+  double elapsed = now - _last_update;
+  if (elapsed < 0.0 || elapsed >= _update_interval) {
+    do_update();
+  }
+
+  return TextNode::cull_callback(trav, data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameRateMeter::do_update
+//       Access: Private
+//  Description: Resets the text according to the current frame rate.
+////////////////////////////////////////////////////////////////////
+void FrameRateMeter::
+do_update() {
+  _last_update = _clock_object->get_frame_time();
+
+  double frame_rate = _clock_object->get_average_frame_rate();
+
+  static const size_t buffer_size = 1024;
+  char buffer[buffer_size];
+#ifdef WIN32_VC
+  // Windows doesn't define snprintf().  Hope we don't overflow.
+  sprintf(buffer, _text_pattern.c_str(), frame_rate);
+#else
+  snprintf(buffer, buffer_size, _text_pattern.c_str(), frame_rate);
+#endif
+  nassertv(strlen(buffer) < buffer_size);
+
+  if (get_text() == buffer) {
+    // Never mind; the frame rate hasn't changed.
+    return;
+  }
+
+  set_text(buffer);
+}

+ 99 - 0
panda/src/grutil/frameRateMeter.h

@@ -0,0 +1,99 @@
+// Filename: frameRateMeter.h
+// Created by:  drose (23Dec03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef FRAMERATEMETER_H
+#define FRAMERATEMETER_H
+
+#include "pandabase.h"
+#include "textNode.h"
+#include "nodePath.h"
+#include "graphicsWindow.h"
+#include "graphicsLayer.h"
+#include "pointerTo.h"
+
+class GraphicsChannel;
+class ClockObject;
+
+////////////////////////////////////////////////////////////////////
+//       Class : FrameRateMeter
+// Description : This is a special TextNode that automatically updates
+//               itself with the current frame rate.  It can be placed
+//               anywhere in the world where you'd like to see the
+//               frame rate.
+//
+//               It also has a special mode in which it may be
+//               attached directly to a channel or window.  If this is
+//               done, it creates a layer for itself and renders
+//               itself in the upper-right-hand corner.
+////////////////////////////////////////////////////////////////////
+class EXPCL_FRAMEWORK FrameRateMeter : public TextNode {
+PUBLISHED:
+  FrameRateMeter(const string &name);
+  virtual ~FrameRateMeter();
+
+  INLINE void setup_layer(GraphicsWindow *window);
+  void setup_layer(GraphicsChannel *channel);
+  void clear_layer();
+
+  INLINE GraphicsLayer *get_layer() const;
+
+  INLINE void set_update_interval(double update_interval);
+  INLINE double get_update_interval() const;
+
+  INLINE void set_text_pattern(const string &text_pattern);
+  INLINE const string &get_text_pattern() const;
+
+  INLINE void set_clock_object(ClockObject *clock_object);
+  INLINE ClockObject *get_clock_object() const;
+
+protected:
+  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
+
+private:
+  void do_update();
+
+private:
+  PT(GraphicsLayer) _layer;
+  NodePath _root;
+
+  double _update_interval;
+  double _last_update;
+  string _text_pattern;
+  ClockObject *_clock_object;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TextNode::init_type();
+    register_type(_type_handle, "FrameRateMeter",
+                  TextNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "frameRateMeter.I"
+
+#endif

+ 1 - 4
panda/src/grutil/grutil_composite1.cxx

@@ -1,7 +1,4 @@
-
 #include "cardMaker.cxx"
 #include "cardMaker.cxx"
 #include "config_grutil.cxx"
 #include "config_grutil.cxx"
 #include "lineSegs.cxx"
 #include "lineSegs.cxx"
- 
- 
-     
+#include "frameRateMeter.cxx"