11.Установить величину crease (складки) на рёбрах, содержащихся в группах вершин TextTop и TextBottom .
Наш окончательный скрипт следует за этой схемой почти в точности и использует инструменты, которые мы разработали раньше в этой главе. Мы покажем здесь наиболее важные секции (полный скрипт доступен как engrave.py). Мы начинаем с преобразования объекта Text3d (c в следующем коде) в список, содержащий список позиций вершин для каждого сегмента кривой в тексте, и мы добавляем новый пустой Меш-объект в сцену с несколькими пустыми группами вершин:
vlist = curve2mesh(c)
me = Blender.Mesh.New('Mesh')
ob = Blender.Scene.GetCurrent().objects.new(me,'Mesh')
me.addVertGroup('TextTop')
me.addVertGroup('TextBottom')
me.addVertGroup('Outline')
Следующий шаг должен добавить эти вершины в меш и создать соединяющие рёбра. Так как все сегменты кривой в символе замкнуты, мы должны позаботиться о добавлении дополнительного ребра, чтобы соединить мостом промежуток между последней и первой вершиной, как показано на выделенной строке. На всякий случай, мы удаляем любые задвоения, которые могут присутствовать в интерполированном сегменте кривой. Мы добавляем вершины к группе вершин TextTop и сохраняем ссылку на список новых рёбер для будущего использования.
loop=[]
for v in vlist:
offset=len(me.verts)
me.verts.extend(v)
edgeoffset=len(me.edges)
me.edges.extend([(i+offset,i+offset+1)
for i in range(len(v)-1)])
me.edges.extend([(len(v)-1+offset,offset)])
me.remDoubles(0.001)
me.assignVertsToGroup('TextTop',
range(offset,len(me.verts)),
1.0,
Blender.Mesh.AssignModes.ADD)
loop.append([me.edges[i] for i in range(edgeoffset,
len(me.edges) )])
Для каждого рёберного цикла, который мы сохранили в предыдущей части, мы создаем новый, и немного больший, рёберный цикл вокруг него и добавляем эти новые вершины и рёбра к нашему мешу. Мы также хотим создать грани между этими рёберными циклами, и это действие начинается на выделенной строке: здесь мы используем встроенную функцию Питона zip() , чтобы получить пары рёбер двух рёберных циклов. Каждый рёберный цикл упорядочен вспомогательной функцией (доступной в Tools.py ), которая сортирует рёбра, чтобы они лежали в порядке, в котором они соединены друг с другом. Для каждой пары рёбер мы создаем две возможных организации индексов вершин и вычисляем, какая из них формирует нескрученную грань. Это вычисление производится посредством функции least_warped() (код не показан), которая основана на сравнении периметров граней, заданных двумя различными порядками вершин. Нескрученная грань будет иметь самый короткий периметр, именно её мы затем добавляем к мешу.
for l in range(len(loop)):
points = expand.expand(me,loop[l],
0.02,loop[:l]+loop[l+1:])
offset=len(me.verts)
me.verts.extend(points)
edgeoffset=len(me.edges)
me.edges.extend([(i+offset,i+offset+1)
for i in range(len(points)-1)])
me.edges.extend([(len(points)-1+offset,offset)])
eloop=[me.edges[i] for i in
range(edgeoffset,len(me.edges))]
me.assignVertsToGroup('Outline',
range(offset,len(me.verts)),
1.0,
Blender.Mesh.AssignModes.ADD)
faces=[]
for e1,e2 in zip( expand.ordered_edgeloop(loop[l]),
expand.ordered_edgeloop(eloop)):
f1=(e1.v1.index,e1.v2.index,
e2.v2.index,e2.v1.index)
f2=(e1.v2.index,e1.v1.index,
e2.v2.index,e2.v1.index)
faces.append(least_warped(me,f1,f2))
me.faces.extend(faces)
Мы опустили код выдавливания рёберной петли символа, но следующие строки содержательны, так как они показывают, как заполняется рёберный цикл. Сначала мы выбираем все важные рёбра, используя две вспомогательные функции (это - выдавленные рёбра символов). Затем, мы вызываем метод fill() . Этот метод будет заполнять любой набор замкнутых рёберных циклов до тех пор, пока они лежат в одной плоскости. Он даже позаботится об отверстиях (подобно небольшому острову в букве e ):
deselect_all_edges(me)
select_edges(me,'TextBottom')
me.fill()
Дополнение cartouche - просто вопрос добавления прямоугольного рёберного цикла вокруг наших символов. Если этот рёберный цикл выбрать вместе с вершинами в группе вершин Outline , можно снова использовать метод fill() для заполнения этого cartouche. Это не показано здесь. Несколько заключительных штрихов: мы по возможности преобразуем треугольники в нашем меше в четырехугольники, используя метод triangleToQuad() , затем подразделяем меш. Мы также добавляем модификатор subsurface, устанавливаем атрибут сглаживания ( smooth ) на всех гранях и пересчитываем нормали всех граней, чтобы они согласованно указывали наружу.
Читать дальше