Draw cube if any key clicked opengl 3d - opengl

i need help with drawing cube by the keyboardup method , For example if i clicked 'a' then a cube must be displayed.
what i have reached so far
void KeyUp(unsigned char key, int x, int y) {
if (key == 'a') {glutSolidCube(5);}
glutPostRedisplay();
}
but nothing appear in the opengl.
want to let you know that when i put glutSolidCube(5); in the display method it works.

Toggle a "display cube" Boolean in your keyboard callback (and keep the glutPostRedisplay()) and (selectively) draw the cube in your display callback.

but nothing appear in the opengl.
Because after drawing glutSolidCube(5) in keyboard method, you clear the viewport in the display method. Thus everything drawn is wiped out.
when i put glutSolidCube(5); in the display method it works.
It is working there because you are probably drawing at the right location (i.e.) after clearing the viewport and before posting.
Declare a global boolean and set it true at key callback method.
Use the boolean to decide if you have to draw the cube or not in your display mathod.

Related

Preserve DrawingArea 'image' on draw signal

I am trying to make simple square where you could paint with mouse. Problem is, whenever draw signal is happens, cairo surface seems to be cleared entirely. I understand this because after first queue_draw() white background is gone and I see my GTK theme color (which is grey).
I thought I could save surface or context, but you can't just create empty surface in cairo, and I can't create it using this->get_window()->create_cairo_surface() (where this is object of class inherited from Gtk::DrawingArea) because when constructor is called, widget isn't attached to any window yet, so it is a null pointer. I mean, I could create some public function called you_are_added_to_window_create_cairo_surface() but I'd really like not to do this.
So I really don't know what to do and what I don't understand about cairo.
How do I preserve, or save 'canvas' current state, so whatever is actually being drawn is just applied on existing drawing?
Here is callback function of my class:
bool MyDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context> & cr) {
/* clear and fill background with white in the beginning */
if (first_draw) {
cr->save();
cr->set_source_rgb(255.0, 255.0, 255.0);
cr->paint();
cr->restore();
first_draw = false;
}
cr->save();
cr->set_source_rgb(0.0, 0.0, 0.0);
cr->begin_new_path();
while (!dots_queue.empty()) {
auto dot = dots_queue.front();
cr->line_to(dot.first, dot.second);
dots_queue.pop();
}
cr->close_path();
cr->stroke();
cr->restore();
return false;
}
Remove first_draw and instead of dots_queue.pop(), just iterate over the dots_queue and redraw all of them each time.
The draw function is not meant for "I want to add some drawing". Instead, it is "hey, the windowing system has no idea what should be drawn here, please fill this with content". That's why the cairo surface is cleared.
So while storing all actions works, it's really not ok if you are trying to have your program save your drawings, you will have to use second surface to save everything on.
My solution combines both answers of Uli Schlachter.
First, I have structure, in which I store last drawing action, since last Button Press, and until Button Release. This allows me to show things such as lines in real time, while keeping canvas clean of it.
Second, I store everything drawn on canvas on a surface, which is created like that:
// this - is object of class, derived from DrawingArea
auto allocation = this->get_allocation();
this->surface = Cairo::ImageSurface::create(
Cairo::Format::FORMAT_ARGB32,
allocation.get_width(),
allocation.get_height()
);
Then, on each draw signal, I restore it like that:
cr->save();
cr->set_source(surface, 0.0, 0.0);
cr->paint();
cr->restore();
Whenever I want to save surface, i.e. apply drawing on to canvas, I do the following:
Cairo::RefPtr<Cairo::Context> t_context = Cairo::Context::create(surface);
t_context->set_source(cr->get_target(), -allocation.get_x(), -allocation.get_y());
t_context->paint();
Here is the important moment. Without adjusting for the allocation coordinates, your canvas is going to slide away on each surface save and restore.
With that, I can easily keep my drawings on canvas, load canvas from file (because I am using ImageSurface), or save it to the file.

Change scenes in game openGL

i'm continue my dialog with openGL and c++ and for a now i want to make "scenes", that will change each other. for example screen with button "go next", i push button and then begin game.
What is the best approach with openGL in c++ for this ? The main question is what make with glut initialization commands like :
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(0,0);
glutCreateWindow("Puzzle quest!");
// Registration
glutDisplayFunc(Draw);
glutIdleFunc(Draw);
Is i need to implement this method in both classes, or only in one, and then only "show start button/ hide game functionality, hide start button/ show game functionality+start timer" ?
I do not mess with screen settings during scene/mode changes. Screen setings is changed on resize of the OpenGL window not on some button event...
You have to write your visualization and UI logic stuff dependent on some variables for example:
enum _game_screens_enum
{
_game_screen_main_menu=0,
_game_screen_game,
_game_screen_game_over,
_game_screen_help,
_game_screen_intro,
_game_screen_redefine_keys,
_game_screen_high_score,
_game_screen_exit,
};
int screen=_game_screen_main_menu;
Now in draw,update and UI handling functions just add appropriate ifs for example:
void draw()
{
if (screen==_game_screen_main_menu)
{
// draw main menu ...
}
else if (screen==_game_screen_game)
{
// draw in game screen stuff...
}
else ...
}
And that is it ...
Are you looking for a fade effect or some sort of transition where they are blended? Fade effect should be easy if using alpha channel... enable blend... draw black quad in front of everything as its alpha value increases from 0 to 1 over whatever time frame you want the fade to occur. The fade in would be the opposite. Not sure about the blending scenes effect... maybe accum buffer, or read pixels and then draw pixels if you can change alpha values.
Otherwise, glutDisplayFunc is the correct way to switch between scenes/drawing functions.
Try just fading effect, it could be of great help.
You should only initialize glut once.
Normally, the display and idle callbacks would do different things depending on what state you're in.
On a high level:
void idle()
{
if (showingMenu)
menu.idle();
else
currentScene.idle();
}
You could do it by switching functions, but I think that makes debugging more difficult.
(You should probably not use the same function for drawing and idling, though.)

3d object wont update in for loop

I am trying to rotate a 3d object but it doesnt update when applying transforms in a for loop.
The object jumps to the last position.
How does one update a 3d object's position in a sequence of updates if it wont update in a for loop?
Just calling glTranslate, glRotate or such won't change things on the screen. Why? Because OpenGL is a plain drawing API, not a scene graph. All it knows about are points, lines and triangles that draws to a pixel framebuffer. That's it. You want to change something on the screen, you must redraw it, i.e. clear the picture, and draw it again, with the changes.
BTW: You should not use a dedicated loop to implement animations (neither for, nor while, nor do while). Instead perform animation in the idle handler and issue a redraw event.
I reckon you have a wrong understanding what OpenGL does for you.
I'll try to outline:
- Send vertex data to the GPU (once)
(this does only specify the (standard) shape of the object)
- Create matrices to rotate, translate or transform the object (per update)
- Send the matrices to the shader (per update)
(The shader then calculates the screen position using the original
vertex position and the transformation matrix)
- Tell OpenGL to draw the bound vertices (per update)
Imagine programming with OpenGL like being a web client - only specifying the request (changing the matrix and binding stuff) is not enough, you need to explicitly send the request (send the transformation data and tell OpenGL to draw) to receive the answer (having objects on the screen.)
It is possible to draw an animation from a loop.
for ( ...) {
edit_transformation();
draw();
glFlush(); // maybe glutSwapBuffers() if you use GLUT
usleep(100); // not standard C, bad
}
You draw, you flush/swap to make sure that what you just drew is sent to the screen, and you sleep.
However, it is not recommended to do this in an interactive application. The main reason is that while you are in this loop, nothing else can run. Your application will be unresponsive.
That's why window systems are event-based. Every few miliseconds, the window system pings your app so you can update your state, for example do animation. This is the idle function. When the state of your program changed, you tell the window system that you would like to draw again. It is then up the the window system to call your display function. You do your OpenGL calls when the system tells you to.
If you use GLUT for communicating with the window system, this looks like the code below. Other libraries like GLFW have equivalent functions.
int main() {
... // Create window, set everything up.
glutIdleFunc(update); // Register idle function
glutDisplayFunc(display); // Register display function
glutMainLoop(); // The window system is in charge from here on.
}
void update() {
edit_transformation(); // Update your models
glutPostRedisplay(); // Tell the window system that something changed.
}
void display() {
draw(); // Your OpenGL code here.
glFlush(); // or glutSwapBuffers();
}

display lists wont run

I am trying to create a tool that will draw a shape in openGL and then modify the values of the properties of that shape in a windows form. So if my shape is a rectangle, I will create a form that will allow the user to control the size, color etc of the rectangle. I have written the openGL code in managed c++ and the form in c#, and as some of these shapes got more complicated I decided to make display lists for them (for both performance and predictability purposes).
I define the display list in the constructor for the shape and I call the display lists in the render method.
My issue is that my display lists won't run at all. The parts that I render outside of a display list will be rendered, but the parts inside the display list will not be rendered.
Here's some sample code of my process:
//c# side
GLRectangle rect
public CSharpRectangle() {
rect = new GLRectangle();
}
//managed c++ side
public GLRectangle() {
width = 50;
height = 50;
//initialize more values
rectDL = glGenLists(1);
glNewList(rectDL, GL_COMPILE);
renderRect();
glEndList();
}
public render() {
//Draw border
glBegin(GL_LINE_LOOP);
glVertex2f(0, 0);
glVertex2f(width, 0);
glVertex2f(width, height);
glVertex2f(0, height);
glEnd();
//Draw interior
glCallList(rectDL);
}
private renderRect() {
glRectf(0,0,width,height);
}
In this example, the border of the rectangle would be rendered, but the rectangle itself won't be rendered... if I replace the display list with simply a method call, the rectangle is rendered fine. Does anyone know why this might be happening?
I want to give my 2 cents.
The code in your question seems correct to me, so probably there something else in your application that make your display list not runnable.
The only thing I can think is there's no current context when compiling the display list (indeed when executing GlRectangle constructor). So, is that routine executed in the same thread which have called glMakeCurrent? Is that routine called after glMakeCurrent?
Further, check with glGetError after each OpenGL routine in order to validate the operation. In the case it returns an error, you can know what's wrong in your code..
The reason you may not get what you want is simply because it isn't there anymore. In time I was reading openGL Red book, I've noticed that display lists were deprecated in openGL 3.1 and higher (means simply removed) and googling for that confirmed it. I don't remember reason anymore, but I believe because it was messing with VAOs and VBOs. So if you are using higher than opengl 3.1 you won't get display lists anymore.

Bspline should be redrawn, without deleting all of the rest of the window

In my mousefunc i call a function bspline. It works like this:
With your mouse you can put controllpoints and according to these points the bspline is drawn.So if you have drawn three points a curve between those points is displayed. By adding another point the old curve disappears and a new one appears. This new one lies now between the four points.This works just fine. BUT: This bspline curve is only displayed in one viewport.This viewport has a black border. This border disappears when my bspline is redrawn. This happens because of calling glutPostredisplay. Because in my glutDisplayFunc i call glClear(GL_COLOR_BUFFER_BIT). So it is the natural thing to happen. If i delete the glClear(GL_COLOR_BUFFER_BIT) in my displayfunc the border stays but the old curves stay too. Even if i say that the border should be redrawn nothing happens. I cant think of an alternative. Would appreciate it if you could help me...
In OpenGL the usual approach is to rerender the whole scene whenever some part of it changes. In your case changing the control points of the B-Spline should trigger a redisplay of the scene instead of perform drawing operations in the mouseclick handler function.
OpenGL has no geometry persistency, it just draws primitves to a pixelbased framebuffer. And as such you must use it.
To clarify, some pseudocode:
BSpline *b_spline;
void on_mouseclick(int x, int y)
{
float x_, y_;
transform_screen_to_scene(x,y, &x_, &y_);
bspline_add_control_point(b_spline, x_, y_);
trigger_redisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
setup_viewport_and_projection();
bspline_draw(b_spline);
swap_buffers();
}