Opengl视点转换如何gluLookAt

Posted

技术标签:

【中文标题】Opengl视点转换如何gluLookAt【英文标题】:Opengl viewpoint transformation how to gluLookAt 【发布时间】:2019-12-04 16:51:34 【问题描述】:

我想通过我的键盘使用极坐标来操纵上、下、左和右相机点。

#include <stdlib.h>
#include <glut.h>

GLint TopLeftX, TopLeftY, BottomRightX, BottomRightY ;

static int HourOfDay = 0;
static int DayOfYear = 10;

void init(void) 
    glClearColor(0.0, 0.0, 0.0, 0.0);



void myDisplay(void) 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix(); // Origin

    glClear(GL_DEPTH_BUFFER_BIT);

    /* Sun */
    glColor3f(1.0, 1.0, 0.0);
    glutSolidSphere(1.0, 20, 10);


    /* Mercury */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear, 0.0, 0.0, 1.0);
    glTranslatef(3.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.87, 0.53, 0.25);
    glutSolidSphere(0.3, 10, 2);
    glPopMatrix();

    /* Venus */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 195, 0.0, 0.0, 1.0);
    glTranslatef(5.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.99, 0.91, 0.66);
    glutSolidSphere(0.5, 10, 2);
    glPopMatrix();

    /* Earth */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 80, 0.0, 0.0, 1.0);
    glTranslatef(7.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.47, 0.82, 0.98);
    glutSolidSphere(0.5, 10, 2);

    /* Earth's Moon 1*/
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear, 0.0, 0.0, 1.0);
    glTranslatef(0.7, 0.0, 0.0);
    glColor3f(0.89, 0.93, 0.95);
    glutSolidSphere(0.1, 5, 5);
    glPopMatrix();

    glPopMatrix();

    /* Mars */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 275, 0.0, 0.0, 1.0);
    glTranslatef(9.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.84, 0.16, 0.15);
    glutSolidSphere(0.35, 10, 2);
    glPopMatrix();

    /* Jupiter */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 33, 0.0, 0.0, 1.0);
    glTranslatef(11.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.93, 0.64, 0.27);
    glutSolidSphere(1.0, 10, 2);
    glPopMatrix();

    /* Saturn */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 180, 0.0, 0.0, 1.0);
    glTranslatef(15.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.92, 0.82, 0.45);
    glutSolidSphere(0.9, 10, 2);
    glPopMatrix();

    /* Uranus */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 90, 0.0, 0.0, 1.0);
    glTranslatef(17.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.64, 0.84, 0.78);
    glutSolidSphere(0.8, 10, 2);
    glPopMatrix();

    /* Neptune */
    glPushMatrix();
    glRotatef((GLfloat)DayOfYear + 150, 0.0, 0.0, 1.0);
    glTranslatef(20.0, 0.0, 0.0);
    glRotatef((GLfloat)HourOfDay, 0.0, 0.0, 1.0);
    glColor3f(0.29, 0.74, 0.95);
    glutSolidSphere(0.25, 10, 2);
    glPopMatrix();

    glutSwapBuffers();

    // Animation State
    DayOfYear = (DayOfYear + 1) % 360;
    HourOfDay = (HourOfDay + 5) % 360;


void Timer(int iUnused) 
    glutPostRedisplay();
    glutTimerFunc(30, Timer, 0);


static float cam_axis_x = 0.0;
static float cam_axis_y = 0.0;
static float cam_axis_z = -50.0;

void reshape(int w, int h) 
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 1.0, 90.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(cam_axis_x, cam_axis_y, cam_axis_z);


/*void reshape(int w, int h) 
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLsizei)w / (GLsizei)h, 0.0, 90.0);
*/

void keyboard(unsigned char key, int x, int y) 
    switch (key) 
    case 'q': // Esc
        exit(0);
        break;
    case '75': // left
        break;
    case '77': // right
        break;
    case '72': // up
        break;
    case '80': // down
        break;
    


void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y) 
    if (Button == GLUT_LEFT_BUTTON && State == GLUT_DOWN) 
        TopLeftX = X;
        TopLeftY = Y;
    


void MyMouseMove(GLint X, GLint Y) 
    BottomRightX = X;
    BottomRightY = Y;
    glutPostRedisplay();


int main(int argc, char** argv) 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(myDisplay);
    glutReshapeFunc(reshape);
    Timer(0);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(MyMouseClick);
    glutMotionFunc(MyMouseMove);

    glutMainLoop();
    return 0;

我想围绕太阳移动相机

你能告诉我gluLookAt吗?

【问题讨论】:

myDisplay 末尾缺少一个glPopMatrix();。 (与glPushMatrix(); // Origin相反) 你能告诉我关于 gluLookAt 的事吗?”听起来你需要一个教程而不是一个特定问题的答案。 *** 认为此类问题过于宽泛。 【参考方案1】:

我不知道你所说的极坐标是什么意思,通常是二维的。也许你的意思是球坐标。

方法完全相同:

假设您的太阳位于世界的起源处(目前确实如此)

你有两种方法

假设 Theta 是您希望相机绕太阳运行的角度 并且 Phi 是围绕您的 xAxis 框架的一些“俯仰”(您可能想要也可能不想要它)。

1) 使用基本公式计算相机的 x、y、z 位置: https://en.wikipedia.org/wiki/Spherical_coordinate_system

球坐标:

// r is the distance to the sun
cam_axis_x = r * sin(theta) * cos(phi);
cam_axis_y = r * r * cos(theta);
cam_axis_z = r * sin(theta) * sin(phi);

“极坐标”:

cam_axis_x = r * sin(theta);
cam_axis_z = r * cos(theta);

然后像以前一样应用翻译

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(cam_axis_x, cam_axis_y, cam_axis_z);

2) 将相机平移到原始位置后对其应用旋转:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(cam_axis_x, cam_axis_y, cam_axis_z);
glRotatef(0, theta, phi);

【讨论】:

以上是关于Opengl视点转换如何gluLookAt的主要内容,如果未能解决你的问题,请参考以下文章

两个Sphere和gluLookAt函数之间的OpenGL碰撞

图形学计算机图形学知识点提纲8

解释 OpenGL 如何管理它的变换矩阵

OpenGL gluLookAt

OpenGL的gluLookAt和glOrtho的关系

OpenGL 使用 gluLookat()