シーングラフのエンティティのトランスフォームは、エンティティの平行移動 (位置)、回転 (向き)、スケール (サイズ) を定義します。 Scene Graph エンティティをトランスフォームするには、エンティティに transform_component が必要です。 transform_component には、UEFN または Verse コードで操作できる以下の 2 つのフィールドがあります。
[Origin (原点)]:LocalTransform が計算される任意の原点。
LocalTransform:エンティティの親からの (またはオプションの [Origin (原点)] フィールドが設定されている場合は原点からの) 相対
(/Verse.org/SpatialMath:)transform。
エンティティの原点とは、エンティティの transform_component の LocalTransform を計算するときの基準となるエンティティのことです。 transform_component の [Origin (原点)] フィールドが設定されている場合はその値、[Origin (原点)] フィールドが設定されていない場合は、Scene Graph 階層のエンティティの親となります。
トランスフォームと transform_component を区別することが重要です。 トランスフォームは、/Verse.org/SpatialMath モジュールで定義されたコンポジット データ型です。これは LUF (Left-Up-Forward:左上前) 座標系における以下の数量を格納します。
平行移動 (
vector3):オブジェクトの位置。回転 (
rotation):オブジェクトの向き。スケール (
vector3):オブジェクトのサイズ。
transform_component は、/Verse.org/SceneGraph モジュールで定義された Verse クラスで、 Scene Graph エンティティの LocalTransform と、オプションで代替の原点を格納します。 transform_component は、シミュレーションにおけるその場所を定義する transform のためにエンティティに供給されるコンテナであると考えることができます。
Verse のトランスフォーム
Scene Graph では /Verse.org/SpatialMath モジュールのトランスフォームを使用します。 Verse モジュールのトランスフォームは、右手 LUF 座標系を使用します。 Verse トランスフォームを構築するには、クラス アーキタイプと rotations を作成するための組み込みメソッドを使用できます。
# 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 の座標系の詳細については、「LUF 座標系」ページを参照してください。 /UnrealEngine.com/Temporary/SpatialMath モジュールの XYZ トランスフォームと Verse モジュール トランスフォームの間の変換に関する情報も記載されています。
transform_component でエンティティを構築する
エンティティの作成は、UEFN アウトライナーまたは Verse で行うことができます。
UEFN の場合
[Place Actors (アクタの配置)] メニューから、シーングラフのエンティティをプロジェクトに素早く追加できます。
[Place Actors (アクタの配置)] メニューから Scene Graph のエンティティをプロジェクトに追加すると、エンティティにはデフォルトで transform_component が実装されています。
必要であれば、[Outliner (アウトライナー)] パネルで最近配置したエンティティに移動し、transform_component を見つけ、[Remove Component (コンポーネントの削除)] を選択することで、transform_component を削除できます。
以下は、問題のエンティティに transform_component がない状態です。
Verse 内
Verse コードで、クラス アーキタイプを使って Scene Graph エンティティを作成する方法を説明します。
MyEntity:entity = entity{}エンティティには transform_component が実装されていません。 逆に、transform_component をエンティティに追加する必要があります。 トランスフォームを扱う際に推奨されるメソッドは、SetLocalTransform と SetGlobalTransform です。 これらの関数は、transform_component の作成、値の設定、transform コンポーネントのエンティティへの追加を同時に処理します。
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}Verse コードで Scene Graph エンティティに transform_component を追加するその他のメソッドについては、「Verse における transform_component を操作する」セクションを参照してください。
エンティティのトランスフォームの計算方法
transform_component を使用して Scene Graph エンティティで実行できる最も重要な演算は、エンティティのトランスフォームを取得または設定することです。
トランスフォームには、ローカル トランスフォームとグローバル トランスフォームの 2 種類があります。 エンティティのトランスフォームを効果的に操作するには、これらのトランスフォームがどのように計算されるかを理解することが重要です。
ローカル トランスフォームはエンティティの原点に関するトランスフォームです。 Scene Graph エンティティのローカル トランスフォームは、Scene Graph エンティティの transform_component の [LocalTransform (LocalTransform)] フィールドの値です。
グローバル トランスフォームは、グローバル空間における LUF 座標系の原点に関するトランスフォームです。 Scene Graph エンティティのグローバル トランスフォームは、エンティティの LocalTransform と以下を合成して計算されます。
[Origin (原点)] フィールドがエンティティの transform_component に設定されていない場合は、エンティティの親のグローバル トランスフォーム。
[Origin (原点)] フィールドがエンティティの transform_component に設定されている場合は、エンティティの原点のグローバル トランスフォーム。
以下の例では、平行移動を使って回転やスケーリングを行わず、トランスフォーム結果を平行移動の足し算で計算できるようにしています。 この例では、すべてのトランスフォームにおいて回転とスケーリングがそれぞれの同一のままであることを前提としているため、エンティティのトランスフォームをエンティティのトランスフォーム平行移動ベクターで参照する省略表現が使用されています。
3 つの Scene Graph エンティティが以下のように構成されているとします。
BaseEntity:LUF 座標系で LocalTransform (0.0, 0.0, 0.0)。
A:LocalTransform (750.0,100.0, 0.0)
B:LocalTransform (-250.0,100.0, 0.0)
以下は、BaseEntity が mesh_component を持たず、A が立方体、B が円錐であるシーンにおける 3 つのエンティティです。
たとえば、エンティティ B のローカル トランスフォームとグローバル トランスフォームの両方を決定するとします。 ローカル トランスフォームは、下にあるように、エンティティ B transform_component のローカル [LocalTransform (LocalTransform)] フィールドの値であるため、すぐに分かります。
エンティティ B のローカル トランスフォームは (-250.0,100.0, 0.0).
エンティティ B のグローバル トランスフォームを計算するには、エンティティ B の階層をシミュレーション エンティティまで遡り、シミュレーション エンティティからエンティティ B までトランスフォームを合成します。 シミュレーション エンティティは現在のシミュレーションのルートに位置しており、他のすべてのシミュレーション エンティティはその下位にある子です。
エンティティ B のグローバル トランスフォームを計算する手順は以下のとおりです。
シミュレーション エンティティは、現在のシミュレーションのルートです。
シミュレーション エンティティのグローバル トランスフォーム:(0.0, 0.0, 0.0)。
BaseEntity はシミュレーション エンティティの子です。 BaseEntity は、画像 1.0 にあるように、(0.0, 0.0, 0.0) のローカルト ランスフォームを持ちます。 シミュレーション エンティティのグローバル トランスフォームと BaseEntity のローカル トランスフォームを合成すると、次のようになります。
BaseEntity グローバル トランスフォーム:(0.0, 0.0, 0.0) + (0.0, 0.0, 0.0) = (0.0, 0.0, 0.0)
エンティティ A は BaseEntity の子です。 エンティティ A は画像 1.1 にあるように、(750.0,100.0, 0.0) のローカル トランスフォームを持ちます。 BaseEntity のグローバル トランスフォームとエンティティ A の位置トランスフォームを合成すると、次のようになります。
エンティティ A のグローバル トランスフォーム:(0.0, 0.0, 0.0) + (750.0,100.0, 0.0) = (750.0,100.0, 0.0).
エンティティ B はエンティティ A の子です。 エンティティ B は画像 1.2 にあるように、(-250.0,100.0, 0.0) のローカル トランスフォームを持ちます。 A のグローバル トランスフォームとエンティティ B の位置トランスフォームを合成すると、次のようになります。
エンティティ B のグローバル トランスフォーム:(750.0,100.0, 0.0) + (-250.0,100.0, 0.0) = (500.0,200.0, 0.0).
したがって、LUF 座標系におけるエンティティ B のグローバル トランスフォームは (500.0,200.0, 0.0) となります。
エディタで transform_component を操作する
LocalTransform と Origin を使うことで、エンティティのトランスフォームを操作することができます。
ローカルトランスフォーム
エンティティの transform_component の [LocalTransform (LocalTransform)] フィールドは、その原点に対するエンティティの (/Verse.org/SpatialMath:) トランスフォームです。 [Origin (原点)] フィールドが明示的に設定されていない場合、エンティティの原点は、Scene Graph 階層内の親をデフォルトとします。 [LocalTransform (LocalTransform)] フィールドは、エンティティを直接編集する UEFN に表示されるフィールドであり、以下を編集することが可能です。
平行移動:親または手動で定義された原点に対する相対的な位置。
エンティティをレベル内で移動させるために、エンティティの平行移動を変更します。
回転:親または手動で定義された原点に対する相対的な向き。
エンティティをピボット ポイントを中心として回転させるために、エンティティの回転を変更します。
スケール:親または手動で定義した原点に対する相対的なサイズ。
エンティティのスケールを変更し、大きくまたは小さくします。
原点
エンティティの transform_component の原点とは、LocalTransform が計算されるオブジェクトです。 transform_component 上にあるこのフィールドはオプションです。 デフォルトでは、transform_component の LocalTransform は、所有するエンティティの親エンティティを基準として計算された、エンティティの原点に基づくエンティティのトランスフォームです。 オプションで、エンティティの transform_component に [Origin (原点)] フィールドを設定すると、そのエンティティの親オブジェクト以外のオブジェクトを基準にして LocalTransform を計算することができます。
たとえば、エンティティの原点をまったく別のエンティティに設定することができます。 このフィールドは、Verse origin インターフェースを実装する任意のクラスで設定できます。 具体的には、[Origin (原点)] フィールドを別の Scene Graph エンティティに設定する場合、entity_origin クラスを選択し、新しい原点にするエンティティを選択します。
transform_component における原点と LUF 座標系の原点を混同しないことが重要です。 LUF 座標系の原点はワールド空間の点であり、平行移動 (0.0, 0.0, 0.0) を備えています。
エンティティの transform_component における原点とは、LocalTransform の平行移動が (0.0, 0.0, 0.0) であるときに、そのエンティティが存在する場所のことです。
以下は、[Origin (原点)] フィールドと LocalTransform が実際にどのように機能するかを示した例です。 ワールド空間の原点に位置する BaseEntity を考えます。これは、立方体の mesh_component で表される子エンティティ A と、円錐の mesh_component で表される子エンティティ B を持っています。
上の画像からわかるように、BaseEntity は、ワールド空間の原点に位置しています。これは、transform_component の [Origin (原点)] フィールドが設定されておらず、LocalTransform がワールド空間の原点に設定されているためです。
下の図では、エンティティ A の [Origin (原点)] フィールドも設定されていないため、LocalTransform は親エンティティ BaseEntity の transform_component を基準に計算されます。
BaseEntity はワールド空間の原点に位置し、エンティティ A の LocalTransform の平行移動が vector3{Left := 750.0, Up := 100.0, Forward := 0.0} に設定されているため、エンティティ A は vector3{Left := 750.0, Up := 100.0, Forward := 0.0} に位置しています。 エンティティ A の回転とスケールは変化しません。なぜなら、BaseEntity 上の LocalTransform の 回転とスケールが、それぞれ同じであるからです。
下の画像では、エンティティ B があります。これは、BaseEntity の子でもあり、その transform_component にある [Origin (原点)] フィールドがエンティティ A として設定されています。
その結果、エンティティ B の transform_component の [LocalTransform (LocalTransform )] フィールドは、エンティティ A の計算済みトランスフォームに対する相対値となります。エンティティ B の LocalTransform は vector3{Left := -250.0, Up := 100.0, Forward := 0.0} に設定されており、エンティティ A の LocalTransform は vector3{Left := 750.0, Up := 100.0, Forward := 0.0} に設定されているため、エンティティ B のグローバル トランスフォームは vector3{Left := 500.0, Up := 200.0, Forward := 0.0} となります。
エンティティ A の transform_component にある [LocalTransform (LocalTransform)] フィールドの回転コンポーネントを前方軸に対して -90.0 度に変更すると、エンティティ B も前方軸に対して -90.0 度回転します。 これは、子の回転も親から継承されるためです。
Verse で transform_component を操作する
エンティティが 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 を直接操作するのではなく、エンティティ拡張メソッドを使用することを推奨します。
トランスフォーム
エンティティのローカルまたはグローバル トランスフォームを、エンティティ拡張メソッドの 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{}
これらの拡張メソッドは、Verse コードで Scene Graph エンティティにトランスフォームを設定するのに適した方法です。 これらのメソッドは、該当するエンティティのローカル (エンティティの親を基準とする) またはグローバル (ワールド基点を基準とする) トランスフォームを明示的に設定します。 これらの関数のいずれかが呼び出されたときにエンティティが transform_component を持っていない場合、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
原点
transform_component の [Origin (原点)] フィールドを含む演算にもエンティティ拡張メソッドを使うことができます。 エンティティの transform_component における [Origin (原点)] フィールドは、エンティティ拡張メソッド 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 オブジェクトになります。これは、origin インターフェースを実装する Verse クラスです。 このインターフェースは、エンティティの指定された原点のトランスフォームを取得する単一の関数 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()
最後に、エンティティの transform_component の [Origin (原点)] フィールドをリセットするには、ResetOrigin を使います。
MyEntity.ResetOrigin()ResetOrigin を呼び出すと、MyEntity のtransform_component の [Origin (原点)] フィールドがリセットされ、MyEntity のトランスフォームは Scene Graph 階層内の MyEntity の親エンティティを基準に計算されるようになります。
従属コンポーネント
他のいくつかの Scene Graph コンポーネントは、機能するために transform_component を使用します。 次のような情報を入力します。
light_component とその子クラス
mesh_component
particle_system_component
これらのコンポーネントのいずれかを、まだ transform_component を持っていない Scene Graph エンティティに追加すると、デフォルトで transform_component がエンティティに追加されます。
XYZ トランスフォームに関する注記
XYZ 座標系を使用したトランスフォームは、引き続き /UnrealEngine.com/Temporary/SpatialMath Verse モジュールに存在します。 これらのトランスフォームは、引き続き /Fortnite.com Verse モジュールにおけるクリエイティブの仕掛けや小道具に使用されています。 これらのトランスフォームのステータスや、Verse における各種トランスフォーム間の変換の詳細については、「LUF 座標系」のページを参照してください。