What does sprintf do? (was: FPS Calculation in OpenGL) - c

For FPS calculation, I use some code I found on the web and it's working well. However, I don't really understand it. Here's the function I use:
void computeFPS()
{
numberOfFramesSinceLastComputation++;
currentTime = glutGet(GLUT_ELAPSED_TIME);
if(currentTime - timeSinceLastFPSComputation > 1000)
{
char fps[256];
sprintf(fps, "FPS: %.2f", numberOfFramesSinceLastFPSComputation * 1000.0 / (currentTime . timeSinceLastFPSComputation));
glutSetWindowTitle(fps);
timeSinceLastFPSComputation = currentTime;
numberOfFramesSinceLastComputation = 0;
}
}
My question is, how is the value that is calculated in the sprint call stored in the fps array, since I don't really assign it.

This is not a question about OpenGL, but the C standard library. Reading the reference documentation of s(n)printf helps:
man s(n)printf: http://linux.die.net/man/3/sprintf
In short snprintf takes a pointer to a user supplied buffer and a format string and fills the buffer according to the format string and the values given in the additional parameters.
Here's my suggestion: If you have to ask about things like that, don't tackle OpenGL yet. You need to be fluent in the use of pointers and buffers when it comes to supplying buffer object data and shader sources. If you plan on using C for this, get a book on C and thoroughly learn that first. And unlike C++ you can actually learn C to some good degree over the course of a few months.

This function is supposedly called at every redraw of your main loop (for every frame). So what it's doing is increasing a counter of frames and getting the current time this frame is being displayed. And once per second (1000ms), it's checking that counter and reseting it to 0. So when getting the counter value at each second, it's getting its value and displaying it as the title of the window.
/**
* This function has to be called at every frame redraw.
* It will update the window title once per second (or more) with the fps value.
*/
void computeFPS()
{
//increase the number of frames
numberOfFramesSinceLastComputation++;
//get the current time in order to check if it has been one second
currentTime = glutGet(GLUT_ELAPSED_TIME);
//the code in this if will be executed just once per second (1000ms)
if(currentTime - timeSinceLastFPSComputation > 1000)
{
//create a char string with the integer value of numberOfFramesSinceLastComputation and assign it to fps
char fps[256];
sprintf(fps, "FPS: %.2f", numberOfFramesSinceLastFPSComputation * 1000.0 / (currentTime . timeSinceLastFPSComputation));
//use fps to set the window title
glutSetWindowTitle(fps);
//saves the current time in order to know when the next second will occur
timeSinceLastFPSComputation = currentTime;
//resets the number of frames per second.
numberOfFramesSinceLastComputation = 0;
}
}

Related

Reducing firebase latency by only sending changed value?

I am using an Wemos D1 Mini (Arduino) to send sensor data to Firebase. It is one value I'm sending. I found that this makes the program slow down, so the sensor isn't able to get the data as fast, as data is being sent (which is kind of obvious).
Anyhow, I want to send the value to Firebase only when this value changed its property. It is an int value, but I'm not sure how to go around this. Should I use a listener? This is a portion of my code:
int n = 0; // will be used to store the count
Firebase.setInt("Reps/Value", n); // sends value to fb
delay(100); // Wait 1 second and scan again
I was hoping that the sensor could scan every second, which it does. But at this rate (pun intended) the value is being pushed every second to FB. This slows down the scanning to every 3 seconds. How can I only use the firebaseSetInt method when n changes its value?
You can check after every reading every new value whether the value has been changed or not by adding just a simple conditional statement.
int n = 0; // will be used to store the count
int n_old; // old value saved to fb
if(n!=n_old) { //checks whether value is changed
Firebase.setInt("Reps/Value", n); // sends value to fb
n_old = n; // updates the old value to the last updated
}
delay(100); // Wait 1 second and scan again
Or if you want to go for a tolerance approach, you can further do something like this:
int n = 0; // will be used to store the count
int n_old; // old value saved to fb
int tolerance = 3; // tolerance upto 3%
if(abs((n-n_old)/((n+n_old)/2))*100 > tolerance) {
Firebase.setInt("Reps/Value", n); // sends value to fb
n_old = n; // updates the old value to the last updated
}
delay(100); // Wait 1 second and scan again
Coming from a professional use of remote databases, you should go for a gliding average approach. You do this by creating a circle buffer with lets say 30 sensor values and calculate an average value. As long as a value is +/- 3% within the average recorded at time0 you do not update. If the value is above or under you send to Firebase and set a new time0 average. Depending on your precision and needs you ease the stress on the systems.Imho only life safers like current breakers or flow cutting (liquids) have to be real time, all hobby applications like measuring wind speed, heating etc are well designed with 20 - 60 sec intervals.
The event listener by the way is this approach, just do something if its out of the norm. If you have a fixed target value as a reference its much easier to check for the +/- difference. If the pricing of FB changes it will be an issue for devs - so plan ahead.

How can I implement a timer, using sdl2 libraries in C, making lunar lander game

I'm making a lander mole version (Atari 1979) in C.I need to implement a timer in my game and then print on the screen.
I'm using SDLDrawLine because i have a vector that represent's my charactes. I need my code to run a string of characters, that's good. I use the sprintf function to transform a number into a string of characters to print it on the screen.
char aux_str[MAX_VALUES];
sprintf(aux_str,"%d",*value);
for(j=0;j<strlen(aux_str);j++){
*tam_caracter_numero = letra_a_longitud(aux_str[j]);
*ptr_valor = letra_a_vector(aux_str[j]);
for(i=0;i<*tam_caracter_numero-1;i++){
SDL_RenderDrawLine(
renderer,
(*ptr_valor)[i][0] * escalado + pos_x,
-(*ptr_valor)[i][1] * escalado + pos_y,
(*ptr_valor)[i+1][0] * escalado + pos_x,
-(*ptr_valor)[i+1][1] * escalado + pos_y
);
}
This works properly, but I need my timer to start in 0000, changing to 0001,0002,.... But when i transform my number in a string using sprintf, the results is only 1, and doesn't print de 0s. There is some function o some way to make this posible? That let begin in 0000?
To print leading zeros just use the format "%04d" instead of plain "%d" in your sprintf-statement.
On account of timing the whole thing I'd recommend going through Lazyfoos's SDL tutorials about timers.
To get the time use SDL_GetTicks(). This will get the time in milliseconds since SDL was initialized. See the man page for more details on that.
To use it as a timer you have to get the delta time since last call to SDL_GetTicks and update it as such.
unsigned time = SDL_GetTicks();
while(game_is_running) { // Your game loop or whatever thread
// keeps track of time
unsigned now = SDL_GetTicks();
unsigned delta_time = now - time;
// Either delay next frame to get a stable FPS and/or use it as
// calculation in physics/collision
// Update the time
time = now;
}
SDL_GetTime is expensive so I would not recommend calling it more than once per loop.
Off-topic: I also wouldn't recommend allocating a string repeatedly in a loop. instead allocate once and overwrite every iteration.
edit: In my "off-topic"-comment I am referring to aux_str[MAX_VALUES];, even though it's 1 instruction it's still unnecessary if it's inside OP's gameloop.

Average from error prone measurement samples without buffering

I got a µC which measures temperature with of a sensor with an ADC. Due to various circumstances it can happen, that the reading is 0 (-30°C) or a impossible large Value (500-1500°C). I can't fix the reasons why these readings are so bad (time critical ISRs and sometimes a bad wiring) so I have to fix it with a clever piece of code.
I've come up with this (code gets called OVERSAMPLENR-times in a ISR):
#define OVERSAMPLENR 16 //read value 16 times
#define TEMP_VALID_CHANGE 0.15 //15% change in reading is possible
//float raw_tem_bed_value = <sum of all readings>;
//ADC = <AVR ADC reading macro>;
if(temp_count > 1) { //temp_count = amount of samples read, gets increased elsewhere
float avgRaw = raw_temp_bed_value / temp_count;
float diff = (avgRaw > ADC ? avgRaw - ADC : ADC - avgRaw) / (avgRaw == 0 ? 1 : avgRaw); //pulled out to shorten the line for SO
if (diff > TEMP_VALID_CHANGE * ((OVERSAMPLENR - temp_count) / OVERSAMPLENR)) //subsequent readings have a smaller tollerance
raw_temp_bed_value += avgRaw;
else
raw_temp_bed_value += ADC;
} else {
raw_temp_bed_value = ADC;
}
Where raw_temp_bed_value is a static global and gets read and processed later, when the ISR got fired 16 times.
As you can see, I check if the difference between the current average and the new reading is less then 15%. If so I accept the reading, if not, I reject it and add the current average instead.
But this breaks horribly if the first reading is something impossible.
One solution I though of is:
In the last line the raw_temp_bed_value is reset to the first ADC reading. It would be better to reset this to raw_temp_bed_value/OVERSAMPLENR. So I don't run in a "first reading error".
Do you have any better solutions? I though of some solutions featuring a moving average and use the average of the moving average but this would require additional arrays/RAM/cycles which we want to prevent.
I've often used something what I call rate of change to the sampling. Use a variable that represents how many samples it takes to reach a certain value, like 20. Then keep adding your sample difference to a variable divided by the rate of change. You can still use a threshold to filter out unlikely values.
float RateOfChange = 20;
float PreviousAdcValue = 0;
float filtered = FILTER_PRESET;
while(1)
{
//isr gets adc value here
filtered = filtered + ((AdcValue - PreviousAdcValue)/RateOfChange);
PreviousAdcValue = AdcValue;
sleep();
}
Please note that this isn't exactly like a low pass filter, it responds quicker and the last value added has the most significance. But it will not change much if a single value shoots out too much, depending on the rate of change.
You can also preset the filtered value to something sensible. This prevents wild startup behavior.
It takes up to RateOfChange samples to reach a stable value. You may want to make sure the filtered value isn't used before that by using a counter to count the number of samples taken for example. If the counter is lower than RateOfChange, skip processing temperature control.
For a more advanced (temperature) control routine, I highly recommend looking into PID control loops. These add a plethora of functionality to get a fast, stable response and keep something at a certain temperature efficiently and keep oscillations to a minimum. I've used the one used in the Marlin firmware in my own projects and works quite well.

Spawning after time passed in C

I'm making simple game and trying to make char spawn after 5 sec from the start of the game. This is part of my code and I not sure if I have to use time.h or loop function or something. Can anyone give me some advice? Thank you
char * image =
/**/ "H H"
/**/ "H H"
/**/ "HHHHH"
/**/ "H H"
/**/ "H H";
#define HERO_WIDTH (5)
#define HERO_HEIGHT (5)
void setup_hero( void ) {
// Set up the hero at the centre of the screen.
int hero_x = ( screen_width() - HERO_WIDTH ) / 2;
int hero_y = ( screen_height() - HERO_HEIGHT ) / 2;
hero = sprite_create( hero_x, hero_y, HERO_WIDTH, HERO_HEIGHT, image );
wait(5); // not working
sprite_draw(image);
show_screen();
}
Normally, games are event-oriented. They have a main loop that pretty much does nothing but poll the user input, update a timer, and update/render all the entities in the scene.
The timer updated by the main loop keeps track of the number of milliseconds passed since the last iteration of the loop, and is often called the 'delta' time. Delta time is extremely useful for scaling the speed of animation and sound, because the amount of time it takes for the main loop to complete varies depending on a large number of factors.
One way to accomplish what you're trying to do give your entity a counter set to 0 when it's first spawned. Every time the entity is updated, add the delta time to the counter. When the counter is greater than or equal to 5000ms, then 5 seconds have passed.
The best way to implement delta time in C is to use the clock function in <time.h>. It returns the number of cpu cycles that have passed since the program was started. Dividing this value by CLOCKS_PER_SEC / 1000 will give you the number of milliseconds that have passed. subtract the time for the last iteration from the current time to get the delta time.
see: http://www.tutorialspoint.com/c_standard_library/c_function_clock.htm

Getting individual frames using CV_CAP_PROP_POS_FRAMES in cvSetCaptureProperty

I am trying to jump to a specific frame by setting the CV_CAP_PROP_POS_FRAMES property and then reading the frame like this:
cvSetCaptureProperty( input_video, CV_CAP_PROP_POS_FRAMES, current_frame );
frame = cvQueryFrame( input_video );
The problem I am facing is that, OpenCV 2.1 returns the same frame for the 12 consecutive values of current_frame whereas I want to read each individual frame, not just the key frames. Can anyone please tell me what's wrong?
I did some research and found out that the problem is caused by the decompression algorithm.
The MPEG-like algorithms (including HD, et all) do not compress each frame separately, but save a keyframe from time to time, and then only the differences between the last frame and subsequent frames.
The problem you reported is caused by the fact that, when you select a frame, the decoder (ffmpeg, likely) automatically advances to the next keyframe.
So, is there a way around this? I don't want only key frames but each individual frame.
I don't know whether or not this would be precise enough for your purpose, but I've had success getting to a particular point in an MPEG video by grabbing the frame rate, converting the frame number to a time, then advancing to the time. Like so:
cv::VideoCapture sourceVideo("/some/file/name.mpg");
double frameRate = sourceVideo.get(CV_CAP_PROP_FPS);
double frameTime = 1000.0 * frameNumber / frameRate;
sourceVideo.set(CV_CAP_PROP_POS_MSEC, frameTime);
Due to this limitation in OpenCV, it may be wise to to use FFMPEG instead. Moviepy is a nice wrapper library.
# Get nth frame from a video
from moviepy.video.io.ffmpeg_reader import FFMPEG_VideoReader
cap = FFMPEG_VideoReader("movie.mov",True)
cap.initialize()
cap.get_frame(n/FPS)
Performance is great too. Seeking to the nth frame with get_frame is O(1), and a speed-up is used if (nearly) consecutive frames are requested. I've gotten better-than-realtime results loading three 720p videos simultaneously.
CV_CAP_PROP_POS_FRAMES jumps to a key frame. I had the same issue and worked around it using this (python-)code. It's probably not totally efficient, but get's the job done:
def seekTo(cap, position):
positiontoset = position
pos = -1
cap.set(cv.CV_CAP_PROP_POS_FRAMES, position)
while pos < position:
ret, image = cap.read()
pos = cap.get(cv.CV_CAP_PROP_POS_FRAMES)
if pos == position:
return image
elif pos > position:
positiontoset -= 1
cap.set(cv.CV_CAP_PROP_POS_FRAMES, positiontoset)
pos = -1
I've successfully used the following on OpenCV 3 / Python 3:
# Skip to 150 frame then read the 151th frame
cap.set(cv2.CAP_PROP_POS_FRAMES, 150))
ret, frame = cap.read()
After some years assuming this as a unsavable bug, I think I've figured out a way to use with a good balance between speed and correctness.
A previous solution suggested to use the CV_CAP_PROP_POS_MSEC property before reading the frame:
cv::VideoCapture sourceVideo("/some/file/name.mpg");
const auto frameRate = sourceVideo.get(CV_CAP_PROP_FPS);
void readFrame(int frameNumber, cv::Mat& image) {
const double frameTime = 1000.0 * frameNumber / frameRate;
sourceVideo.set(CV_CAP_PROP_POS_MSEC, frameTime);
sourceVideo.read(image);
}
It does return the expected frame, but the problem is that using CV_CAP_PROP_POS_MSEC may be very slow, for example for a video conversion.
Note: using global variables for simplicity.
On the other hand, if you just want to read the video sequentially, it is enough to read frame without seeking at all.
for (int frameNumber = 0; frameNumber < nFrames; ++frameNumber) {
sourceVideo.read(image);
}
The solution comes from combining both: using a variable to remember the last queried frame, lastFrameNumber, and only seek when requested frame is not the next one. In this way it is possible to increase the speed in a sequential reading while allowing random seek if necessary.
cv::VideoCapture sourceVideo("/some/file/name.mpg");
const auto frameRate = sourceVideo.get(CV_CAP_PROP_FPS);
const int lastFrameNumber = -2; // guarantee seeking the first time
void readFrame(int frameNumber, cv::Mat& image) {
if (lastFrameNumber + 1 != frameNumber) { // not the next frame? seek
const double frameTime = 1000.0 * frameNumber / frameRate;
sourceVideo.set(CV_CAP_PROP_POS_MSEC, frameTime);
}
sourceVideo.read(image);
lastFrameNumber = frameNumber;
}

Resources