Related
I have two draw functions - "drawComponents" and "drawSignals" which look as follows:
static void drawComponents(ARdouble trans1[3][4], ARdouble trans2[3][4], int r, int g, int b )
{
for (int i = 0; i < numComponents; i++){
glPushMatrix(); // Save world coordinate system.
glTranslatef(0.0f, 0.0f, 0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &(components[i].combCoords[0]));
glColor4ub(r, g, b, 0);
glDrawElements(GL_LINES, components[i].nIndeces, GL_UNSIGNED_INT, &(components[i].combIndeces[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix(); // Restore world coordinate system.
}
}
static void drawSignals(ARdouble trans1[3][4], ARdouble trans2[3][4], int r, int g, int b)
{
for (int i = 0; i < numSignals; i++)
{
glPushMatrix(); // Save world coordinate system.
glTranslatef(0.0f, 0.0f, 0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, signal[i].combCoords);
glColor4ub(r, g, b, 0);
glDrawElements(GL_LINES, signal[i].nIndeces, GL_UNSIGNED_INT, &(signal[i].combIndeces[0]));
glPopMatrix();
}
}
These functions work fine if i just call the directly in the MainLoop, however I want to call them based on user input. So if the "1" key is pressed then the drawComponents will be called, and if the "2" key is pressed the the drawSignals function will be called.
To do this I have the following keyEvent function:
static void keyEvent(unsigned char key, int x, int y)
{
switch (key) {
case '1':
drawComponents(config->trans, config->marker[3].trans, 255, 0, 0);
break;
case '2':
drawSignals(config->trans, config->marker[3].trans, 0, 0, 255);
break;
}
}
I thought would work fine, however with this function, nothing happens when I press the keys. Anyone have any suggestions as to where I'm going wrong
I try to design a scene with 3 spheres and one line horizontal as equator. I got to draw the 3 spheres but I don't know why the line is not draw.
This is my code, for if you can see where I'm wrong:
#include <GL/gl.h>
#include <GL/glut.h>
void render(void);
void reshape(int w, int h);
int angle = 90;
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(50, 50);
glutInitWindowSize(800, 600);
glutCreateWindow("Planets");
glutDisplayFunc(render);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
void render(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
// Equator
glBegin(GL_LINES);
glColor3f(1,1,1);
glLineWidth(1);
glTranslated(0, 0, 0);
glVertex2f(0, 2);
glVertex2f(2,2);
glEnd();
// Sun
glPushMatrix();
glLoadIdentity();
glColor3f(1.0, 1.0, 0.0);
glTranslated(0, 0, -2);
glRotated(angle, 1, 0, 0);
glutWireSphere(.3, 20, 20);
glPopMatrix();
//Earth
glPushMatrix();
glLoadIdentity();
glColor3f(0.0, 0.0, 1.0);
glTranslated(0.7, 0, -2);
glRotated(angle, 1, 0, 0);
glutWireSphere(.15, 20, 20);
glPopMatrix();
// Moon
glPushMatrix();
glLoadIdentity();
glColor3f(1.0, 0.0, 1.0);
glTranslated(1, 0, -2);
glRotated(angle, 1, 0, 0);
glutWireSphere(.05, 10, 10);
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h) {
const double ar = (double) w / (double) h;
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
You specify a frustum that has the near clip plane at z=-2. Your intended line would be drawn at z=0, thus outside the projection volume, thereby clipped into non-rendering.
glTranslate(0,0,0) is a no-op BTW.
How is the reshape() function working in this code and how is it getting its parameter from glutReshapeFunc(reshape) without any parameter in reshape of glutReshapeFunc(reshape)?
What is the value of int x, int y in void keyboard (unsigned char key, int x, int y) function?
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
static int year = 0, day = 0;
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glPushMatrix();
glutWireSphere(1.0, 20, 16); /* draw sun */
glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
glTranslatef (2.0, 0.0, 0.0);
glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8); /* draw smaller planet */
glPopMatrix();
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case `d':
day = (day + 10) % 360;
glutPostRedisplay();
break;
case `D':
day = (day - 10) % 360;
glutPostRedisplay();
break;
case `y':
year = (year + 5) % 360;
glutPostRedisplay();
break;
case `Y':
year = (year - 5) % 360;
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
It appears that the glutReshapeFunc() function takes a pointer to a function; presumably, in fact, it is declared as something somewhat similar to:
void glutReshapeFunc(void (*function)(int x, int y));
Similarly, glutDisplayFunc() takes another pointer to a function, and glutKeyboardFunc() also takes a pointer to a function. When a function is specified by name without the function call parentheses after it, it reduces to 'pointer to a function' (or you can think of a bare function name as a pointer to the function body, like a bare array name is a pointer to the start of the array).
You'd have to read the manual to discover the purpose of the x and y parameters to the keyboard() function. They aren't used by the code shown. They are likely the position of something, but which something is less than clear without reading the manual.
reshape and keyboard functions are used as so called callbacks. You're giving GLUT pointers to those functions, GLUT keeps those pointers and calls those function, with parameters, at the times as specified in the GLUT documentation.
About like that:
void (*display_callback)(void);
void (*reshape_callback)(int, int);
void (*keyboard_callback(unsigned char, int, int);
/* ... */
void eventloop(...)
{
while(...) {
if( keyboard_event )
keyboard_callback(keyboard_event->key, mouse_x, mouse_y);
if( window_reshaped )
reshape_callback(window->width, window->height);
if( needs_redraw )
display_callback();
}
}
Now regarding what's done in the reshape callback: Everything that's placed there in beginner tutorials is actually much better done in the display function. Setting the viewport, setting the projection I mean. Later you'll probably want to draw a HUD, some text or a minimap, or a split view. And once you've reached that point, a reshape function doing viewport and projection setup becomes a liability. So get rid of it now.
void display(void)
{
int const w = glutGet(GLUT_WINDOW_WIDTH);
int const h = glutGet(GLUT_WINDOW_HEIGHT);
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
glutWireSphere(1.0, 20, 16); /* draw sun */
glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
glTranslatef (2.0, 0.0, 0.0);
glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8); /* draw smaller planet */
glPopMatrix();
glutSwapBuffers();
}
I hope this will be a direct answer to this question.
The reshape function is a call back function which is called whenever size or shape of the application window changes. Reshape function takes 2 arguments,they are width and height of reshaped window. Mainly these parameters are used to set a new viewport.
This is the weirdest bug i have ever encountered. My triangle will not be drawn unless I Load the view matrix twice. What is going on?
If i remove one of the gfxSetCamera(&camera->t); nothing is drawn.
void shipDraw() {
glPushMatrix();
glMultMatrixf(ship->t.m);
glBegin(GL_TRIANGLES);
glColor3f(0,0,1);
glVertex3f(0, 0, -1);
glVertex3f(0, 1, 1);
glVertex3f(0, -1, 1);
glEnd();
glPopMatrix();
}
//Draw loop
while(!gfxUserQuit()) {
entUpdateAll();
gfxPrepare(1,1);
gfxSetCamera(&camera->t); //Have to call this twice!?!?
gfxSetCamera(&camera->t);
entDrawAll();
gfxPresent();
}
//Graphics code
void gfxPrepare(int clearColor, int clearStencil) {
//TODO parse args
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
void gfxPresent() {
glfwSwapBuffers();
}
void gfxSetCamera(transform *t) {
float *m = t->m;
float viewmatrix[16]={
m[0], m[4], m[8], 0,
m[1], m[5], m[9], 0,
m[2], m[6], m[10], 0,
-(m[0]*m[12] +
m[1]*m[13] +
m[2]*m[14]),
-(m[4]*m[12] +
m[5]*m[13] +
m[6]*m[14]),
-(m[8]*m[12] +
m[9]*m[13] +
m[10]*m[14]), 1};
glLoadMatrixf(viewmatrix);
}
EDIT: I have reduced the error down to the following
while(!gfxUserQuit()) {
entUpdateAll();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float *m = camera->t.m;
float viewmatrix[16]={
m[0], m[4], m[8], 0,
m[1], m[5], m[9], 0,
m[2], m[6], m[10], 0,
-(m[0]*m[12] +
m[1]*m[13] +
m[2]*m[14]),
-(m[4]*m[12] +
m[5]*m[13] +
m[6]*m[14]),
-(m[8]*m[12] +
m[9]*m[13] +
m[10]*m[14]), 1};
float viewmatrix2[16]={
m[0], m[4], m[8], 0,
m[1], m[5], m[9], 0,
m[2], m[6], m[10], 0,
-(m[0]*m[12] +
m[1]*m[13] +
m[2]*m[14]),
-(m[4]*m[12] +
m[5]*m[13] +
m[6]*m[14]),
-(m[8]*m[12] +
m[9]*m[13] +
m[10]*m[14]), 1};
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf(viewmatrix2);
entDrawAll();
glfwSwapBuffers();
}
If i remove the definition and initialization of 'float viewmatrix' nothing is draw to screen. If i restore it it renders as normal. Is this some memory corruption or something?
EDIT2 they are different.
How can i debug this?
EDIT3 I was calling glfwGetTime() without including the file. This is what was breaking it :O
What if, from your second example, you replaced "float viewmatrix...;" with "char tmpbuffer[16 * sizeof(float);" and then (assuming that did nothing) added "memset(tmpbuffer, 0, sizeof(tmpbuffer));"?
It sounds like something is corrupting your stack and that the first viewmatrix definition "fixes" it for the second one. What I'm suggesting should verify the problem is something along this line.
I'm reading the sample code for the bezier curve on the online version of opengl's tutorial.
I'm curious about how is resize being handled in the example cause I figure I might use it on my own version of this program , I placed my questions on its comments:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h); // what's GLsizei? Why is it called inside glViewPort?
glMatrixMode(GL_PROJECTION); // is it necessary to reset the projection matrix?
glLoadIdentity();
if (w <= h) // is this calculation universal, could I use it on another program?
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW); // why do I set to GL_MODELVIEW at the end?
glLoadIdentity(); // why does it get a reset?
}
Full code:
#include <stdlib.h>
#include <GL/glut.h>
GLfloat ctrlpoints[4][3] = {
{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},
{2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}};
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
}
void display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 30; i++)
glEvalCoord1f((GLfloat) i/30.0);
glEnd();
/* The following code displays the control points as dots. */
glPointSize(5.0);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h); // what's GLsizei? Why is it called inside glViewPort?
glMatrixMode(GL_PROJECTION); // is it necessary to reset the projection matrix?
glLoadIdentity();
if (w <= h) // is this calculation universal, could I use it on another program?
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW); // why do I set to GL_MODELVIEW at the end?
glLoadIdentity(); // why does it get a reset?
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape); // el reshape funciona correctamente
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}
GLsizei is a type, not a function. Therefore, it's not being called; its being casted; it's converting an int into a GLsizei. It's basically an int, but it makes it clear that you're using it for a size (I think). (I'm a Python programmer, so this is a guess)
glMatrixMode(...);
This does not reset the matrix, unless it is followed by a glLoadIdentity() call. Instead, it sets the current target of OpenGL's matrix operations to the matrix specified. This way, OpenGL knows what matrix you're trying to affect.
I've seen that calcuation before in the OpenGL superbible (or at least something like it); why don't you talk yourself through it and see what it's deciding and why? (Hint (I think): it's trying to keep the viewport square to avoid stretching)
At the end, it sets it back to GL_MODELVIEW since that matrix handles transformations, like translation and rotation, which are used to position vertices onscreen. It should be reset every frame so that your code can assume that the coordinate plane is currently at (0,0); that simplifies calculations about where to translate to.
Also note that reshape is not called by OpenGL, but by GLUT. OpenGL is platform-independent and does not handle windowing; this is why you need GLUT.
If you're new to OpenGL, you should work through it from the beginning - later tutorials will assume this sort of knowledge.