Reputation: 939
I'm trying to change the field of view in my scene when touching F2 and F3.
For this I have in my specialKey
function this:
void specialKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_F2:
changeFOV = true;
fovScale = 0.05;
break;
case GLUT_KEY_F3:
changeFOV = true;
fovScale = -0.05;
break;
}
I have a timed function that call myDisplay each milisecond and in that function I do:
if(changeFOV){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
fovAngle += fovScale;
gluPerspective(fovAngle, screenWidth/screenHeight, 2, 200);
glTranslatef(camera.x, camera.y, camera.z);
glMatrixMode(GL_MODELVIEW);
changeFOV = false;
}
Now the first time I press F2 or F3, the scene gets small to the size of one pixel (aprox) but if I keep pressing F3 the scene gets closer and closer and then it works correctly (F2 and F3).
fovAngle
is 60.0f at the beginning (The scene looks good without pressing F2 or F3).
This is my init() function:
void init() {
glInitNames();
gluPerspective(fovAngle, screenWidth/screenHeight, 2, 200);
glTranslatef(camera.x, camera.y, camera.z);
glClearColor(0, 0, 0, 1);
glViewport(0.0, 0.0, screenWidth, screenHeight);
glutInitWindowSize(screenWidth, screenHeight);
string windowName = "AMAZING 3D MODELING - ";
windowName += (sceneMode ? "Scene" : "Camera");
glutCreateWindow(windowName.c_str());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
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);
glMaterialfv(GL_FRONT, GL_AMBIENT, object_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, object_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, object_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, object_shine);
glutDisplayFunc(displayFunc);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutSpecialFunc(specialKey);
glutKeyboardFunc(keyboard);
glutTimerFunc(2, idle, 1);
glutMainLoop();
}
Any thoughts? (if more code is needed please ask and I will edit the question)
Upvotes: 0
Views: 183
Reputation: 54582
The main problem is that you're calling GL functions before you have an OpenGL context. The context is created as part of glutCreateWindow()
, so all your OpenGL calls, like your whole initial projection setup, need to be moved after glutCreateWindow()
.
You also seem to be missing a call to glutInit()
, which should be at the very start. I'm surprised that your code works at all without it.
The camera translation should normally be in modelview matrix mode. It won't change the resulting position of your geometry, but the lighting will be wrong otherwise.
The reason this behaves the way it does is most likely that your camera is very far away. Since the projection/camera is not set up on the initial rendering, it is not applied, and the geometry appears. Then the first time the projection/camera are applied, everything gets very small because you're looking at it from very far away. Then, as you make the FOV smaller, the size of the geometry increases.
So what you need to do is:
glutInit()
at the start.glutCreateWindow()
.I would put the transformation setup in a function that you can call both at init time, and when it changes. The function would contain something like this:
void setTransformations() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovAngle, screenWidth/screenHeight, 2, 200);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(camera.x, camera.y, camera.z);
}
Then you call it during init:
glutCreateWindow(...);
setTransformations();
and when the FOV changes:
if (changeFOV) {
fovAngle += fovScale;
changeFOV = false;
setTransformations();
}
Upvotes: 3