Align To Spline в кустарных условиях

да не сцы, это не очень сложно.
да не сцы, это не очень сложно.

Ты ж знаешь чо такое Align To Spline? Ща покажу как он внутри работает, чтобы ты смог его сделать в любом софте, в котором его не окажется, либо сделать кустомный со своими фичами.

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

offset -точка на сплайне, от нуля до единицы. 0 — начало сплайна, 1 — конец, 0,5 — середина
offset -точка на сплайне, от нуля до единицы. 0 — начало сплайна, 1 — конец, 0,5 — середина

Позишн в точке сплайна понятно — сразу в позишн объекта суёшь, и тот на сплайне, в конкретной точке. Надо как-то определить ориентацию объекта на сплайне, чтоб он осью Z совпадал с направлением сплайна. Как помнишь — матрица есть набор векторов, в 3-мерном пространстве набор 3 векторов, соответствующих осям X Y Z. Направление сплайна — это как раз тангента, так что её в ось Z матрицы и впихну.

на данный момент готова такая залупа. Вектор Offset в матрице — это простой человеческий позишн
на данный момент готова такая залупа. Вектор Offset в матрице — это простой человеческий позишн

С осью X разобраться нехер делать — векторное произведение (cross product, ниже покажу) Z и Y. А вот откуда Y взять хз, в обычном случае прога спрашивает для неё Up Vector, потому что ну откуда ей в натуре знать, как ты хочешь повернуть объект вокруг направления сплайна. Либо прога спрашивает Rail Spline, который помогает вычислить Up Vector для каждой точки сплайна.

оба способа
оба способа

Но этот же Up Vector или Rail пугает юзеров до усрачки, потому что откуда простому юзеру знать что это за хуйня воще, чо в неё сувать, инопланетная блять настройка какая-то. У меня есть предложение, как это сделать проще для юзера (и сложнее для тебя бггг), но сначала векторное произведение. Когда кроссишь два вектора — результатом получается вектор, перпендикулярный обоим. Ну и вот, в вектор X матрицы можно сувать Cross(Y,Z).

CrossProduct наглядно. Обрати внимание, что AxB = -BxA, т.е. порядок умножения играет роль.
CrossProduct наглядно. Обрати внимание, что AxB = -BxA, т.е. порядок умножения играет роль.
Align To Spline Beatch
Align To Spline Beatch

Теперь я хочу сделать немного поюзерфрендовее, убрав на хрен Rail. Если участок сплайна не прямой, то на нём можно выявить нормаль. Она там прям в глаз бросается, осталось только проге объяснить, где она. Ну это можно сделать каскадом из векторных произведений, смотри как:
направление сплайна в нужной мне точке обозначу t1, направление в предыдущей точке — t2. Если их скроссить, получится вектор куда-то влево от направления (эту парашу иногда называют бинормалью). Если этот результат скроссить с t1, то алилуйя блять, у нас нормаль! Вот так получается:
cross(cross(t1, t2), t1).

хуль тут непонятного.
хуль тут непонятного.

Можно её нормировать и сувать в Y, а бинормаль в X. И нужно побороть пару ексепшенов. Первый — если сплайн прямой, т.е. t1 = t2, нормаль здесь будет неопределена. Предлагаю голову не ебать, и взять какой-нибудь умолчательный t2, например глобальную ось Z. Или локальную сплайновую. Да в общем-то можно её брать как t2 во всех случаях, потому что сама нормаль особо не нужна, нужен просто определённый устойчивый вектор поперёк сплайна. Теперь все ексепшены сами отваливаются, но плодится один новый: нормаль будет не определена в местах, где тангента будет совпадать с осью Z. Да и хуй с ним, вот увидишь. В XPresso здесь начинается уже какое-то безбашенное нодовое месиво, так что предлагаю пересесть на питон, рот ёб.

так гораздо компактнее. Финалку скину на XPresso.
так гораздо компактнее. Финалку скину на XPresso.

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

я тебя заебу с этой шпаргалкой. Вращение вектора (1, 0, 0) вокруг оси z.

У меня значит есть базисные вектора — binorm, norm, t1. Вращать я собрался binorm вокруг t1. Вращнутый вектор v раскладывается на базисные вот так:
v = binorm * cos(a) + norm * sin(a). В шпаргалке binorm соответсвует иксу, а norm игреку. Окай, вектор binorm вращнул, теперь на его основе norm нужно заново посчитать, чтоб они были перпендикулярны.

хуль тут трудного.
хуль тут трудного.

Теперь можно добавить фичу — смещение объекта поперёк сплайна. Это к позишну добавлять norm умноженный на велечину смещения, здесь всё изи-пизи.

на этом пожалуй тормозну.
на этом пожалуй тормозну.

Ну вот и всё ебать. Вот тебе этот сетапчик, собранный на XPresso.

1122 views·17 shares