Модель

объект Модель; ModelReactor

Производный от: Система координат (TransformNodeReactor)

Объект «Модель» позволяет добавлять в проект 3D модель с анимацией.

../_images/model_screen.png

Модель можно перемещать, поворачивать, масштабировать при помощи манипуляторов в панели инструментов вкладки «Сцена». Модель можно трансформировать, также указывая точные значения трансформации в окне свойства (подробное описание ниже). В панели инструментов можно просматривать анимации, если они присутствуют в модели.

../_images/model_screen_1.png

По умолчанию объект «модель» располагается в сцене, но она не привязана к метке. Ее можно увидеть в режиме предпросмотра, если переместить модель по координате Z в отрицательном направлении, так чтобы сетка была над моделью, как на изображении ниже (виртуальная камера находится в центре координат и «смотрит» вдоль оси z в отрицательном направлении).

Для того чтобы модель располагалась на метке и была привязана к ней в режиме дополненной реальности, необходимо перетащить объект «Модель» на объект «Метка». Так, чтобы метка стала родительским узлом, а модель дочерним (как на изображении).

../_images/model_screen_2.png

Свойства модели

Вводится в Модель (ModelReactor)

Параметр Описание
Ресурс модели (model) Ресурс модели для отображения.
Действие Описание
Модель - изменить ресурс (setModel) Установить новый ресурс модели
параметр Ресурс модели; model

Параметр позволяет выбрать ресурс модели для данного объекта.

Примечание

Можно присваивать как ресурс, так и id ресурса. Подробнее см. /articles/resources.

действие Модель - изменить ресурс; setModel(modelResource)

Установить новый ресурс модели (параметр Ресурс модели (model)).

Данный вызов равносилен присваиванию параметра Ресурс модели (model)

Параметры:Ресурс модели / modelResource – Новый ресурс модели, который будет выставлен объекту

Работа с анимациями

Вводится в Модель (ModelReactor)

../_images/model_animations.png
Событие Описание
Анимация - завершилась (onAnimationFinished) Вызывается при завершении какой-либо анимации
Анимация - началась (onAnimationStart) Вызывается на старте какой-либо анимации (см. действие Анимация - запустить (playAnimation))
Анимация - прервана (onAnimationStop) Вызывается на паузе какой-либо анимации (см. действия Анимация - остановить (stopAnimation), Анимация - пауза (pauseAnimation))
Действие Описание
Анимация - запустить (playAnimation) Запустить анимацию по имени. Перед запуском предварительно сбрасывает анимацию в начальное состояние.
Анимация - остановить (stopAnimation) Остановить запущенную анимацию. Анимация при этом вернётся в начальное состояние.
Анимация - остановить все (stopAllAnimations) Остановить все запущенные анимации. Все анимации вернутся в начальное состояние.
Анимация - пауза (pauseAnimation) Приостановить анимацию по её имени. Модель застынет в том положении, которое было перед остановкой.
Анимация - приостановить все (pauseAllAnimations) Приостановить все анимации. Можель при этом останется в том же состоянии, которое было до приостановки.
Анимация - сброс (resetAnimation) Сбросить состояние анимации с именем animationName в начальное состояние. В случае, если анимация проигрывалась, она сбрасывается на начало, но продолжает проигрываться с начала.
resetAllAnimations (resetAllAnimations) Сбросить все анимации. Возвращает модель в исходное положение.
Анимация - смена режима (setAnimationPlayMode) Изменяет текущий режим проигрывания анимации. Имеет смысл только для проигрываемых в данный момент анимаций.

Каждая 3D модель может иметь одну или несколько анимаций. Ниже приведены события и действия по работе с анимациями.

Примечание

Если модель скрыта, то анимация будет стоять на паузе всё время, пока она будет скрыта, при этом никакие события не будут вызваны

Предупреждение

Если была запущена анимация у скрытой модели, то событие onAnimationStart будет запущено только после того, как модель будет показана.

Такая же ситуация может происходить, если сначала была запущена анимация, и сразу после этого - её сокрытие:

local model = reactorController:getReactorByName("MyModel")

-- Неправильно:

model:playAnimation("Deactivate")
model:hide()


-- Правильно:

-- Инициализация
model:subscribeEvent("onAnimationFinished", function(animationName)
    if animationName == "Deactivate" then
        model:hide()
    end
end)

model:playAnimation("Deactivate")

Неправильно Правильно
model_hide_anim_image model_hide_anim_ok_image

действие Анимация - запустить; playAnimation(animationName, playMode = "once", stopOthers = false)

Запустить анимацию по имени. Перед запуском предварительно сбрасывает анимацию в начальное состояние.

После запуска будет вызвано событие Анимация - началась (onAnimationStart). Данное событие может быть вызвано не моментально, в зависимости от видимости объекта. Поднобнее см. выше

Если playMode выставлен в once, то после окончания анимации будет вызвано событие Анимация - завершилась (onAnimationFinished). Если режим проигрывания выставлен в loop, то анимация никогда не закончится сама, и, соответственно, событие вызвано не будет. Однако режим проигрывания анимации может быть изменён явно при помощи действия Анимация - смена режима (setAnimationPlayMode).

Параметры:
  • Имя анимации / animationName – Имя анимации, которую необходимо запустить
  • Режим проигрывания / playMode – Режим проигрывания: once - проиграть один раз, loop - проигрывать в цикле
  • Остановить остальные / stopOthers – Надо ли останавливать остальные проигрываемые в данный момент анимации
действие Анимация - остановить; stopAnimation(animationName = nil)

Остановить запущенную анимацию. Анимация при этом вернётся в начальное состояние.

В случае, если анимация проигрывалась, будет запущено событие Анимация - прервана (onAnimationStop). Если такая анимация не проигрывалась, то событие вызвано не будет.

Если анимация не проигрывалась, то вызов равносилен вызову Анимация - сброс (resetAnimation)

Примечание

Данный вызов равносилен следующим двум вызовам:

local model = ...

model:pauseAnimation("Rotate")
model:resetAnimation("Rotate")

Имя анимации может быть неопределено, тогда будут остановлены все анимации (вызов будет равносилен Анимация - остановить все (stopAllAnimations)). Соответственно, событие Анимация - прервана (onAnimationStop) будет вызвано для всех анимаций, которые в данный момент проигрывались.

Параметры:Имя анимации / animationName – Имя анимации, которую необходимо остановить. Если значение отсутвует, то будут остановлены все анимации
действие Анимация - остановить все; stopAllAnimations()

Остановить все запущенные анимации. Все анимации вернутся в начальное состояние.

Для каждой проигрываемой анимации будет вызвано событие Анимация - прервана (onAnimationStop)

действие Анимация - пауза; pauseAnimation(animationName = nil)

Приостановить анимацию по её имени. Данная анимация останется в том положении, которое было до остановки. Остальные проигрываемые анимации при этом продолжат проигрывание.

Для каждой анимации будет вызвано событие Анимация - прервана (onAnimationStop)

Вызов с animationName равным nil или „“ равносильно вызову Анимация - остановить все (stopAllAnimations).

Параметры:Имя анимации / animationName – Имя анимации, которая должна быть приостановлена. Отсутвующее значение означают приостановку всех анимаций.
действие Анимация - приостановить все; pauseAllAnimations()

Приостановить все анимации. Модель при этом застынет в том положении, которое было до приостановки.

Для каждой проигрываемой анимации будет вызвано событие Анимация - прервана (onAnimationStop)

действие Анимация - сброс; resetAnimation(animationName = nil)

Сбросить состояние анимации с именем animationName в начальное состояние. В случае, если анимация проигрывалась, она сбрасывается на начало, но продолжает проигрываться с начала.

При вызове не запускается никаких событий.

Параметры:Имя анимации / animationName – Имя анимации, которая будет сброшена. Если имя анимации не установлено, то будут сброшены все анимации

действие resetAllAnimations()

Сбросить все анимации. Возвращает модель в исходное положение.

Никакие события вызваны не будут.

действие Анимация - смена режима; setAnimationPlayMode(animationName, playMode)

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

При смене режима Никакие события вызваны не будут.

Параметры:
  • Имя анимации / animationName – Имя анимации
  • Режим проигрывания / playMode – Новый режим проигрывания: „once“ или „loop“.

Пример использования действия:

-- Проигрывать анимацию "RotateClockwise" в цикле до тех пор, пока пользователь не нажмёт кнопку.
-- После нажатия кнопки доигрывается анимация "RotateClockwise",после чего
-- запускается анимация "RotateCounterClockwise". Затем процесс повторяется.
local model = ...
local button = ...

-- Подписка на нажатие на кнопку.
button:subscribeEvent("onClick", function()
    -- В данный момент времени проигрывается ровно одна из этих анимаций,
    -- однако для остановленной анимации данный вызов будет проигнорирован:
    model:setAnimationPlayMode("RotateClockwise", "once")
    model:setAnimationPlayMode("RotateCounterClockwise", "once")

    -- Теперь остаётся дождаться, пока проигрываемая анимация закончится.
end)

-- После нажатия на кнопку одна из анимаций проигрывается в режиме "once", и скоро закончится.
-- Необходимо поймать это событие, и запустить следующую анимацию
model:subscribeEvent("onAnimationFinished", function(animationName)
    if animationName == "RotateClockwise" then
        model:playAnimation("RotateCounterClockwise", "loop")
    else
        model:playAnimation("RotateClockwise", "loop")
    end
end)

-- Запускаем весь процесс
model:playAnimation("RotateClockwise", "loop")

../_images/model_change_animation.png

событие Анимация - завершилась; onAnimationFinished()

Вызывается при завершении какой-либо анимации

Параметры:Имя анимации / animationName – Имя анимации, которая закончилась
событие Анимация - началась; onAnimationStart()

Вызывается на старте какой-либо анимации (см. действие Анимация - запустить (playAnimation))

Параметры:Имя анимации / animationName – Имя анимации, которая началась
событие Анимация - прервана; onAnimationStop()

Вызывается на паузе какой-либо анимации (см. действия Анимация - остановить (stopAnimation), Анимация - пауза (pauseAnimation))

Параметры:Имя анимации / animationName – Имя анимации, которая остановилась

Пример использования анимаций:

local model = ...

model:subscribeEvent("onAnimationFinished", function(animationName)
    if animationName == "TurnLeft" then
        model:playAnimation("TurnRight")
    elseif animationName == "TurnRight" then
        model:playAnimation("TurnLeft")
    else
        logwarn("Unknown animation is finished:", animationName)
    end
end)

model:playAnimation("TurnLeft")

Положение объекта

Вводится в Система координат (TransformNodeReactor)

Параметр Описание
Перемещение (trans) Перемещение объекта относительно родительского объекта.
Вращение (rotate) Поворот объекта относительно родительского объекта.
Масштаб (scale) Масштаб объекта относительно родителя.
Действие Описание
Объект - переместить (setTrans) Установить новое перемещение объекта (значение параметра Перемещение (trans))
Объект - повернуть (setRotate) Установить новый поворот объекта (значение параметра Вращение (rotate))
Объект - масштабировать (setScale) Установить новый масштаб объекта (значение параметра Масштаб (scale))
../_images/transform_transform_actions.png
параметр Перемещение; trans

Вводится в Система координат (TransformNodeReactor)

Параметр позволяет задать точный сдвиг объекта по координатам (x, y, z) относительно родительского объекта.

Перемещение задаётся в виде объекта osg.Vec3. Пример использования:

-- Заставим мячик прыгать на месте
local ball = ...

local velocity = 0                   -- Текущая скорость объекта
ball.trans = osg.Vec3(0, 0, 0.2)     -- Задаём начальное положение - 20 см.

local delta_time = 0.01              -- Время между кадрами для обновления

-- Функция для обновления
function update_velocity_and_position()
    -- Обновляем положение объекта.
    -- Для простоты считаем, что скорость за этот период времени не менялась
    ball.trans = ball.trans + osg.Vec3(0, 0, 1) * velocity * delta_time

    -- Обновляем скорость: на мячик действует ускорение свободного падения
    -- 9.8 м/с^2, с предыдущей итерации прошло время delta_time
    velocity = velocity - 9.8 * delta_time

    -- Мячик достиг земли - отскок от земли
    if ball.trans:z() <= 0 then
        velocity = - velocity
    end
end

-- Вызывать функцию обновления позиции каждые delta_time секунд
timer:subscribe(update_velocity_and_position, delta_time)

Доступны следующие действия:

  • img_reset сбросить в нулевое положение
  • img_auto поместить на метку автоматически (совместить центр с родительской меткой)
параметр Вращение; rotate

Вводится в Система координат (TransformNodeReactor)

Параметр позволяет задать точный поворот объекта по осям (x, y, z) относительно родительского объекта.

В данном параметре используются углы Крылова (или углы Эйлера), где порядок поворота осей определяется в порядке: z, x, y. Все углы задаются в градусах.

Параметр имеет тип osg.Vec3, где каждая компонента вектора соответствует своей оси.

Для перевода в градусы и из градусов можно воспользоваться функциями deg2rad(x) и rad2deg(x). Данные функции могут быть использованы как для чисел, так и для векторов osg.Vec3, osg.Vec2.

Для перевода в/из osg.Quat можно воспользоваться функциями euler2quat(ypr) и quat2euler(quat). Важно отметить, что обе функции работают с векторами в радианах. Таким образом, для получения кватерниона из параметра Вращение (rotate), а также наоборот необходимо сделать по два вызова:

local model = ...

-- Получение кватерниона по параметру rotate
local rotation_quat = euler2quat(deg2rad(model.rotate))

-- Присвоение кватерниона параметру rotate
model.rotate = rad2deg(quat2euler(rotation_quat))

Пример вращения логотипа:

local logo = ...

local function update_logo_rotation()
    -- Забираем текущий поворот
    local rot = logo.rotate

    -- Добавляем небольшое вращение вдоль одной из осей
    rot:y((rot:y() + 1) % 360)

    -- Присваиваем новое значение объекту
    logo.rotate = rot
end

-- Подписываемся на таймер, чтобы обновление происходило каждые 0.01 секунд
timer:subscribe(update_logo_rotation, 0.01)

Пример поворота объекта в сторону метки:

local model = ...
local marker = ...

-- Функция построения кватерниона для поворота от from к to
local function _make_directed_rotation(from, to)
    -- Вращать будем относительно оси, ортогональной обоим векторам,
    --   для его получения воспользуемся векторным произведением
    local axis = osg.Vec3.cross(from, to)

    -- Для получения угла вращения воспользуемся скалярным произвелением:
    --   v1 * v2 = |v1| |v2| cos(angle(v1, v2)) => angle = acos(v1 * v2 / (|v1| |v2|))
    local angle_cos = osg.Vec3.dot(from, to) / (from:length() * to:length())
    local angle = math.acos(angle_cos)

    -- Возвращаем кватернион вращения с найденной осью и углом
    return osg.Quat(angle, axis)
end

local function update_rotation()
    -- Направление от модели к метке
    local delta_trans = marker.trans - model.trans

    -- Получим вращение модели в виде кватерниона
    local rotation = _make_directed_rotation(osg.Vec3(1, 0, 0), delta_trans)

    -- Присваиваем вращение. Заметим, что необходимо перевести кватернион
    -- сначала в углы Крылова, а затем перевести их значения из радианов в градусы
    model.rotate = deg2rad(quat2euler(rotation))
end

-- Будем обновлять вращение каждые 10 миллисекунд
timer:subscribe(update_rotation, 0.01)

Доступны следующие действия:

  • img_reset2 сбросить в начальное состояние
параметр Масштаб; scale

Вводится в Система координат (TransformNodeReactor)

Параметр позволяет задать точный масштаб по координатам (x, y, z) относительно родительского объекта.

Доступны следующие действия:

  • img_reset3 сбросить в начальное состояние
  • img_auto3 поместить на метку автоматически (совместить габариты объекта и родительской метки)
  • img_lock зафиксировать оси (масштабировать отдельно по каждой оси, или по всем одновременно)
действие Объект - переместить; setTrans(trans)

Установить новое значение перемещения объекта (параметра Перемещение (trans))

Данное действие равносильно присваиванию параметра Перемещение (trans)

transform:setTrans(osg.Vec3(0.0, 0.0, 0.0))
transform.trans = osg.Vec3(0.0, 0.0, 0.0)

Параметры:Перемещение / trans – Новое значение перемещения
действие Объект - повернуть; setRotate(rotate)

Установить новое значение вращения объекта (параметра Вращение (rotate)).

Данное действие равносильно присваиванию параметра Вращение (rotate)

transform:setRotate(osg.Vec3(0.0, 0.0, 0.0))
transform.rotate = osg.Vec3(0.0, 0.0, 0.0)

Параметры:Вращение / rotate – Новое значение вращения
действие Объект - масштабировать; setScale(scale)

Установить новое значение масштабирования объекта (параметра Масштаб (scale)).

Данное действие равносильно присваиванию параметра Масштаб (scale)

transform:setScale(osg.Vec3(1.0, 1.0, 1.0))
transform.scale = osg.Vec3(1.0, 1.0, 1.0)

Параметры:Масштаб / scale – Новое значение вращения
действие Объект - преобразование; setTransform(trans, rotate, scale)

Установить новые значения перемещения, вращения и масштаба (параметров Перемещение (trans), Вращение (rotate), Масштаб (scale). Данный вызов равносилен последовательным вызовам Объект - переместить (setTrans), Объект - повернуть (setRotate), Объект - масштабировать (setScale):

Следующие две конструкции полностью равносильны:

model:setTransform(osg.Vec3(0.0, 0.0, 0.0), osg.Vec3(0.0, 0.0, 0.0), osg.Vec3(1.0, 1.0, 1.0))
model:setTrans(osg.Vec3(0.0, 0.0, 0.0))
model:setRotate(osg.Vec3(0.0, 0.0, 0.0))
model:setScale(osg.Vec3(1.0, 1.0, 1.0))

transform_set_transform_image
transform_set_transform_separated_image
Равносильная конструкция