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

Шрифт
Интервал

стр.

. У него есть метод extend(), который принимает список кортежей, каждый из которых содержит координаты x, y, и z создаваемых вершин. Точно так же метод extend() атрибута faces принимает список кортежей, каждый из которых содержит три или больше индексов, указывающих на вершины, которые вместе определяют грань. Порядок здесь важен: нам нужно сначала добавить новые вершины; в противном случае вновь созданные грани не смогут ссылаться на них. Нет необходимости определять какие-либо рёбра, так как добавление граней также неявно создаст рёбра, которые ещё не присутствуют.

Меш по своей сути еще не является объектом, которым может манипулировать пользователь, так что в следующих нескольких строках (выделено), мы извлекаем текущую сцену и добавляем в неё новый объект. Аргументы функции new() - меш-объект, который мы создали ранее, и имя, которое мы хотим дать объекту. Имя, даваемое объекту, может быть таким же, как и данное мешу, так как имена мешей и имена объектов существуют в различных пространствах имён. Как и с мешем, существующее имя будет сделано уникальным посредством добавления суффикса. Если имя опущено, новый объект получит в качестве имени по-умолчанию тип своего аргумента (Mesh в нашем случае).

Вновь созданный объект будет выбран, но не активен, так что мы исправим это, присвоив наш объект в scene.objects.active.

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


Преобразование топологии меша

Создание существа из строительных блоков требует, чтобы мы применяли дублирование, масштабирование, и отражение к этим строительным блокам прежде, чем мы склеим их вместе. В Блендере 2.49, это означает, что мы должны определить некоторые вспомогательные функции (утилиты), чтобы выполнить эти действия, так как они не присутствуют в API. Мы определяем эти вспомогательные функции в модуле Tools (инструменты), но мы осветим некоторые из них здесь, так как они покажут несколько интересных методов.

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


Схема кода сшивания рёберных циклов

В функции, которая создает новые грани, мы должны выполнить следующие шаги:

1. Удостовериться, что оба рёберных цикла цикла имеют одинаковую и ненулевую длину.

2. Для каждого ребра в цикле 1:

1. Найти ребро в цикле 2, которое ближе всего.

2. Создать грань, соединяющую эти два ребра.

Функция, которая осуществляет эту довольно сложную на вид схему:

>def bridge_edgeloops(e1,e2,verts):

>    e1 = e1[:]

>    e2 = e2[:]

>    faces=[]

>    if len(e1) == len(e2) and len(e1) > 0 :

Функция принимает аргументы: два списка рёбер и список вершин. Рёбра представлены в виде кортежей двух целых (индексы в списке вершин verts), а вершины - в виде кортежей координат x, y, и z.

Первая вещь, которую мы сделаем - создадим копии двух рёберных списков, поскольку мы не хотим испортить списки в их оригинальном контексте. Список граней, который мы будем строить, инициализируется в пустой список, и мы проверяем разумность и равенство длин обоих рёберных списков. Если это подтверждается, мы приступаем к следующему куску:

>for a in e1:

>    distance = None  # расстояние

>    best = None      # лучший

>    enot = []        # отвергнутые рёбра


стр.