10/23/2019

Сетки с Python & Blender: Два 2D сетка





Процедурное поколение потрясающе! В этой серии уроков мы рассмотрим создание сеток с помощью API-интерфейса Blender Создание сетки программно открывает много возможностей. Вы можете создавать параметрические объекты, которые реагируют на настройки реального мира, генеративное искусство, математические формы или даже процедурный контент для игр.Blender - отличный выбор для такого рода работ, поскольку он сочетает в себе полноценный пакет моделирования и анимации с мощным (и достаточно хорошо документированным) Python API .
В этой серии мы рассмотрим создание нескольких примитивов и некоторые базовые преобразования, а также несколько советов, которые помогут облегчить разработку. Я предполагаю, что вы уже знаете базовый Python и достаточно Blender, чтобы обойти его. Для этого введения мы пропустим 3D и вместо этого сосредоточимся на создании простой плоской сетки. Совет для профессионалов: часто сохраняйте при работе с сетками! Вы заставите Блендер падать не раз

Серия учебников

Настройка его

Система данных Blender делает различие между данными сетки и объектами в сцене. Мы должны добавить меш и связать его с объектом, а затем связать этот объект со сценой, прежде чем мы сможем увидеть какие-либо результаты.
Давайте начнем с импорта bpy (сюрприз!) И настройки некоторых переменных.
import bpy

# Settings
name = 'Gridtastic'
rows = 5
columns = 10
Nameбудет и сеткой, и именем объекта, rowsа также columnsбудет контролировать количество вершин сетки. Далее мы настраиваем сетку и добавляем объект. Сначала мы должны добавить блок данных сетки, затем объект, который использует эту сетку, и, наконец, связать их с текущей сценой. Я также добавил несколько пустых списков для вертов и граней. Мы будем заполнять их позже.
verts = []
faces = []

# Create Mesh Datablock
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(verts, [], faces)

# Create Object and link to scene
obj = bpy.data.objects.new(name, mesh)
bpy.context.scene.objects.link(obj)

# Select the object
bpy.context.scene.objects.active = obj
obj.select = True
Самая интересная часть Эта функция создает сетку из трех списков питонов: вершин, ребер и граней. Обратите внимание, что если вы пропустите список граней, вы можете пропустить края. Проверьте API Docs для получения дополнительной информации об этой функцииfrom_pydata()
Попробуйте запустить скрипт сейчас. Вы увидите, что новый объект был добавлен, но геометрия не видна (поскольку мы еще не добавили его). Когда базовые строительные леса готовы, удалите этот объект и продолжайте читать, чтобы начать строить сетку.

Сетка вершин

Давайте начнем с добавления одного верт. Вершины представлены 3 координатами (X, Y и Z). Наша сетка будет 2D, поэтому мы заботимся только о X и Y, Z всегда будет нулевым. Мы разместим вертушку в центре сцены, которая также является источником глобальных координат. Другими словами, в координатах (0, 0, 0). Каждая вершина представляет собой кортеж из 3-х чисел, поэтому измените список следующим образом:
verts = [(0, 0, 0)]
Попробуйте запустить скрипт еще раз, и вы увидите одинокую точку. Теперь вы можете перейти в режим редактирования и поиграть с ним. Позволяет нарастить и сделать ряд вертов. Для этого нам нужно зациклить и добавить столько вершин, сколько столбцов мы установили. Это действительно легко сделать с помощью выражения списка:
verts = [(x, 0, 0) for x in range(columns)]
range()возвращает целые числа, поэтому координата вершины X будет номером их столбца. Это означает, что каждый столбец будет иметь ширину 1 блендер (или метр). Запустите скрипт еще раз, и вы увидите 10 вершин, выстроенных в ряд по оси X. Чтобы завершить сетку, все, что нам нужно сделать, это больше строк. Мы также можем легко расширить выражение для цикла по строкам:
verts = [(x, y, 0) for x in range(columns) for y in range(rows)]
Теперь мы можем видеть вершинную сетку во всей ее красе.
Мы можем начать делать лица сейчас, но сначала мы должны понять, как.

Понимание лица

Каждый добавленный нами верт имеет порядковый номер. Индексы устанавливаются при добавлении каждого вертикаля, поэтому первый равен 0, второй равен 1 и так далее.
Чтобы сделать лицо, вам нужно добавить кортеж индексов в список лиц. Этот кортеж может иметь 3 (три), 4 (четыре) или более (ngon) индекса. Кстати, это все целые числа. Блендер не подведет или не будет жаловаться, но он их окружит. Поскольку мы делаем четверки, нам нужно найти четыре индекса вершин для каждой грани. Но как? Вы можете попытаться угадать их, но есть лучший способ. Мы можем включить режим отладки в Blender. Откройте консоль Python в Blender и введите следующее:
bpy.app.debug = True
Если вы что-нибудь получите из этого урока, я надеюсь, что это режим отладки. Это наиболее полезная настройка, которую вы можете использовать для создания сетки и даже для разработки общих дополнений. Чтобы увидеть индексы вершин, выберите 2D сетку вершин и перейдите в режим редактирования. Откройте N-панель и переключите «Индексы» на панели отображения сетки. Он находится под колонкой «Edge Info». Если вы не видите его, возможно, вы еще не включили режим отладки. Теперь любая выбранная вами вершина покажет ее индекс, поэтому выберите их все, чтобы увидеть их индексы.
Давайте сосредоточимся на первом лице. Как вы можете видеть, он состоит из вершин 0, 1, 5 и 6. Давайте попробуем создать одно лицо с этими индексами:
faces = [(0, 1, 5, 6)]
Попробуйте снова запустить скрипт и… подождите, что-то выглядит не так! Похоже, что мы подключили неправильные вершины.
Ну, мы подключили правильные вершины, но в неправильном порядке . Да, при настройке граней необходимо следовать порядку: против часовой стрелки, начиная с нижнего левого.
Поэтому порядок для лица 0, 5, 6, 1 . Исправьте эту строку и снова запустите скрипт.
Сейчас мы находимся в бизнесе. Каждый раз, когда вы видите подобные проблемы, попробуйте поменять местами первые или последние два набора индексов. Хорошо, здесь все становится смешно. Нам нужно выяснить, как рассчитать все индексы, чтобы сделать ряд граней. Если мы внимательно посмотрим на индексы вершин, мы увидим шаблон:
  • Все индексы прыгают на 5 по оси X. Это равно количеству строк.
  • Первый индекс начинается с 0, а второй начинается с 1
Мы можем вычислить первый индекс в цикле, умножив текущий столбец на rowsПоскольку второй смещен на 1, нам просто нужно добавить 1, чтобы получить его.
Попробуйте распечатать эти значения, чтобы проверить их.
for x in range(columns - 1):
     print(x * rows)
     print((x + 1) * rows)
Вы можете быть удивлены, почему мы зацикливаемся У нас есть 10 столбцов вершин, но они создают только 9 столбцов граней. Последний столбец не соединяется ни с чем после него.columns - 1
Третий и четвертый индексы есть и  соответственно. Мы добавляем 1 к X перед умножением, чтобы установить индекс в следующей строке.(+ 1) * rows + 1* rows + 1
Вот цикл для печати всех индексов:
для й в диапазоне ( столбцах - 1 ): печать ( 'первые:' , х * строки ) печать ( 'вторые:' , ( х + 1 ) * строка ) печати ( 'третья:' , ( х + 1 ) * строки + 1 ) печать ( 'четвертый:' , х * строки + 1 ) печать 
    
       
        
     
    ( '---' )

Мясо из сетки

Вооружившись всеми этими знаниями, мы теперь можем построить первый ряд граней. Но прежде чем мы перейдем к этому, давайте разделим код лица на его собственную функцию, чтобы мы могли сохранить код красивым и чистым. Я также добавил поддержку для создания лица в любом ряду. Строки увеличивают индексы на 1 при увеличении по оси Y, поэтому мы можем просто добавить номер строки в конце.
def face(column, row):
    """ Create a single face """

    return (column* rows + row,
            (column + 1) * rows + row,
            (column + 1) * rows + 1 + row,
            column * rows + 1 + row)
Давайте поместим это в выражение, как мы сделали с вершинами:
faces = [face(x, y) for x in range(columns - 1) for y in range(rows - 1)]
Мы используем строки - 1 по той же причине, что и столбцы. Запустите скрипт и вот.
И с этим решетка теперь завершена. Вы сделали скрипт, который может создавать 2D сетки! Погладьте себя по спине и продолжайте читать, чтобы узнать о некоторых тонких настройках и проблемах.

пересчет

Мы можем контролировать, сколько вершин имеет наша сетка, но квадраты всегда имеют размер точно 1  BU . Давайте изменим это.
Все, что нам нужно сделать, это умножить координаты X и Y на коэффициент масштабирования. Начните с добавления переменной размера. Мы можем добавить это непосредственно к выражению verts, но, опять же, будет чище, если мы сделаем это в своей собственной функции.
size = 1

def vert(column, row):
    """ Create a single vert """

    return (column * size, row * size, 0)


verts = [vert(x, y) for x in range(columns) for y in range(rows)]
Попробуйте установить размер, отличный от 1, и проверьте сетку.

Финальный код

import bpy

# Settings
name = 'Gridtastic'
rows = 5
columns = 10
size = 1

# Utility functions
def vert(column, row):
    """ Create a single vert """

    return (column * size, row * size, 0)


def face(column, row):
    """ Create a single face """

    return (column* rows + row,
            (column + 1) * rows + row,
            (column + 1) * rows + 1 + row,
            column * rows + 1 + row)

# Looping to create the grid
verts = [vert(x, y) for x in range(columns) for y in range(rows)]
faces = [face(x, y) for x in range(columns - 1) for y in range(rows - 1)]

# Create Mesh Datablock
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(verts, [], faces)

# Create Object and link to scene
obj = bpy.data.objects.new(name, mesh)
bpy.context.scene.objects.link(obj)

# Select the object
bpy.context.scene.objects.active = obj
obj.select = True

Заворачивать

Надеюсь, вам понравилось это введение в создание мешей в Python. Это только самый простой пример, который я могу придумать, и есть много других интересных вещей, которые можно сделать. Вот несколько простых вещей, которые вы можете попробовать сделать для себя:
  • Сделайте так, чтобы использовались 2 коэффициента масштабирования: X и Y
  • Добавьте смещение, чтобы сетка не начиналась с (0, 0).
  • Выделите все это в свою функцию (или класс)
Оставайтесь с нами для следующего урока, где мы, наконец, перейдем к 3D с кубиками.

Комментариев нет:

Отправить комментарий