Задача обхода графа 3D-сцены - PullRequest
2 голосов
/ 13 июля 2011

Я реализовал небольшой граф сцены, который будет отображаться OpenGL, все объекты происходят из общего класса Node, и во время рендеринга фрейма OpenGL я просто вызываю метод visit корневого узла, и он рекурсивно обходит граф , Первая матрица, которую я прохожу при начале обхода, - это матрица камеры.

Метод visit выглядит следующим образом:

void Node::visit(const QMatrix4x4 &mv) {
    QMatrix4x4 m = mv;
    m.rotate(m_rot);
    m.translate(m_pos);
    m.scale(m_scale);

    m_effectiveMV = m;

    for (int i = 0; i < m_children.size(); i++) {
        m_children[i]->visit(m_effectiveMV);
    }

    draw(); // draws if this node has anything to draw,
            // otherwise just transformation.
}

Проблема, с которой я сталкиваюсь, заключается в том, что, когда я устанавливаю ротацию для дочернего узла, ротация происходит относительно родительского узла, а не вокруг самого узла. Кто-нибудь может заметить, что я здесь делаю не так?

Ответы [ 2 ]

6 голосов
/ 13 июля 2011

Предполагая, что ваши матричные методы работают правильно, перевод должен быть первым в списке:

m.translate(m_pos);
m.rotate(m_rot);
m.scale(m_scale);

Это сначала масштабирует и вращает вершину, затем переводит ее в родительскую систему и т. Д.на.

4 голосов
/ 13 июля 2011

Матричные операции не являются коммутативными, то есть порядок, в котором происходит умножение матриц, имеет значение. Сначала вращение чего-либо, затем его перевод, отличается от первого перевода, а затем вращения / вращения вокруг исходного центра.

Вместо создания преобразования путем последовательного применения различных преобразований, я рекомендую создать его напрямую. Верхний левый 3 × 3 - это часть вращения, которую вы можете скопировать непосредственно из матрицы вращения. Масштабирование умножает коэффициенты x, y, z на 1-й, 2-й и 3-й столбцы матрицы. Перевод 4-й колонки. Вращение сохраняется как матрица 3 × 3 или кватернион. Не используйте углы Эйлера, они численно нестабильны.

...