我试图在一个简单的场景上实现相机功能,但输出失真。我认为这与透视投影有关,或者我在错误使用gluLookAt()
函数,但是我似乎无法查明问题所在。每当我按箭头键查看更多摄像机时,视图就会不断失真。在另一个示例中,相机代码可以正常工作。我用完全相同的代码替换了我的场景的显示。我为gluLookAt()
尝试了不同的论据,甚至尝试了正交投影,但似乎没有任何效果。
实施摄像头之前:
实施摄像头后:
代码:
#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();
}
注意:
纹理贴图汽车和建筑代码因过大而被排除在外,但它们可以正常工作,我不认为这是问题所在。如果您需要完整的工作代码,请告诉我,我将上传它。我被这个问题困扰了一段时间。感谢您的帮助
答案 0 :(得分:2)
问题是Z-fighting问题。
要解决您的问题,您必须禁用Depth Test并将对象从背面拖到前面:
glEnable(GL_DEPTH_TEST)
或者您必须使用不同的z坐标绘制对象,该坐标定义了对象的z顺序。
请注意,在视图空间中,z轴指向视口之外。因此,如果一个对象的z坐标大于另一个对象的z坐标,则该对象在另一个对象的前面。
仅当对象的深度不同时,才能实现透视效果,从而使后面的对象看起来比比更靠近视点(眼睛位置)的对象小。
但是您必须确保不修剪对象。
这意味着对象到眼睛位置(gluLookAt
的前三个参数)的(视图空间)z距离必须在近平面和远平面之间(gluPerspective
的后两个参数)之间。