PDA

View Full Version : OpenGL rotate a cube with keyboard



ZuoKsrf
12-02-2017, 08:00 AM
I try to rotate a cube with keyboard but I can't. The first rotation works correctly but the second rotation is broken.I understand why, but I can't figure out how to fix it. First glRotatef is for rotation on x.It works but the second glRotote that is for rotation on y is not working like first one.

Think like I want to rotate on the camera axis.But when you click Left or Right,the cube turns on its own y axis

NOTE.:: You need to press the arrows when it first work ///////////


#include <GL/glut.h>
#include <iostream>
using namespace std;

GLfloat rx = 0, ry = 0;

void drawCube(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);


glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);

glColor3f(1.0, 0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);

glColor3f(1.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);

glColor3f(0.0, 0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, 1.0);

glColor3f(1.0, 0.5, 0.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(-1.0, -1.0, 1.0);

glColor3f(1.0, 0.5, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glEnd();

glutSwapBuffers();


}
void arrows(int key, int x, int y)
{
glLoadIdentity();
gluLookAt(0,0,5,0,0,0,0,1,0);
switch (key) {

case GLUT_KEY_LEFT: ry += 5;

glRotatef(rx, 1, 0, 0); // Up and down arrow keys 'tip' view.
glRotatef(ry, 0, 1, 0); // Right/left arrow keys 'turn' view.

break;
case GLUT_KEY_RIGHT: ry -= 5;
glRotatef(rx, 1, 0, 0); // Up and down arrow keys 'tip' view.
glRotatef(ry, 0, 1, 0); // Right/left arrow keys 'turn' view.
break;
case GLUT_KEY_UP: rx += 5;
glRotatef(rx, 1, 0, 0); // Up and down arrow keys 'tip' view.
glRotatef(ry, 0, 1, 0); // Right/left arrow keys 'turn' view.
break;
case GLUT_KEY_DOWN: rx -= 5;
glRotatef(rx, 1, 0, 0); // Up and down arrow keys 'tip' view.
glRotatef(ry, 0, 1, 0); // Right/left arrow keys 'turn' view.
break;

}
cout << rx << " " << ry << "\n";
drawCube();
}

int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitWindowPosition(300, 150);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);


glutCreateWindow("");
glutSpecialFunc(arrows);

glClearColor(1.0, 1.0, 1.0, 1.0);

glMatrixMode(GL_PROJECTION);
gluPerspective(100, 1.5, 1, 10);
glMatrixMode(GL_MODELVIEW);

glPushMatrix();
glutMainLoop();
return 0;
}

GClements
12-02-2017, 11:23 AM
You can't achieve what (I think) you're trying to do by accumulating X and Y angles; you need to accumulate matrices. E.g. using GLM:


#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

glm::mat4 m(1.0f);

void drawCube(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);


glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);

glColor3f(1.0, 0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);

glColor3f(1.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);

glColor3f(0.0, 0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, 1.0);

glColor3f(1.0, 0.5, 0.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(-1.0, -1.0, 1.0);

glColor3f(1.0, 0.5, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glEnd();

glutSwapBuffers();


}

void arrows(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
m = glm::rotate(glm::mat4(1.0f), glm::radians( 5.0f), glm::vec3(0, 1.0f, 0)) * m;
break;
case GLUT_KEY_RIGHT:
m = glm::rotate(glm::mat4(1.0f), glm::radians(-5.0f), glm::vec3(0, 1.0f, 0)) * m;
break;
case GLUT_KEY_UP:
m = glm::rotate(glm::mat4(1.0f), glm::radians( 5.0f), glm::vec3(1.0f, 0, 0)) * m;
break;
case GLUT_KEY_DOWN:
m = glm::rotate(glm::mat4(1.0f), glm::radians(-5.0f), glm::vec3(1.0f, 0, 0)) * m;
break;
}

glutPostRedisplay();
}

void display(void)
{
glLoadIdentity();
gluLookAt(0,0,5,0,0,0,0,1,0);
glMultMatrixf(glm::value_ptr(m));
drawCube();
}

int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitWindowPosition(300, 150);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);


glutCreateWindow("test");
glutSpecialFunc(arrows);
glutDisplayFunc(display);

glClearColor(1.0, 1.0, 1.0, 1.0);


glMatrixMode(GL_PROJECTION);
gluPerspective(100, 1.5, 1, 10);
glMatrixMode(GL_MODELVIEW);

glPushMatrix();
glutMainLoop();
return 0;
}


Also note that the rendering has been moved to the display callback; the keyboard callback simply updates the state then calls glutPostRedisplay().

ZuoKsrf
12-02-2017, 01:18 PM
You can't achieve what (I think) you're trying to do by accumulating X and Y angles; you need to accumulate matrices. E.g. using GLM:


#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

glm::mat4 m(1.0f);

void drawCube(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);


glBegin(GL_QUADS);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);

glColor3f(1.0, 0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);

glColor3f(1.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);

glColor3f(0.0, 0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, 1.0);

glColor3f(1.0, 0.5, 0.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(-1.0, -1.0, 1.0);

glColor3f(1.0, 0.5, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glEnd();

glutSwapBuffers();


}

void arrows(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
m = glm::rotate(glm::mat4(1.0f), glm::radians( 5.0f), glm::vec3(0, 1.0f, 0)) * m;
break;
case GLUT_KEY_RIGHT:
m = glm::rotate(glm::mat4(1.0f), glm::radians(-5.0f), glm::vec3(0, 1.0f, 0)) * m;
break;
case GLUT_KEY_UP:
m = glm::rotate(glm::mat4(1.0f), glm::radians( 5.0f), glm::vec3(1.0f, 0, 0)) * m;
break;
case GLUT_KEY_DOWN:
m = glm::rotate(glm::mat4(1.0f), glm::radians(-5.0f), glm::vec3(1.0f, 0, 0)) * m;
break;
}

glutPostRedisplay();
}

void display(void)
{
glLoadIdentity();
gluLookAt(0,0,5,0,0,0,0,1,0);
glMultMatrixf(glm::value_ptr(m));
drawCube();
}

int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitWindowPosition(300, 150);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);


glutCreateWindow("test");
glutSpecialFunc(arrows);
glutDisplayFunc(display);

glClearColor(1.0, 1.0, 1.0, 1.0);


glMatrixMode(GL_PROJECTION);
gluPerspective(100, 1.5, 1, 10);
glMatrixMode(GL_MODELVIEW);

glPushMatrix();
glutMainLoop();
return 0;
}


Also note that the rendering has been moved to the display callback; the keyboard callback simply updates the state then calls glutPostRedisplay().

I cant Use GLM.I can just simple opengl functions like in my code

GClements
12-02-2017, 09:41 PM
I cant Use GLM.I can just simple opengl functions like in my code
In which case, you just need to write replacements for glm::rotate() and operator* (matrix multiplication).

You can either copy the rotate() code from GLM or use the information in the glRotate reference page (https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml). Or you can write specialised versions for the X and Y axes.

didydriver
12-05-2017, 04:35 PM
I try to rotate a cube with keyboard but I can't. The first rotation works correctly but the second rotation is broken.I understand why, but I can't figure out how to fix it. First glRotatef is for rotation on x.It works but the second glRotote that is for rotation on y is not working like first one.

Think like I want to rotate on the camera axis.But when you click Left or Right,the cube turns on its own y axis

NOTE.:: You need to press the arrows when it first work ///////////
[/highlight]

The fact that you wait for a callback before drawing is good. However you should probably draw first and wait for another callback before redrawing. Secondly, I think this one was overlooked slightly in your design , you have global variables , meaning they can be used anywhere. I'm not a user of Glut so I can't say for sure when the glLoadIdentity() equivalent is called but is it possible that calling your draw from inside has somehow triggered such an event?

Maybe Clement can tell me when such an event occurs?