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

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

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

Это похоже на режим "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() мы сначала извлекаем целевой меш. Это может вызвать исключение, например, если целевой объект не является мешем, но оно будет поймано Блендером самостоятельно. Тогда  ограничение не станет воздействовать, ошибка будет показана в консоли, но Блендер продолжит нормальную работу.

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

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


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