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

Если оба объекта имеют сравнимую массу, гравитационное искажение должно быть сравнимого размера на обоих объектах. У нас может появиться искушение добавить  ограничения TrackTo и moon_constraint.py к обоим объектам, чтобы видеть эффект воздействия их друг на друга, но, к несчастью, это не будет работать, поскольку это создаст циклическую зависимость, и Блендер запротестует.

Привязка к вершинам меша

Это похоже на режим "snap to vertex" (привязка к вершине), который доступен в Блендере из меню Object | Transform | Snap (информацию   о   привязках   смотрите   тут: http://wiki.blender.org/index.php/Doc:Manual/Modelling/Meshes/Snap_to_ Mesh), за исключением того, что эффект не постоянный (объект вернётся в свою изначальную позицию, как только ограничение будет удалено) и силу ограничения можно регулировать (даже анимировать), изменяя движок Influence (Влияние).

В ограничениях, которые мы до сих пор разрабатывали, нам нужна была только позиция целевого объекта для вычисления эффектов на ограничиваемом объекте. Эту позицию было легко применять в функции doConstraint(), так как матрицы целей принимались в качестве аргументов. Теперь мы все же встречаем другой вызов: если мы хотим привязать к вершине, мы должны иметь доступ к данным меша целевого объекта, но целевой объект не передаётся в функцию doConstraint().

Путь в обход этого препятствия - аргумент idprop, который передаётся в  doConstraint(). Перед тем, как вызвать doConstraint(), Блендер сначала вызывает doTarget() для каждого целевого объекта. Эта функция передаётся в виде ссылки на целевой объект и в свойства ограничения. Это позволяет нам включать ссылку на целевой объект в эти свойства, и поскольку эти свойства передаются в doConstraint(), это обеспечивает нас средствами для передачи необходимой информации в doConstraint() для получения Меш-данных. Есть мелочь, которую мы всё-же рассмотрим здесь: свойствами в Блендере могут быть только числа или строки, так что мы не можем на самом деле хранить ссылку на объект, но должны удовольствоваться его именем. Поскольку имя является уникальным, и функция Блендера Object.Get() предоставляет способ извлекать объект по имени, это - не проблема.

Код для функций doConstraint() и doTarget() будет выглядеть так (полный код находится в zoning_constraint.py):

def doConstraint(obmatrix, targetmatrices, idprop):

    obloc = obmatrix.translationPart().resize3D()

    obrot = obmatrix.toEuler()

    obsca = obmatrix.scalePart()

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

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

    me = to.getData(mesh=1)

    # получаем местоположение целевого объекта

    tloc = targetmatrices[0].translationPart().resize3D()

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

    smallest = 1000000.0

    delta_ob=tloc-obloc

    for v in me.verts:

        d = (v.co+delta_ob).length

        if d < smallest:

            smallest=d

            sv=v

    obloc = sv.co + tloc

    # восстанавливаем матрицу объекта

    mtxrot = obrot.toMatrix().resize4x4()

    mtxloc = Mathutils.TranslationMatrix(obloc)

    mtxsca = Mathutils.Matrix([obsca[0],0,0,0],

                              [0,obsca[1],0,0],

                              [0,0,obsca[2],0],

                              [0,0,0,1])

    outputmatrix = mtxsca * mtxrot * mtxloc

    return outputmatrix

def doTarget(target_object, subtarget_bone, target_matrix,

             id_prop_of_constr):

   id_props_of_constr['target_object']=target_object.name

   return target_matrix

Выделенные строки показывают, как мы передаем имя целевого объекта в doConstraint(). В doConstraint() мы сначала извлекаем целевой меш. Это может вызвать исключение, например, если целевой объект не является мешем, но оно будет поймано Блендером самостоятельно. Тогда  ограничение не станет воздействовать, ошибка будет показана в консоли, но Блендер продолжит нормальную работу.

Перейти на страницу:

Похожие книги