Michel Anders - Написание скриптов для Blender 2.49
me=ob.getData(mesh=1)
mats=[ Blender.Material.New(), Blender.Material.New()]
mats[0].rgbCol=[1.0,1.0,1.0]
mats[1].rgbCol=[0.0,0.0,0.0]
ob.setMaterials(mats)
ob.colbits=3
for f in me.faces:
if f.index%2 == 0 :
f.mat=0
else:
f.mat=1
Выделенная строка гарантирует, что индексы материалов, используемые для каждой грани, относятся к материалам, назначенным на объект. (Также возможно связать материалы с меш-данными, как мы увидим в следующей секции.)
Материалы Объекта против материалов ObData
В Блендере и Меш-объект и объект Блендера верхнего уровня, содержащий Меш-объект, могут иметь свой собственный список из 16 материалов. Это удобно, если нам нужно множество экземпляров копии одного и того же меша, но с приложенными различными материалами. Тем не менее, в некоторых ситуациях, мы можем захотеть приложить некоторые или все материалы к Мешу, а не к объекту. Это управляется атрибутом объекта colbits. Этот атрибут состоит из 16 битов, и каждый из них указывает использовать материал от Объекта или от Меша. Мы уже видели пример с этим атрибутом в предыдущей секции.
Объект Кривой (Curve) также может иметь собственный набор материалов, и выбор фактического материала подчиняется тем же правилам, что и для Меш-объекта. Метаболлы также имеют свой собственный набор материалов, и переключение между комплектами материалов производится так же, но в отличие от многих типов объектов, которые состоят из частей (смотри следующую секцию), нет способа соединять различные материалы с различными элементами в пределах Метаболла (это истиннно также и в графическом интерфейсе пользователя: кнопки на панели Links and Materials контекста Редактирования существуют, чтобы назначать индексы материалов индивидуальным элементам метаболла, но они не дают эффекта). Используется только первый слот списка материалов.
Заметьте, что объекты, которые не визуализируются сами, как например, арматуры и решетки, не имеют связанных материалов (таким образом, любые материалы, связанные с Объектом верхнего уровня, содержащим арматуру или решетку, будут проигнорированы). Некоторые объекты, которые не имеют связанных материалов, могут иметь связанные с ними текстуры. Объекты Мира и Лампы, например, можно связать с текстурами, чтобы управлять их цветами.
Назначение материалов частям Объекта
В пределах меша каждая грань может иметь собственный, связанный с ней материал. Этот материал идентифицируется своим индексом в списке материалов и сохраняется в атрибуте mat. В пределах объекта Text3d, каждый символ может иметь собственный материал, опять же идентифицируемый своим индексом в списке материалов. На этот раз, этот индекс не хранится непосредственно в атрибуте, но может быть установлен или извлечен методами accessor, которые принимают индекс символа в тексте в качестве аргумента.
Секциям внутри Кривой (объекты CurNurb), можно назначить индекс материала их методом setMatIndex(). Индекс мог быть извлечен из них соответствующим методом getMatIndex(). Заметьте, что связь материала с кривыми, которые состоят из единственной линии без настроенной выдавленной ширины или связанного объекта скоса, не будет иметь видимых эффектов, так как эти кривые не рендерятся.
Следующий кусок кода показывает как назначать различные материалы различным символам в пределах объекта Text3d. Сам код прост, но как Вы можете заметить, мы определяем список из трех материалов, но используем только один. Это расточительно, но необходимо, чтобы обойти специфику в функции setMaterial(). Её аргумент индекса материала должен быть смещён на один, например, индекс 2 имеет отношение ко второму материалу в списке, тем не менее, самый большой индекс может пройти не смещённым на единицу. Так если мы хотели бы использовать два материала, мы должны бы использовать индексы 1 и 2, чтобы иметь доступ к материалам 0 и 1, но фактический список материалов должен содержать три материала, в противном случае мы не сможем передать 2 в качестве аргумента в setMaterial().
mats=[Material.New(),Material.New(),Material.New()]
mats[0].rgbCol=[1.0,1.0,1.0]
mats[1].rgbCol=[0.0,0.0,0.0]
mats[2].rgbCol=[1.0,0.0,0.0]
ob.setMaterials(mats)
ob.colbits=3
txt=ob.getData()
for i in range(len(txt.getText())):
txt.setMaterial(i,1+i%2)
Выделенный код показывает коррекцию на 1. Полный код представлен как TextColors.py.
Вершинные цвета против материалов граней
Один важный аспект работы с материалами, с которым мы пока не имели дела - цвета вершин. В мешах каждая вершина может иметь собственный цвет вершины. Цвет вершины отличается от материала, но будут ли цвета вершин вызывать какие-то видимые эффекты, контролируется флагами режима материала. Чтобы использовать любые цвета вершины в материале, должен быть установлен бит VColPaint вызовом метода setMode(). Когда используется этот режим, цвета вершин определяют диффузный (рассеянный) цвет материала, тогда как все обычные атрибуты материалов управляют способом, которым этот диффузный цвет будет рендериться. Обычное использование для цветов вершин - это запекание дорогих в вычислительном отношении эффектов, как например, ambient occlusion. Поскольку цвета вершин можно рендерить очень быстро, ambient occlusion может быть аппроксимирована этим способом, даже в настройке реального времени, как например, в игровом движке. (Аппроксимирована, поскольку при этом не будет такой же реакции на изменения в освещении.)
Цвета вершин сохраняются как объекты Mesh.MCol (основаны на кортежах RGBA) в атрибуте грани col. Атрибут col является списком, содержащим ссылку на объект MCol для каждой вершины в грани. У такого размещения проявится смысл, когда Вы поймёте, что фактически материалы связаны с гранями, а не с вершинами. Когда цвета вершин различны, они линейно интерполируются через грань.
Присваивать атрибуту грани col возможно, если только у меша был установлен его атрибут vertexColors в Истину.
Следующий пример показывает, как мы можем установить цвета вершин меша. Мы выбираем градации серого в зависимости от координаты z вершин (выделено).
import Blender
ob=Blender.Scene.getCurrent().objects.active
me=ob.getData(mesh=1)
me.vertexColors=True
for f in me.faces:
for i,v in enumerate(f.verts):
g = int(max(0.0,min(1.0,v.co.z))*255)
f.col[i].r=g
f.col[i].g=g
f.col[i].b=g
mats=[Blender.Material.New()]
mats[0].setMode(Blender.Material.Modes['VCOL_PAINT'])
ob.setMaterials(mats)
ob.colbits=1
ob.makeDisplayList()
Blender.Window.RedrawAll()
Полный код доступен как VertexColors.py.
Добавление материалов в нашу гравюру
Как последний штрих в нашей деятельности с гравюрой, мы добавим два материала. Один индекс материала назначим вершинам на поверхности, и другой вершинам в выточенных канавках. Этим методом мы можем, например, создать проявление вновь созданной надписи на куске выветренного камня.
Так как мы ранее определили несколько удобных групп вершин, назначение индексов материала будет вопросом итерации над всеми гранями и назначения в каждую вершину грани подходящего индекса материала в зависимости от того, членом какой вершинной группы является вершина. Функция, показанная ниже, принимает чуть более общий подход, так как она принимает меш и список регулярных выражений, и назначает индекс материала на каждую грань в зависимости от принадлежности к группе вершин, которая имеет имя, соответствующее одному из регулярных выражений.
Эти функции делают очень легким назначение одинакового индекса материала во все группы вершин, которые имеют аналогичные имена, например все хвосты и сегменты грудной клетки меша, создаваемого creepycrawlies.py (они все имеют такие имена как, например, tail.0, tail.1, , и так далее).
Функция доступна в Tools.py. Она зависит от функции Питона re.search(), которая сопоставляет регулярное выражение со строкой. Выделенная строка показывает, что мы вставляем строку регулярного выражения в так называемые якоря (^ и $). Этим путём регулярное выражение, такое как например, aaaa, сопоставится только с группой вершин с именем aaaa, а не с именем aaaa.0, так что мы сможем различить их, если мы хотим. Если же мы хотим соответствия всем именам групп вершин, которые начинаются с tail, мы могли бы, например, передать регулярное выражение tail.* .
Регулярные выражения являются чрезвычайно мощным способом сопоставления строк. Если Вы незнакомы с ними, Вы должны обратиться к документации по модулю Питона re (http://docs.python.org/library/re.html). Можно начать, например, с http://wiki.intuit.ru.