При помощи Blender Geometry Nodes можно заполнить кривую нужным количеством одинаковых объектов. Также мы можем сделать заполнение немного интереснее, изменяя размер заполняющих объектов случайным образом.
В начальную сцену добавим кривую (shift + a – Curve – Bezier). Назначим для нее модификатор Geometry Nodes и инициализируем начальное дерево нод.
Добавим ноды Instance on Points (shift + a – Instance – Instance On Points) и UV Sphere (shift + a – Mesh Primitives – UV Sphere) в главную ветку нодового дерева для распределения объектов (сфер) по точкам кривой.
Добавим нод Resample Curve (shift + a – Curve – Resample Curve) для увеличения количества точек на кривой. Установим в нем количество точек равное 10.
Сделаем так, чтобы каждая сфера на кривой имела случайные размеры. Для генерации случайного числа добавим нод Random Value (shift + a – Utilities – Random Value) и соединим его выход Value со входом Scale нода Instance on Points.
Размер каждой сферы действительно изменился на случайное число. Однако этого явно недостаточно. Кроме изменения масштаба самих сфер нужно соответственно изменить и их расположение на кривой.
Для того чтобы перераспределить точки кривой, на которых располагаются сферы, нужным нам образом, добавим в нодовое дерево ноды Sample Curve (shift + a – Curve – Sample Curve) и Set Position (shift + a – Geometry – Set Position). Включим их в главную ветку нодового дерева и выход Position нода Sample Curve соединим со входом Position нода Set Position.
Нод Sample Curve устанавливает каждую точку кривой пропорционально значению со входа Length начиная от начала кривой. Так как значение Length сейчас равно 0.0, все сферы располагаются в начальной точке кривой.
Будем смещать каждую точку кривой на случайное расстояние, полученное с нода Random Value. Для того чтобы смещения накапливались для каждой последующей точки, можно использовать нод Accumulate Field (shift + a – Utilities – Accumulate Field). Соединим его выход Trailing со входом Length нода Sample Curve. А вход Value с выходом Value нода Random Value.
Выход Trailing дает нам промежуточную сумму из набора. В нашем случае мы получаем для каждой точки кривой сумму случайного смещения этой точки и суммы всех смещений для всех предыдущих точек.
Для наглядности немного уменьшим значение входа Max нода Random Value.
Сейчас каждая сфера располагается в каждой точке кривой. Это работает в случае одинаковых по размеру сфер так как расстояние от точки кривой до соседних точек слева и справа одинаковое.
В нашем случае расстояние между точками на кривой разное и располагая сферу в самой точке, если ее радиус достает до соседней точки слева, он не будет при этом попадать на соседнюю точку справа.
Поэтому для того чтобы размер сферы соответствовал расстоянию между точками, нам нужно размещать сферы не в самих точках кривой, а в центре промежутков между этими точками.
Чтобы сместить положение центра сферы в нужное место, нужно вычесть из получаемого с выхода Trailing смещения его половину.
Добавим нод Math (shift + a – Utilities – Math) и переключим его в режим деления Divide. На верхний вход подадим значение с выхода Value нода Random Value а в нижнем поле укажем значение равное 2.
Однако же складывать полученную половину смещения для каждой точки нужно все равно к полной суммой смещений для предыдущих точек.
Добавим еще один нод Math (shift + a – Utilities – Math), переключим его в режим сложения Add. Верхний вход Value соединим с выходом Value нода деления, а нижний с выходом Trailing нода Accumulate Attribute. Результат сложения подадим на вход Length нода Sample Curve.
Как мы видим, точки, к которым привязаны центры сфер, сместились.
Если мы сейчас будем менять значение Max в ноде Random Value, мы увидим, что весь набор сфер изменяется пропорционально. Так происходит потому, что при помощи Random Value и Trailing мы получили фиксированный набор смещений для точек, независящий от длины исходной кривой.
Чтобы полученный набор соответствовал длине кривой, переведем его из текущего диапазона значений – от 0 до суммы смещений, в диапазон длины кривой.
Добавим нод Map Range (shift + a – Utilities – Map Range) и вставим его перед нодом Sample Curve. Поле From Max соединим с выходом Total нода Accumulate Attribute. С выхода Total мы получаем полную сумму всех смещений для точек.
Добавим в главную ветку нодового дерева нод Curve Length (shift + a – Curve – Curve Length) для получения длины кривой. Выход Length соединим со входом To Max нода Map Range.
Теперь мы можем свободно менять значение Max нода Random Value и количество точек в ноде Resample Curve – набор сфер всегда будет занимать всю длину кривой.
Осталось привязать масштабирование сфер к тому же самому коэффициенту, завязанному на длине кривой.
Добавим еще один нод Map Range (shift + a – Utilities – Map Range) и вставим его перед нодом Instance On Points. Вход Value соединим с выходом Value нода Divide, вход From Max соединим, как и раньше, с выходом Total нода Accumulate Attribute, а вход To Max соединим с выходом Length нода Curve Length. Выход Result соединим со входом Scale нода Instance On Points.
Таким образом мы привели масштаб сфер к длине кривой.
Теперь изменения значений в ноде Random Value не будут оказывать никакого эффекта, а при изменении количества точек в ноде Resample Curve весь набор сфер будет корректно пересчитываться.
Для примера поставим значение 25.
Меняя значение Seed в ноде Random Value можно получить различные случайные наборы сфер.