Книга: Написание скриптов для Blender 2.49

Выравнивание вдоль вершинной нормали

Выравнивание вдоль вершинной нормали

Теперь, когда мы смогли привязать объект к ближайшей вершине в целевом меше, мы можем видеть, что что-то пропустили: объект не сориентирован в правильном направлении. Это не всегда является проблемой, например, деревья обычно направлены вверх, но во многих ситуациях было бы неплохо, если бы мы смогли сориентировать  ограничиваемый объект перпендикулярно поверхности. Это делается также для всех практических целей, как ориентация ограничиваемого объекта вдоль вершинной нормали той вершины, к которой мы сделали привязку.

Следовательно, после обнаружения ближайшей вершины, мы определяем угол между вершинной нормалью и осью z (то есть, мы произвольно определяем направление Z как 'вверх'), затем вращаем ограничиваемый объект на тот же самый угол вокруг оси, перпендикулярной как вершинной нормали, так и оси z. Это сориентирует ограничиваемый объект вдоль этой вершинной нормали. Если ограничиваемый объект был вручную повёрнут до добавления  ограничения, эти предыдущие вращения будут потеряны. Если это - не то, что нам нужно, мы можем применить все вращения перед добавлением ограничения.

Для того, чтобы осуществить эту возможность выравнивания, наш код изменится (zoning_constraint.py уже содержит эти изменения): doConstraint() должно вычислять поворотную часть матрицы преобразования. Мы должны вычислить угол вращения, ось вращения, и затем новую матрицу вращения. Выделенная часть следующего кода показывает, что основные инструменты для этих вычислений уже предусмотрены модулем Mathutils:

vnormal = sv.no
if idprop['NormalAlign'] :
    zunit=Mathutils.Vector(0,0,1)
    a=Mathutils.AngleBetweenVecs(vnormal,zunit)
    rotaxis=zunit.cross(vnormal)
    rotmatrix=Mathutils.RotationMatrix(a,4,"r",rotaxis)
    mtxrot = rotmatrix
else:
    mtxrot = obrot.toMatrix().resize4x4()

В предыдущем коде мы можем видеть, что мы сделали выравнивание зависимым от свойства NormalAlign. Только если оно задано, мы вычисляем необходимое преобразование. Следовательно, нам нужно адаптировать также функцию getSettings(), поскольку пользователю нужен способ выбирать, нужно ему выравнивание или нет:

def getSettings(idprop):
    if not idprop.has_key('NormalAlign'):
       idprop['NormalAlign'] = True
    align = Draw.Create(idprop['NormalAlign'])
    block = []
    block.append("Additional restrictions: ")
    block.append(("Alignment: ",align,
                  "Align along vertex normal"))
    retval = Draw.PupBlock("Zoning Constraint", block)
    if (retval):
        idprop['NormalAlign']= align.val

Как показано, свойство NormalAlign по умолчанию будет установлено в True (Истина). Опция затем будет представлена как простое выпадающее меню с кнопкой-переключателем. Если пользователь щелкает за пределами меню или нажимает клавишу EscPupBlock() вернёт значение None, мы не будем изменять свойство NormalAlign. В противном случае, оно будет установлено в соответствии со значением кнопки-переключателя.

Эффекты показаны на иллюстрациях. Первая показывает небольшую ёлку с ограничением привязки к вершине простой подразделенной плоскости земли. Она привязана в точную позицию вершины, но ось z указывает ровно вверх вдоль глобальной оси z. Скриншот показывает ёлку с ограничением к вершине в скалистом пейзаже.


Если мы включим свойство NormalAlign, мы увидим, что модель дерева больше не указывает ровно вверх, но что ось z выровнена вдоль направления вершинной нормали той вершины, к которой она привязана. Следующий скриншот показывает елку с ограничением к вершине и выравниванием вдоль вершинной нормали.


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


Оглавление книги


Генерация: 0.037. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз