Я работаю над симулятором nbody и хочу отобразить его с помощью OpenGL. Я хочу всегда смотреть в центр массовой системы отсчета. У меня есть следующий код. Я вычисляю COM, и я установил центральную координату в функции gluLookAt как центр масс. Затем я вычитаю «зум» из координаты z, чтобы получить положение глаз. По логике это должно гарантировать, что я всегда смотрю на то, какое значение имеет центр масс. Единственная проблема в том, что я отметил, где центр масс должен быть на экране с красной точкой, и он движется. Разве он не должен двигаться, если я всегда смотрю на него с той же относительной позиции? Вот мой код. Сосредоточьтесь на функции отображения, так как я предполагаю, что там будет ошибка. У меня был аналогичный код, работающий в другом проекте, и я не могу найти никаких различий.gluLookAt, похоже, работает неправильно, OpenGL
#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;
}
'glRotated (angle, 1, 0, 0);' Вы не вращаете камеру там от ориентации, которую установил 'gluLookAt()'? На боковой ноте ваш 'far' слишком велик, а ваш' near' слишком мал. –
Я вроде как не очень хочу, чтобы вы обрезали плоскость. Я никогда не понимал, что касается плоскости отсечения или почему это необходимо. – chasep255
На самом деле имеет решающее значение тот факт, что графические процессоры имеют ограниченный z-буфер. Когда вы устанавливаете 'near' и' far', вы определяете диапазон, в который будут распределены значения глубины. Подумайте об этом, как будто у вас есть X-метки, которые вы можете распространять на линейку любой длины. Чем больше линейка, тем точнее она становится с этими ярлыками, но если ее очень мало, ваши ярлыки будут очень близки, и можно будет точно измерить микрометры с помощью линейки. Количество меток аналогично размеру вашего z-буфера. Единственное отличие состоит в том, что z-буфер нелинейный (вид логарифмический, посмотрите его). –