RailUnion.net


http://railunion.net/blog/Света/RE_%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0_%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%8C%D0%B5%D1%80%D0%BD%D0%BE%D0%B9_%D0%BA%D0%B0%D0%BC%D0%B5%D1%80%D1%8B_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_Animated_Body_Node_r-822_sid-6e40bb2394a111db272be2823c1204b5.html

Автор:  Skif [ 10.04.2016, 12:52 ]
Тема блога:  Настройка интерьерной камеры через Animated Body Node

Animated Body Node - узел, введенный и задокументированный в Train Simulator сравнительно недавно, предназначен для создания пользовательской анимации интерьерных и экстерьерных камер.

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

Итак, при помощи Animated Node Name можно сделать следующее (но не всегда все это одновременно):

1. Регулируемое по высоте кресло в кабине. Это я рассматривать не буду - как сделать, будет понятно из описания ниже, когда дойдем до анимации и скрипта.

2. Заменить переключение камер в кабине имитацией (весьма реалистичной) перехода по кабине и даже целому локомотиву (с проходом и действиями в машинном отделении или на площадках).

3. В процессе перемещения по кузову, ваш "аватар" будет реагировать на препятствия, если правильно настроить анимацию - пригибаться и протискиваться в проходах, останавливаться перед запертыми дверями и ждать их открытия (можно сделать и автоматическое), садиться и вставать из кресла.


Начнем с описания и подготовки необходимой геометрии и анимации.

1. Подготовка и анимация сцены в 3D Max


В сцене, которая содержит вашу модель локомотива (внешнюю, это важно!) мы должны создать небольшого размера анимированный объект, к которому позже и прикрепим камеру. Желательно разместить его аккурат в том месте, где будет находиться наша "голова" или чуть ниже. Можно использовать полноценный "болван", обычный в 3D шутерах - безголовую фигуру, которую мы сможем увидеть, наклоняя камеру, чтобы посмотреть "на себя". Но я не рекомендую этого делать - вам придется возиться с анимацией рук и ног, а для рук она все равно будет выглядеть неестественно в тех местах, где вы захотите сделать переключение каких-то органов управления или нажатие кнопок, например. Ограничимся квадратиком черного цвета. Назовем его, скажем, avatar, и не забываем про правила именования. Дальности в 100 метров будет более чем достаточно:

Изображение


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

Теперь поясню суть всего процесса с Animated Body Node. Камера, прикрепленная к этому узлу, будет повторять все его эволюции в точности. Это открывает широкие возможности по настройке ее поведения. Так, замечено, что анимированная камера значительно лучше реагирует на тряску и раскачивание локомотива, чем дефолтная, а также при перемещениях очень реалистично имитирует ходьбу и "плюханье" на кресло в кабине. Заставим теперь наш анимированный объект работать.

Экспортируйте обновленную сцену с внешней моделью локомотива.

2. Добавление описания камеры в блюпринты локомотива.

Первым делом добавляем в свиток RailVehicleComponent название нашего анимированного узла в поле AnimatedBodyNodeName:

Изображение


Поскольку узел - анимированный, необходимо добавить и описание анимации в список AnimSet свитка RenderComponent , и указать путь к файлу анимации камеры.

Изображение


Важно! Для удобства управления аватаром нет ничего удобнее, чем создать Control - ведь только он будет хранить свое значение из такта в такт скрипта, из него легко можно получить текущее положение, и изменить его скриптом или вручную. Так и поступим - добавим в ControlContainerComponent в список ControlValues новый контрол, который мы будем использовать для управления аватаром (и камерой) :

Изображение


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



На этом добавление элемента закончено, но он пока работать не будет - нужно сделать скрипт. Им мы займемся чуть позже, а пока настроим камеру.

3. Настройка анимированной интерьерной камеры.

С использованием анимированной камеры вам будет более чем достаточно единственной камеры на весь локомотив - все ее эволюции мы можем теперь реализовать анимацией. Откроем CabCameraBlueprint и настроим одну единственную камеру. У меня, как видно, настроена и "левая" камера к правой, но она совершенно необязательна. Чтобы ее убрать, уберите галочку с HasWindowCamera и вставьте в нее те же числа, что и в основную.

Изображение

Большой скриншот, поэтому распишем поля построчно комментариями...

CameraOffset - геометрическое положение камеры относительно кабины. X - боковое смещение, Y - вертикальное смещение, Z - продольное (вдоль локомотива), единицы - метры.
CameraDirection - начальные углы поворота камеры. Оставляйте все три 0.0 , нам эта функциональность не нужна - никто не мешает повернуть на 180 наш анимированный аватар.

HasWindowCamera - позволяет задать альтернативную камеру. Переключается стрелочками курсора влево и вправо. Выключим ее и будем использовать для смены камер наш контрол (на него, как всем известно, можно назначить через Input Remapper те же стрелочки или любые удобные клавиши, помимо управления скриптом).

WindowCameraOffset , WindowCameraDirection - блоки настроек, аналогичные описанным, но для альтернативной камеры. Оставляем ненастроенными или копируем основные.

verticalDirectionalFreedom - угол поворота камеры в вертикальной плоскости. Наклон головы , в rad
horizontalDirectionalFreedom - угол поворота камеры в горизонтальной плоскости. Вращение головой, в rad. Число 4 позволяет вращать на 360 градусов, для игр это допустимо, так как будем считать, что мы помогаем себе осматриваться и туловищем. Но можно и ограничить, если желаете. Просто это не всегда удобно.

MinFOV - угол обзора на максимальном зуме, в долях от 1.0
MaxFOV - нормальный угол обзора, в долях от 1.0

Эти две настройки выставляйте под свою кабину, на свой вкус. Стремитесь только ставить более-менее близкие к реальному глазу цифры.

WindowMinFOV , WindowMaxFOV - то же самое, для альтернативной камеры.

А сейчас подходим к самому вкусному... Эти параметры описывают "шейную пружину", на которой болтается голова нашего аватара, и по неведомой мне причине они по разному влияют на "дефолтную" камеру и камеру, которую мы сейчас создаем. Причем анимированная с ними работает просто на ура. Итак,

SpringXCoefficient - упругость нашей "шеи" в поперечном направлении (влево-вправо)
SpringYCoefficient - упругость нашей "шеи" в вертикальном направлении (может имитировать шаги или подпрыгивание на подушке сиденья, больше всего чувствительно к Uneveness пути)
SpringZCoefficient - упругость нашей "шеи" в продольном направлении (передает "отдачу" при разгоне и торможении, толчках)

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

TimelineEntry - свиток для добавления дополнительных камер. Они нам теперь не понадобятся.


Переходим к...

4. Создание блока скрипта для управления аватаром.

Скрипт для управления камерой лучше размещать во "вспомогательном" скрипте, не описывающем Simulation процессы. Я располагаю в нем мессенджер для обмена сообщениями в составе, а также методы, синхронизирующие анимацию на модели - жалюзи, форточки, двери, различного рода приводы . Добавим в код следующую конструкцию в функцию Update (time):

Изображение

Принцип действия:

- каждый кадр сбрасываем анимацию узла avatar (это имя из AnimSet)
- устанавливаем анимацию Avatar на кадр, соответствующий текущему положению контрола TU7A-Avatar. Вот для чего мы и создали контрол - теперь нам в этом либо симуляционном скрипте достаточно лишь через SetControlValue установить любое его значение - и камера переместится в него.

Коэффициент 1.7, 3.4. и подобные - подгонный, позволяет увязать положение контрола и позицию на временной линейке в анимации. К сожалению, я не разобрался толком, как они соотносятся, и предпочитаю найти коэффициент "подгоном". Величины чисел заставляют думать, что это как-то связано с делением на 60 в анимации вместо 100 у контрола. Т.е. с временной и десятичной осями этих величин. Просто "откалибруйте" свой контрол в процессе настройки - например, если вы знаете, что на 50-ом кадре из 100 камера должна находиться на правом кресле, добейтесь того, чтобы при значении контрола 0.5 от 1.0 она именно там и находилась, при этом на 1.0 выходя на конец анимации.

Рекомендую управляющему контролу задать диапазон не (0 - 1.0) , а побольше - скажем, (0 -100) . Это позволит вам более точно и плавно управлять анимацией. Также следует написать функцию, которая позволит вам выставлять желаемое значение контрола не рывком, а плавно и с задаваемой скоростью. Камера ОЧЕНЬ не любит резких рывков - вы в этом убедитесь, когда будете повторять мои действия.

Дарю:
Код: Выделить всё

function UpdateControl (time, name, index, target, speed)         

-- функция апдейта контрола на новое значение с задаваемой скоростью единиц/сек.
-- name - имя контрола
-- index - индекс контрола
-- target - целевое значение
-- speed - скорость перевода

n_value = Call ("*:GetControlValue", name, index);
n_step = time*speed;


if ( n_step > math.abs(n_value - target) ) then   -- устранение "дребезга" вокруг конечного значения.
   n_step = math.abs(n_value - target);
end

if (speed > 0) then

if (n_value > target) then
   Call("*:SetControlValue", name, index, n_value - n_step);
end
if (n_value < target) then
   Call("*:SetControlValue", name, index, n_value + n_step);
end

if (n_value == target) then
   Call("*:SetControlValue", name, index, n_value);
   return 1;
end

else return -1;

end
end





На этом настройка закончена - экспортируйте локомотив и наслаждайтесь. Не забудьте только определиться с управлением контролом аватара. Хотя бы просто установите для начала этот контрол в дефолтное ненулевое положение.



{ BLOG_REPLIES }

Автор:  Skif [ 10.04.2016, 19:31 ]

Upd.

1. Есть мнение, что в корректирующих множителях нет надобности, если контролу, управляющему анимацией, выставить макс. значение, кратное числу кадров в анимации узла. Например, если их 30, то контрол должен иметь значения от 0 до 300.

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

Так, например, если часть пола в локомотиве покрыта стальным листом, а в кабинах - линолеум, мы можем создать два зацикленных звука шагов. Будем проигрывать оба, пока изменяется значение контрола управления аватаром (значит, он шагает или поворачивается), а кривые громкости выставляем на те диапазоны (следовательно - кадры), где этот звук уместен... Вуаля! Мы можем топать, стучать, скрипеть пружинами кресла. Много чего, в общем, можем делать.

3. Также есть мнение, что на AnimatedBodyNode можно прицепить и источник света. И у нас получится... Правильно, карманный фонарик. Он будет повторять движения камеры-головы и светить в направлении взгляда. Очень полезная штука для осмотра машинного отделения или работы в высоковольтной камере.

Автор:  радиомастер [ 31.07.2017, 17:08 ]

Для внешней анимации можно проще и одной строчкой
Call( "*:SetTime", "door", door );

Автор:  радиомастер [ 31.07.2017, 17:12 ]

Шейдер для объектов для камеры лучше использовать Invizible

Автор:  Света [ 21.08.2017, 12:15 ]

Коэффициент 1.7, 3.4. и подобные - подгонный, позволяет увязать положение контрола и позицию на временной линейке в анимации. К сожалению, я не разобрался толком, как они соотносятся, и предпочитаю найти коэффициент "подгоном".
Там всё очень просто.
Количество кадров в этом случае нас вообще не интересует.
Анимация имеет время проигрывания - вот как раз этот параметр нам нужен.
Если анимация прописана в конфиге, во вкладке левера контрола, то движок будет сам масштабировать это время так, чтобы максимальному значению контрола соответствовал конец анимации, а минимальному - начало.
Если же нужно вручную установить анимацию в определенное положение, то приходится делать это масштабирование этими коэффициентами. Так как у вызове Call( "*:SetTime", "имя", время) (или Call( "Reset", "имя") с последующим Call("AddTime", "имя", время), что эквивалентно), анимация устанавливается непосредственно на указанное время, то масштаб будет равен соотношению максимального времени с максимальным значением контрола. То есть, если полное время анимации равно 1 сек, а максимальное значение контрола равно 1, то никакие коэффициенты не нужны. Если же полное время анимации равно 4,5 сек, а максимальное значение контрола равно 1,5, коэффициент будет равен 4,5/1,5 = 3. То есть, для получения значения коэффициента, всё, что надо сделать - это разделить полное время анимации на максимальное значение контрола (естественно, если минимальное значение контрола равно 0).

Часовой пояс: UTC + 4 часа

Powered by phpBB © 2002, 2006 phpBB Group
www.phpbb.com

Blogs powered by User Blog Mod © EXreaction
www.lithiumstudios.org