Rotating cube only rotates when window resized

hi i am trying to create a program where a cube rotates, but it only rotates when the window is resized. im 99% positive it has to do with the main while loop in the main function. here is my code:

#include "gl_core_4_3.h"
#include "matrixfuncs.h"
#include <stdio.h>
#include <stdlib.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include <string.h>
#include <math.h>

GLuint yaxis = 0, xaxis = 0;

GLuint vao, buffers[2], matrixloc;
GLfloat matrixy[] = {1, 0, 0, 0, 
0, 1, 0, 0, 
0, 0, 1, 0, 
0, 0, 0, 1};
GLfloat matrixx[] = {1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};


Display                 *dpy;
Window                  root;
GLint                   att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo             *vi;
Colormap                cmap;
XSetWindowAttributes    swa;
Window                  win;
GLXContext              glc;
XWindowAttributes       gwa;
XEvent                  xev;

void display();
void init();
void rotate();

int main(int argc, char **argv) {

 dpy = XOpenDisplay(NULL);
 
 if(dpy == NULL) {
        printf("
	cannot connect to X server

");
        exit(0);
 }
        
 root = DefaultRootWindow(dpy);

 vi = glXChooseVisual(dpy, 0, att);

 if(vi == NULL) {
        printf("
	no appropriate visual found

");
        exit(0);
 } 
 else {
        printf("
	visual %p selected
", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
 }


 cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

 swa.colormap = cmap;
 swa.event_mask = ExposureMask | KeyPressMask;
 
 win = XCreateWindow(dpy, root, 0, 0, 600, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);

 XMapWindow(dpy, win);
 XStoreName(dpy, win, "Testing Transformations");
 
 glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
 glXMakeCurrent(dpy, win, glc);

	init(); 
 
 while(1) {
        XNextEvent(dpy, &xev);

	        
	
        if(xev.type == Expose) {
                XGetWindowAttributes(dpy, win, &gwa);
                glViewport(0, 0, gwa.width, gwa.height);
		rotate();
                display(); 
                glXSwapBuffers(dpy, win);
        }
                
        if(xev.type == KeyPress) {
                glXMakeCurrent(dpy, None, NULL);
                glXDestroyContext(dpy, glc);
                XDestroyWindow(dpy, win);
                XCloseDisplay(dpy);
                exit(0);
        }
    } /* this closes while(1) { */
} /* this is the } which closes int main(int argc, char *argv[]) { */

void display()
{
	if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
	    {
	        printf("error with ogl");
	        exit(1);
	    }

	glClear(GL_COLOR_BUFFER_BIT);
	
	glEnable(GL_PRIMITIVE_RESTART);
	glPrimitiveRestartIndex(1000);
		
	glBindVertexArray(vao);
	glDrawElements(GL_TRIANGLE_STRIP, 17, GL_UNSIGNED_SHORT, NULL);
	
	glDisable(GL_PRIMITIVE_RESTART);
	
	glFlush();
}

void init()
{
		if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
	    {
	        printf("error with ogl");
	        exit(1);
	    }
	
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);	
	
	glClearColor(0, 1, 0, 1);
	const char *fshader =
	    	    "#version 430 core
"
	    		"out vec4 fColor;
"
	    		"void main()
"
	    	    "{
"
	    		"fColor = vec4(1, 0, 0, 1);
"
	    	    "}
";

	    const char *vshader =
	    	    "#version 430 core
"
		"uniform mat4 Matrix;
"
	    	    "layout (location = 0) in vec4 vPosition;
"
	    		"void main()
"
	    	    "{
"
	    	    "gl_Position = Matrix * vPosition;
"
	    		"}
";

	    GLuint prog = glCreateProgram();

	    GLuint vert = glCreateShader(GL_VERTEX_SHADER);
	    GLuint frag = glCreateShader(GL_FRAGMENT_SHADER);

	    GLint vlen = (GLint)strlen(vshader);
	    GLint flen = (GLint)strlen(fshader);

	    glShaderSource(vert, 1, &vshader, &vlen);
	    glShaderSource(frag, 1, &fshader, &flen);
	    glCompileShader(vert);
	    glCompileShader(frag);


	    glAttachShader(prog, vert);
	    glAttachShader(prog, frag);
	    glLinkProgram(prog);
	    glUseProgram(prog);

	matrixloc = glGetUniformLocation(prog, "Matrix");
	
	GLfloat vertices[] = {
	-.5, -.5, -.5, 1,
	-.5, -.5, .5, 1,
	-.5, .5, -.5, 1,
	-.5, .5, .5, 1,
	.5, -.5, -.5, 1,
	.5, -.5, .5, 1,
	.5, .5, -.5, 1,
	.5, .5, .5, 1
	};
	
	GLushort cubeindices[] = {
	0, 1, 2, 3, 6, 7, 4, 5, 
	1000,
	2, 6, 0, 4, 1, 5, 3, 7
	};
	
	glGenBuffers(2, buffers);
	
	glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
	
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof cubeindices, cubeindices, GL_STATIC_DRAW);
		
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void *)0);
	glEnableVertexAttribArray(0);	
}

void rotate()
{
		if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
	    {
	        printf("error with ogl");
	        exit(1);
	    }
	GLfloat matrixresult[16];
	
	matrixy[0] = cos(yaxis);
	matrixy[2] = sin(yaxis);
	matrixy[8] = (-1) * sin(yaxis);
	matrixy[10] = cos(yaxis);

	matrixx[5] = cos(xaxis);
	matrixx[6] = sin(xaxis);
	matrixx[9] = (-1) * sin(xaxis);
	matrixx[10] = cos(xaxis);

	Mult4fv(matrixy, matrixx, matrixresult);
	glUniformMatrix4fv(matrixloc, 1, GL_FALSE, matrixresult);
	yaxis += 2;
	xaxis++;
}

XNextEvent() blocks until an event is received. If you aren’t receiving events, nothing will be executed.

My first recommendation is not to try to write an application using raw Xlib. Use GLUT, GLFW, SDL, SFML, GTK, Qt, Motif, wxWidgets or whatever. Failing that, look at the source code for one of those toolkits to see how to write an event loop which can handle timers or other event sources.

In any case, none of this is specific to OpenGL, so it’s off-topic for this forum.

i would not say it is off-topic for this forum. this is the linux section, so any problem concerning linux and opengl can be posted here.
especially this one because, apparently, the program posted above is a linux example from the opengl wiki.

anyway, there is another source there which is more appropriate for animations:

http://www.opengl.org/wiki/Programming_OpenGL_in_Linux:_Programming_Animations_with_GLX_and_Xlib

That has exactly the same problem as the original code, i.e. it blocks until an event is received.

FWIW, the way that freeglut does it is to only call XNextEvent() while XPending() returns non-zero. Then it checks for timers, then runs any idle callback, then (if no idle callback is installed), select()s on the descriptor for the connection to the X server (with a timeout determined by the next timer event).

nope, it doesn’t. the example i linked uses XCheckWindowEvent (), which doesnt block anything.

My mistake. I was looking at the program fragment at the top of the page (which, on further reading, is given as an example of the problem).

Even so, the program itself is also a fairly good example of how not to do event handling with Xlib.

Realistically, the OpenGL wiki shouldn’t be discussing Xlib, with the possible exception of initialisation (visual selection, context creation, etc). I say “possible” because most of the people who actually need to know that stuff already know it.

About the only people who need to know how to use Xlib are the people writing GUI toolkits (in much the same way that about the only people who need to know assembly language are the people writing compilers).

Everyone else will get better results with less effort if they just use a toolkit (either a full GUI toolkit such as GTK or Qt, or a “graphics window” toolkit such as GLUT, SDL or GLFW). The code will be more portable and better behaved, it will continue to work if Xlib gets eliminated in favour of XCB (or Wayland, Mir, etc), and so on.

Realistically, the OpenGL wiki shouldn’t be discussing Xlib, with the possible exception of initialisation (visual selection, context creation, etc).

Um, why not? As long as it’s good information and represents good practice, I see no reason why the wiki shouldn’t host a code example of how to use XLib to initialize OpenGL and deal with animation. If the example code has bugs in it, by all means, use the wiki as it’s intended: fix them.

I certainly don’t know enough about XLib to do so :wink:

I say “possible” because most of the people who actually need to know that stuff already know it.

… that’s patently absurd. The people “who actually need to know” are the people who want to know.

I encourage the use of cross-platform libraries where possible. I’ve even written several recommendations on the Wiki, discouraging people from manually loading OpenGL functions and linking them directly to several loading libraries. But that doesn’t mean I want the knowledge of how to properly handle OpenGL functions to be hidden away. To be something that only those select few “who actually need to know” by some arbitrary metric can actually discover.

There is absolutely nothing to be gained by hiding this knowledge from the world. Yes, encourage people not to do it, and tell them why they should use cross-platform solutions. But that doesn’t mean you actively prevent them from learning the manual approach.

in much the same way that about the only people who need to know assembly language are the people writing compilers

Ah, so it’s in the way that it’s not true at all.

Most people don’t need to write assembly language. But any C/C++ programmer who is interested in low-level performance, at some point, is going to have to be able to read the disassemble of some function and then decide if there are ways to optimize that. Those ways might be to write inline assembly, but they may also be to restructure the C/C++ code to generate better code.

Which you can’t do unless you know that it’s generating bad code. Which requires being able to read and understand it.

and the reason is…?

Realistically, the OpenGL wiki shouldn’t be discussing Xlib,

because you, personally, don’t like xlib or don’t use xlib?
currently, the page Programming OpenGL in Linux: GLX and Xlib - OpenGL Wiki has 95k hits. not all generated by myself.
in my opinion, that shows that people are interested in xlib. and knowing xlib helps you to understand qt or glut in a better way.

with the possible exception of initialisation (visual selection, context creation, etc).

that doesnt make any sense at all. i show you how you can initialise an opengl window, but i dont show you how to use it in a program?

Everyone else will get better results with less effort if they just use a toolkit (either a full GUI toolkit such as GTK or Qt, or a “graphics window” toolkit such as GLUT, SDL or GLFW).

i have been thinking about making a qt tutorial for a while, but that would not fit on a single page like the xlib example, and it would need much more work to do it in a comprehensible way.
we have had that discussion in another thread. qt needs a good amount of c++ knowledge, xlib does not.

The code will be more portable

ofc.

and better behaved,

how so?

it will continue to work if Xlib gets eliminated in favour of XCB (or Wayland, Mir, etc), and so on.

i have not much info about xcb etc. but i would be much surprised if there is no backward compatibility.

in my opinion, that shows that people are interested in xlib.

That could show a lot of things. It should show that people can easily find that page from the wiki. Or that Google led them there when they Googled “Linux OpenGL Programming.” Because apparently, that’s what you get when you Google that (which is kinda sad). The fact that Google quickly finds a page doesn’t mean that the page is necessarily what they wanted.

Don’t confuse popularity with quality.

and knowing xlib helps you to understand qt or glut in a better way.

No it doesn’t. As someone who understands Qt and GLUT, my understanding of them would not be enhanced in any way by knowing anything about XLib. Nor has my understanding of them been enhanced by knowing Win32. GLUT especially hides both APIs very well.

A good abstraction makes learning about the lower levels pointless because it abstracts them.

i didnt say anything about quality at all. i was saying that people seem to be interested about programming opengl with xlib.
if someone googles something, it shows clearly that he is interested in that topic. about the wiki page being on top of google-
well, i wouldn’t boast with it, but it doesn’t make me sad either. btw, back to quality- when i look at the bottom of the page,
it seems that it has received more good than bad ratings.

A good abstraction makes learning about the lower levels pointless because it abstracts them.

thats completely wrong. even if you program just in plain c, there are some things that you should know, even when
you don’t have to deal with them directly. memory management, for example: you should know that local variables
are created on the stack. you should know that for example writing to an array beyond its limits doesn’t necessarily cause
a segmentation fault if the array is a local variable and therefore on the stack, but may change other local variables.

you should know that something as simple as realloc() behaves differently on linux and windows. on linux, you may get
exactly the same pointer in return, while on windows, the original pointer is always free’d, a new pointer is alloc’ed, and
the original data are memcpy’d to the new pointer, which results in poor performance.

and, for example, you should know why

typedef struct
{
char c1, c2;
int i1, i2;
} S1;

is better than

typedef struct
{
char c1;
int i1;
char c2;
int i2;
} S2;

even though your compiler probably will optimize the structure internally.

if someone googles something, it shows clearly that he is interested in that topic.

The whole point of that Google link is that the person wasn’t necessarily Googling about XLib. They were Googling about Linux OpenGL programming; it just so happened that the first link talked about XLib.

See the difference? Someone who has no idea about what XLib even is having it given to them. So you can’t say that the page being high on Google means that people are “interested in” XLib; they’re just having it shoved into their faces.

when i look at the bottom of the page,
it seems that it has received more good than bad ratings.

And if the ratings of random users were indicative of quality, this might mean something.

thats completely wrong. even if you program just in plain c, there are some things that you should know, even when
you don’t have to deal with them directly.

C has been accused of many things. Being a “good abstraction” is not one of them. But then, that’s not C’s purpose and it never has been. It’s purpose is to be a higher-level assembly, and that necessitates not being a “good abstraction” over assembly. It’s leaky by design.

Also, a lot of those things you mention are not something you “need” to know. They’re useful, but hardly mandatory for being able to use the language. I certainly don’t waste any thought on the memory layout of data structures unless I’m trying to match std140 in OpenGL or a file format or something.

Qt by contrast is a good abstraction over platform-specific windowing systems. You can be a skilled Qt user without having any knowledge of how the underlying platform-specific windowing system works. You can’t always ignore platform-specifics, but you can in the vast majority of your code.

on linux, you may get
exactly the same pointer in return

No you don’t. You sometimes do if the memory allocator can expand the memory of your allocation in-situ. If there is not enough room to do so in that allocation block, you will get a new pointer.

i dont see any difference between “you may get the same pointer” and “you sometimes get the same pointer”

maybe some native english speaker can clarify if “you may get the same pointer” means “you always get the same pointer”.

Using Xlib to write anything other than a toolkit isn’t good practice. It’s just too low level to be used directly for writing applications.

I agree that the parts which relate to OpenGL (i.e. glX* functions and any Xlib functions which directly related to them) are relevant. But that doesn’t include X event handling.

You can’t meaningfully teach someone X11 programming in a page or two. You can either deal with the OpenGL-specific parts and let them get the rest elsewhere (unfortunately, X is old enough that most of the decent guides are only available in hardcopy form), or provide half-baked (at best) examples which will misinform them.

It’s just too low level to be used directly for writing applications.

Some people say the same thing about Win32. That doesn’t make them right.

You can’t meaningfully teach someone X11 programming in a page or two.

And it’s not trying to; it’s just explaining part of X11 programming.

You can either deal with the OpenGL-specific parts and let them get the rest elsewhere (unfortunately, X is old enough that most of the decent guides are only available in hardcopy form), or provide half-baked (at best) examples which will misinform them.

Assuming that this is true (and I have no knowledge of X11, so I have no idea one way or the other), then this falls under not being “good information,” since it misinforms people about how to make the system work. If you’re claiming that the tutorial is doing event handling wrong, then fix it so that it’s doing it right.

Failing that, you could at least explain how it’s wrong, rather than simply declaring it to be so.

Reasons, plural. Enough of them that a complete list would be longer than the program. Obvious flaws include: synchronous XGetWindowAttributes() instead of handling ConfigureNotify events, continuing to render if the window is unmapped (minimised), handling one event per redraw rather than all pending events, no error handling.

But the more general issue is “that’s not how you do event processing”. As soon as you try to extend it to handle more than one type of event, you’ll need to restructure it. If you want to be able to pause the animation (in the sense of not continually redrawing) or skip redraw when the window is minimised, you’ll need to restructure it. Etc.

I don’t use it directly unless I absolutely have to. Look at the source (and/or revision logs) for an existing toolkit. Getting an X event framework working properly involves a lot of effort (and testing), and I’d rather not go through that unnecessarily.

How to do event handling isn’t specific to OpenGL. That code would be the same if you were using the core X protocol or XRender. And if you’re doing it properly, it doesn’t look anything like that example (the source code is available for Xt, GTK, Qt, and wxWidgets; along with several less popular toolkits, most of which never became mainstream because their authors couldn’t stomach the years of incremental refinement required to make an X11 toolkit handle all of the messy edge cases).

[QUOTE=RigidBody;1253465]i have been thinking about making a qt tutorial for a while, but that would not fit on a single page like the xlib example, and it would need much more work to do it in a comprehensible way.
[/QUOTE]
You’d be lucky to fit a decent Xlib example on 20 pages, assuming that you’re offering some explanation as to the whys and wherefores, rather than just dumping code.

If C++ is the problem, use GTK.

Error handling, performance/efficiency, overall integration with the window manager and desktop environment. The only reason the example doesn’t have concrete, readily-observable flaws is that it does so little. As soon as you try to add anything to it, the lack of a more generalised event mechanism will bite you.

XCB is even lower-level than Xlib; it doesn’t try to be anything more than an interface to the wire protocol. Most of the existing toolkits and libraries are being (or have been) refactored to use it instead of (or as an alternative to) Xlib. In libraries which support both, the XCB code tends to see real-world use while the Xlib version gets unit tests if you’re lucky, resulting in the Xlib version suffering from bit-rot.

The bigger question is whether X11 itself gets displaced by Wayland, or whether Wayland just ends up being the driver API used by the X server (I don’t believe they can coexist horizontally). If it’s the former, code which uses Xlib directly isn’t going to be much use.

frankly, i don’t care a bit about all that stuff.

i don’t care if checking for configure events is better than using xgetwindowattributes. just because i haven’t ever come across any problems using xgetwindowattributes.

i don’t care that rendering continues when minimized- because of the usleep(), the program causes a cpu load of less than 1% anyway.

it is simple, and it seems to work. it is neither meant to be an xlib tutorial, nor an opengl tutorial. it simply shows how to set up an opengl
capable window in linux, so the focus is not on the event loop anyway.

it is a tutorial. a tutorial is the beginning of learning to program something, not the end.
btw, if you think something should be changed in the code, go ahead and change it. it is a WIKI.
if you think something should be added, please, go wild, and add it.
but i predict that nobody will read a 20 page tutorial.

and if you want people to use qt- you are free to add a qt tutorial to the wiki.
will be much appreciated, i suppose.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.