Вращение в MaxScript - пожалуй одно из самых загадочных преобразований. Использование кватернионов только усиливает впечатление (для любознательных - см. статью в Википедии). В справке по MaxScript сначала написано достаточно просто: кватернион состоит из угла поворота (скалярная часть) и направления оси поворота (векторная часть) - вроде все понятно. Следующее предложение интереснее: если кватернион нормализован, то скалярная часть равна косинусу половины угла поворота, а векторная часть - есть ось вращения, а длина вектора оси равна синусу половины угла поворота. Т.е. когда смотришь в окне консоли (Listener) на значение нормализованного кватерниона, то сии циферки, кроме тривиальных случаев, не вызывают никаких ассоциаций. Например, (quat 0 0 0.258819 0.965926)
означает всего навсего поворот на 30° вокруг оси Z. Не буду спорить, что алгебра кватернионов - штука мощная и полезная как в вычислительном плане, так и для получения "сглаженного и естественного движения", но для человеческого разума - совершенно неудобоваримая.
Дополнительной пикантности придает путаница с положительным направлением поворота относительно оси: везде в Максе используется правая система, а при работе с матрицей трансформации - левая. (Для запоминания: сожмите руку в кулак и вытяните большой палец - большой палец указывает направление оси, а остальные - положительное направление поворота.)
Далее представлены плоды моих изысканий в данной области. Целью было понять, как в MaxScript выполнить поворот вектора или объекта на заданный угол относительно заданной точки. Поэтому некоторые моменты, связанные с наследованием трансформаций, координатными системами и т.п. просто не учитывались.
Скрипт состоит из трех функциональных частей:
point3
) вокруг указанного центра и визуализация его конечного положения в виде объектов Point (помечено красным цветом);about ... rotate
(помечено синим цветом);about ... rotate
, посредством присваивания свойствам pos и rotation соответствующих значений (помечено зеленым цветом).
В каждой части имеется цикл, в котором переменная a принимает значения от 0° до 150° с шагом 30°. Использование конечного значения 150° позволяет лучше видеть начальное и конечное положение, а также направление поворота.
Остальные комментарии - в теле скрипта. Если редакторе MaxScript кириллица отображается некорректно, то в файле <maxroot>/MXS_Editor.properties
необходимо заменить значение code.page
на 0 (вместо -1) и перезапустить 3ds Max.
В результате работы скрипта должна появиться вот такая картинка:
-- Проверка вращения вектора относительно произвольной точки undo "rotationTest" on ( pt = [50, 0, 0] -- вектор center = [50, 50, 0] -- центр вращения axis = [0, 0, 1] -- ось вращения (Z) -- при использовании матрицы вращения -- происходит левый поворот (против часовой стрелки) for a = 0 to 150 by 30 do ( -- угол вращения q = quat a axis -- кватернион: поворот на угол a относительно положительного направления оси Z rm = q as matrix3 -- преобразуем кватернион в матрицу вращения -- rm = inverse rm -- инвертировать матрицу поворота для правого поворота (по часовой стрелке) -- этот оператор должен стоять ДО задания цетра поворота rm.row4 = center -- четвертая строка матрицы - задаем центр вращения rotpt = pt * rm -- поворачиваем вектор point pos:rotpt box:true wirecolor:red -- создаем объект Point в текущем положении повернутого вектора -- здесь вращаем только вектор, объект создается без поворота format "a = % rotpt = %\n" a rotpt -- выводим лог в Listener ) -- при использовании конструкции about ... rotate -- происходит правый поворот (по часовой стрелке) pobj = point pos:(pt + center) box:true wirecolor:blue name:"rotPoint00" size:15 for a = 0 to 150 by 30 do ( -- угол вращения npobj = instance pobj -- создаем инстанс объекта Point npobj.wirecolor = blue q = quat a axis -- кватернион: поворот на угол a относительно положительного направления оси Z about center rotate npobj q -- поворачиваем объект вокруг заданного центра на текущий угол ) delete pobj -- удаляем исходный объект -- поворот объекта, аналогичный использованию конструкции about ... rotate, -- посредством присваивания свойствам pos и rotation соответствующих значений pobj = point pos:pt box:true wirecolor:green name:"rotmatrixPoint00" size:10 for a = 0 to 150 by 30 do ( -- угол вращения npobj = instance pobj -- создаем инстанс объекта Point npobj.wirecolor = green q = quat a axis -- кватернион: поворот на угол a относительно положительного направления оси Z rm = q as matrix3 -- преобразуем кватернион в матрицу вращения rm = inverse rm rm.row4 = center -- четвертая строка матрицы - задаем центр вращения npobj.pos *= rm -- поворачиваем объект вокруг заданного центра на текущий угол (без вращения самого объекта!) in coordsys (transmatrix npobj.pos) npobj.rotation = q -- поворачиваем сам объект вокруг пивота на текущий угол ) delete pobj -- удаляем исходный объект ) -- undo
© Black Sphinx, 2009. All rights reserved. | Counter |