2014-11-03 271 views
0

我试图实现机器人可以四处走动的简单3D环境。我希望用户能够在机器人的第一人称视角和第三人称视角之间切换。在第一人称视角和第三人称视角之间切换(OpenGL)

我已经实现了机器人和一个简单的区域与其他几个对象。目前,该视图是第三人称。我一直在使用gluPerspective函数来尝试实现第一个在头部转动时转动的头部(头部转动已经实现),但看起来不管我使用的参数如何,我都无法切换到工作状态。它始终保持不变。有没有比迄今为止我尝试过的更简单的方法来实现这种效果?因为我的方法,我在做什么不工作?

以下代码足以将透视图设置为第一人称视角,但它并不像我期望的那样跟随图形的头部。我可以初始化它,但是我不知道如何让机器人随着相机移动,因为景观在他周围有效地移动。我想我可以通过在第一人时移除机器人来“假”这种事情。思考? :

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
double atx = xPos + cos(lookAngle); 
double atz = zPos + sin(lookAngle); 
double atHeight = eyeHeight + eyeIncline; 
gluLookAt(xPos, eyeHeight, zPos, atx, atHeight, atz, 0.0, 1.0, 0.0); 

我曾尝试在键盘功能中调用switch语句切换到第三人称。键盘调用看起来像这样:

void key(unsigned char k, int x, int y) 
{ 
if (k == 27) /* Escape */ 
    exit(0); 
else if (k == 86) { /* 'v' for view change */ 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(0, 0, -20, 0, 0, -1, 0, 1, 0); //Look down z-axis 

} 
glutPostRedisplay(); 
} 

但它不起作用。没有切换完成。下面

代码:

#define GLUT_DISABLE_ATEXIT_HACK 

#include <GL/glut.h> 
#include <GL/gl.h> 
#include <math.h> 

#define TORSO_HEIGHT 5.0 
#define UPPER_ARM_HEIGHT 3.0 
#define LOWER_ARM_HEIGHT 2.0 
#define UPPER_LEG_RADIUS 0.5 
#define LOWER_LEG_RADIUS 0.5 
#define LOWER_LEG_HEIGHT 2.0 
#define UPPER_LEG_HEIGHT 3.0 
#define UPPER_LEG_RADIUS 0.5 
#define TORSO_RADIUS 1.0 
#define UPPER_ARM_RADIUS 0.5 
#define LOWER_ARM_RADIUS 0.5 
#define HEAD_HEIGHT 1.5 
#define HEAD_RADIUS 1.0 

double cubeX[] = { 5.0, 5.0, 5.0 }; 
double cubeY[] = { 3.0, 3.0, 3.0 }; 
double cubeZ[] = { 7.0, 5.0, 3.0 }; 
double cubeR[] = { 1.0, 0.0, 0.0 }; 
double cubeG[] = { 0.0, 1.0, 0.0 }; 
double cubeB[] = { 0.0, 0.0, 1.0 }; 

double xPos = 2.0, zPos = 5.0; 
double eyeHeight = 4.5; 
double eyeIncline = -0.5; 
double lookAngle = 0.0; //In rads 

double posIncr = 0.25; 
double thetaIncr = 0.1; 

typedef float point[3]; 

static GLfloat theta[11] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0, 
     180.0,0.0,180.0,0.0}; /* initial joint angles */ 
static GLint angle = 2; 

GLUquadricObj *t, *h, *lua, *lla, *rua, *rla, *lll, *rll, *rul, *lul, *lf1, *lf2; 

double size=1.0; 

void torso() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(t,TORSO_RADIUS, TORSO_RADIUS, TORSO_HEIGHT,10,10); 
glPopMatrix(); 
} 

void head() 
{ 
glPushMatrix(); 
glTranslatef(0.0, 0.5*HEAD_HEIGHT,0.0); 
glScalef(HEAD_RADIUS, HEAD_HEIGHT, HEAD_RADIUS); 
gluSphere(h,1.0,10,10); 
glPopMatrix(); 
} 

void left_upper_arm() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(lua,UPPER_ARM_RADIUS, UPPER_ARM_RADIUS, UPPER_ARM_HEIGHT,10,10); 
glPopMatrix(); 
} 

void left_lower_arm() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(lla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10); 
glPopMatrix(); 
} 

void left_finger1() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(lf1,FINGER_1_RADIUS, FINGER_1_RADIUS, FINGER_1_HEIGHT,10,10); 
glPopMatrix(); 
} 

void left_finger2() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(lla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10); 
glPopMatrix(); 
} 

void right_upper_arm() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(rua,UPPER_ARM_RADIUS, UPPER_ARM_RADIUS, UPPER_ARM_HEIGHT,10,10); 
glPopMatrix(); 
} 

void right_lower_arm() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(rla,LOWER_ARM_RADIUS, LOWER_ARM_RADIUS, LOWER_ARM_HEIGHT,10,10); 
glPopMatrix(); 
} 

void left_upper_leg() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(lul,UPPER_LEG_RADIUS, UPPER_LEG_RADIUS, UPPER_LEG_HEIGHT,10,10); 
glPopMatrix(); 
} 

void left_lower_leg() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(lll,LOWER_LEG_RADIUS, LOWER_LEG_RADIUS, LOWER_LEG_HEIGHT,10,10); 
glPopMatrix(); 
} 

void right_upper_leg() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(rul,UPPER_LEG_RADIUS, UPPER_LEG_RADIUS, UPPER_LEG_HEIGHT,10,10); 
glPopMatrix(); 
} 

void right_lower_leg() 
{ 
glPushMatrix(); 
glRotatef(-90.0, 1.0, 0.0, 0.0); 
gluCylinder(rll,LOWER_LEG_RADIUS, LOWER_LEG_RADIUS, LOWER_LEG_HEIGHT,10,10); 
glPopMatrix(); 
} 

void drawCube(int i) 
{ 
double x = cubeX[i]; 
double y = cubeY[i]; 
double z = cubeZ[i]; 

glColor3i(1, 0, 0); //Red cube 
glPushMatrix(); 
glTranslatef(x,y,z); 
glutSolidCube(1); 
glPopMatrix(); 

glColor3i(0, 1, 0); //Green Cube 
glPushMatrix(); 
glTranslatef(x,y,z); 
glutSolidCube(1); 
glPopMatrix(); 

glColor3i(0, 0, 1); //Blue Cube 
glPushMatrix(); 
glTranslatef(x,y,z); 
glutSolidCube(1); 
glPopMatrix(); 

glColor3i(0, 1, 1); 
glPushMatrix(); 
glTranslatef(x,y,z); 
glutSolidCube(1); 
glPopMatrix(); 

} 

void drawCubes(void) 
{ 

glLoadName(1); 
drawCube(0); 

glLoadName(2); 
drawCube(1); 

glLoadName(3); 
drawCube(2); 

/* Set name back to '0' to indicate background. */ 
glLoadName(0); 
} 

void drawFloor(void) 
{ 
GLfloat mat_diffuse[] = { 0.5, 0.5, 0.5, 1.0 }; 
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); 
glBegin(GL_POLYGON); 
    glNormal3f(0.0, 1.0, 0.0); 
    glVertex3f(-10.0, 0.0, -10.0); 
    glVertex3f(10.0, 0.0, -10.0); 
    glVertex3f(10.0, 0.0, 10.0); 
    glVertex3f(-10.0, 0.0, 10.0); 
glEnd(); 
} 

void doDrawing(void) 
{ 

drawCubes(); 

drawFloor(); 

/* Everything else is a lighter shade of grey. */ 
GLfloat mat_diffuse[] = { 0.8, 0.8, 0.8, 1.0 }; 
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); 
} 

void drawEnviro(void) 
{ 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
double atx = xPos + cos(lookAngle); 
double atz = zPos + sin(lookAngle); 
double atHeight = eyeHeight + eyeIncline; 
gluLookAt(xPos, eyeHeight, zPos, atx, atHeight, atz, 0.0, 1.0, 0.0); 

glPushMatrix(); 
doDrawing(); 
glPopMatrix(); 
} 

void display(void) 
{ 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
drawEnviro(); 
glLoadIdentity(); 
gluLookAt(0, 0, -20, 0, 0, -1, 0, 1, 0); 
glColor3f(0.0, 0.0, 0.0); 

glRotatef(theta[0], 0.0, 1.0, 0.0); 
torso(); 
glPushMatrix(); 

glTranslatef(0.0, TORSO_HEIGHT+0.5*HEAD_HEIGHT, 0.0); 
glRotatef(theta[1], 1.0, 0.0, 0.0); 
glRotatef(theta[2], 0.0, 1.0, 0.0); 
glTranslatef(0.0, -0.5*HEAD_HEIGHT, 0.0); 
head(); 

glPopMatrix(); 
glPushMatrix(); 
glTranslatef(-(TORSO_RADIUS + UPPER_ARM_RADIUS), 0.9 * TORSO_HEIGHT, 0.0); 
glRotatef(theta[3], 1.0, 0.0, 0.0); 
left_upper_arm(); 

glTranslatef(0.0, UPPER_ARM_HEIGHT, 0.0); 
glRotatef(theta[4], 1.0, 0.0, 0.0); 
left_lower_arm(); 

glTranslatef(0.0, LOWER_ARM_HEIGHT, 0.0); 
glRotatef(theta[11], 1.0, 0.0, 0.0); 
left_finger1(); 

glPopMatrix(); 
glPushMatrix(); 
glTranslatef(TORSO_RADIUS+UPPER_ARM_RADIUS, 0.9*TORSO_HEIGHT, 0.0); 
glRotatef(theta[5], 1.0, 0.0, 0.0); 
right_upper_arm(); 

glTranslatef(0.0, UPPER_ARM_HEIGHT, 0.0); 
glRotatef(theta[6], 1.0, 0.0, 0.0); 
right_lower_arm(); 

glPopMatrix(); 
glPushMatrix(); 
glTranslatef(-(TORSO_RADIUS+UPPER_LEG_RADIUS), 0.1*UPPER_LEG_HEIGHT, 0.0); 
glRotatef(theta[7], 1.0, 0.0, 0.0); 
left_upper_leg(); 

glTranslatef(0.0, UPPER_LEG_HEIGHT, 0.0); 
glRotatef(theta[8], 1.0, 0.0, 0.0); 
left_lower_leg(); 

glPopMatrix(); 
glPushMatrix(); 
glTranslatef(TORSO_RADIUS+UPPER_LEG_RADIUS, 0.1*UPPER_LEG_HEIGHT, 0.0); 
glRotatef(theta[9], 1.0, 0.0, 0.0); 
right_upper_leg(); 

glTranslatef(0.0, UPPER_LEG_HEIGHT, 0.0); 
glRotatef(theta[10], 1.0, 0.0, 0.0); 
right_lower_leg(); 

glPopMatrix(); 

glFlush(); 
glutSwapBuffers(); 
} 

void setProjection(void) 
{ 
gluPerspective(60.0, 1.0, 0.1, 100.0); 
} 

void mouse(int btn, int state, int x, int y) 
{ 
    if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
    { 
    theta[angle] += 5.0; 
    if(theta[angle] > 360.0) theta[angle] -= 360.0; 
    } 
    if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 
    { 
    theta[angle] -= 5.0; 
    if(theta[angle] < 360.0) theta[angle] += 360.0; 
    } 
    display(); 
} 

void menu(int id) 
{ 
if (id < 11) angle = id; 
if (id == 11) exit(0); 
} 

void specialKey(int k, int x, int y) 
{ 
/* Accept commands to move the viewpoint. */ 
switch (k) { 
    case GLUT_KEY_UP: 
    xPos += posIncr * cos(lookAngle); 
    zPos += posIncr * sin(lookAngle); 
    break; 
    case GLUT_KEY_DOWN: 
    xPos -= posIncr * cos(lookAngle); 
    zPos -= posIncr * sin(lookAngle); 
    break; 
    case GLUT_KEY_LEFT: 
    lookAngle -= thetaIncr; 
    break; 
    case GLUT_KEY_RIGHT: 
    lookAngle += thetaIncr; 
    break; 
    case GLUT_KEY_PAGE_UP: 
    eyeIncline += 0.5; 
    break; 
    case GLUT_KEY_PAGE_DOWN: 
    eyeIncline -= 0.5; 
    break; 
    case GLUT_KEY_HOME: 
    eyeHeight += 0.5; 
    break; 
    case GLUT_KEY_END: 
    eyeHeight -= 0.5; 
    break; 
    default: 
    return; 
    } 
    glutPostRedisplay(); 
} 

void reshape(int w, int h) 
{ 
glViewport(0, 0, w, h); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
gluPerspective (65.0, w/h, 1, 1000.0); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
} 

void init() 
{ 
    GLfloat mat_specular[]={1.0, 1.0, 1.0, 1.0}; 
    GLfloat mat_diffuse[]={1.0, 1.0, 1.0, 1.0}; 
    GLfloat mat_ambient[]={1.0, 1.0, 1.0, 1.0}; 
    GLfloat mat_shininess={100.0}; 
    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}; 

    glLightfv(GL_LIGHT0, GL_POSITION, light_position); 
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); 

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); 
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); 
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); 
    glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess); 

    glShadeModel(GL_SMOOTH); 
    glEnable(GL_LIGHTING); 
    glEnable(GL_LIGHT0); 
    glDepthFunc(GL_LEQUAL); 
    glEnable(GL_DEPTH_TEST); 

    glClearColor(0.0, 0.0, 0.0, 0.0); 
    glMatrixMode(GL_PROJECTION); 

    glLoadIdentity(); 
    setProjection(); 

    //Fill the body parts of the robot 
    h=gluNewQuadric(); 
    gluQuadricDrawStyle(h, GLU_FILL); 
    t=gluNewQuadric(); 
    gluQuadricDrawStyle(t, GLU_FILL); 
    lua=gluNewQuadric(); 
    gluQuadricDrawStyle(lua, GLU_FILL); 
    lla=gluNewQuadric(); 
    gluQuadricDrawStyle(lla, GLU_FILL); 
    rua=gluNewQuadric(); 
    gluQuadricDrawStyle(rua, GLU_FILL); 
    rla=gluNewQuadric(); 
    gluQuadricDrawStyle(rla, GLU_FILL); 
    lul=gluNewQuadric(); 
    gluQuadricDrawStyle(lul, GLU_FILL); 
    lll=gluNewQuadric(); 
    gluQuadricDrawStyle(lll, GLU_FILL); 
    rul=gluNewQuadric(); 
    gluQuadricDrawStyle(rul, GLU_FILL); 
    rll=gluNewQuadric(); 
    gluQuadricDrawStyle(rll, GLU_FILL); 
    lf1=gluNewQuadric(); 
    gluQuadricDrawStyle(lf1, GLU_FILL); 

} 

int main(int argc, char **argv) 
{ 
glutInit(&argc, argv); 
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
glutInitWindowSize(500, 500); 
glutCreateWindow("robot"); 
init(); 
glutReshapeFunc(reshape); 
glutDisplayFunc(display); 
glutMouseFunc(mouse); 
glutSpecialFunc(specialKey); 

glutCreateMenu(menu); 
glutAddMenuEntry("torso", 0); 
glutAddMenuEntry("head1", 1); 
glutAddMenuEntry("head2", 2); 
glutAddMenuEntry("right_upper_arm", 3); 
glutAddMenuEntry("right_lower_arm", 4); 
glutAddMenuEntry("left_upper_arm", 5); 
glutAddMenuEntry("left_lower_arm", 6); 
glutAddMenuEntry("right_upper_leg", 7); 
glutAddMenuEntry("right_lower_leg", 8); 
glutAddMenuEntry("left_upper_leg", 9); 
glutAddMenuEntry("left_lower_leg", 10); 
glutAddMenuEntry("quit", 11); 
glutAttachMenu(GLUT_MIDDLE_BUTTON); 

glutMainLoop(); 

return 0; 
} 

回答

0

像是一个(与设置视口和模型视图矩阵一起)相关东西,设置投影矩阵一切都属于到绘图代码路径,你的情况display 。不要把它放在reshape。而init这样做是完全错误的。

+0

我在这方面看到了矛盾的观点。在风格上,这可能是事实,但它没有帮助解决我的问题。 – 2014-11-03 17:58:34