Weird problems making a SetFPS function

Started by
0 comments, last by LCO 17 years, 7 months ago
Hi, I'm trying to make a function for controlling the number of frames per second by using OpenGL and SDL as glcontext for an hardware accelerated 2d engine i'm writing. In order to understand the context of the problem, this engine has a renderer that contains a set of sprites. Sprites have functions for controlling its xform data (position, rotation and scale): These functions are called by the library user: Internally, this data is stored into each sprite object and, later, matrix modifications are performed. The updating functions must be locked for a number of milliseconds determined by FPS, so that they can't change any data. There are two options: -a) Blocking the user calls: This option is not desired, since it's the user who implements the FPS control. -b) Blocking the matrix multiplications: By this way, data changes are not visible during the requested amount of time. Using the last option brings me a very weird problem: Looks like sprites are not changing its data, but.. it's changed! The sprite is watched in its original position, rotation and scale but, sometimes, a fast blink with the sprite changed appears. Let's take a look at the code. First of all, let's show the user calls:

int main()
{
        //Main function
 	Core::getSingleton()->setRenderer(Core::SDL_GL);  //Tells the engine we want to use the renderer implemented with OpenGL and SDL
 	Core::getSingleton()->init(800, 600, CD_32, false); //Typical init funcion :)
 	
 	cPointer<Sprite> sprite = Core::getSingleton()->getRenderer()->createSprite();
 	sprite->loadFrame("sample.png");
 
        //We are using the default FPS value, so there is no any setFPS functions below.	
 	while(1)
 	{
		sprite->setX(sprite->getY() + 0.01);
 		sprite->setY(sprite->getY() + 0.01);
		sprite->rotate(sprite->getRotation() + 0.01);
 		sprite->scale(sprite->getScaleX() + 0.001, sprite->getScaleY() + 0.001);
 		Core::getSingleton()->render(); //This call the render function of the selected renderer
 	}
 	return 0;
}

As expected, the Core::getSingleton()->render() function renders the scene. If applicable, it doesn't render the last changes.

void SDL_GL_Renderer::render()
{
	if(SDL_GetTicks() - init_ms > Uint32(1000/fps)) //Get the milliseconds per frame
	{
		frame_rendered = false;
		init_ms = SDL_GetTicks();
	}

        //OGL Junk	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glMatrixMode(GL_MODELVIEW);
 	glLoadIdentity();
 	glPushMatrix();
 	
 	typedef std::deque<cPointer<Sprite> >::iterator It;
 	for(It i = sprites.begin(); i != sprites.end(); i++)
 	{
 		if(!frame_rendered) //Update the sprite data if applicable
	 		(*i)->update();

 		(*i)->render();
 	}
 		
        if(double_buffer)
 	        SDL_GL_SwapBuffers();
 	
 	frame_rendered = true; //Let's wait the amount of milliseconds per frame
	
}

Next, let's take a look at Sprite::update() (unsurpringsly, OpenGL implementation :)):


//Updating
void SDL_GL_Sprite::update()
{
	updateUVCoords(); //Change the UV coordinates of the current frame
	updateSize(); //Change the sprite size to the current frame size
	
	glTranslatef(x, y, 0.0); //Matrix operations
	glScalef(scale_x, scale_y, 0.0);
	glRotatef(rot, 0.0, 0.0, 1.0);
	glPushMatrix();

	changes_done = true;	
}

//...

void SDL_GL_Sprite::popMatrices() //If changes performed, pop matrices of them
{
	if(changes_done)
	{
		glPopMatrix();
		changes_done = false;
	}
}

(I had to put the popMatrices call in the SDL_GL_Sprite::render() function). Everything seems to work fine if I block the SetX, setRotation and you know which functions in the user main loop, but that unexpected blinking appears if i block matrix operations. Currently i neither don't know why this code is wrong nor find the problem, so your help will be very appreciated. In advance, thank you very much.
Advertisement
I'm really idiot, i've found the problem and it is trivial.
Obviously, not calling the matrix operations will set the sprite in its first position, rotation and scale.

Sorry.

This topic is closed to new replies.

Advertisement