Reputation: 161
I'm trying to implement camera functionality on a simple scene but the output is distored. I think it has something to do with perspective projection or maybe I'm using the gluLookAt()
function wrong but I can't seem to pinpoint the problem. Whenever I press the arrow keys to more the camera the view keeps getting distorted. The camera code works fine in another example. I've used the exact same code with the display replaced for my scene. I have tried different arguments for gluLookAt()
and even tried ortho projection but nothing seems to work.
Before camera implementation:
After camera implementation:
Code:
#include <Windows.h>
#include <math.h>
#include "glut.h"
float angle = 0.0f;
float lx = 0.0f, lz = -0.1f;
float x = 0.0f, z = 0.5f;
float deltaAngle = 0.0f;
float deltaMove = 0;
double rot = 0;
double doorAngle = 0;
double carMove = -0.75; //Initially car positioned at the start of road
void myInit(void)
{
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(1000, 480);
glutInitWindowPosition(100, 150);
glutCreateWindow(" project part1 ");
glClearColor(0.333, 0.725, 0.905, 0);
glColor3f(0.0f, 0.0f, 0.0f);
}
void reshape(int w, int h) {
if (h == 0)
h = 1;
float ratio = w* 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45.0f, ratio, 0.1f, 20.0f);
glMatrixMode(GL_MODELVIEW);
}
void computePos(float deltaMove) //compute camera position
{
x += deltaMove * lx * 0.1f;
z += deltaMove * lz * 0.1f;
}
void computeDir(float deltaAngle)//compute camra direction
{
angle += deltaAngle;
lx = sin(angle);
lz = -cos(angle);
}
void display(void)
{
if (deltaMove)
computePos(deltaMove);
if (deltaAngle)
computeDir(deltaAngle);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(x, 0.0f, z, x + lx, 0.0f, z + lz, 0.0f, 1.0f, 0.0f);
//display quads road
glPushMatrix();
glLineWidth(3.0);
glColor3f(0.474, 0.552, 0.603);
glBegin(GL_QUADS);//grey road
glTexCoord2f(0.0, 0.0);
glVertex3f(-1, 0, 0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1, 0, 0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1, -1, 0);
glTexCoord2f(1.0, 0.0);
glVertex3f(-1, -1, 0);
glEnd();
//green grass above
glColor3f(0.305, 0.513, 0.341);
glBegin(GL_QUADS);
glVertex3f(-1, 0, 0);
glVertex3f(1, 0, 0);
glVertex3f(1, -0.1, 0);
glVertex3f(-1, -0.1, 0);
glEnd();
//green grass below
glColor3f(0.372, 0.407, 0.070);
glBegin(GL_QUADS);
glVertex3f(-1, -1, 0);
glVertex3f(1, -1, 0);
glVertex3f(1, -0.8, 0);
glVertex3f(-1, -0.8, 0);
glEnd();
//white lines on road
glColor3f(0.929, 0.850, 0.850);
glPointSize(5.0);
int factor = 10; GLushort pattern = 0x3333;
glEnable(GL_LINE_STIPPLE);
glLineStipple(factor, pattern);
glBegin(GL_LINES);
glVertex3f(1, -0.45, 0);
glVertex3f(-1, -0.45, 0);
glEnd();
glDisable(GL_LINE_STIPPLE);
glColor3f(0.929, 0.850, 0.850);
glPointSize(5.0);
glBegin(GL_LINES);
glVertex3f(1, -0.75, 0);
glVertex3f(-1, -0.75, 0);
glVertex3f(1, -0.15, 0);
glVertex3f(-1, -0.15, 0);
glEnd();
glPushMatrix();
glTranslatef(-0.8, 0.4, 0);
glScalef(0.5, 0.45, 0);
building(0, 0.17, 0.394);
glPopMatrix();
glPushMatrix();
glTranslatef(-0.35, 0.27, 0);
glScalef(0.55, 0.3, 0);
building(0.552, 0.266, 0.505);
glPopMatrix();
glPushMatrix();
//glLoadIdentity();
glTranslatef(0.2, 0.45, 0);
glScalef(1.2, 0.5, 0);
building(0.294, 0.337, 0.584);
glPopMatrix();
glPushMatrix();
glTranslatef(0.75, 0.27, 0);
glScalef(0.55, 0.3, 0);
building(0.309, 0.396, 0.427);
glPopMatrix();
//building bases
//car1
glPushMatrix();
glTranslatef(carMove, -0.2, 0);
glScalef(0.5, 0.5, 0.5);
car(0.65, 0, 0);
glPopMatrix();
glutSwapBuffers();
}
void pressKey(int key, int xx, int yy) {
switch (key) {
case GLUT_KEY_LEFT:
if (deltaAngle > 30)
break;
deltaAngle = -0.01f;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT: deltaAngle = 0.01f; break;
case GLUT_KEY_UP: deltaMove = 0.05f; break;
case GLUT_KEY_DOWN: deltaMove = -0.05f; break;
}
}
void releaseKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT:
case GLUT_KEY_RIGHT: deltaAngle = 0.0f; break;
case GLUT_KEY_UP:
case GLUT_KEY_DOWN: deltaMove = 0; break;
}
}
void main(int argc, char **argv)
{
glutInit(&argc, argv);
myInit();
glutDisplayFunc(display);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(display);
glutSpecialFunc(pressKey);
glutSpecialUpFunc(releaseKey);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
Note:
The texture mapping car and building code have been excluded for being too large but they work fine and I don't think that they're the problem. If you require the full working code then kindly let me know and I'll upload it. I've been stuck at this problem a while. Any help is appreciated
Upvotes: 2
Views: 279
Reputation: 210978
The issue is a Z-fighting issue.
To solve you issue you have to disable the Depth Test and draw the objects form the back to the front:
glEnable(GL_DEPTH_TEST)
Or you have to draw the object with a different z coordinates, which define the z order of the object.
Note, in view space the z axis points out of the viewport. So if the z coordinate of an object is greater than that of an other object, then the object is in front of the other object.
A perspective effect can only be achieved if the depth of the objects is different, so that object in the behind appear smaller, than that object which are closer to the point of view (eye position).
But you have to ensure that the objects are not clipped.
This mean the (view space) z distance of the object to the eye position (first 3 parameters of gluLookAt
) has to be in between the near and far plane (last 2 parameters of gluPerspective
).
Upvotes: 2