Недавние вопросы

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

Вот вам шпаргалка.

 
Категория:VEX

Struct — это структура данных, которая позволяет использовать инкапсуляцию, пусть и в ограниченном виде.

Struct необходимо создавать во внешнем файле, а не в самом Врангле. Создайте внешний файл так, как это описано в этом вопросе: http://hipnc.club/ufaqs/custom-functions/

Struct может содержать как поля, так и методы (если пользоваться терминологией ООП).

// Упрощенный пример использования структуры для создания двумерного массива
struct IntArray
{
	int _xSize;
	int _array[];

	void Create(int xSize, ySize)
	{
		_xSize=xSize;
		resize(_array, xSize*ySize);
	}

	int Value(int x, y)
	{
		return _array[y*_xSize + x];
	}

	void Set(int x, y, value)
	{
		_array[y*_xSize + x] = value;
	}
}

После этого во Врангле делаем #include с именем вашего файла. Обращаться к структуре можно следующим образом:

#include "arrays.h"

IntArray arr;
arr->Create(10,10);
arr->Set(3,5,1000);
printf("Array value: %d", arr->Value(3,5));
printf("Array X size: %d", arr._xSize);

К «полям» мы обращаемся через знак «точка», а к «методам» через «->».

Также у структур есть конструктор, проще говоря их можно инициализировать следующим образом:

MyStruct var = MyStruct(10, 20, "String");

То есть мы используем название структуры в качестве функции и перечисляем в аргументах значения для всех полей.

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

 
Категория:VEX

Создайте файл с расширением .h, например myvex.h. Этот файл необходимо поместить в папку, которая указана в переменной окружения HOUDINI_VEX_PATH или же в папку ДОКУМЕНТЫ/HoudiniXX.XX/vex/include.

После этого вы сможете обращаться к указанным в этом файле функциям, добавив в начало кода во Врангле строку

#include "myvex.h"

Если же вам нужно передать проект кому-то другому и у вас нет уверенности, что на другой машине будут такие же файлы, можно в include использовать относительный путь:

#include "$HIP/myvex.h"

Также можно встроить функцию прямо во врангл:

  1. Разлочить врангл (Allow Editing of contents на ноде Врангл)
  2. Заходим внутрь два раза, до ноды Snippet
  3. В ноде Snippet можно в параметр Include files записать прямой путь до вашего файла. К сожалению, путь должен быть абсолютным.
  4. Также в ноде Snippet можно скопировать полностью код из вашего h-файла в параметр Outer Code (или можно запромоутить его на верхний уровень ассета).
  5. После этого команду #include можно убрать из кода

 
Категория:VEX

Допустим, вы не знаете точно названия атрибутов на геометрии. Как получить список их имен, чтобы выбрать нужный?

Для этого существуют следующие интринсики на уровне детали: pointattributes, primitiveattributes, vertexattributes и detailattributes. Их можно прочитать в строковые массивы и уже дальше работать с ними, как с обычными строками. Например, можно сделать поиск по какому-то условию через re_find, найти имя нужного атрибута и записать в него что-то через функции setpointattrib, setprimattrib и так далее.

Чтение из интринсиков выглядит так:

string pointattribs[] = detailintrinsic(0,"pointattributes");
string primattribs[] = detailintrinsic(0,"primitiveattributes");
string vertexattribs[] = detailintrinsic(0,"vertexattributes");
string detailattribs[] = detailintrinsic(0,"detailattributes");
 
Категория:VEX

Поскольку функции point(), prim(), detail() и им подобные могут возвращать разные типы данных, то просто написать f@attr = point(1, «P», @ptnum).x; не получится, Врангл выдаст ошибку Ambiguous call to function

Чтобы подобная записать сработала, необходимо сказать Вексу, что мы читаем именно вектор. Это можно сделать двумя путями: создать векторную переменную и читать значение позиции в нее или скастовать функцию в векторный тип.

// В этом примере мы сначала записываем позицию в векторную переменную и читаем значение компоненты из нее
vector pos = point(1, "P", @ptnum);
f@height = pos.y;

// В этом примере мы используем приведение типа функции
f@height = vector(point(1, "P", @ptnum));

Приведение типа функции или по-английски Cast выполняется записью вида ТИП_ДАННЫХ(выражение). Этот тип приведения не использует никакого реального преобразования, он просто говорит Вексу, какой из перегруженных вариантов функции использовать.

 
Категория:VEX

В ноде Carve есть режим Extract — Extract Point(s). В нем от кривой останется одна или две точки (при включенном параметре Second U).

Если нужно решение в вексе, то здесь понадобится функция Primuv.

// На первый вход врангла подается одна точка, на второй - кривая. 
// Параметром anim можно перемещать точку по этой кривой.
// Ноль означает номер примитива. Если примитивов больше одного, нужно будет подставить вместо него правильные номера.
@P = primuv(1, "P", 0, ch("anim"));
 
Категории:SOP, VEX

Если речь про целое число, то существует функция itoa(number), которая из числа типа 125 возвращает строку «125». Эта функция часто используется для работы с атрибутом name, мультипармами или инстансами.

// в атрибут instance запишется строка box0, box1, box2 и так далее в зависимости от числа в атрибуте id.
s@instance = "/box"+ itoa(i@id);

// в атрибут text запишется строковое значение из строкового параметра мультипарма (text0, text1, text2 и так далее).
s@text = chs("text" + itoa(num));

Если же нам нужно перевести в строку флоат или как-то отформатировать результат, то необходимо использовать функцию sprintf(). В ней задается произвольная строка, в которой встречаются служебные последовательности символов типа %g, %d, а после строки через запятую перечисляются значения, которые подставятся вместо этих символов. Также эта функция поддерживает дополнительные опции форматирования, такие как выравнивание, padzero и т.д.

// В атрибут filename запишется значение типа image_0001.jpg, где 0001 - это номер кадра
// Запись вида %04d сделает длину числа равной 4 и забьет свободные места нулями
s@filename = sprintf("image_%04d.jpg",@Frame);

// В атрибут floatstring запишется значение атрибута pscale
s@floatstring = sprintf("%g", f@pscale);

Описание всех возможных вариантов форматирования можно почитать здесь.

 
Категория:VEX

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

function int[] foo()
{
int array[] = {1,2,3};
return array;
}

 
Категория:VEX

Для проверки вхождения точки-примитива-вертекса в группу есть функции inpointgroup(), inprimgroup(), invertexgroup().

Но удобнее использовать виртуальный атрибут @group_название

В этом атрибуте будет 0, если элемент не принадлежит группе, и 1, если принадлежит.

Таким образом проверку на вхождение в группу start можно осуществлять так:

if @group_start==1 ...
или
if (@group_start) ...
 
Категория:VEX

Очевидный способ — использовать функции point(), prim(), vertex(), detail(), где первым аргументом указать номер входа.

Есть более простой синтаксис, который выглядит так:

@opinput1_P, i@opinput2_index, v@opinput3_dir

Указание типа происходит по стандартным правилам. После знака @ ставим opinput номер входа и через нижнее подчеркивание название атрибута. Нумерация начинается от нуля.

При этом берется атрибут с элемента с таким же номером, который отрабатывается Вранглом в данный момент. Если Врангл запущен по точкам и отрабатывается точка номер 10, то и с другого входа атрибут будет прочитан с точки номер 10.

Но также у ноды Wrangle есть параметр Attribute to match. В случае его наличия, будет проверяться не номер элемента, а значение в этом атрибуте, например id. Значит, что атрибут будет читаться не с текущего номера элемента, а с элемента, у которого id совпадает.

 
Категория:VEX

В Вексе можно прочитать и записать атрибут на геометрии в синтаксисе тип@название. Если тип не указан, а атрибут не находится в списке «известных», то он получит тип Float.

ТипСинтаксис
floatf@имя
vector2u@имя
vectorv@имя
vector4p@имя
inti@имя
matrix22@имя
matrix33@имя
matrix4@имя
strings@имя
dictd@имя

Существуют атрибуты с известным типом, который автоматически распознается вексом. В их случае тип указывать необязательно.

ТипАтрибуты
vectorP, accel, Cd, N, scale, force, rest, torque, up, uv, v
center, dPdx, dPdy, dPdz в Volume wrangle
vector4backtrack, orient, rot
intid, nextid, pstate
переменные индексирования: elemnum, ptnum, primnum, vtxnum, numelem, numpt, numprim, numvtx
group_*
ix, iy, iz, resx, resy, resz в Volume wrangle
stringname, instance

Таким образом можно не указывать тип атрибута, если он типа float, а так же для известных атрибутов. Во всех остальных случаев при первом упоминании атрибута в коде этот тип указывать обязательно. После того, как в коде уже был указан тип атрибута, дальше к нему можно обращаться без типа.

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

 
Категория:VEX

Часть функций в Вексе читают информацию с входящей геометрии. Например атрибуты, группы, габариты и так далее. В хелпе у таких функций обычно присутствует аргумент Geometry.

В этот аргумент записывается или номер входа Врангла, с которого забирается значение (включая отрицательные числа для Spare inputs), или же путь до нужной ноды в формате «op:…».

В том случае, если функция меняет геометрию, то есть создает новые атрибуты, группы, удаляет или создает точки и так далее, то у нее есть аргумент Geohandle.

Это НЕ номер входа, это идентификатор геометрии, на которой происходят изменения. Этот аргумент был добавлен для возможного наращивания функционала в будущем, например для изменения геометрии где-то в другом месте нетворка. Но на данный момент он принимает на вход только текущую геометрию, то есть число ноль.

Дословный перевод хелпа

Geohandle — это идентификатор геометрии, на которой происходит запись. На данный момент единственное возможное значение — ноль или geoself(), то есть текущая геометрия в ноде. Этот аргумент может быть использован в будущем, чтобы дать возможность записи в другие геометрии.

По хорошему нужно писать в этот аргумент функцию geoself(), но это функция-пустышка, которая всегда возвращает ноль. Поэтому записывать в geohandle ноль или geoself() — исключительно вопрос философии разработки и читаемости кода. Главное — не путать этот аргумент с номером входа Врангла.

 
Категория:VEX

Короткий ответ — нет, но на практике это может зависеть от конкретных нод.

Векс — язык быстрый, но все равно высокоуровневый. Большинство стандартных нод скомпилированы и будут выполняться быстрее. Другое дело, что ноды меняются, обрастают новым функционалом и не всегда работают оптимально. Проблема в том, что это можно проверить только опытным путём, сравнивая время исполнения ноды и аналогичного кода во Врангле через Performance Monitor.

На мой взгляд лучше искать возможности для оптимизации в другом месте.

 
Категория:VEX

В Sublime выбрать пункт меню Preferences/Package Control. Набрать «Install package». В появившемся окне найти и установить VEX Syntax. Теперь синтаксис Векса появится в списке в меню View/Syntax.

 
Категория:VEX

Самое простое — включить выход нужной ноды в один из входов Врангла и подставить в функции номер этого входа. Если входов не хватает, вы всегда можете добавить сколько угодно Spare input через меню шестеренки и Add spare input, подключить в них нужные ноды и обращаться к ним по номеру со знаком минус (-1, -2 и т.д.).

Второй вариант: использовать синтаксис op:/путь/до/ноды

Например, если нужно прочитать число точек на ноде с названием sphere1, которая лежит в этом же нетворке, то синтаксис будет таким:

npoints("op:../sphere1");

То есть, относительный путь работает так же, как и в Hscript. Абсолютный путь будет таким:

npoints("op:/obj/geo1/sphere1");

 
Категория:VEX

В вексе для этого есть две функции:

atof("строка") - преобразует строку во флоат
atoi("строка") - преобразует строку в целое число

При этом в строке не должно быть других символов, кроме цифр, десятичной точки и знака «е» для записи типа 1.25e+5

Например atof(«12.5») вернет число 12.5

Для целых чисел есть функция opdigits(), которая возвращает последнюю последовательность целых чисел из строки. Обычно она используется, чтобы парсить пути до нод, но и для обычных строк работает.

opdigits("gfhfhg123jshfh") вернет 123

Если же в строке есть другие символы, кроме цифр, и нужно вытащить из нее флоат, то задача сводится к удалению лишних символов из строки. Это делается с помощью регулярных выражений (regular expression, regexp).

Функции для работы с регулярными выражениями в вексе начинаются с приставки «re_».

s@in = "gfhdg12.5jahd";
@out=atof(re_replace(r"[^.0-9]+", "", @in));
В @out окажется число 12.5

Во второй строке мы используем функцию re_replace, которая ищет в атрибуте @in подстроку по регулярному выражению [^.0-9]+, то есть все, кроме точки и цифр 0-9. Буква r перед кавычками важна. 

Дальше мы заменяем найденное на пустую строку «». На выходе у нас остаются только цифры и точка, к которым мы уже применяем atof.

А вот если нужно распарсить строку, где может быть несколько чисел с буквами и символами между ними, то используем такую конструкцию:

s@in="123hjh765.4hfhsd12jsh";
string array[] = re_split(r"[^.0-9]+", @in);

Эта функция создаст массив строк, а в качестве разделителя использует все то же выражение. Единственное, если исходная строка начинается не с цифры, то в начале массива создастся пустой элемент, надо это учитывать. В данном примере на выходе будет массив из строк “123″, “765.4″, “12″. Дальше уже можно по этому массиву идти циклом и использовать atof().

 
Категория:VEX