Panda3D
 All Classes Functions Variables Enumerations
frameRateMeter.cxx
00001 // Filename: frameRateMeter.cxx
00002 // Created by:  drose (23Dec03)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
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>  // For sprintf/snprintf
00025 
00026 PStatCollector FrameRateMeter::_show_fps_pcollector("*:Show fps");
00027 
00028 TypeHandle FrameRateMeter::_type_handle;
00029 
00030 ////////////////////////////////////////////////////////////////////
00031 //     Function: FrameRateMeter::Constructor
00032 //       Access: Published
00033 //  Description: 
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   // The top of the visible frame is 80% of the line height, based on
00047   // the calculation within TextAssembler.
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   //  set_usage_hint(Geom::UH_client);
00060 
00061   do_update(current_thread);
00062 }
00063 
00064 ////////////////////////////////////////////////////////////////////
00065 //     Function: FrameRateMeter::Destructor
00066 //       Access: Published, Virtual
00067 //  Description: 
00068 ////////////////////////////////////////////////////////////////////
00069 FrameRateMeter::
00070 ~FrameRateMeter() {
00071   clear_window();
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: FrameRateMeter::setup_window
00076 //       Access: Published
00077 //  Description: Sets up the frame rate meter to create a
00078 //               DisplayRegion to render itself into the indicated
00079 //               window.
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   // Create a display region that covers the entire window.
00098   _display_region = _window->make_mono_display_region();
00099   _display_region->set_sort(frame_rate_meter_layer_sort);
00100     
00101   // Finally, we need a camera to associate with the display region.
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 //     Function: FrameRateMeter::clear_window
00122 //       Access: Published
00123 //  Description: Undoes the effect of a previous call to
00124 //               setup_window().
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 //     Function: FrameRateMeter::cull_callback
00138 //       Access: Protected, Virtual
00139 //  Description: This function will be called during the cull
00140 //               traversal to perform any additional operations that
00141 //               should be performed at cull time.  This may include
00142 //               additional manipulation of render state or additional
00143 //               visible/invisible decisions, or any other arbitrary
00144 //               operation.
00145 //
00146 //               Note that this function will *not* be called unless
00147 //               set_cull_callback() is called in the constructor of
00148 //               the derived class.  It is necessary to call
00149 //               set_cull_callback() to indicated that we require
00150 //               cull_callback() to be called.
00151 //
00152 //               By the time this function is called, the node has
00153 //               already passed the bounding-volume test for the
00154 //               viewing frustum, and the node's transform and state
00155 //               have already been applied to the indicated
00156 //               CullTraverserData object.
00157 //
00158 //               The return value is true if this node should be
00159 //               visible, or false if it should be culled.
00160 ////////////////////////////////////////////////////////////////////
00161 bool FrameRateMeter::
00162 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00163   Thread *current_thread = trav->get_current_thread();
00164 
00165   // Statistics
00166   PStatTimer timer(_show_fps_pcollector, current_thread);
00167   
00168   // Check to see if it's time to update.
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 //     Function: FrameRateMeter::do_update
00180 //       Access: Private
00181 //  Description: Resets the text according to the current frame rate.
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   // Windows doesn't define snprintf().  Hope we don't overflow.
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     // Never mind; the frame rate hasn't changed.
00202     return;
00203   }
00204 
00205   set_text(buffer);
00206 }
 All Classes Functions Variables Enumerations