Преобразование модуля Scene Graph определяется параметрами переносом (местоположением), вращением (ориентацией) и масштабом (размером) модуля. Для преобразования модуля Scene Graph он должен иметь transform_component. transform_component содержит два поля, которые можно менять через элементы управления UEFN или код Verse:
Origin: необязательное начало координат, относительно которого рассчитывается LocalTransform.
LocalTransform: преобразование
(/Verse.org/SpatialMath:)transformотносительно родительского модуля или начала координат, если заданы значения для необязательного поля Origin.
Начало координат модуля — это модуль, на основе которого рассчитывается LocalTransform для transform_component модуля. Это значение поля Origin, если оно задано в transform_component, или значение из родительского модуля в иерархии Scene Graph, если значение в поле Origin не задано.
Важно различать преобразование и transform_component. Преобразование — это составной тип данных, определённый в модуле /Verse.org/SpatialMath, который хранит следующие величины в системе координат влево-вверх-вперёд (LUF):
Перенос (
vector3): местоположение объекта.Вращение (
rotation): ориентация объекта.Масштаб (
vector3): размер объекта.
transform_component — это класс Verse, определённый в модуле /Verse.org/SceneGraph, в котором хранится значение LocalTransform модуля Scene Graph и, необязательное альтернативное начало координат. transform_component можно представить как контейнер, предоставляющий модулю значения преобразования, определяющие его расположение в симуляции.
Преобразования Verse
Scene Graph использует модуль преобразования /Verse.org/SpatialMath . Преобразования в модуле Verse используют правостороннюю систему координат LUF. Чтобы создать преобразование Verse, можно использовать архетип класса и встроенные методы для создания переменных вращения rotation.
# Transform specifying all fields
MyTransform:transform = transform:
Translation := vector3{Left := 2.0, Up := -4.0, Forward := 8.0}
Rotation := MakeRotationFromEulerDegrees(-90.0, 180.0, 0.0)
Scale := vector3{Left := 2.0, Up := 4.0, Forward := 2.0}
# Transform specifying only Translation
MyOtherTransform:transform = transform:
Translation := vector3{Up := 512.0}
Дополнительную информацию о системе координат в UEFN см. на странице Система координат «влево-вверх-вперёд». Там же можно найти информацию о конвертации преобразований в системе XYZ, расположенных в модуле /UnrealEngine.com/Temporary/SpatialMath, в преобразования модуля Verse и обратно.
Создание модуля с помощью transform_component
Вы можете создать модуль на панели «Структура» UEFN или через Verse.
В UEFN
Вы можете быстро добавить модуль Scene Graph в проект через меню Расстановка Акторов.
Когда вы добавляете модуль Scene Graph в проект через меню Расстановка Акторов, он по умолчанию добавляется с transform_component.
При желании вы можете удалить transform_component. Для этого перейдите к недавно размещённым модулям на панели «Структура», найдите transform_component и нажмите Удалить компонент.
Ниже показан модуль с удалённым компонентом transform_component.
В Verse
При создании модуля Scene Graph в коде Verse с архетипом класса:
MyEntity:entity = entity{}У модуля нет компонента transform_component. Его нужно добавить. Для работы с преобразованиями рекомендуется использовать SetLocalTransform и SetGlobalTransform. Эти функции одновременно обрабатывают создание transform_component, задают значения и добавляют компонент преобразования в модуль.
MyEntity:entity = entity{}
# Add entity to simulation entity so MyEntity begins simulating when play begins
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity})
# Identity transform
IdentityTransform:transform = transform:
Translation := vector3{Left := 0.0, Up := 0.0, Forward := 0.0}
Rotation := MakeRotationFromEulerDegrees(0.0, 0.0, 0.0)
Также можно добавить компонент напрямую с помощью AddComponents:
# Add entity to simulation entity so MyEntity begins simulating when play begins
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity})
# Use AddComponents
MyEntity.AddComponents(array{ transform_component{ Entity := MyEntity }})
# Same as above, but more readable if adding multiple components at once
MyEntity.AddComponents of array:
transform_component{Entity := MyEntity}Дополнительные методы добавления transform_component в модуль Scene Graph в коде Verse рассмотрены в разделе «Работа с transform_component в Verse».
Как рассчитывается преобразование модуля
Наиболее важная операция, которую можно выполнить с модулем Scene Graph с помощью transform_component, — это получить или задать преобразование модуля.
Существует два типа преобразования, которые могут вас заинтересовать: локальное преобразование и глобальное преобразование. Чтобы эффективно управлять преобразованиями модуля, важно понимать, как эти преобразования рассчитываются.
Локальное преобразование — это преобразование относительно начала координат модуля. Локальное преобразование любого модуля Scene Graph — это значение в поле LocalTransform компонента transform_component модуля Scene Graph.
Глобальное преобразование — это преобразование относительно начала координат системы LUF в глобальном пространстве. Глобальное преобразование модуля Scene Graph рассчитывается как сочетание значений модуля LocalTransform и:
глобального преобразования родительского модуля, если в поле Origin компонента transform_component модуля не задано значение;
глобального преобразования начала координат модуля, если значение в поле Origin компонента transform_component задано.
Ниже приведён пример с использованием переноса без поворота или масштабирования, чтобы конечное преобразование можно было рассчитать путём сложения значений переноса. Так как в этом примере предполагается, что вращение и масштаб остаются как есть во всех преобразованиях, используется сокращение для ссылки на преобразование модуля с помощью вектора переноса этого модуля.
Рассмотрим три модуля Scene Graph, организованные следующим образом:
BaseEntity: LocalTransform (0,0, 0,0, 0,0) в системе координат LUF.
A:: LocalTransform (750,0, 100,0, 0,0)
B: LocalTransform (–250,0, 100,0, 0,0)
Ниже приведены три модуля в сцене, где BaseEntity не имеет mesh_component, A — это куб, а B — конус:
Представьте, что вы хотите определить как локальное, так и глобальное преобразование модуля B. Локальное преобразование можно увидеть сразу: это значение поля LocalTransform компонента transform_component модуля B, как показано ниже:
Локальное преобразование модуля B: (–250,0, 100,0, 0,0).
Чтобы рассчитать глобальное преобразование модуля B, нужно отследить иерархию модуля B вверх до модуля симуляции и скомпилировать преобразования, начиная с модуля симуляции, а затем вниз до модуля B. Модуль симуляции — это корневой элемент текущей симуляции, относительно которого все другие симулируемые модули являются дочерними.
Глобальное преобразование модуля B рассчитывается так:
Модуль симуляции является корневым элементом текущей симуляции.
Глобальное преобразование модуля симуляции: (0,0, 0,0, 0,0).
BaseEntity является дочерним элементом модуля симуляции. Локальное преобразование BaseEntity имеет значения (0,0, 0,0, 0,0), как показано на рис. 1.0. Если объединить глобальное преобразование модуля симуляции и локальное преобразование BaseEntity, мы получим:
Глобальное преобразование BaseEntity: (0,0, 0,0, 0,0) + (0,0, 0,0, 0,0) = (0,0, 0,0, 0,0).
Модуль A является дочерним элементом BaseEntity. Локальное преобразование модуля A составляет (750,0, 100,0, 0,0), как показано на рис. 1.1. Сложив глобальное преобразование BaseEntity с преобразованием расположения модуля A, мы получим:
Глобальное преобразование модуля A: (0,0, 0,0, 0,0) + (750,0, 100,0, 0,0) = (750,0, 100,0, 0,0).
Модуль B является дочерним для модуля A. Локальное преобразование модуля B составляет (-250,0, 100,0, 0,0), как на показано на рис. 1.2. Сложив глобальное преобразование модуля A с преобразованием расположения модуля A, мы получим:
Глобальное преобразование модуля B: (750,0, 100,0, 0,0) + (–250,0, 100,0, 0,0) = (500,0, 200,0, 0,0).
Поэтому глобальное преобразование модуля B будет равно (500,0, 200,0, 0,0) в системе координат LUF.
Работа с transform_component в редакторе
С помощью LocalTransform и значений Origin можно управлять преобразованием модуля.
Локальное преобразование
Поле LocalTransform компонента transform_component модуля — это (/Verse.org/SpatialMath:)transform модуля относительно его начала координат. Если значения в поле Origin не заданы, в качестве начала координат модуля по умолчанию устанавливается начало координат его родительского элемента в иерархии Scene Graph. Поле LocalTransform — это редактируемое поле, которое появляется в UEFN, в котором вы можете напрямую редактировать модуль:
Перенос: местоположение относительно родительского элемента или указанного начала координат.
Измените значение переноса модуля, чтобы перемещать его по уровню.
Вращение: ориентация относительно родительского элемента или указанного начала координат.
Измените значение вращения модуля, чтобы повернуть его вокруг его точки вращения.
Масштаб: размер относительно родительского элемента или указанного начала координат.
Измените значение масштаба модуля, чтобы сделать его больше или меньше.
В начале координат
Началом координат компонента transform_component модуля является объект, по отношению к которому рассчитывается LocalTransform. Это поле в transform_component является необязательным. По умолчанию LocalTransform в transform_component — это преобразование модуля, основанное на начале координат модуля, рассчитанное относительно родительского элемента модуля. При необходимости вы можете указать значения в поле Origin компоенента transform_component модуля, чтобы рассчитывать LocalTransform относительно объекта, не являющегося родительским для модуля.
К примеру, вы можете задать в качестве начала координат совершенно другой модуль. Вы можете задать это поле для любого класса, в котором реализован интерфейс Origin Verse. В частности, чтобы указать в поле Origin другой модуль Scene Graph, выберите класс entity_origin , а затем выберите модуль, который будет использоваться в качестве нового начала координат.
Важно согласовать начало координат transform_component и начало координат системы LUF. Началом координат системы LUF является точка в пространстве мира с переносом (0,0, 0,0, 0,0).
Начало координат transform_component модуля — это место, в котором находится модуль, когда LocalTransform в transform_component имеет значение Translation (0,0, 0,0, 0,0).
Ниже приведён пример того, как на практике работают поля Origin и LocalTransform. Рассмотрим BaseEntity, находящийся в начале координат пространства мира, с дочерним модулем A, представленным кубом mesh_component, и дочерним модулем B, представленным конусом mesh_component.
Как показано на рисунке выше, BaseEntity находится в точке начала координат пространства мира, поскольку значения в поле Origin в transform_component для него не заданы, а для LocalTransform задано начало координат пространства мира.
Как показано ниже, поле Origin модуля A также имеет нулевые значения, поэтому LocalTransform рассчитывается с учётом transform_component его родительского элемента BaseEntity.
Поскольку BaseEntity располагается в начале координат пространства мира, а перенос LocalTransform модуля A задан как vector3{Left := 750.0, Up := 100.0, Forward := 0.0}, модуль A располагается в vector3{Left := 750.0, Up := 100.0, Forward := 0.0}. Вращение и масштаб модуля A остаются без изменений, поскольку параметры Вращение и Масштаб LocalTransform в BaseEntity соответствуют аналогичным в родительском модуле.
На рисунке ниже можно увидеть, что модуль B, который также является дочерним элементом BaseEntity, имеет поле Origin в transform_component, заданное как у модуля A.
В результате поле LocalTransform модуля B в его transform_component зависит от рассчитанного преобразования модуля A. Поскольку для LocalTransform модуля B установлено значение vector3{Left := -250.0, Up := 100.0, Forward := 0.0}, и LocalTransform модуля A также vector3{Left := 750.0, Up := 100.0, Forward := 0.0}, глобальное преобразование модуля B — vector3{Left := 500.0, Up := 200.0, Forward := 0.0}.
Если изменить компонент «Вращение» поля LocalTransform компонента transform_component модуля A на –90,0 градусов относительно оси «вперёд», модуль B также повернётся на –90,0 градусов относительно оси «вперёд». Это происходит потому, что вращение дочернего объекта также наследуется от родительского.
Работа с transform_component в Verse
Вы можете проверить, содержит ли модуль компонент transform_component с помощью GetComponent:
MyEntityNoTransform:entity = entity{}
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntityNoTransform})
MyEntityWithTransform:entity = entity{}
MyEntityWithTransform.AddComponents of array:
transform_component{Entity := MyEntityWithTransform}
if (SimEntity := Entity.GetSimulationEntity[]):
Вместо получения transform_component с помощью GetComponent и работы непосредственно с transform_component рекомендуется взаимодействовать с transform_component через методы расширения модуля.
Transform
Вы можете напрямую задать локальное или глобальное преобразование своего модуля с помощью методов расширения модуля SetLocalTransform или SetGlobalTransform.
MyEntity:entity = entity{}
MyTransform:transform = transform{}
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity})
# Set the local transform
MyEntity.SetLocalTransform(MyTransform)
MyOtherEntity:entity = entity{}
Эти методы расширения — рекомендуемый способ задать преобразование модуля Scene Graph в коде Verse. Эти методы явно задают локальное (относительно родительского модуля) или глобальное (относительно точки начала координат мира) преобразование рассматриваемого модуля. Если вызов любой из этих функций определяет, что у модуля нет transform_component, этот компонент неявно создаётся и добавляется к модулю. После вызова любой из этих функций модуль будет иметь transform_component. Вы можете проверить это, выполнив последующий вызов GetComponent.
if (MyEntity.GetComponent[transform_component]):
# success, entity has a transform_component
else:
# failure, entity does not have a transform_component
Используя методы расширения, вы можете получить локальное или глобальное преобразование компонента transform_component, связанного с модулем. GetLocalTransform возвращает преобразование модуля относительно его родительского элемента или по значениям в поле Origin, если они заданы. Если модуль не имеет transform_component, эта функция возвращает преобразование его родительского элемента.
# Entity object
MyEntity:entity = entity{}
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity})
# Obtain the local transform with respect to Parent or Origin (if set)
EntityLocalTransform := MyEntity.GetLocalTransform() # no transform component, returns identity
MyOtherEntity:entity = entity{}
GetGlobalTransform возвращает преобразование модуля относительно точки начала координат мира. Если модуль не имеет transform_component, эта функция возвращает глобальное преобразование ближайшего предка с transform_component.
# Entity object
MyEntity:entity
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity})
# Obtain the global transform
EntityGlobalTransform := MyEntity.GetGlobalTransform() # returns global transform of Simulation Entity
В начале координат
Также вы можете использовать методы расширения модуля для операций, связанных с полем Origin компонента transform_component. Вы можете напрямую задать значения поля Origin компонента transform_component вашего модуля с помощью метода расширения модуля SetOrigin.
MyEntity:entity = entity{}
MyOtherEntity:entity = entity{}
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity, MyOtherEntity})
MyEntity.SetLocalTransform(transform{Translation := vector3{Left := 100.0}})
# Construct an entity_origin object and set the new origin of MyEntity to MyOtherEntity
NewOrigin:entity_origin = entity_origin{Entity := MyOtherEntity}
Чтобы получить начало координат модуля в коде Verse, используйте GetOrigin.
MyEntity:entity = entity{}
if (SimEntity := Entity.GetSimulationEntity[]):
SimEntity.AddEntities(array{MyEntity})
if (OriginValue := MyEntity.GetOrigin[]):
# should not succeed
else:
# should fail, no transform_component on entity MyEntity
GetOrigin определяет, заданы ли значения поля Origin модуля, и, если да, возвращает значения этого поля. Если нет, вызов завершается с ошибкой. В случае успешного выполнения GetOrigin возвращаемый тип является объектом origin, классом Verse, в котором реализован интерфейс origin. Этот интерфейс предоставляет единичную функцию GetTransform для получения преобразования указанного начала координат модуля. Вы также можете проверить, задано ли альтернативное поле Origin для модуля, и определить, какой модуль задан в качестве начала координат вашего модуля.
if:
OriginValue := MyOtherEntity.GetOrigin[] # get Origin object
OriginEntityCast := entity_origin[OriginValue] # cast to entity_origin
then:
# Obtain the entity that is set as MyOtherEntity's Origin field on its transform_component
MyOtherEntityOrigin := OriginEntityCast.Entity
# Obtain the origin's transform
TransformOfOrigin := OriginEntityCast.GetTransform()
Наконец, вы можете сбросить поле Origin компонента transform_component модуля с помощью ResetOrigin.
MyEntity.ResetOrigin()После вызова ResetOrigin, поле Origin компонента transform_component модуля MyEntity сбрасывается, и теперь преобразование MyEntity рассчитывается относительно элемента, являющегося родительским для MyEntity в иерархии Scene Graph.
Зависимые компоненты
Работа некоторых других компонентов Scene Graph зависит от transform_component. Вам доступны:
light_component и его дочерние классы;
mesh_component;
particle_system_component.
Если вы добавляете любой из этих компонентов в модуль Scene Graph, в котором ещё нет transform_component, transform_component добавляется к модулю по умолчанию.
Примечание о преобразованиях в системе координат XYZ
Преобразования, использующие систему координат XYZ, по-прежнему существуют в модуле /UnrealEngine.com/Temporary/SpatialMath в Verse. Эти преобразования по-прежнему используются устройствами и объектами окружения творческого режима в модуле /Fortnite.com в Verse. Дополнительную информацию о статусе этих преобразований и конвертации преобразований различных типов в Verse см. на странице Система координат «влево-вверх-вперёд».