Чтение онлайн

ЖАНРЫ

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

Anders Michel

Шрифт:

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

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

Нашей первой проблемой будут некоторые ранее используемые функции, которые мы писали для презентации модели с несколькими видами. Эти функции находятся в текстовом буфере с именем combine.py, и мы не сохраняли его во внешний файл. Мы создадим наш скрипт cardboard.py как новый текстовый буфер в том же .blend файле, где и combine.py, и хотим ссылаться на последний так же, как на внешний модуль. Блендер позволяет это делать, так как он ищет модуль в текущих текстовых буферах, если он не может найти внешний файл.

Поскольку внутренние текстовые буферы не имеют информации о том, когда они последний раз изменялись, мы должны убедиться, что загружена самая последняя версия. Об этом позаботится функция reload. Если мы её не выполним, Блендер не сможет обнаружить возможных изменений в combine.py, что могло бы провести нас к использованию его более старой скомпилированной версии:

import combine

reload(combine)

Мы не будем использовать заново функцию render из combine.py, поскольку сейчас у нас другие требования для рендеренных изображений, которые мы наложим на билборды. Как уже объяснялось, мы должны убедиться, что мы не получим никаких светлых краёв в местах с частичной прозрачностью, так что мы заранее включаем premultiply в альфа-канале (выделено). Мы восстанавливаем контекст рендера в 'рендер неба' (rendering the sky) обратно до возврата из этой функции, поскольку легко забыть установить его обратно вручную, и Вы можете потратить время на удивление, куда подевалось ваше небо:

def render(camera):

cam = Object.Get(camera)

scn = Scene.GetCurrent

scn.setCurrentCamera(cam)

context = scn.getRenderingContext

frame = context.currentFrame

context.endFrame(frame)

context.startFrame(frame)

context.displayMode=0

context.enablePremultiply

context.renderAnim

filename= context.getFrameFilename

camera = os.path.join(os.path.dirname(filename),camera)

try:

os.remove(camera) # удаление, в противном случае

# переименование

# потерпит неудачу в windows

except:

pass

os.rename(filename,camera)

context.enableSky

return camera

Каждое отрендеренное изображение должно быть преобразовано в подходящий материал, чтобы наложить его на квадрат с UV-отображением. Функция imagemat будет делать это просто; она принимает объект Блендера Image в качестве аргумента и возвращает объект Материала. Этот материал будет сделан полностью прозрачным (выделено), но эта прозрачность и цвет модифицируются текстурой, которую мы назначаем в первый текстурный канал (вторая выделенная строка). Тип текстур установлен в Image и, поскольку мы визуализировали эти изображения с premultiplied альфа-каналом, мы используем метод setImageFlags, чтобы указать, что мы хотим использовать этот альфа-канал, и устанавливаем атрибут premul изображения в Истину:

def imagemat(image):

mat = Material.New

mat.setAlpha(0.0)

mat.setMode(mat.getMode|Material.Modes.ZTRANSP)

tex = Texture.New

tex.setType('Image')

tex.image = image

tex.setImageFlags('UseAlpha')

image.premul=True

mat.setTexture(0,tex,Texture.TexCo.UV,

Texture.MapTo.COL|Texture.MapTo.ALPHA)

return mat

Каждая грань, к которой мы применяем материал, должна иметь UV-раскладку. В нашем случае, это будет самой простой из возможных раскладок, так как квадратная грань будет отображена так, чтобы в точности соответствовать прямоугольному изображению. Это часто называют сбросом отображения, и следовательно, функция, которую мы определим, называется reset. Она принимает объект Блендера MFace, который мы считаем четырёхугольником, и присваивает его атрибуту uv список 2D-векторов, по одному для каждой вершины. Эти векторы размещают каждую из вершин в углах изображения:

def reset(face):

face.uv=[vec(0.0,0.0),vec(1.0,0.0),

vec(1.0,1.0),vec(0.0,1.0)]

Функция cardboard заботится о создании фактического Меш-объекта из двух объектов Image, переданных как аргументы. Она начинается с создания двух квадратных граней, которые пересекают друг друга вдоль оси z. Следующий шаг должен добавить UV-слой (выделено) и сделать его активным:

def cardboard(left,right):

mesh = Mesh.New('Cardboard')

verts=[(0.0,0.0,0.0),(1.0,0.0,0.0),

(1.0,0.0,1.0),(0.0,0.0,1.0),

(0.5,-0.5,0.0),(0.5,0.5,0.0),

(0.5,0.5,1.0),(0.5,-0.5,1.0)]

faces=[(0,1,2,3),(4,5,6,7)]

mesh.verts.extend(verts)

mesh.faces.extend(faces)

mesh.addUVLayer('Reset')

mesh.activeUVLayer='Reset'

Затем мы создаем подходящие материалы из обоих изображений, и назначаем эти материалы в атрибут меша materials. Далее, мы сбрасываем (reset) UV-координаты обеих граней, и назначаем им материалы (выделено). Мы обновляем (update) меш, чтобы сделать изменения видимыми до возврата из функции:

mesh.materials=[imagemat(left),imagemat(right)]

reset(mesh.faces[0])

reset(mesh.faces[1])

Поделиться с друзьями: