new FrameRateMeter

This commit is contained in:
David Rose 2003-12-23 23:12:40 +00:00
parent 12ef28166f
commit 212e00c3e9
11 changed files with 455 additions and 7 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -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:

View File

@ -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

View File

@ -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();
} }

View File

@ -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

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// 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;
}

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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);
}

View File

@ -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
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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

View File

@ -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"