Сохранение вращений в OpenGL - PullRequest
1 голос
/ 01 октября 2010

Я рисую объект (скажем, куб) в OpenGL, который пользователь может вращать, щелкая / перетаскивая мышь по окну.Куб нарисован так:


void CubeDrawingArea::redraw()
{ 
    Glib::RefPtr gl_drawable = get_gl_drawable();

    gl_drawable->gl_begin(get_gl_context());

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    {
        glRotated(m_angle, m_rotAxis.x, m_rotAxis.y, m_rotAxis.z);
        glCallList(m_cubeID);
    }
    glPopMatrix();

    gl_drawable->swap_buffers();

    gl_drawable->gl_end();
}

и вращается с помощью этой функции:

<pre> bool CubeDrawingArea::on_motion_notify_event(GdkEventMotion* motion) { if (!m_leftButtonDown) return true;</p> <pre><code>_3V cur_pos; get_trackball_point((int) motion->x, (int) motion->y, cur_pos); const double dx = cur_pos.x - m_lastTrackPoint.x; const double dy = cur_pos.y - m_lastTrackPoint.y; const double dz = cur_pos.z - m_lastTrackPoint.z; if (dx || dy || dz) { // Update angle, axis of rotation, and redraw m_angle = 90.0 * sqrt((dx * dx) + (dy * dy) + (dz * dz)); // Axis of rotation comes from cross product of last / cur vectors m_rotAxis.x = (m_lastTrackPoint.y * cur_pos.z) - (m_lastTrackPoint.z * cur_pos.y); m_rotAxis.y = (m_lastTrackPoint.z * cur_pos.x) - (m_lastTrackPoint.x * cur_pos.z); m_rotAxis.z = (m_lastTrackPoint.x * cur_pos.y) - (m_lastTrackPoint.y * cur_pos.x); redraw(); } return true;

}

Там есть кое-что о GTK +, но должно быть достаточно очевидно, для чего оно.Функция get_trackball_point () проектирует окно координаты XY на полушарии (виртуальный «трекболом»), который используется в качестве опорной точки для вращения объекта.В любом случае, это более или менее работает, но после того, как я закончу вращение и я снова поверну, куб вернется в исходное положение, очевидно, так как m_angle будет сброшен обратно почти до 0 в следующий раз, когда я поверну.Есть ли способ избежать этого и сохранить вращение?

1 Ответ

0 голосов
/ 01 октября 2010

Да, я тоже столкнулся с этой проблемой.

Что вам нужно сделать, так это сохранить матрицу вращения, которая "накапливает" текущее состояние вращения, и использовать ее в дополнение к матрице вращения, которая приходитиз текущей операции перетаскивания.

Скажем, у вас есть две матрицы, lastRotMx и currRotMx.Сделайте их членами CubeDrawingArea, если хотите.

Вы не показали нам это, но я предполагаю, что m_lastTrackPoint инициализируется всякий раз, когда кнопка мыши нажимается для перетаскивания.Когда это произойдет, скопируйте currRotMx в lastRotMx.

Затем в on_motion_notify_event(), после вычисления m_rotAxis и m_angle, создайте новую матрицу вращения draggingRotMx на основе m_rotAxis и m_angle;затем умножьте lastRotMx с помощью draggingRotMx и поместите результат в currRotMx.

Наконец, в redraw() вместо

   glRotated(m_angle, m_rotAxis.x, m_rotAxis.y, m_rotAxis.z);

поверните на currRotMx.

Обновление: Или вместо всего этого ... Я не проверял это, но я думаю, что это сработало бы:

Сделайте cur_pos членом класса, чтобы он оставался, но он был инициализирован нулем, какm_lastTrackPoint.Затем, всякий раз, когда начинается новое движение перетаскивания, перед инициализацией m_lastTrackPoint, пусть _3V dpos = cur_pos - m_lastTrackPoint (псевдокод).Наконец, когда вы инициализируете m_lastTrackPoint на основе координат события мыши, вычтите из него dpos.

Таким образом, ваши cur_pos уже будут смещены от m_lastTrackPoint на величину, основанную на накоплении смещений от прошлых перетаскиваний дуги.

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

PS Ваше имя пользователя демотивирует.Предложите выбрать еще один.

PPS Для тех, кто позже ищет ответы на этот вопрос, ключевые слова для поиска: « arcball вращение ».Окончательной статьей является раздел Кена Шумейка в Graphical Gems IV .Смотрите также этот учебник по Arcball для JOGL .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...