Я пытаюсь воссоздать солнечную систему в 3D. Солнце, планеты и луны рассчитываются и рисуются правильно, но я хочу нарисовать «полый» круг, представляющий орбиту каждого объекта, который у меня есть.
Мне удалось вычислить серию точек для каждой орбиты, которую я сохраняю в vector<glm::vec3>
, например, с орбитой с 20 точками:
(1.40129, 3.20724, 0)
(2.36675, 2.57846, 0)
(3.07574, 1.67027, 0)
(3.45143, 0.58108, 0)
(3.4531, -0.571081, 0)
(3.08057, -1.66136, 0)
(2.37421, -2.5716, 0)
(1.41057, -3.20317, 0)
(0.294079, -3.48762, 0)
(-0.854285, -3.39414, 0)
(-1.91007, -2.93285, 0)
(-2.75888, -2.15374, 0)
(-3.30871, -1.14124, 0)
(-3.5, -0.00506855, 0)
(-3.312, 1.13165, 0)
(-2.7651, 2.14574, 0)
(-1.91856, 2.92731, 0)
(-0.864112, 3.39165, 0)
(0.283976, 3.48846, 0)
(1.40129, 3.20724, 0)
Здесь орбита остается на z = 0, но это не всегда так.
Я думал, что мне просто нужно провести линии между каждой из этих точек, вот так:
glBegin(GL_LINES);
glColor3f(1.0f, 1.0f, 1.0f); // White color
for (auto& point : planet->orbitPoints) {
glVertex3f(point.x, point.y, point.z);
}
glEnd();
Но ничего не появляется. Я пытался рисовать простые линии, вручную записывая разные координаты, но это тоже не работает.
Я работаю в трехмерном пространстве, используя glm::perspective
в качестве проекции и матрицы модели / вида / проекции для шейдера.
Можно ли в этих условиях просто рисовать линии или это сложнее?
Редактировать: Нашел решение.
Как упоминал genpfault, я пытался объединить шейдеры и код с фиксированной функцией, что является причиной того, что приведенный выше код не работал.
Поскольку точки кругов / орбит, которые я хотел нарисовать, уже были рассчитаны, мне просто нужно было провести линию между этими точками. Для заинтересованных, вот как я это сделал:
1. Сгенерируйте вектор для хранения вершин круга (перед циклом визуализации во время):
// Create the vector which will store the vertices of each orbit, and create a buffer for it
vector<vec3> orbitVertices;
GLuint orbitVertexBuffer;
glGenBuffers(1, &orbitVertexBuffer);
2. В цикле при рендеринге переключитесь на этот буфер и используйте его для рисования линий с помощью функции glDrawArrays
:
// Change the vertex buffer to the orbit one
glBindBuffer(GL_ARRAY_BUFFER, orbitVertexBuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *) nullptr // array buffer offset
);
// Re-init the "model" matrix to an identity matrix
mat4 model = mat4(1.0f);
glUniformMatrix4fv(glGetUniformLocation(programID, "model"), 1, GL_FALSE, value_ptr(model));
// Draw the orbits
for (auto &object : objects) { // For each planet, moon, etc.
orbitVertices = object->orbitPoints; // Get the points making up the circle
glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * orbitVertices.size(), orbitVertices.data(), GL_DYNAMIC_DRAW); // Pass it as data for the buffer
glDrawArrays(GL_LINE_LOOP, 0, orbitVertices.size()); // Draw the lines
}
Что, с некоторыми настройками цвета и большим количеством очков для больших кругов, дает мне результаты, которые я хотел:
см. мой glCircle3D .. однако, если вы используете реальные орбиты, увидите Можно ли создать реалистичную симуляцию солнечной системы из n тел с точки зрения размера и массы? и решение уравнения Кеплера
Спасибо за разъяснения, это вернуло меня к поиску хорошего решения.
Используйте линии для аппроксимации круга: glDrawElements(GL_LINES, ...
Также, как упоминалось в genpfault, переключитесь на поток объектов буфера вершин / индексов.
http://ogldev.atspace.co.uk/www/tutorial10/tutorial10.html
Нашел решение (см. Отредактированный пост). Как вы упомянули genpfault, я переключился на поток объектов буфера вершин. Однако мне не пришлось использовать индексный буфер, так как я хотел только рисовать линии. glDrawArrays
, которому нужен только буфер вершин, в этом случае подойдет.
Комбинация шейдеров и кода с фиксированными функциями - это гигантский красный флаг. Отредактируйте в минимальный воспроизводимый пример.