Can the FrameRateMeter Be Shown at Runtime in C++

Is it possible to show/hide the framerate meter at runtime in C++?

In the manual it describes base.setFrameRateMeter(True)
but I can’t find a C++ equivalent.

There’s no such functionality in c++'s framework. But that counter is intended for debugging purposes anyway, you should do your own if you want to show it to the user on request.

I’ve adapted the following from some code in Panda 2, you can use it to obtain the fps, then just put it in a textnode and update it every second or so. Note that it is untested so beware of parse errors.


//you'll need these variables in the scope
float _fps, _start_time, _frame_count;

//call this to reset it
void reset_frame_rate() {
  _fps = 0;
  _start_time = ClockObject::get_global_clock()->get_frame_time();
  _frame_count = ClockObject::get_global_clock()->get_frame_count();
}

//and this to get the current fps
float get_frame_rate() {
  double now = ClockObject::get_global_clock()->get_frame_time();
  double delta = now - _start_time;
  
  int frame_count = ClockObject::get_global_clock()->get_frame_count();
  int num_frames = frame_count - _frame_count;
  if (num_frames > 0) {
    _fps = ((double)num_frames) / delta;
  }
  return _fps;
}

Always call reset_frame_rate() after get_frame_rate() and also call it once on initialization.

In the future there will be a way to switch the default meter on and off just like in python, though.

Note that the actual visible counter is created by a FrameRateMeter object. You can easily create one in C++ with code like this:

PT(FrameRateMeter) meter = new FrameRateMeter("fps");
meter->setup_window(window->get_graphics_output());

David

Oh, I thought that class would force me to the default appearance but it actually inherits from TextNode, so yeah, forget what I said.

Hi ,

I have tried to find a code sample for this but had no real luck.

I have copied the code you posted but it doesn’t do anything.
I guess it needs to be reparented to a node ?

chrys

You can reparent it to a node, but the setup_window() call is supposed to do this for you automatically.

David

Note that there is sample code in panda/src/framework/windowFramework.cxx. And also note that this code will be invoked if you simply have:

show-frame-rate-meter 1

in your Config.prc file. This is what enables the meter when you run pview with this config setting.

David

ok here is a short test program i wrote which does
this

here is the code for this

#include "pandaFramework.h"
#include "pandaSystem.h" 

PandaFramework framework; 


int main(int argc, char *argv[]) 
{    
	//open a new window framework  
	framework.open_framework(argc, argv);    
	//set the window title to My Panda3D Window  
	framework.set_window_title("My Panda3D Window");

	//open the window  
	WindowFramework *window = framework.open_window();
	//here is room for your own code
	window->setup_trackball();

	PT(FrameRateMeter) meter = new FrameRateMeter("fps"); 
	meter->setup_window(window->get_graphics_output());

	float myY = 0;
	float myX = 0;

	for (int y = 0; y < 5; ++y)
	{
		myX = 0;
		for (int x = 0; x < 5; ++x)
		{
			NodePath model = window->load_model(framework.get_models(), "models/environment");
			model.reparent_to(window->get_render());
			model.set_scale(0.25, 0.25, 0.25);
			model.set_pos(myX, myY, 0);
			
			myX += 320;
		}
		myY += 320;
	}

	//do the main loop, equal to run() in python  
	framework.main_loop();    
	//close the window framework  
	framework.close_framework();  
	return (0);
}

I dot not use instancing on purpose.
compiled in release version i get not even 30fps (I got a good enough computer to run most next gen games etc…) This FPS Seems a bit low to me ?

When you load multiple models you have to flatten them together to get performance. Try this:

   NodePath root = window->get_render().attach_new_node("root");
   for (int y = 0; y < 5; ++y)
   {
      myX = 0;
      for (int x = 0; x < 5; ++x)
      {
         NodePath model = window->load_model(framework.get_models(), "models/environment");
         model.reparent_to(root);
         model.set_scale(0.25, 0.25, 0.25);
         model.set_pos(myX, myY, 0);
         
         myX += 320;
      }
      myY += 320;
   } 
   root.flatten_strong();

Note that the first parameter of load_model() is the parent you want to attach the model to, so you might as well replace:

         NodePath model = window->load_model(framework.get_models(), "models/environment");
         model.reparent_to(root);

with:

         NodePath model = window->load_model(root, "models/environment");

That has nothing to do with performance, however.

Also, you want to disable video sync for performance measurements. With video sync enabled you will always get either 60fps or 30fps, never anything in between. Put:

sync-video 0

in your Config.prc file.

David

Thanks that root->flatten_strong() has improved performance significantly.

I have noticed though that if I parent the panda3d window to another window it won’t show the FPS anymore.

Also is there a way to display the polycount ?

What do you mean by “parent the panda3d window to another window”? The meter->setup_window() call will create a new DisplayRegion and parent the FrameRateMeter in the upper-right corner of that DisplayRegion; it will continue to draw the frame rate as long as that DisplayRegion exists and is sorted to draw on top of the other DisplayRegions.

There’s no automatic way to display the polycount onscreen every frame, but you can see it in PStats if you enable that. You can also use the SceneGraphAnalyzer to do some static analysis of your scene, including the total polygon count.

David

Ignore my comment about “reparenting the window doesn’t show the fps” … It was just me covering the “upper right corner” with a toolbar, silly me.

I will look into PStats, thanks again.

chrys