PDA

View Full Version : rotating cube only rotates when window resized



sandbucket
08-01-2013, 09:00 AM
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("\n\tcannot connect to X server\n\n");
exit(0);
}

root = DefaultRootWindow(dpy);

vi = glXChooseVisual(dpy, 0, att);

if(vi == NULL) {
printf("\n\tno appropriate visual found\n\n");
exit(0);
}
else {
printf("\n\tvisual %p selected\n", (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\n"
"out vec4 fColor;\n"
"void main()\n"
"{\n"
"fColor = vec4(1, 0, 0, 1);\n"
"}\n";

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

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++;
}

GClements
08-01-2013, 03:55 PM
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.
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.

RigidBody
08-02-2013, 01:56 AM
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_Animation s_with_GLX_and_Xlib

GClements
08-02-2013, 02:51 PM
anyway, there is another source there which is more appropriate for animations:

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).

RigidBody
08-03-2013, 01:25 PM
That has exactly the same problem as the original code, i.e. it blocks until an event is received.

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

GClements
08-03-2013, 09:55 PM
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.

Alfonse Reinheart
08-04-2013, 02:15 AM
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 ;)


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.

RigidBody
08-04-2013, 03:59 AM
Even so, the program itself is also a fairly good example of how not to do event handling with Xlib.

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 http://www.opengl.org/wiki/Programming_OpenGL_in_Linux:_GLX_and_Xlib 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.

Alfonse Reinheart
08-04-2013, 04:11 AM
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 (https://www.google.com/search?q=Linux+OpenGL+Programming&ie=utf-8&oe=utf-8&aq=t) (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.

RigidBody
08-04-2013, 04:54 AM
Don't confuse popularity with quality.

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.

Alfonse Reinheart
08-04-2013, 12:20 PM
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.

RigidBody
08-04-2013, 01:08 PM
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".

GClements
08-04-2013, 02:11 PM
Um, why not? As long as it's good information and represents good practice,
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 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.
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.


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.
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.

Alfonse Reinheart
08-04-2013, 02:51 PM
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.

GClements
08-04-2013, 02:59 PM
and the reason is...?
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.


because you, personally, don't like xlib or don't use xlib?
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.


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?
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).


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.

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.


qt needs a good amount of c++ knowledge, xlib does not.
If C++ is the problem, use GTK.


how so?
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.


i have not much info about xcb etc. but i would be much surprised if there is no backward compatibility.
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.

RigidBody
08-05-2013, 04:38 AM
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.