gluLookAt似乎产生了错误的观点,OpenGL

gluLookAt seems to be producting wrong view, OpenGL

本文关键字:观点 OpenGL 错误 产生了 gluLookAt      更新时间:2023-10-16

我正在研究一个nbody模拟器,我想用OpenGL显示它。 我想始终关注质量参考系的中心。 我有以下代码。 我计算 COM,并将 gluLookAt 函数中的中心坐标设置为质心。然后,我从z坐标中减去"缩放"以获得眼睛位置。 从逻辑上讲,这应该确保我总是在看质心是什么值。 唯一的问题是我用红点标记了质心应该在屏幕上的位置,并且它正在移动。 如果我总是从相同的相对位置看它,它不应该永远不会移动吗? 这是我的代码。专注于显示功能,因为我认为这就是错误所在。 我在另一个项目中有类似的代码,但我真的找不到任何差异。

#include "Universe.cuh"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "timer.hpp"
#include <GL/glut.h>
Universe u;
float* vbuf;
double angle = 0.0, zoom = 1000;
void display()
{   
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    float3 c = u.getCenterOfMass();
    gluLookAt(c.x, c.y, c.z - zoom, c.x, c.y, c.z, 0, 1, 0);
    glScalef(0.1, 0.1, 0.1);
    glRotated(angle, 1, 0, 0);
    glColor4f(1, 1, 1, 0.25);
    glBegin(GL_POINTS);
    {
        glColor3f(1.0, 0.0, 0.0);
        glVertex3d(c.x, c.y, c.z);
    }
    glEnd();
    glutSwapBuffers();
}
void reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, (double)w / (double)h, 1.0, zoom * 1e9);
    glMatrixMode(GL_MODELVIEW);
}
void copy_to_vbuf()
{
    for(int i = 0; i < u.size(); i++)
    {
        vbuf[3 * i + 0] = u.getObjects()[i].p.x;
        vbuf[3 * i + 1] = u.getObjects()[i].p.y;
        vbuf[3 * i + 2] = u.getObjects()[i].p.z;
    }
}
void keyboard(unsigned char c, int x, int y)
{
    if(c == 'w')
        angle += 1;
    else if(c == 's')
        angle -= 1;
    else if(c == '=')
        zoom /= 1.2;
    else if(c == '-')
        zoom *= 1.2;
    glutPostRedisplay();
}
void idle()
{
    u.timeStep();
    copy_to_vbuf();
    glutPostRedisplay();
}
int main(int argc, char** argv)
{
    cudaSetDevice(0);
    srand(time(0));
    u.getConfiguration().max_velocity = 10;
    u.getConfiguration().softening_factor = 0.01;
    u.getConfiguration().threshold_angle = 35;
    u.getConfiguration().time_step = 0.1;
    const int N = 5;
    vbuf = new float[3 * N];
    for(int i = 0; i < N; i++)
    {
        Object o;
        o.m = rand() % 100 + 1;
        o.p.x = 500.0 * rand() / RAND_MAX - 250.0;
        o.p.y = 500.0 * rand() / RAND_MAX - 250.0;
        o.p.z = 500.0 * rand() / RAND_MAX - 250.0;
        u.addObject(o);
    }
    copy_to_vbuf();
    glutInit(&argc, argv);
    glutInitDisplayMode(GL_DOUBLE);
    glutInitWindowSize(1000, 1000);
    glutCreateWindow("N-Body");
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutKeyboardFunc(keyboard);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPointSize(1.0);

    glutMainLoop();
    return 0;
}

关于以下两点:

glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
  1. 由于您的轴不在"COM"上居中,因此当您应用旋转时,COM 点将不会停留在原位,逻辑上会在屏幕上移动。

  2. AFIK的正常顺序是缩放,旋转,平移进行转换。这将应用旋转,然后缩放。

编辑:

扩展一下:目前,您采用任意点旋转它,缩放它,然后专注于它曾经所在的点。如果要围绕自身旋转模型(例如标记"COM"的点),则需要将其居中(0,0,0)。