Чтение онлайн

ЖАНРЫ

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

Anders Michel

Шрифт:

if (retval):

idprop['NormalAlign']= align.val

Как показано, свойство

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

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

Если мы включим свойство

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

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

Привязка к вершинам в вершинной группе

Что, если мы хотим определить конкретно те вершины, к которым мы можем привязать объект? Это можно достигнуть, определив группу вершин, и, затем, рассматривая только вершины из этой группы в качестве кандидатов, к которым можно привязывать. Код необходимый для этого, увеличится всего на несколько строк, и важная часть

doConstraint
будет выглядеть примерно так (выделенный код показывает дополнительные строки, имеющие дело с проверкой на принадлежность к группе вершин):

# получаем целевой меш

to = Blender.Object.Get(idprop['target_object'])

me = to.getData(mesh=1)

# получаем положение целевого меша

tloc = targetmatrices[0].translationPart.resize3D

# ищем ближайшую вершину в целевом объекте

smallest = 1000000.0

delta_ob=tloc-obloc

try:

verts = me.getVertsFromGroup(idprop['VertexGroup'])

for vi in verts:

d = (me.verts[vi].co+delta_ob).length

if d < smallest :

smallest = d

si = vi

obloc = me.verts[si].co+tloc

vnormal = me.verts[si].no

except AttributeError:

for v in me.verts:

d = (v.co+delta_ob).length

if d < smallest:

smallest=d

sv=v

obloc = sv.co + tloc

vnormal = sv.no

Автор здесь нарушил одно из важнейших правил качественного программирования, которое гласит «Нет дублированию кода!» Текст после try желательно переписать, например, так:

try:

verts = me.getVertsFromGroup(idprop['VertexGroup'])

except AttributeError:

verts = range(len(me.verts))

for vi in verts:

d = (me.verts[vi].co+delta_ob).length

if d < smallest :

smallest = d

si = vi

obloc = me.verts[si].co+tloc

vnormal = me.verts[si].no

Примечание занудного и наглого переводчика Striver'а

Конструкция

try/except
гарантирует, что если свойство
VertexGroup
ссылается на несуществующую группу вершин, мы получим шанс проверить все вершины. Конечно, нам теперь нужен способ для пользователя, позволяющий выбирать группу вершин, так что функцию
getSettings
нужно тоже адаптировать. Мы довольствуемся простым полем ввода строки, где можно набрать имя группы вершин. Нет проверки на существование группы, и если мы не хотим ограничиваться привязкой к группе вершин, тогда мы можем или оставить это поле ввода пустым, или занести имя несуществующей группы. Не слишком изящно, но это работает (дополнительные строки выделены):

def getSettings(idprop):

if not idprop.has_key('VertexGroup'):

idprop['VertexGroup'] = 'Zone'

if not idprop.has_key('NormalAlign'):

idprop['NormalAlign'] = True

vgroup = Draw.Create(idprop['VertexGroup'])

align = Draw.Create(idprop['NormalAlign'])

block = []

block.append("Additional restrictions: ")

block.append(("Vertex Group: ",vgroup,0,30,"Vertex

Group to restrict location to"))

block.append(("Alignment: ",align,

"Align along vertex normal"))

retval = Draw.PupBlock("Zoning Constraint", block)

if (retval):

Поделиться с друзьями: