Повернуть gluCylinder() вокруг определенной оси?

Я пишу функцию для рисования цилиндра, центр каждой базы которого находится в определенной точке, используя конвейерные команды OpenGL и функцию gluCylinder().

В качестве первой попытки я просто попытался нарисовать цилиндр, и в результате получился цилиндр с нижним основанием в центре (0, 0, 0), а с другим основанием в центре (0, 0, height), где height было передано в качестве аргумента функции.

Затем я попытался центрировать первую базу на первой выбранной точке, и все сработало как по маслу.

Теперь я изо всех сил пытаюсь получить правильное положение для второй точки: я вычислил расстояние между двумя точками и сохранил расстояние по каждой оси, чтобы получить разность векторов, поэтому все, что мне нужно сделать, это выполнить вращения так, что в любой системе отсчета ось цилиндра лежит на разности векторов двух точек.

Все-таки мне нужно найти координаты оси цилиндра и повернуть его, а как это сделать я не знаю.

Вот мой код, надеюсь, он будет полезен:

void drawCylinder(float pHeight, std::vector<float> center1, std::vector<float> center2) {

    const GLfloat* projection = glm::value_ptr(glm::perspective(glm::radians(fov), (float)WIN_WIDTH / (float)WIN_HEIGHT, 0.1f, 100.0f));
    const GLfloat* view = glm::value_ptr(camera.GetViewMatrix());

    glm::vec3 diff = glm::vec3(center2[0] - center1[0], center2[1] - center1[1], center2[2] - center1[2]);
    float distance = sqrt(pow(center2[0] - center1[0], 2) + pow(center2[1] - center1[1], 2) + pow(center2[2] - center1[2], 2));

    glUseProgram(0);

    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(projection);

    glPushMatrix();
    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(view);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glColor3f(1.0f, 1.0f, 0.0f);
    glTranslated(center1[0] - 12.25f, (center1[1]) + 0.0f, (center1[2]) - 12.25f);
    // Here I should perform the rotation in order to draw the cylinder in the right position
    gluCylinder(quadric, 0.1f, 0.1f, pHeight, 32, 32);
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

}

Я думал об обоих углах Эйлера и методах кватернионов, но я не могу понять, как использовать любой из них. Возможно, учитывая, что я использую метод конвейерных команд OpenGL, углы Эйлера были бы лучше. Тем не менее, если у вас есть лучший способ сделать все это, я буду рад узнать что-то новое.

Как я могу определить это вращение?


person F. Màlato    schedule 26.09.2019    source источник
comment
Такие вызовы, как glMatrix... устарели. Вместо этого рекомендуется использовать тени.   -  person doron    schedule 26.09.2019
comment
И как я могу использовать GLUT с шейдерами?   -  person F. Màlato    schedule 26.09.2019
comment
Только не употребляйте переедание. Современный OpenGl имеет все необходимые инструменты.   -  person churill    schedule 26.09.2019
comment
Вам необходимо ознакомиться с современным OpenGL. Я не уверен, чего вы пытаетесь достичь. Например, если вы хотите вращаться вокруг оси x-y-z, просто используйте glRotate после glTranslate. Или вы хотите вращаться вокруг определенного вектора? Кроме того, ваш вектор направления не нормализован.   -  person Constantinos Glynos    schedule 26.09.2019
comment
Я пытаюсь повернуть ось цилиндра так, чтобы она проходила через center1 и center2.   -  person F. Màlato    schedule 26.09.2019
comment
Используйте профиль совместимости (glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE) перед glutInitDisplayMode), после чего вы сможете использовать Legacy OpenGL ( glBegin/ glEnd, glLoadMatrixf, gluCylinder, ...)   -  person Rabbid76    schedule 26.09.2019
comment
@Rabbid76 Уже сделал это! Цилиндры нарисованы, но не в правильном положении, просто потому, что я не знаю, как создать экземпляр gluClylinder по заданной оси.   -  person F. Màlato    schedule 26.09.2019


Ответы (1)


Я рекомендую использовать математическую библиотеку, такую ​​как OpenGL Mathematics (GLM). библиотека.

Библиотека glm — это библиотека шаблонов. Для следующих операций вам просто нужно включить следующие файлы:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

Вычислите вектор от center2 до center1. И определите опорный вектор, например. (0, 0, 1):

glm::vec3 ref  = lm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 diff = glm::vec3(center2[0] - center1[0],
                           center2[1] - center1[1],
                           center2[2] - center1[2]);

Вы хотите определить матрицу вращения, которая вращается от ref до diff. Вычислите угол поворота - Скалярный продукт 2 Единичные векторы возвращает косинус угла между двумя векторами (единичный вектор имеет длину 1, и вектор можно превратить в единицу вектор от glm::normalize). Ось вращения может быть рассчитана с помощью перекрестного произведения. Настройте матрицу вращения, которая вращается вокруг оси на угол:

float     angle  = acos(glm::dot(ref, glm::normalize(diff)));
glm::vec3 axis   = glm::cross(b, a);
glm::mat4 rotmat = glm::rotate(glm::mat4(1.0f), angle, axis);

Используйте glMultMatrixf, чтобы умножить текущую матрицу на матрица вращения. например:

glTranslated(center1[0] - 12.25f, (center1[1]) + 0.0f, (center1[2]) - 12.25f);

// multiply current matrix by the rotation matrix
glMultMatrixf(glm::value_ptr(rotmat))

gluCylinder(quadric, 0.1f, 0.1f, pHeight, 32, 32);
person Rabbid76    schedule 26.09.2019
comment
Еще раз, это сработало для меня! Большое тебе спасибо. Кроме того, glm сделал все намного проще. - person F. Màlato; 26.09.2019