- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Написание скриптов для Blender 2.49 - Michel Anders
Шрифт:
Интервал:
Закладка:
Чтобы доказать, что Блендер адаптируется ко многим задачам помимо интерактивного создания 3D-графики, мы покажем Вам, как импортировать внешние данные (электронная таблица в формате CSV) и автоматизировать задачу создания и рендеринга представленной в 3D гистограммы.
Идея в том, чтобы запустить Блендер с аргументами, указывающими ему запустить скрипт, который читает .csv файл, рендерит изображение и сохраняет это изображение по окончании. Чтобы это было возможным, нам нужен способ вызывать Блендер с правильными параметрами. Мы дойдём скоро до этого скрипта, но сначала давайте увидим, как передавать параметры в Блендер, чтобы он запускал скрипт на Питоне:
blender -P /full/path/to/barchart.py
Также возможно вместо этого запустить скрипт из текстового буфера внутри .blend файла по имени этого текстового буфера. Обратите внимание на порядок параметров в этому случае - сначала ставится имя .blend файла:
blender barchart.blend -P barchart.py
В противоположность тому, что описано в документации API, в Питоне мы можем просто получить доступ к аргументам командной строки следующим образом:
import sys
print sys.argv
Последний фрагмент выведет все аргументы, включая имя программы Блендера первым. Наш скрипт должен пропускать любые аргументы, предназначенные для самого Блендера при использовании этого списка. Любые аргументы, предполагаемые только для нашего скрипта, которые не должны быть интерпретированы самим Блендером, должны находится после аргумента конца-опций (end-of-options), двойного минуса (--).
Наконец, мы не хотим, чтобы Блендер появлялся и показывал графический интерфейс пользователя. Вместо этого, мы укажем ему работать в фоне и выйти по завершении. Это делается посредством прохождения опции -b. Задав всё это вместе, командная строка будет выглядеть похожей на это:
blender -b barchart.blend -P barchart.py –- data.csv
Если Блендер работает в фоновом режиме, Вы должны определить .blend файл, в противном случае Блендер разрушится. Если мы должны определить .blend файл, мы так же хорошо можем использовать внутренний текст для нашего скрипта на Питоне, иначе нам пришлось бы держать два файла одновременно вместо одного.
Скрипт построения гистограммыЗдесь мы покажем важные части кода кусками (полный файл доступен как barchart.blend, который включает barchart.py как вложенный текст). Мы начинаем с создания нового объекта Мира и установки цветов его зенита и горизонта целиком в нейтральный белый (выделенная часть следующего кода):
if __name__ == '__main__':
w=World.New('BarWorld')
w.setHor([1,1,1])
w.setZen([1,1,1])
Затем, мы извлекаем последний аргумент, переданный в Блендер и проверяем является ли расширение файла тем же самым .csv. Реальный промышленный код должен, конечно, иметь более серьёзную проверку на ошибки:
csv = sys.argv[-1]
if csv.endswith('.csv'):
Если у него правильное расширение, мы создаём новую Сцену с именем BarScene и присваиваем её атрибут world к нашему вновь созданному миру (Это было вдохновлено более сложным сценарием jessethemid на Blender Artists http://blenderartists.org/forum/showthread.php?t=79285). Фоновый режим не загружает никакого .blend файла по-умолчанию, так что сцена по-умолчанию не будет содержать никаких объектов. Тем не менее, просто, чтобы убедиться, мы создаем новую пустую сцену со значимым именем, которое будет содержать наши объекты:
sc=Scene.New('BarScene')
sc.world=w
sc.makeCurrent()
Затем, мы передаем имя файла в функцию, которая добавляет объекты barchart (гистограммы) на текущую сцену и возвращает центр диаграммы, чтобы наша функция addcamera() могла использовать его, чтобы направить туда камеру. Мы также добавляем лампу, чтобы сделать рендер возможным (в противном случае наш рендер будет весь черный).
center = barchart(sys.argv[-1])
addcamera(center)
addlamp()
Рендеринг самый простой (мы столкнемся с более сложными примерами в Главе 8, Рендеринг и Обработка Изображения). Мы извлекаем контекст рендеринга, который хранит всю информацию о рендеринге, например, номер кадра, какой выходной формат, размер изображения, и так далее. И, поскольку большинство атрибутов по умолчанию разумны, мы установим только выходной формат на PNG и запустим рендер.
context=sc.getRenderingContext()
context.setImageType(Scene.Render.PNG)
context.render()
Наконец, мы устанавливаем выходной каталог в пустую строку, чтобы сделать наш вывод в текущий каталог (каталог, в котором мы были, когда вызывали Блендер) и сохраняем наше визуализированное изображение. Изображение будет иметь то же базовое имя, как у .csv-файла, который мы приняли как первый аргумент, но будет иметь расширение .png. Мы проверили, что имя файла заканчивается на .csv, так что вполне безопасно тупо удалить последние четыре символа из имени файла и добавить .png
context.setRenderPath('')
context.saveRenderedImage(csv[:-4]+'.png')
Добавление лампы не значительно отличается от добавления любого другого объекта и очень подобно примеру "hello world". Мы создаём новый объект Lamp, добавляем его к текущей сцене и устанавливаем его позицию. Объект Lamp имеет, конечно, много настраиваемых параметров, но мы в этом примере довольствуемся не-направленной лампой по-умолчанию. Выделенный код показывает типичную идиому Питона: loc - кортеж из трех величин, но setLocation() принимает три отдельных аргумента, так что мы указываем, что хотим распаковать кортеж на отдельные значения с помощью * нотации:
def addlamp(loc=(0.0,0.0,10.0)):
sc = Scene.GetCurrent()
la = Lamp.New('Lamp')
ob = sc.objects.new(la)
ob.setLocation(*loc)
Добавление камеры будет чуть-чуть сложнее, так как мы должны направить её на нашу гистограмму и убедиться, что угол обзора достаточно широкий, чтобы все видеть. Мы определяем здесь перспективную камеру и устанавливаем довольно широкий угол. Поскольку камера по-умолчанию уже сориентирована вдоль оси z, мы не должны задавать никакого вращения, только установим позицию в 12 единиц от центра вдоль оси z, как выделено на второй снизу строке следующего кода:
def addcamera(center):
sc = Scene.GetCurrent()
ca = Camera.New('persp','Camera')
ca.angle=75.0
ob = sc.objects.new(ca)
ob.setLocation(center[0],center[1],center[2]+12.0)
sc.objects.camera=ob
Сама функция barchart не такая уж большая неожиданность. Мы открываем файл с полученным именем и используем стандартный модуль csv из Питона, чтобы читать данные из файла. Мы загружаем все заголовки столбцов в xlabel, а остальные данные в rows (строки).
from csv import DictReader
def barchart(filename):
csv = open(filename)
data = DictReader(csv)
xlabel = data.fieldnames[0]
rows = [d for d in data]
Для того, чтобы масштабировать нашу гистограмму до разумных величин, мы должны определить пределы данных. Первый столбец каждой записи содержит значение по x (или метку), так что мы исключаем его из нашего вычисления. Так как каждая величина загружена в виде строки, мы должны преобразовать её в величину с плавающей точкой для сравнений.
maximum = max([float(r[n]) for n in data.fieldnames[1:]
for r in rows])
minimum = min([float(r[n]) for n in data.fieldnames[1:]
for r in rows])
Чтобы фактически создать столбики, мы проходим по всем строкам. Поскольку значение по x может быть текстовой меткой (как название месяца, например), мы сохраняем отдельно цифровое значение x для того, чтобы позиционировать столбики. Само значение x добавляется к сцене в виде объекта Text3d функцией label(), поскольку значения y визуализируются соответственно масштабированными объектами Cube (Куб), добавляемыми функцией bar(). Функции label() и bar() не показаны здесь.
for x,row in enumerate(rows):
lastx=x
label(row[xlabel],(x,10,0))
for y,ylabel in enumerate(data.fieldnames[1:]):
bar(10.0*(float(row[ylabel])-minimum)/maximum,
(x,0,y+1))
x = lastx+1
Наконец, мы подписываем каждый столбец (то есть, каждый набор данных) своим собственным заголовком столбца как label. Мы сохранили число значений по x, так что мы можем вернуть центр нашей гистограммы деля его на два (y-компонент установлен на 5.0, так как мы масштабировали все значения по y, чтобы они лежали в пределах диапазона от 0 до 10).
for y,ylabel in enumerate(data.fieldnames[1:]):
label(ylabel,(x,0,y+0.5),'x')
return (lastx/2.0,5.0,0.0)

