I'm trying to move my camera around the object, a house, using some keyboard keys and the gluLookAt()
function.
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int win_id;
const float raio = 100;
float camera_x = 0.0f, camera_y = 0.0f, camera_z = raio; // Posicao inicial da camera
float up_x = 0.0f, up_y = 1.0f, up_z = 0.0f; // Posicao inicial do Up Vector
float phi = 0, theta = 0;
// Desenha uma piramide de base quadrangular de lado 1 centrado na origem e altura 0.5
void desenhaPiramide(){
glBegin(GL_QUADS);
glVertex3f(-0.5, 0, -0.5);
glVertex3f(-0.5, 0, 0.5);
glVertex3f(0.5, 0, 0.5);
glVertex3f(0.5, 0, -0.5);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(-0.5, 0, -0.5);
glVertex3f(-0.5, 0, 0.5);
glVertex3f(0, 0.5, 0);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(-0.5, 0, 0.5);
glVertex3f(0.5, 0, 0.5);
glVertex3f(0, 0.5, 0);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(0.5, 0, 0.5);
glVertex3f(0.5, 0, -0.5);
glVertex3f(0, 0.5, 0);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(0.5, 0, -0.5);
glVertex3f(-0.5, 0, -0.5);
glVertex3f(0, 0.5, 0);
glEnd();
}
// Desenha um quadrado de lado 1
void desenhaQuadrado(){
glBegin(GL_QUADS);
glVertex3f(-0.5, -0.5, 0);
glVertex3f(-0.5, 0.5, 0);
glVertex3f(0.5, 0.5, 0);
glVertex3f(0.5, -0.5, 0);
glEnd();
}
// Aqui se capturam as teclas comuns (letras, números e ESC, por exemplo)
void myKeyboard(unsigned char key, int x, int y){
float camera_speed = 0.1f;
switch (key){
case 'a': // Rotação para cima
phi += camera_speed;
break;
case 'w': // Rotação para a esquerda
theta -= camera_speed;
break;
case 'd': // Rotação para baixo
phi -= camera_speed;
break;
case 's': // Rotação para a direita
theta += camera_speed;
break;
case 'r':
phi = 0.0f;
theta = 0.0f;
up_y = 1;
break;
case 27:
glutDestroyWindow(win_id);
exit(0);
break;
default:
printf("Voce apertou a tecla codigo: %d\n", key);
break;
}
if (theta >= 359){
theta = 0;
} else if (theta < 0){
theta = 359;
}
if (phi >= 179){
phi = 0;
} else if (phi < 0){
phi = 179;
}
camera_x = raio * cos(theta) * sin(phi);
camera_y = raio * sin(theta) * sin(phi);
camera_z = raio * cos(phi);
glutPostRedisplay();
}
// Aqui se capturam as teclas especiais (Alt, Control, Shift, F1, F2, etc.)
void myKeyboardSpecial(int key, int x, int y ){
switch (key){
case GLUT_KEY_UP:
glutFullScreen(); // Modo tela cheia
break;
case GLUT_KEY_DOWN:
glutReshapeWindow(800, 600); // Modo janela de 800 por 600
break;
default:
printf("Voce apertou a tecla especial codigo: %d\n", key);
break;
}
}
// Trecho de codigo para interacoes com o mouse
/*
void myMouse(int button, int state, int x, int y){
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN){
float r, g, b;
r = (double)rand() / (double)RAND_MAX;
g = (double)rand() / (double)RAND_MAX;
b = (double)rand() / (double)RAND_MAX;
glColor3f(r,g,b);
printf("%.2f, %.2f, %.2f\n", r, g, b);
}
glutPostRedisplay();
}
*/
void init(void){
glClearColor(0.5, 0.9, 0.4, 0.0);
// Define o modo de rastreio de cor utilizado para misturar a cor do material nos pontos da face (smoothing)
glShadeModel(GL_SMOOTH);
// Habilita a definição da cor do material a partir da cor corrente
glEnable(GL_COLOR_MATERIAL);
// Parâmetros para a luz ambiente, difusa e especular, definindo também a posição da luz
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 10.0, 10.0, 10.0, 0.0 };
// Passa os parâmetros definidos acima para a OpenGL
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
// Habilita a luz ambiente, a luz zero e o depth buffer
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
void display(void){
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Define a posição da câmera, para onde ela aponta e qual o vetor UP
gluLookAt(camera_x, camera_y, camera_z, 0.0f, 0.0f, 0.0f, up_x, up_y, up_z);
// Base da casa
glPushMatrix();
glColor3f(0.392, 0.584, 0.929);
glScalef(0.75, 1, 1.5);
glutSolidCube(35);
glPopMatrix();
// Porta da casa
glPushMatrix();
glColor3f(0.21, 0.27, 0.31);
glTranslatef(0, -10, 26.50);
glScalef(8, 15, 1);
desenhaQuadrado();
glPopMatrix();
// Telhado da casa
glPushMatrix();
glColor3f(0.804, 0.522, 0.247);
glTranslatef(0, 17.5, 0);
glScalef(26.25, 30, 52.5);
desenhaPiramide();
glPopMatrix();
glFlush();
}
void reshape (int w, int h){
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
// Se a largura for menor que a altura, a projeção é feita para manter a proporção da janela
glOrtho(-50, 50, -50*(GLfloat)h/(GLfloat)w, 50*(GLfloat)h/(GLfloat)w, -500.0, 500.0);
else
// Se a altura for menor que a largura, a projeção é feita para manter a proporção da janela
glOrtho(-50*(GLfloat)w/(GLfloat)h, 50*(GLfloat)w/(GLfloat)h, -50, 50, -500.0, 500.0);
}
int main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_DEPTH | GLUT_RGB);
glutInitWindowSize(800, 600);
glutInitWindowPosition(300, 50);
win_id = glutCreateWindow("Casa_OpenGL_3D");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(myKeyboard);
glutSpecialFunc(myKeyboardSpecial);
// glutMouseFunc(myMouse);
glutMainLoop();
return 0;
}
If I press the 'a' or 'd' keys, the movement occurs exactly as it should, as if the object itself were rotating, but in reality, it's just the camera that is moving. An odd detail is that if my first keyboard input is 'w' or 's', nothing happens, but if I press that after having already pressed 'a' or 'd', the movement starts to occur.
The major issue is that this translation isn't happening as I imagined... My idea was as if the house were enclosed by a sphere and the camera positioned on the face/perimeter of that sphere, so that it would only move in that region, enabling viewing the house from all angles and positions. But for some reason, when trying to perform a 360-degree translation, for example, the movement doesn't occur as planned.
It's difficult to explain in detail; it's easier to understand by analyzing the result for yourself. Here is an image exemplifying the result I have in mind.