버전 36.00부터 UEFN에서는 에디터와 모든 /Verse.org 모듈 트랜스폼에 LUF 좌표계를 사용합니다. /UnrealEngine.com 및 /Fortnite.com 모듈 트랜스폼에서는 XYZ 좌표계가 사용됩니다.
LUF 좌표계 소개
주요 3D 콘텐츠 제작 툴은 모두 오브젝트를 위치 지정하고 회전하는 데 데카르트 좌표계(X, Y, Z)를 사용합니다. 하지만 어떤 축(X, Y, Z)이 어떤 방향(왼쪽/오른쪽, 위쪽/아래쪽, 앞쪽/뒤쪽)을 나타내는지에 대한 구체적인 해석은 툴마다 다릅니다. 또한 좌표계의 방향성으로 알려진 회전이 모델링되는 방식도 툴마다 서로 다릅니다.
Verse와 UEFN을 3D 콘텐츠 제작과 다른 중요 툴세트의 최신 표준에 맞추기 위해, 에픽은 좌표계 표현에 근본적인 변화를 적용하려 합니다.
먼저, 좌표축을 X, Y, Z로 라벨링하는 대신, 다음과 같이 보다 방향을 설명하는 축 이름을 도입하려고 합니다.
왼쪽(Left)(이전 -Y)
위쪽(Up)(이전 Z)
앞쪽(Forward)(이전 X)
따라서 이전 XYZ 및 FRU에서 LUF로의 변경은 왼손 좌표계(XYZ 및 FRU)에서 오른손 좌표계(LUF)로 방향성이 변경되는 것을 의미합니다.
둘째로, UEFN 뷰포트 기즈모 색상이 다른 3D 콘텐츠 제작 소프트웨어와 일치하도록 변경되었습니다.
왼쪽: 빨간색(이전 녹색)
위쪽: 녹색(이전 파란색)
앞쪽: 파란색(이전 빨간색)
셋째로, /Verse.org/SpatialMath 모듈의 많은 부분이 개선되었습니다.
이제 Verse 공간 수학 모듈 함수가 모두 오른손 기준 연산이 되었습니다. 이에 따라 명시적으로 오른손 좌표계인 베리언트가 있는 모든 함수가 제거되고 오른손 좌표계 연산이 기본값인 버전으로 대체되었습니다. 또한 함수 이름에서 오른손 좌표계 표시가 제거되었습니다. 자세한 내용은 이 페이지의 아래에 있는 오른손 좌표계 섹션을 참고하세요.
각도 파라미터가 포함되어 있거나 값을 반환하는 회전 함수에 이제 라디안 또는 각도 값을 사용하거나 반환하는 버전이 생겼으며, 각 베리언트에 접미사
Radians또는Degrees가 붙습니다.RotateBy,UnrotateBy및 모든(:rotation).Apply*함수가 제거되었으며, 대신 왼쪽에서 오른쪽으로rotations두 개를 조합한 곱셈 연산자가 사용됩니다. 자세한 내용은 이 페이지의 [트랜스폼 및 회전 곱셈 순서] 섹션을 참고하세요.RotateVector및UnrotateVector가 제거되었으며, 대신vector3에rotation을 순서대로 곱해 회전하는 곱셈 연산자가 사용됩니다. 자세한 내용은 이 페이지의 공간 수학 연산 변경사항 섹션을 참고하세요.TransformVector및TransformVectorNoScale이 제거되었으며, 대신vector3에transform을 스케일, 회전, 이동 순서대로 곱해 트랜스폼하는 곱셈 연산자가 사용됩니다. 자세한 내용은 이 페이지의 공간 수학 연산 변경사항 섹션을 참고하세요.
넷째로, FBX에서의 스켈레탈 메시 기본 임포트에 이제 위쪽 및 앞쪽 축 정렬 옵션이 사용되어 임포트된 모든 스켈레탈 메시가 앞쪽 축을 향합니다.
변경에 따른 영향
이러한 좌표계의 변화는 UEFN이나 /Verse.org 모듈에서 트랜스폼을 사용하는 모든 사용자에게 영향을 미치며, 특히 다음을 비롯하여 UEFN과 Verse의 여러 측면에 영향을 줍니다.
UEFN 디테일 패널
UEFN 뷰포트 및 기즈모
Verse 트랜스폼
퍼블리싱한 섬이 LUF에서 제대로 작동하도록 코드나 콘텐츠를 변경할 필요는 없습니다.
UEFN 디테일 패널
UEFN 디테일 패널의 트랜스폼이 이제 LUF 방식으로 좌표를 표시합니다.
UEFN 뷰포트
UEFN 뷰포트에서 기즈모 축과 색상의 매핑이 변경되었습니다.
Verse 트랜스폼
/Verse.org 모듈 트랜스폼에 LUF 방식이 사용됩니다. XYZ 좌표계를 사용하는 /UnrealEngine.com 모듈 트랜스폼은 그대로 존재하며, /UnrealEngine.com 및 /Fortnite.com 모듈에서 기본 트랜스폼으로 사용됩니다.
이러한 모듈 둘 다 트랜스폼 타입이 있으므로 다음에 유의해야 합니다.
같은 파일에서
/Verse.org모듈 트랜스폼과/UnrealEngine.com모듈 트랜스폼을 사용하는 API 함수를 사용하는 경우, 두 모듈 간 모호성을 방지하기 위해 타입 이름을 경로로 한정해야 합니다. 아래 예시 스니펫을 통해 이를 확인할 수 있습니다.Verse경로를 지정해 한정된 타입 이름using { /UnrealEngine.com/Temporary/SpatialMath } using { /Verse.org/SpatialMath } my_class := class: MyUnrealEngineVector:(/UnrealEngine.com/Temporary/SpatialMath:)vector3 = (/UnrealEngine.com/Temporary/SpatialMath:)vector3{} MyVerseVector:(/Verse.org/SpatialMath:)vector3 = (/Verse.org/SpatialMath:)vector3{}씬 그래프에서는
/Verse.org모듈 트랜스폼이 사용됩니다. 따라서 이제 씬 그래프에서는 LUF 좌표계만 사용됩니다.Verse 다이제스트는 UnrealEngine.com/Temporary/SpatialMath 및 Verse.org/SpatialMath 모듈에서 정의된 트랜스폼 타입을 구분하는 데 완전히 한정된 Verse 식별자를 사용합니다.
언리얼 엔진 좌표계에 대한 자세한 내용은 언리얼 엔진의 좌표계 및 스페이스를 참고하세요.
XYZ에서 LUF로 변환하기
/Verse.org 모듈 트랜스폼(LUF)으로 전환한 기존 API 함수를 사용 중인 경우, 사용자 정의 /UnrealEngine.com 트랜스폼(XYZ)이 LUF 를 사용하도록 변환하거나 새로 생성된 FromTransform 변환 함수를 사용해야 합니다. 이 섹션에서 변환 시 발생할 수 있는 몇 가지 문제와 해당 문제의 솔루션을 알아볼 수 있습니다.
상수 또는 변수 타입 모호성
Verse API에 적용된 최근 변경사항에 따라 /UnrealEngine.com/Temporary/SpatialMath 및 /Verse.org/SpatialMath 모두 vector3, rotation, transform 타입을 정의합니다. 그 결과, Verse 파일에 두 도메인을 모두 포함하는 경우 타입 모호성이 발생하게 됩니다.
타입 모호성 예시
다음 Verse 파일은 /UnrealEngine.com/Temporary/SpatialMath 모듈 경로 및 /Verse.org/SpatialMath 모듈 경로를 모두 임포트하며, 사용자 정의 클래스에서는 한정되지 않은 vector3 타입을 사용합니다.
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/SpatialMath }
my_class := class:
MyVectorOne:vector3 = vector3{}
#Compile Error: Identifier vector3 could be one of many types: UnrealEngine.com.Temporary.SpatialMath.vector3 or Verse.org.SpatialMath.vector3
MyVectorTwo:vector3 = vector3{}
#Compile Error: Identifier vector3 could be one of many types: UnrealEngine.com.Temporary.SpatialMath.vector3 or Verse.org.SpatialMath.vector3결과적으로 이 파일을 컴파일하려고 하면 타입 모호성으로 인해 컴파일 오류가 발생하는데, 컴파일러가 MyVectorOne 및 MyVectorTwo를 /UnrealEngine.com vector3 타입으로 컴파일해야 하는지, 아니면 /Verse.org vector3 타입으로 컴파일해야 하는지 알지 못하기 때문입니다. 사용자가 어떤 타입이 지정되었는지 알 수 있을 만한 충분한 정보를 컴파일러에 제공하지 않은 것입니다.
이 컴파일 오류를 해결하려면 각 변수가 사용하는 vector3의 타입에 경로를 지정해 한정해야 합니다. 오류를 해결하기 위해 이 상수에 경로를 지정해 한정할 수 있는 몇 가지 다양한 방법이 있습니다.
아래의 코드 스니펫에 나와 있는 것처럼, vector3 타입의 모든 상수나 변수를 완전히 한정할 수 있습니다.
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/SpatialMath }
my_class := class:
MyVectorOne:(/UnrealEngine.com/Temporary/SpatialMath:)vector3 = (/UnrealEngine.com/Temporary/SpatialMath:)vector3{}
MyVectorTwo:(/Verse.org/SpatialMath:)vector3 = (/Verse.org/SpatialMath:)vector3{}아래의 코드 스니펫에 나와 있는 것처럼, /Verse.org 모듈의 상수나 변수를 한정할 수 있습니다.
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org } # Change the module path to avoid import ambiguity
my_class := class:
MyVectorOne:vector3 = vector3{}
MyVectorTwo:SpatialMath.vector3 = SpatialMath.vector3{} # Specify the submodule아래의 코드 스니펫에 나와 있는 것처럼, /UnrealEngine.com 모듈의 상수나 변수를 한정할 수 있습니다.
using { /UnrealEngine.com/Temporary } # Change the module path to avoid import ambiguity
using { /Verse.org/SpatialMath }
my_class := class:
MyVectorOne:SpatialMath.vector3 = SpatialMath.vector3{} # Specify the submodule
MyVectorTwo:vector3 = vector3{}씬 그래프 타입 변경
Verse 파일에서 씬 그래프 API를 사용 중이며 공간 수학을 사용하는 다른 API는 사용하지 않는 경우, Verse 코드에서 using 키워드로 임포트하는 공간 수학 모듈을 변경하여 공간 수학 타입을 변경할 수 있습니다. 예를 들어 다음과 같은 코드가 있다고 가정해 보겠습니다.
using { /UnrealEngine.com/Temporary/SpatialMath }
my_component := class<final_super>(component):
@editable # This change will work regardless of this field being editable or not
MyVector3:vector3 = vector3{}
MyVector2:vector2 = vector2{}이는 다음과 같이 변경할 수 있습니다.
using { /Verse.org/SpatialMath } # Changed the module path
my_component := class<final_super>(component):
@editable # This change will work regardless of this field being editable or not
MyVector:vector3 = vector3{} # All transform types now use /Verse.org/SpatialMath
# MyVector2:vector2 = vector2{} Removed since /Verse.org/SpatialMath does not define a vector2유일한 예외는 vector2 타입이 있는 경우로, 제거하거나 vector3을 사용하도록 변환해야 합니다. 이는 /Verse.org 모듈이 현재 vector2 타입을 정의하지 않기 때문입니다.
함수 타입 불일치
타입에 경로를 지정해 한정하거나 코드를 변환해야 하는 또 다른 시나리오가 있는데, 다음과 같습니다.
호출된 함수나 할당된 변수가
/UnrealEngine.com모듈의 타입을 예상하고 있지만/Verse.org모듈의 타입이 제공된 경우호출된 함수나 할당된 변수가
/Verse.org모듈의 타입을 예상하고 있지만/UnrealEngine.com모듈의 타입이 제공된 경우
함수 타입 불일치 예시
다음과 같은 두 개의 Verse 파일이 동일한 프로젝트에 있다고 가정해 보겠습니다. FileOne.verse는 /UnrealEngine.com/Temporary/SpatialMath 모듈의 트랜스폼을 출력하는 함수를 정의합니다. FileTwo.verse는 /Verse.org/SpatialMath 모듈의 상수 트랜스폼과 이 값을 출력하는 함수(FileOne.verse의 함수를 호출)를 정의합니다.
using { /UnrealEngine.com/Temporary/SpatialMath }
PrintTransform(T:transform):void=
Print("T: {T}")using { /Verse.org/SpatialMath }
my_class := class:
T:transform = transform{}
DoPrint():void=
PrintTransform(T) # Compile error: This function parameter expects a value of type (/UnrealEngine.com/Temporary/SpatialMath:)transform, but this argument is an incompatible value of type (/Verse.org/SpatialMath:)transform.트랜스폼 타입이 서로 다른 모듈에서 정의된 두 개의 서로 다른 트랜스폼 타입을 참조하게 되므로 이는 컴파일 오류로 이어집니다.
이 컴파일 오류를 해결하려면 트랜스폼 타입을 적절한 모듈의 올바른 트랜스폼 타입으로 변환해야 합니다. FileTwo.verse에서 FromTransform 함수를 사용하도록 코드를 편집하여, /Verse.org/SpatialMath의 트랜스폼을 /UnrealEngine.com/Temporary/SpatialMath의 트랜스폼으로 변환합니다.
사용할 수 있는 변환 함수의 전체 목록은 다음 섹션을 참고하세요.
# Include /UnrealEngine.com to access conversion functions
using { /UnrealEngine.com }
using { /Verse.org/SpatialMath }
my_class := class:
T:transform = transform{}
DoPrint():void=
PrintTransform(Temporary.SpatialMath.FromTransform(T)) # Compile error fixed after converting transform to the correct type from the proper module벡터, 회전, 트랜스폼 타입 변환
/UnrealEngine.com 모듈은 몇 가지 새로운 변환 함수를 제공하는데, /UnrealEngine.com 모듈과 /Verse.org 모듈에 정의된 혼동 가능성이 있는 타입 간에 변환해 주는 역할을 합니다.
언리얼 엔진 공간 수학에서 Verse 공간 수학으로 변환하기
# Util function for converting a `vector3` from /UnrealEngine.com/Temporary/SpatialMath to a `vector3` from /Verse.org/SpatialMath.
FromVector3<public>(InVector3:(/UnrealEngine.com/Temporary/SpatialMath:)vector3)<reads>:(/Verse.org/SpatialMath:)vector3
# Util function for converting a `rotation` from /UnrealEngine.com/Temporary/SpatialMath to a `rotation` from /Verse.org/SpatialMath
FromRotation<public>(InRotation:(/UnrealEngine.com/Temporary/SpatialMath:)rotation)<reads>:(/Verse.org/SpatialMath:)rotation
# Util function for converting a `transform` from /UnrealEngine.com/Temporary/SpatialMath to a `transform` from /Verse.org/SpatialMath.
FromTransform<public>(InTransform:(/UnrealEngine.com/Temporary/SpatialMath:)transform)<reads>:(/Verse.org/SpatialMath:)transform
Verse 공간 수학에서 언리얼 엔진 공간 수학으로 변환하기
# Util function for converting a `vector3` from /Verse.org/SpatialMath to a `vector3` from /UnrealEngine.com/Temporary/SpatialMath.
FromVector3<public>(InVector3:(/Verse.org/SpatialMath:)vector3)<reads>:(/UnrealEngine.com/Temporary/SpatialMath:)vector3
# Util function for converting a `rotation` from /Verse.org/SpatialMath to a `rotation` from /UnrealEngine.com/Temporary/SpatialMath.
FromRotation<public>(InRotation:(/Verse.org/SpatialMath:)rotation)<reads>:(/UnrealEngine.com/Temporary/SpatialMath:)rotation
# Util function for converting a `transform` from /Verse.org/SpatialMath to a `transform` from /UnrealEngine.com/Temporary/SpatialMath.
FromTransform<public>(InTransform:(/Verse.org/SpatialMath:)transform)<reads>:(/UnrealEngine.com/Temporary/SpatialMath:)transform
Verse 공간 수학 연산 및 함수
오른손 좌표계
이제 Verse 공간 수학 모듈 함수가 모두 오른손 기준 연산이 되었습니다. 이에 따라 명시적 좌표계 베리언트가 있는 모든 함수가 제거되고 오른손 좌표계 연산이 기본값인 버전으로 대체되었습니다. 또한 함수 이름에서 방향성 표시가 제거되었습니다. vector3에 rotation을 곱하거나 vector3에 transform을 곱하는 등, 방향성을 선택할 수 있는 모든 연산은 오른손 좌표계 연산입니다.
예를 들어 다음 코드는 위쪽 축에서 +90도로의 회전을 생성하여 이를 앞쪽 벡터 유닛에 적용하면 단위 왼쪽 벡터가 도출됨을 보여줍니다.
ForwardToLeft:rotation = MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
ForwardVector:vector3 = vector3{Forward := 1.0}
ResultantVector:vector3 = ForwardVector * ForwardToLeft # Apply rotation on the right of the multiplication operator
Print("{ResultantVector}") # {Forward = 0.000000, Left = 1.000000, Up = 0.000000} = {Forward = 1.000000, Left = 0.000000, Up = 0.000000} * {Axis = {Forward = 0.000000, Left = 0.000000, Up = 1.000000}, Angle = 90.000000}
트랜스폼 및 회전 곱셈 순서
회전은 내부적으로 매트릭스로 표현된다고 생각하면 됩니다. 회전 R이 벡터 v에 적용되면 행 벡터 곱셈 순서로 적용됩니다. 즉, 벡터 v는 행 벡터이고 벡터가 회전하면 곱셈이 오른쪽에 적용되어 v' = v * R과 같은 결과를 얻게 됩니다. 여기서 결과 벡터 v'는 새로운 행 벡터입니다. 이는 transform T를 vector v에 적용하는 경우(v' = v * T)와 유사하며, 결과 벡터 v'는 다른 행 벡터가 됩니다.
순서는 벡터에 회전 및 트랜스폼을 적용할 때 중요합니다. 책과 같은 오브젝트를 손에 들고 상단부가 위쪽을 향하고, 전면부/커버가 자신을 향하도록 한다고 생각해 보세요. 오른손 좌표계 적용 시 앞쪽 축에서 +90도 회전하면 책의 상단부가 이제 오른쪽을 향하게 됩니다. 다음으로, 왼쪽 축에서 90도 회전하면 책의 전면부가 위를 향하게 되고 상단부는 계속 오른쪽을 향합니다.
이제 동일한 회전을 반대 순서로 적용해 보겠습니다. 왼쪽 축에서 90도 회전하면 책의 상단부가 앞쪽을 향하고 전면부가 위쪽을 향하게 됩니다. 다음으로, 앞쪽 축에서 90도 회전하면 책의 상단부는 계속 앞쪽을 향하고 전면부는 오른쪽을 향하게 됩니다. 이는 앞서 다른 순서로 회전을 적용하는 것과 동일한 방향이 아니며, 회전 순서가 중요함을 보여줍니다.
이를 염두에 두고, 두 개의 회전 R과 R'을 벡터 v에 적용할 때는 원하는 순서로 적용하도록 해야 합니다. 회전 R을 회전 R' 전에 적용하려면 올바른 순서는 v' = v * R * R'입니다.
동일한 원칙이 회전 자체에도 적용됩니다. 회전 R이 있고 사전 회전 PreR을 R에 적용할 때 사전 회전이 R과 회전 R 후에 진행되는 사후 회전 PostR 전에 진행되도록 하려면 PreR * R * PostR의 순서로 수행해야 합니다. 이와 동일하게 사전 트랜스폼 PreT 및 사후 트랜스폼 PostT를 트랜스폼 T에 적용하려면 PreT * T * PostT의 순서로 수행해야 합니다. 이후 이를 벡터 v에 적용하여 새 벡터 v'를 얻으려면 위의 방법, v' = v * PreR * R * PostR 또는 v' = v * PreT * T * PostT 연산을 수행해야 합니다.
트랜스폼 및 회전의 결합 법칙도 중요합니다. Verse 코드 한 줄에서 하나의 벡터에 여러 연산을 적용하려는 경우(예: 트랜스폼과 회전을 순서대로) 연산의 결합 법칙이 중요합니다. 예를 들어 다음과 코드를 사용하고자 할 수 있습니다.
ForwardVector:vector3 = vector3{Forward := 1.0}
ForwardToLeftUpOne:transform = transform:
Translation := vector3{Up := 1.0}
Rotation := MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
UpToForward:rotation = MakeRotationFromEulerDegrees(90.0, 0.0, 0.0)
ResultantVector:vector3 = ForwardVector * ForwardToLeftUpOne * UpToForward # compiles이 코드는 묵시적으로 다음과 같은 연산을 결합하므로 올바르게 컴파일됩니다.
ResultantVector:vector3 = (ForwardVector * ForwardToLeftUpOne) * UpToForward # compiles
하지만 다음과 같이 명시적으로 다른 방식을 사용하면 어떻게 될까요?
ResultantVector:vector3 = ForwardVector * (ForwardToLeftUpOne * UpToForward) # error, no operator'*'(:transform,:rotation)
이 코드에서는 오류가 발생합니다. 이러한 오류를 방지하려면 벡터와 트랜스폼 또는 벡터와 회전 사이에 명시적으로 첫 번째 연산을 사용해야 합니다.
ResultantVector:vector3 = (ForwardVector * ForwardToLeftUpOne) * UpToForward # explicitly associated
공간 수학 연산 변경사항
회전 및 회전 곱셈
RotateBy 및 UnrotateBy가 제거되었으며, 두 회전을 위한 곱셈 연산자로 대체되었습니다.
ForwardToLeft:rotation = MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
UpToForward:rotation = MakeRotationFromEulerDegrees(90.0, 0.0, 0.0)
UpToLeft:rotation = UpToForward * ForwardToLeft # RotateBy, correcting for handedness회전을 되돌리려면('회전 취소') 먼저 회전을 반전한 후 그 회전 값을 곱합니다. UpToLeft에서 UpToForward 회전을 다시 얻으려면 ForwardToLeft 회전을 반전한 후 이를 UpToLeft 회전의 오른쪽에 적용합니다. 다음은 이를 수행하는 방법을 단계별로 보여줍니다.
# The following comments show the steps involved to reach the desired result.
# This involves multiplication on the right by the inverse, associativity, existence and definition of inverse rotation, and existence and definition of identity rotation
# Pseudocode Steps:
# UpToLeft * ForwardToLeft.Invert() = (UpToForward * ForwardToLeft) * ForwardToLeft.Invert() # multiply on the right by the same expression on both sides of the equality operator
# UpToLeft * ForwardToLeft.Invert() = UpToForward * (ForwardToLeft * ForwardToLeft.Invert()) # reassociate
# UpToLeft * ForwardToLeft.Invert() = UpToForward * IdentityRotation() # rotation * inverse = identity
# UpToLeft * ForwardToLeft.Invert() = UpToForward # rotation * identity = rotation
UpToForwardAgain:rotation = UpToLeft * ForwardToLeft.Invert() # UnrotateBy, correcting for handednessVector3 및 회전 곱셈
마찬가지로, Rotate 및 Unrotate가 제거되었으며, vector3에 오른쪽 rotation을 곱해 회전하는 곱셈 연산자로 대체되었습니다.
ForwardVector:vector3 = vector3{Forward:=1.0}
ForwardToLeft:rotation = MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
LeftVector:vector3 = ForwardVector * ForwardToLeft # Rotate, correcting for handedness회전을 되돌리려면(회전 취소) 먼저 회전을 반전한 후 회전에 벡터 값을 곱합니다. LeftVector에서 ForwardVector를 다시 얻으려면 ForwardToLeft 회전을 반전한 후 이를 LeftVector의 오른쪽에 적용합니다.
# The steps involved in achieving this calculation are very similar to the steps shown above for obtaining the correct expression for unrotating by a rotation
ForwardVectorAgain:vector3 = LeftVector * ForwardToLeft.Invert() # Unrotate, correcting for handednessVector3 및 트랜스폼 곱셈
TransformVector 및 TransformVectorNoScale이 제거되고, vector3에 오른쪽 트랜스폼 값을 곱해 트랜스폼하는 곱셈 연산자로 대체되었습니다.
DoubleLengthForwardToLeftTranslateUp := transform:
Translation := vector3{Left := 0.0, Up := 1.0, Forward := 0.0}
Rotation := MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
Scale := vector3{Left := 2.0, Up := 2.0, Forward := 2.0}
ForwardVector:vector3 = vector3{Forward:=1.0}
ResultantVector:vector3 = ForwardVector * DoubleLengthForwardToLeftTranslateUp # TransformVector스케일 조절 없이 트랜스폼을 수행하려면 TransformVectorNoScale을 사용해 생성하는 transform에서 기본 스케일 값을 그대로 둡니다.
ForwardToLeftTranslateUpNoScale := transform:
Translation := vector3{Left := 0.0, Up := 1.0, Forward := 0.0}
Rotation := MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
ForwardVector:vector3 = vector3{Forward:=1.0}
ResultantVector:vector3 = ForwardVector * ForwardToLeftTranslateUpNoScale # TransformVectorNoScale