ofGetWidth slowdown

I’m running OF 0.05 on Linux and I’ve noticed that when I call ofGetWidth or ofGetHeight more than once in the draw() loop I get a massive FPS slowdown.

In this example, the variable windowwidth has cached the value of ofGetWidth during setup. Using this code I get a frame rate of 1400fps in my simple particle app.

  
  
    if (pos.x < -r-100) pos.x = ofGetWidth()+r+100;  
    if (pos.y < -r-100) pos.y = ofGetHeight()+r+100;  
    if (pos.x > windowwidth+r+100) pos.x = -r-100;  
    if (pos.y > windowheight+r+100) pos.y = -r-100;  
  

If I only use the OF ofGetWidth(),ofGetHeight() calls such as follows:

  
  
    if (pos.x < -r-100) pos.x = ofGetWidth()+r+100;  
    if (pos.y < -r-100) pos.y = ofGetHeight()+r+100;  
    if (pos.x > ofGetWidth()+r+100) pos.x = -r-100;  
    if (pos.y > ofGetHeight()+r+100) pos.y = -r-100;  
  

the framerate drops to around 30fps.

This might be a GLUT linux problem, but I think in general it’s bad not to cache API calls like glutGet(GLUT_SCREEN_WIDTH). The OF core should return a variable called “width” that it updates at startup and whenever the screen gets re-sized, not every time a user calls ofGetWidth()

Yes, another problem with this, is that if you call ofGetWidth from another thread or just from an event callback like mousePressed, you can make your app crash as this is indeed an opengl call

I think in general it’s bad not to cache API calls like glutGet(GLUT_SCREEN_WIDTH). The OF core should return a variable called “width” that it updates at startup and whenever the screen gets re-sized, not every time a user calls ofGetWidth()

yea I agree with this. Actually now that there is the resize poco callback, in all my apps I cache the values in the callback - as well as calculating a bunch of others. Namely, I have a ‘globals’ struct which has a ‘window’ struct which is updated whenever resize is called (it also has a mouse struct)

  
  
struct globals {  
   struct window {  
      int width;  
      int height;  
      float invWidth;  
      float invHeight;  
      float aspectRatio;  
   }  
   struct mouse {  
      ofPoint pos;  
      ofPoint oldPos;  
      ofPoint vel;  
   }  
}  
// etc.  
  

so then anywhere in the code globals.window.width, or globals.window.invHeight (or globals.mouse.pos.x, globals.mouse.vel.y etc.) immediately returns the necessary value.

I’m not saying this is the best way, just a suggestion :stuck_out_tongue:

hey memo

could you show me how you do globals?

thanks to your post i’ve found a significant source of solwdown, as i calculate everything from a euclidean float-space from 0.0 to 1.0*aspect and multiply up to screen dimensions.

i’m still a newbie in c++, so if you’ve got a program using the class, i’d love to see it in context. i’m not sure where to place the struct and my attempts have been unsucessful so far.

best / ole

hey ole, this is the biggest problem that people face when coming to C++ (from processing etc.).

What I usually do is:

globals.h :

  
class Globals {  
public:  
	  
	struct {  
		float			size;  
		float			drag;  
		float			dieSpeed;  
		float			camVelMult;  
		float			startAlpha;  
		int				emitSkipBlocks;  
		float			maxSpeed;  
		float			fluidVelMult;  
		float			growSpeed;  
		int				maxParticles;  
		float			sizeVariation;  
		int				phaseDuration;  
		bool			doFlicker;  
		bool			doRotate;  
		float			glitterThreshold;  
		float			glitterSizeX;  
		float			glitterSizeY;  
		float			staticVel;  
		float			flickerAmount;  
		int				numParticles;  
		bool			useVBO;  
		bool			useSprite;  
		bool			useTexture;  
		int				sparkleCount;  
		float			sparkleSizeMin;  
		float			sparkleSizeMax;  
		DustEmitter		emitter;  
	} dust;  
	  
	struct {  
		int				width;  
		int				height;  
		float			invWidth;  
		float			invHeight;  
		float			aspectRatio;  
		float			invAspectRatio;  
		ofPoint			min;  
		ofPoint			max;		  
	} window;  
  
	ofxMSAFluidSolver	fluid;  
	MotionTracker		tracker;  
  
	  
	ofSoundPlayer		audio1;  
	ofSoundPlayer		audio2;  
	float				audioVolume;  
	float				audioVolumeChange;	  
	  
	bool	createPaintOnMovement;  
	bool	createPaintOnContour;  
	  
	float dripProbability;  
	float dripSize;  
	  
	float noiseSpeed;  
	float hueNoiseScaler;  
	float satNoiseScaler;  
	float valNoiseScaler;  
	float noiseTimer;  
	float noiseMax;  
  
	float	paintSaturationMin;  
	float	paintSaturationMax;  
	float	paintBrightnessMin;  
	float	paintBrightnessMax;  
	float	paintGravity;  
	float	paintMomentum;  
	float	paintBounce;  
	float	paintMassMin;  
	int		paintDotsPerOpFlow;  
	  
	float	strokeThickMin;  
	float	strokeThickMax;  
	  
	float	idleImageTime;  
	  
	Globals() {  
		window.width			= RENDER_WIDTH;  
		window.height			= RENDER_HEIGHT;  
		window.invWidth			= 1.0f/window.width;  
		window.invHeight		= 1.0f/window.height;  
		window.aspectRatio		= window.width / window.height;  
		window.invAspectRatio	= 1.0f/window.aspectRatio;  
		window.min.set(0, 0, 0);  
		window.max.set(window.width, window.height, 0);		  
	}  
	  
};  
  
extern Globals globals;  

globals.cpp:

  
Globals globals;  

Then in any file you can #include globals.h and access the values directly :

globals.dust.growSpeed
globals.fluid
globals.window.invWidth

etc.

P.S. A software engineer would probably shoot me for suggesting this method, but it’s easy and it works :stuck_out_tongue:

Another method is using a singleton class or class with static variables. The globals approach lends itself to more readability though I think:

  
  
// global:  
globals.dust.growSpeed;  
  

  
// singleton:  
Globals::getInstance()->dust.growSpeed ;  
//or  
Globals *globals = Globals::getInstance();  
globals->dust.growSpeed;  

  
//static:  
Globals::dust.growSpeed;  
  

hope that helps!

sure does thanks a lot

globals are a new thing for me, as a java person - and i understand why they are :evil: - but in a solo project for a one-off dance performance, i don’t think encapsulation is a design priority.