Clearing screen at key press in GLUT, c++ - c++

I have a program that monitors a text file for changes, and upon detecting one, the user has the option to redisplay the screen based on the contents of this text file. My problem is that when a new screen is requested, the contents of the previous screen stay, while the new contents overlaps it. I want the screen to be cleared before new data is put on the screen.
here is what I have:
void keyboard(unsigned char key, int x, int y){
if(key == 'c'){
c_pressed++;
cout<<"c pressed: "<<c_pressed<<"sound.txt cleared..."<<endl;
clear_file();
}
if(key=='v'){
v_pressed++;
cout<<"v pressed: "<<v_pressed<<"displaying new configuration..."<<endl;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glutPostRedisplay();
}
}
When the key 'c' is pressed, the text file is cleared. I have verified this works properly. Then after a separate program loads in new data into the text file, the user presses 'v' to load these new instructions. I've tried placing the clear function within the 'v' statement, and as well as in the display function...
void display(void){
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
read_in_sound();
cout<<"Number of sound events: "<<numLines<<endl;
for(int j=0; j<numLines; j++){
if(data[0+j*4]==1){
circle(0,0,200,50);
}
if(data[1+j*4]==1){
circle(0,400,200,50);
}
if(data[2+j*4]==1){
circle(400,400,200,50);
}
if(data[3+j*4]==1){
circle(400,0,200,50);
}
}
glFlush();
glutSwapBuffers();
}
But when I call redisplay, both the old and new screens are displayed.

As a general rule you should do OpenGL drawing calls (and clearing the scene is a drawing call) only from the display function. If something in a OpenGL scene changes the canonical way is to redraw the whole thing. So in reaction to any event you change your programs state and issue a redraw, which will ultimately redraw the scene using OpenGL.
If the scene is very complex any you want to only update the scene with only opaque geometry (anything that requires blending mandates a full redraw) you should use store the scene color and depth buffer to textures and use them to start from a well defined state. Ideally you use a framebuffer object for this.

This may not be the best method in the world, but I added a rectangle object that is the size of the window that matches the black background that gets called up each time I want to "redraw". It saves time from having to write in a framebuffer like the previous answer suggested.

Related

OpenGL transformation with keyboard input not working

I'm trying to apply transformation to a specific part of my drawing that will only come in effect when a key is pressed.
I'm using glPushMatrix() then I do my transformation, then glPopMatrix().
What happens when I press my key is that the transformation is done only once, then no matter how many times I press the key again nothing happens.
Here's a snippet from my code:
void drawShapes(){
glClear(GL_COLOR_BUFFER_BIT);
//setting my variables
glPushMatrix();
if (translateFlag) //this is set to true in the keyboard function
{
x += 10;
glTranslated(x, 0, 0);
translateFlag = false;
}
drawCircle();
glPopMatrix();
//more drawings
}
when I remove the pushMatrix and popMatrix it works but it applies the transformation to all of my shapes, which is not what I want.
Any help would be appreciated..
[Update]
I've tried to run my code on 4 other computers (one macbook Air, one macbook Pro -an exact copy of mine- and 2 iMacs and) and it doesn't even run on any of them, could this mean the problem lies in my own macbook?!
Also I copied code that runs perfectly fine on the macbook air, rotating parts and everything and when I run it on mine I got the same disappointing result as my own code.
Here's the heypasteit code for my code 31JL
possible problems:
void drawShapes(){
glClear(GL_COLOR_BUFFER_BIT);
//setting my variables
// maybe you have forgot to set matrix mode correctly. make the projection and modelview
matrices correct.
glPushMatrix();
if (translateFlag) //this is set to true in the keyboard function
//probably your key hit function is not working properly (I can't say without looking at full code)
{
x += 10;
glTranslated(x, 0, 0);
translateFlag = false;
}
drawCircle();
glPopMatrix();
//more drawings
// you are using glFlush() ????? try swapbuffers. exact function depends
on the API you are using (GLUT \ GLFW etc.)
}

Flickering when drawing the background outside of the main loop

Here's my CODE:
#include <SFML\Graphics.hpp>
sf::RenderWindow renderWindow(sf::VideoMode(300, 300), "The Problem");
int main()
{
sf::Texture tX;
tX.loadFromFile("Recursos/Fondo.png");
sf::Sprite tXt(tX);
renderWindow.draw(tXt);
while (true) // main loop
{
renderWindow.display();
}
}
tX is a large sprite (think: background), so I want to avoid redrawing it every frame.
When I try this, I get flickering, and I have no idea where it's coming from.
Your code, simplified, pseudo:
Initialize();
Draw();
Loop {
Display();
}
What you're doing is drawing the scene to a buffer (without clearing it first, by the way), and then displaying it in a loop (without redrawing anything).
I think the reason you have flickering is due to double-buffering (v-sync).
What ends up happening is that you drew to one buffer, but left the other one empty. When you display the active buffer, they get flipped (so the next time you display, it's an empty buffer).
You really should draw inside the loop.
Alternatively, you can disable multiple-buffering, or try drawing, displaying, drawing again, and then looping (so that you draw to both buffers, assuming there are only two).
Both solutions are not elegant.
If drawing the background really needs optimization, I'm afraid SFML won't give you that granularity. You might want to look in to OpemGL Stencil wizardry.

Qt - Adding a drawing to a Layout

I'm trying to make an application where the user can input some drawings (gestures) that will then be saved and displayed in a gallery on the top of the screen:
When the user presses "Validate", the drawing is supposed to be displayed on the scroll area on the top. However, for some reason, my code is not working the way I intended it to. It saves the drawing with no problem, but when I tell it to add it to the top, nothing happens.
Code here:
void MainWindow::galleryUpdate()
{
for (int i = 0; i < gestureTemplates.size(); i++)
{
QPolygonF scaledGesture = gestureTemplates[i].scaleToSquare(gestureTemplates[i]);
StrokeDrawer * strD = new StrokeDrawer();
QPalette Pal(palette());
Pal.setColor(QPalette::Background, Qt::white);
strD->setMinimumSize(50, 50);
strD->setAutoFillBackground(true);
strD->setPalette(Pal);
galleryList.append(strD);
topZone->addWidget(strD);
strD->setStroke(scaledGesture);
}
}
gestureTemplates is a vector of GestureTemplate (a custom class inheriting from QPolygonF) containing all the drawings. The first line inside the for simply scales the drawing to fit in a square, and returns a QPolygonF.
StrokeDrawer is the class used to display the drawing (code below). I then try to fill it with a white background, save it to galleryList which is a list of StrokeDrawer for each drawing, and then add it to the top, by using topZone->addWidget(strD), where topZone is a HBoxLayout.
I also use the setStroke method to set the drawing to the StrokeDrawer (this method also calls the update() function in the class, which calls its paintEvent, which should take care of actually drawing the QPolygonF).
Initially, I tried to do addWidget by directly using the QPolygonF but that didn't work. That's why I'm using this StrokeDrawer class (which just displays the drawing, it doesn't even allow making changes to it).
By debugging the code on QtCreator, everything works fine until the addWidget line, where nothing happens. I mean, even if the drawing is not being correctly displayed, it should at least show a small, white, 50x50 square, or am I missing something here?
Some code for StrokeDrawer:
void StrokeDrawer::setStroke(QPolygonF g)
{
gesture = g;
update();
}
void StrokeDrawer::paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QPainter pait(this);
if (!gesture.empty())
pait.drawPolyline(gesture);
}

SFML 2.1 - Detecting a single mouse click and changing a texture

What I'm trying to do is:
I have a sprite. And this sprite has 3 textures. First texture, let's call it "not-visited", is the initial one. Now, when I click on the sprite it should change it texture to "clicked" meaning that the sprite was clicked. And this texture should remain until I click somewhere else on the screen. When I do this, the texture should change to the third one, "visited". And if I click on the sprite again it should change its texture to "clicked"...
So, I should have here a bool function called "ClickDetected" and its code should do this:
if (event.type == Event::MouseButtonReleased && event.mouseButton.button == Left)
if (mouse_over_sprite)
return true;
Right? OK, then, I have a class Node. This class has a method "Clicked":
bool Clicked {
if (ClickDetected) { return true; }
}
I know it may be unnecessary, but let it stay for now. Next, in Update() method of this class:
if (Clicked) { change_texture_to_"clicked"; if (!visited) visited=true; }
else {
if (!visited) change_texture_to_"not-visited";
if (visited) change_texture_to_"visited";
}
But this doesn't work how it should. When I click on sprite texture changes to "clicked". When I release the mouse button the "clicked" texture stays... But when I move the mouse texture changes to "visited". And it should remain "clicked", until I click somewhere else. I tried to use a while loop here, but it didn't work. What can I do?
I've put this code to Graph class (method Update()) to manage many Nodes. I've change it a little bit and now it works fine.

opengl glutWireTorus artifact

I am working on a small animation of a sinewave being generated by a moving circle similar to this gif.
However I'm having a weird issue with using glutWireTorus for the circle. Even when I comment out all the other drawing code and leave the torus moving along the z axis alone, I get flashing lines on the inside of it:
This is the display function where everything is drawn. I use the display function as my idle function, also, I checked if that was the issue by creating an idle function and putting my update code there but it still persisted.
void display(void)
{
glClearColor(0.f,0.f,0.f,0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the color buffer
and the depth buffer
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f); //Push everything back 5 units into the scene,
otherwise we won't see the primitive
camera();
//yPrev = myCircle.y;
glPushMatrix();
glTranslatef(0.0f,0.0f,t);
glutWireTorus(0.02,1,100,100);
glPopMatrix();
DrawAxes();
glutSwapBuffers(); //swap the buffers
glFlush();//Flush the OpenGL buffers to the window
t-=0.002;
if (t < -T)
{
t = 0;
}
}
Uh, interesting, I run into the same problem.
Here is the picture using parameter
glutWireTorus(/*innerRadius*/0.3, /*outerRadius*/0.5, /*nsides*/32, /*rings*/32);
another picture using parameter
glutWireTorus(/*innerRadius*/0.3, /*outerRadius*/0.5, /*nsides*/64, /*rings*/128);
We don't know why without glutWireTorus function implementation, but we can implements our own torus, or maybe someone can explain it?