Метка

объект Метка
объект MarkerReactor

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

Поддерживаемые интерфейсы:

  • reactor
  • node
  • node.group
  • node.transform
  • layoutable
  • node.marker

Маркер - ключевой объект дополненной реальности. К маркеру, который камера видит в реальном мире привязываются объекты виртуальной сцены. По сути своей маркер является объектом Система координат (TransformNodeReactor), видимостью и положением которого управляет система трекинга приложения. Таким образом, взаимодействие с меткой дополненной реальности ничем не отличается от взаимодействия с Система координат (TransformNodeReactor).

Для «соединения» метки и каких-либо объектов (например, Модель (ModelReactor)) достаточно добавить модель в маркер при помощи интерфейса панели «Проект». Для того, чтобы отследить показ или скрытие метки, следует использовать события Объект - показан (onShow) и Объект - скрыт (onHide) соответственно. Дополнительно для более точного взаимодействия добавлены события Маркер - исчез (onLeft) и Маркер - пропал и появился (onBlink).

Работа с меткой

Вводится в Метка (MarkerReactor)

Параметр Описание
Технология распознавания (markerType) Тип метки: маркерная или безмаркерная.
Ресурс метки (pattern) Ресурс паттерна метки.
Время потери (markerLeftTimeout) Время потери метки. Используется для настройки событий Маркер - исчез (onLeft) и Маркер - пропал и появился (onBlink).
Физический размер (markerPhysSize) Ширина метки дополненной реальности.
Включен (enabled) Активен ли данный маркер.
Событие Описание
Маркер - исчез (onLeft) Вызывается при мгновенном пропадании метки из поля зрения. В отличие от Объект - скрыт (onHide) событие вызывается сразу, без задержек.
Маркер - пропал и появился (onBlink) Вызывается при появлении метки после кратковременной потери, меньшей Время потери (markerLeftTimeout).
Включён (onEnabled) Вызывается при активации метки.
Выключен (onDisabled) Вызывается при деактивации метки.
Действие Описание
Включить (enable) Активировать метку.
Выключить (disable) Деактивировать метку.
../_images/marker_marker_actions.png
параметр Технология распознавания
параметр markerType

Тип метки: маркерная или безмаркерная.

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

В версии Advanced значения для технологий распознавания могут быть установлены как MarkerType.DASH_DOT для меркерной технологии и MarkerType.IMAGE для безмаркерной.

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

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

параметр Ресурс метки
параметр pattern

Паттерн для метки дополненной реальности.

Подробно о требованиях к паттернам см. в разделе Технология трекинга

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

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

параметр Время потери
параметр markerLeftTimeout

Время потери метки в секундах. Используется для настройки событий Маркер - исчез (onLeft) и Маркер - пропал и появился (onBlink).

Время в секундах между вызовами событий Маркер - исчез (onLeft) и Объект - скрыт (onHide). Если значение равно нулю, то оба события вызываются одновременно.

параметр Физический размер
параметр markerPhysSize

Ширина метки дополненной реальности.

Для маркерной технологии распознавания физический размер - расстояние между центрами крайних точек или краёв линий (см. изображение).

../_images/dashdot_tracking_size.png

Для безмаркерной технологии распознавания физический размер - ширина изображения.

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

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

параметр Включен
параметр enabled

Активен ли данный маркер.

Неактивный маркер не будет распознаваться системой, и, соответственно, не будет распознаваться системой и не будет вызывать никаких событий.

Для управления данным параметром существуют действия Включить (enable) и Выключить (disable), при изменении состояния будут вызываться события Включить (enable) и Выключить (disable).

Примечание

При выключении метки в момент, когда она была показана в кадре, события Маркер - исчез (onLeft), Объект - скрыт (onHide) и т.п. вызваны не будут.

событие Маркер - исчез
событие onLeft()

Вызывается при пропаже метки из кадра. В отличие от Объект - скрыт (onHide) данное событие вызывается сразу.

Вызов данного события не означает, что метка уже пропала. Параметр Время потери (markerLeftTimeout) настраивает время, которое будет проходить между вызовами событий Маркер - исчез (onLeft) и Объект - скрыт (onHide).

см. также событие Маркер - пропал и появился (onBlink).

событие Маркер - пропал и появился

Вызывается при появлении метки после кратковременной потери, меньшей Время потери (markerLeftTimeout).

событие Включён
событие onEnabled()

Вызывается при активации метки, т.е. при изменении параметра Включить (enable) на true или вызове действия Включить (enable).

событие Выключен
событие onDisabled()

Вызывается при деактивации метки, т.е. при изменении параметра Выключить (disable) на false или вызове действия Выключить (disable).

действие Включить
действие enable()

Включить метку.

Данный вызов равносилен присваиванию:

marker.enabled = true

действие Выключить
действие disable()

Выключить метку.

Данный вызов равносилен присваиванию:

marker.enabled = false

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

Если данное действие было вызвано в момент, когда метка была показана, то события Маркер - исчез (onLeft) и Объект - скрыт (onHide) вызваны не будут.

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

Вводится в Система координат (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))
transform.trans = osg.Vec3(0, 0, 0)

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

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

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

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

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

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

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

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

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

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

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

model:setTransform(osg.Vec3(0, 0, 0), osg.Vec3(0, 0, 0), osg.Vec3(1, 1, 1))
model:setTrans(osg.Vec3(0, 0, 0))
model:setRotate(osg.Vec3(0, 0, 0))
model:setScale(osg.Vec3(1, 1, 1))

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

Работа с потомками и иерархией

Вводится в Группа (GroupNodeReactor)

Каждый объект, производный от Группа (GroupNodeReactor) может иметь одного или нескольких потомков, производных от Узел (NodeReactor). Например, любой Модель (ModelReactor) может быть добавлен на метку - в Метка (MarkerReactor), или любой объект может быть добавлен в Сцена (SceneReactor).

Примечание

Вся система объектов, производных от Узел (NodeReactor) повторяет структуру библиотеки OpenSceneGraph . Соответственно, многие особенности библиотеки распрастраняются и на систему объектов EV Toolbox.

Иерархия объектов может быть изменена в списке объектов при помощи drag’n’drop или при помощи контекстного меню.

../_images/group_children_actions.png
Параметр Описание
Список потомков (children) Список потомков данного объекта
Действие Описание
Дочерний узел - добавить (addChild) Добавить потомка в конец списка потомков
Дочерний узел - вставить (insertChild) Вставить потомка в середину списка потомков.
Дочерний узел - удалить последний (removeLastChild) Удалить последнего потомка из списка потомков
Дочерний узел - удалить (removeChild) Убирает указанный объект из списка потомков.
Дочерний узел - удалить по индексу (removeChild) Убирает объект по данному индексу из списка потомков.
Группа - удалить дочерние узлы (removeChildren) Убирает заданное число объектов из списка потомков, начиная с заданного индекса.
Группа - удалить все дочерние узлы (clearChildren) Полностью очищает список потомков объекта.
параметр Список потомков
параметр children

Список всех дочерних объектов. Имеет тип table, в котором находятся ссылки на все дочерние объекты.

Примечание

В интерфейсе версии Standard данный параметр устанавливается неявно, путём переноса объектов в списке объектов

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

local marker = ...      -- Тип MarkerReactor
local model = ...       -- Тип NodeReactor или производный
local transform = ...   -- Тип TransformNodeReactor

-- Подписываемся на onHide маркера - событие исчезновения его из вида
marker:subscribeEvent("onHide", function()
    -- Переносим трансформацию маркера на transform
    transform.trans = marker.trans
    transform.rotate = marker.rotate
    transform.scale = marker.scale

    -- Удаляем модель из маркера
    marker:removeChild(model)

    -- Добавляем модель в transform
    transform:addChild(model)
end)

-- При показе метки
marker:subscribeEvent("onShow", function()
    -- Удаляем модель из transform'а
    transform:removeChild(model)

    -- Добавляем модель в маркер
    marker:addChild(model)
end)

действие Дочерний узел - добавить
действие addChild(child)

Добавить потомка в конец списка потомков

Параметры:Узел / child – Объект, производный от Узел (NodeReactor), который будет добавлен в качестве потомка
действие Дочерний узел - вставить
действие insertChild(index, child)

Вставить потомка в середину списка потомков.

Параметры:
  • Индекс / index – Индекс, на который надо вставить нового потомка. Индексация начинается с единицы.
  • Узел / child – Объект, производный от Узел (NodeReactor), который будет добавлен в качестве потомка
действие Дочерний узел - удалить последний
действие removeLastChild()

Удалить последнего потомка из списка потомков

действие Дочерний узел - удалить
действие removeChild(child)

Убирает указанный объект из списка потомков.

Если данного объекта не было в спике потомков, то ничего не происходит. Если в списке потомков данный объект встречался дважды, будет удалено только первое вхождение.

Параметры:Узел / child – Объект, который необходимо убрать из списка потомков
действие Дочерний узел - удалить по индексу
действие removeChild(index)

Убирает объект по данному индексу из списка потомков.

Параметры:Индекс / index – Индекс объекта в списке потомков, который необходимо удалить.
действие Группа - удалить дочерние узлы
действие removeChildren(startIndex, numChildren = 1)

Убирает заданное число объектов из списка потомков, начиная с заданного индекса.

Примечание

Вызов с Числом узлов равным единице равносилен вызову Дочерний узел - удалить по индексу (removeChild)

Параметры:
  • Начать с индекса / startindex – Индекс первого объекта, который должен быть удалён
  • Число узлов / numChildren – Число потомков, которые должны быть удалены из списка потомков
действие Группа - удалить все дочерние узлы
действие clearChildren()

Полностью очищает список потомков объекта.

Видимость объекта

Вводится в Узел (NodeReactor)

Каждый объект в любой момент времени может быть скрыт или показан. Скрытые объекты, а также все потомки скрытых объектов не будут отображаться на экране. Соответственно, объект будет показан на экране только если он сам, а также все его потомки видимы.

Также для скрытых объектов могут «вставать на паузу» некоторые процессы, такие как анимации у модели.

Примечание

Скрытие объекта в терминах OpenSceneGraph - это выставление нулевой маски у вершины. Таким образом для всех скрытых вершин (и их потомков) не будет происходить не один из обходов (Update Traversal, Event Traversal и т.п.), и, соответственно, не будут вызываться никакие NodeCallback

../_images/model_visibility.png
Параметр Описание
Видимость (visible) Регулирует видимость объекта и его потомков на экране
Событие Описание
Объект - показан (onShow) Вызывается при показе объекта
Объект - скрыт (onHide) Вызывается при скрытии объекта
Объект - на кадре (onFrame) Вызывается для показанных объектов на каждом кадре
Действие Описание
Объект - показать (show) Показывает объект
Объект - скрыть (hide) Скрывает объект
параметр Видимость
параметр visible

Вводится в Узел (NodeReactor)

Регулирует видимость объекта и его потомков на экране.

В версии Standard начальная видимость объекта регулируется при помощи иконки eye_icon в списке объектов

Присваивание данного параметра равносильно вызовам Объект - показать (show) и Объект - скрыть (hide)

событие Объект - показан
событие onShow()

Вводится в Узел (NodeReactor)

Вызывается, когда объект показывается на экране.

Примечание

Данное событие вызывается только в случае, если у данного объекта было вызвано действие Объект - показать (show), при этом до этого объект не был показан. Причём на вызов данного события не влияет состояние предков и потомков данного объекта.

Примечание

Например, данное событие вызывается для показанной метки (см. Модель (ModelReactor)). При этом данное событие будет вызвано только для самой метки, и ни для каких её потомков.

Допустим, имеется следующая иерархия объектов

Правильно Неправильно
marker_onshow_handle_ok_image
Стоит подписываться именно на событие Объект - показан (onShow) метки, а не модели
marker_onshow_handle_ne_ok_image
Несмотря на то, что модель теперь показывается на экране, для неё не вызывается события Объект - показан (onShow)

событие Объект - скрыт
событие onHide()

Вводится в Узел (NodeReactor)

Вызывается, когда объект скрывается

Примечание

Данное событие вызывается только в случае, если у данного объекта было вызвано действие Объект - скрыть (hide), при этом до этого объект не был показан. Причём на вызов данного события не влияет состояние предков и потомков данного объекта.

Примечание

Например, данное событие вызывается для показанной метки (см. Модель (ModelReactor)). При этом данное событие будет вызвано только для самой метки, и ни для каких её потомков.

Допустим, имеется следующая иерархия объектов

Правильно Неправильно
marker_onhide_handle_ok_image
Стоит подписываться именно на событие Объект - скрыт (onHide) метки, а не модели
marker_onhide_handle_ne_ok_image
Несмотря на то, что модель теперь показывается на экране, для неё не вызывается события Объект - скрыт (onHide)

событие Объект - на кадре
событие onFrame()

Вводится в Узел (NodeReactor)

Вызывается на каждом кадре только для объектов, которые отображаются на экране.

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

-- На каждом кадре будем переносить вращение метки на аватар
local marker = ...
local avatar = ...

marker:subscribeEvent("onFrame", function()
    avatar.rotate = marker.rotate
end)

действие Объект - показать
действие show()

Вводится в Узел (NodeReactor)

Показывает объект. Если объект до этого был скрыт, то будет вызвано событие Объект - показан (onShow)

Вызов равносилен присваиванию параметра Видимость (visible)

model.visible = true

Примечание

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

действие Объект - скрыть
действие hide()

Вводится в Узел (NodeReactor)

Скрывает объект. Если до этого объект был показан, то будет вызвано событие Объект - скрыт (onHide)

Вызов равносилен присваиванию параметра Видимость (visible)

model.visible = false

Примечание

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

Нажатия на объект

Вводится в Узел (NodeReactor)

События из данной секции необходимы для отслеживания нажатий пользователей на узлы (объекты Узел (NodeReactor) и производные: Модель (ModelReactor), Прямоугольник (RectReactor), Изображение (ImageReactor), Текст (TextReactor) и др.) приложения.

Для объектов, производных от Группа (GroupNodeReactor) (Система координат (TransformNodeReactor), Прямоугольник (RectReactor)) нажатие сработает на них самих, либо на любом потомке. Таким образом, если необходимо подписаться на нажатия двух разных объектов, и при этом выполнять одинаковые действия, то имеет смысл сгруппировать их при помощи объекта Система координат (TransformNodeReactor), и подписываться на нажатие нового родительского объекта:

node_clicks_example_1_separated
Три объекта в иерархии находятся отдельно друг от друга, подписка на события происходит независимо.
node_clicks_example_1_grouped
Объекты сгруппированы, что позволяет подписаться только один раз

Примечание

Для отслеживания нажатия на экран, без привязки к каким-либо объектам, следует использовать события Сцена (SceneReactor) : Нажатия на экран

Примечание

Никакие нажатия не «пробивают» геометрию. Если под курсором (пальцем) оказалось несколько геометрий, то нажатие сработает только на первую (ближайшую) из них

Примечание

Нажатия на скрытые объекты не работают.

Примечание

Для Прямоугольник (RectReactor) и производных для создания прозрачных кнопок нельзя делать подложку объекта полностью прозрачной. В таком случае подложка будет автоматически скрыта. Необходимо выставить минимальное значение прозрачности параметра Прямоугольник.Цвет (RectReactor.rect.color).

../_images/node_clicks_actions.png
Событие Описание
Нажатие (onClick) Вызывается, когда пользователь нажимает на объект или на его потомков
Двойное нажатие (onDoubleClick) Вызывается, когда пользователь дважды нажимает на объект или на его потомков
событие Нажатие
событие onClick()

Вызывается, когда пользователь нажимает на объект или на его потомков

событие Двойное нажатие
событие onDoubleClick()

Вызывается, когда пользователь дважды нажимает на объект или на его потомков

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

Каждому вызову Двойное нажатие (onDoubleClick) будет предшествовать вызов Нажатие (onClick). Таким образом, не стоит подписываться на оба события для одного объекта одновременно, либо необходимо фильтровать клики при помощи объекта Таймер (TimerReactor).

../_images/node_clicks_example_2.png

local model = ...

local singleClickIndicator = ...
local doubleClickIndicator = ...

local clickTimer = ...

local skipClick = false
model:subscribeEvent("onClick", function()
    if skipClick then
        skipClick = false
        return
    end

    clickTimer:start(0.01)
end)

clickTimer:subscribeEvent("onTimer", function()
    singleClickIndicator:show()
    doubleClickIndicator:hide()
end)

model:subscribeEvent("onDoubleClick", function()
    clickTimer:reset()

    doubleClickIndicator:show()
    singleClickIndicator:hide()

    skipClick = true
end)