Dalla versione 36.00, UEFN utilizza il sistema di coordinate LUF per l'editor e tutte le trasformazioni del modulo /Verse.org. Le trasformazioni dei moduli /UnrealEngine.com e /Fortnite.com utilizzano il sistema di coordinate XYZ.
Presentazione del sistema di coordinate LUF
Tutti i principali strumenti di creazione di contenuti 3D utilizzano un sistema di coordinate cartesiane (X, Y e Z) per posizionare e ruotare gli oggetti. Tuttavia, le interpretazioni specifiche per gli assi (X, Y e Z) che rappresentano le direzioni (come sinistra/destra, su/giù e avanti/indietro) sono diverse tra gli strumenti. Inoltre, anche il modo in cui vengono modellate le rotazioni, noto come manualità del sistema di coordinate, varia a seconda degli strumenti.
Per allineare meglio Verse e UEFN agli standard emergenti nella creazione di contenuti 3D e altri set di strumenti importanti, stiamo apportando modifiche fondamentali alla presentazione del nostro sistema di coordinate.
Innanzitutto, invece di etichettare gli assi delle coordinate con X, Y e Z, stiamo introducendo nomi degli assi più descrittivi:
Sinistra (era -Y)
Su (era Z)
Avanti (era X)
La modifica dalle precedenti XYZ e FRU in LUF corrisponde quindi a una modifica della manualità degli assi da un sistema di coordinate sinistrorsi (XYZ e FRU) a un sistema di coordinate destrorsi (LUF).
In secondo luogo, i colori del gizmo della viewport UEFN sono stati modificati per allinearsi con altri software di creazione di contenuti 3D:
Sinistra: rosso (invece di verde)
Su: verde (invece di blu)
Avanti: blu (invece di rosso)
In terzo luogo, sono stati apportati molti miglioramenti al modulo /Verse.org/SpatialMath :
Le funzioni del modulo di matematica spaziale di Verse sono ora tutte operazioni destrorse. Di conseguenza, tutte le funzioni con varianti destrorse esplicite sono state rimosse e sostituite con versioni che per impostazione predefinita prevedono operazioni destrorse e gli indicatori destrorsi sono stati eliminati dai nomi delle funzioni. Per maggiori informazioni, consulta la sezione Sistema destrorso di questa pagina di seguito.
Le funzioni di rotazione che coinvolgono un parametro angolo o un valore return hanno ora versioni che accettano o restituiscono radianti o gradi e sono dotate di suffisso
RadiantioGradiper la rispettiva variante.Le funzioni
RotateBy,UnrotateBye tutte le funzioni(:rotation).Apply*sono state rimosse a favore di un operatore di moltiplicazione che compone duerotazionida sinistra a destra. Per maggiori informazioni, consulta la sezione [Ordine di moltiplicazione di trasformazione e rotazione]() di questa pagina.RotateVectoreUnrotateVectorsono stati rimossi a favore di un operatore di moltiplicazione che ruota unvector3di unarotazione, in quest'ordine. Per maggiori informazioni, vedi la sezione Modifiche alle operazioni di matematica spaziale di questa pagina.TransformVectoreTransformVectorNoScalesono stati rimossi a favore di un operatore di moltiplicazione che trasforma unvector3mediante unatrasformazionenell'ordine seguente: scala, rotazione, traslazione. Per maggiori informazioni, vedi la sezione Modifiche alle operazioni di matematica spaziale di questa pagina.
Quarto, le importazioni predefinite di mesh scheletriche da FBX ora utilizzano l'opzione per allineare gli assi Su e Avanti in modo che tutte le mesh scheletriche importate siano rivolte verso l'asse avanti.
A chi riguarda questa modifica
Questa modifica al sistema di coordinate riguarda chiunque utilizzi UEFN o trasforma nel modulo /Verse.org, in particolare, diversi aspetti di UEFN e Verse che includono:
Pannello Dettagli UEFN
Viewport e gizmo di UEFN
Trasformazione di Verse
Non devi modificare il codice o i contenuti affinché le tue isole pubblicate funzionino correttamente con LUF.
Pannello Dettagli UEFN
Le trasformazioni nel pannello Dettagli UEFN ora mostrano le coordinate in termini di sistema LUF.
Viewport UEFN
La mappatura tra gli assi gizmo e i colori è cambiata nella viewport di UEFN.
Trasformazioni Verse
Le trasformazioni del modulo /Verse.org utilizzano il sistema LUF . La trasformazione del modulo /UnrealEngine.com che utilizza il sistema di coordinate XYZ esiste ancora e viene utilizzata come trasformazione predefinita nei moduli /UnrealEngine.com e /Fortnite.com.
Poiché entrambi i moduli contengono tipi di trasformazione, tieni presente quanto segue:
Se utilizzi funzioni API che utilizzano trasformazioni di moduli
/Verse.orge trasformazioni di moduli/UnrealEngine.comnello stesso file, i nomi dei tipi devono essere qualificati dal loro percorso per evitare ambiguità tra i due moduli. Questo è mostrato nello snippet di esempio seguente.VerseNomi di tipo qualificati dal percorsousing { /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{}Scene Graph utilizza le trasformazioni del modulo
/Verse.org. Ciò significa che Scene Graph ora utilizza solo il sistema di coordinate LUF.Il Verse Digest usa identificatori di Verse completi per distinguere tra i tipi di trasformazione definiti nei moduli UnrealEngine.com/Temporary/SpatialMath e Verse.org/SpatialMath .
Per saperne di più sul sistema di coordinate di Unreal Engine, consulta Sistema di coordinate e spazi in Unreal Engine.
Conversione da XYZ a LUF
Se utilizzi funzioni API esistenti che sono passate alle trasformazioni del modulo /Verse.org (LUF), devi convertire le trasformazioni /UnrealEngine.com definite dall'utente (XYZ) per utilizzare LUF o per utilizzare le funzioni di conversione FromTransform appena create. In questa sezione puoi trovare diversi potenziali problemi di conversione e le relative soluzioni.
Ambiguità di tipo costante o variabile
Con le recenti modifiche all'API Verse, sia /UnrealEngine.com/Temporary/SpatialMath che /Verse.org/SpatialMath definiscono i tipi vector3, rotazione e trasformazione. Di conseguenza, se includi entrambi i domini nel tuo file Verse, si verificherà un'ambiguità di tipo.
Esempio di ambiguità di tipo
Il seguente file di Verse importa sia il percorso del modulo /UnrealEngine.com/Temporary/SpatialMath che quello del modulo /Verse.org/SpatialMath, e la classe definita dall'utente utilizza il tipo non qualificato 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.vector3Di conseguenza, l'ambiguità del tipo fa che si verifichi un errore di compilazione se provi a compilare questo file, perché il compilatore non sa se compilare MyVectorOne e MyVectorTwo come tipo /UnrealEngine.com vector3 o come tipo /Verse.org vector3. L'utente non ha fornito al compilatore informazioni sufficienti per sapere quale tipo è indicato.
Per risolvere questo errore di compilazione, devi qualificare il percorso del tipo di vector3 utilizzato da ogni variabile. Ci sono diversi modi per Percorso-qualificare queste Costanti per risolvere l'errore:
Puoi qualificare completamente qualsiasi costante o variabile di tipo vector3, come mostrato nello snippet di codice seguente:
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{}Puoi qualificare una costante o una variabile dal modulo /Verse.org, come mostrato nello snippet di codice seguente:
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 submodulePuoi qualificare una costante o una variabile dal modulo /UnrealEngine.com, come mostrato nello snippet di codice seguente:
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{}Modifica del tipo di Scene Graph
Se stai usando le API Scene Graph nei tuoi file Verse e non stai utilizzando altre API che ricorrono alla matematica spaziale, puoi cambiare i tipi di matematica spaziale nel tuo codice Verse modificando il modulo di matematica spaziale che importi con la parola chiave using. Ad esempio, se hai il seguente codice:
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{}Puoi modificarlo in:
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 vector2L'unica eccezione è che qualsiasi tipo di vector2 deve essere rimosso o convertito per utilizzare vector3, poiché il modulo /Verse.org non definisce attualmente il tipo vector2.
Tipo di funzione non corrispondente
Un altro caso in cui potresti dover specificare il percorso dei tipi o convertire il codice è quando:
Una funzione chiamata o una variabile assegnata si aspetta un tipo dal modulo
/UnrealEngine.com, ma riceve un tipo dal modulo/Verse.org.Una funzione chiamata o una variabile assegnata si aspetta un tipo dal modulo
/Verse.org, ma riceve un tipo dal modulo/UnrealEngine.com.
Esempio di tipo di funzione non corrispondente
Nel medesimo progetto esistono i due file di Verse seguenti. FileOne.verse definisce una funzione per stampare una trasformazione dal modulo /UnrealEngine.com/Temporary/SpatialMath . FileTwo.verse definisce una trasformazione costante dal modulo /Verse.org/SpatialMath e una funzione per stampare questo valore che chiama la funzione da 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.Ciò risulta in un errore di compilazione dovuto ai tipi di trasformazione che fanno riferimento a due diversi tipi di trasformazione definiti in moduli diversi.
Per correggere questo errore di compilazione, devi convertire il tipo di Trasforma nel tipo di Trasforma corretto dal Modulo appropriato. Modifica il codice in FileTwo.verse per utilizzare la funzione FromTransform, che converte una trasformazione da /Verse.org/SpatialMath a una trasformazione da /UnrealEngine.com/Temporary/SpatialMath.
Per un elenco completo delle funzioni di conversione disponibili, consulta la sezione successiva.
# 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 moduleConversione del tipo di vettore, rotazione e Trasforma
Il modulo /UnrealEngine.com fornisce diverse nuove funzioni di conversione per convertire tra i tipi potenzialmente ambigui definiti nel modulo /UnrealEngine.com e nel modulo /Verse.org.
Da Unreal Engine Spatial Math a Verse Spatial Math
# 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
Da Verse Spatial Math a Unreal Engine Spatial Math
# 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
Operazioni e funzioni di matematica spaziale Verse
Sistema destrorso
Le funzioni del modulo di matematica spaziale di Verse sono ora tutte operazioni destrorse. Di conseguenza, tutte le funzioni con varianti di manualità esplicite sono state rimosse e sostituite con versioni che per impostazione predefinita prevedono operazioni destrorse e gli indicatori destrorsi sono stati eliminati dai nomi delle funzioni. Tutte le operazioni in cui è possibile scegliere la manualità, come ad esempio la moltiplicazione di un vector3 per una rotazione o la moltiplicazione di un vector3 per una trasformazione, sono operazioni destrorse.
Ad esempio, il codice seguente mostra che costruendo una rotazione di 90 gradi positivi attorno all'asse Su e applicando questa rotazione a un vettore unità Avanti si ottiene un vettore unità Sinistra:
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}
Ordine di moltiplicazione di trasformazione e rotazione
Puoi pensare alle rotazioni come rappresentate internamente da una matrice. Quando una rotazione R viene applicata a un vettore v, viene applicata in ordine di moltiplicazione riga-vettore. In altre parole, il vettore v è un vettore riga e quando un vettore viene ruotato, la moltiplicazione viene applicata a destra per ottenere il risultato v' = v * R. In questo caso, il vettore risultante v' è un nuovo vettore di riga. Questo funziona in modo simile per applicare una trasformazione T a un vettore v, v' = v * T e il vettore risultante v' è un altro vettore riga.
L'ordine è importante quando si applicano rotazioni e trasformazioni ai vettori. Tieni in mano un oggetto, come un libro, con la parte superiore rivolta verso l'alto e la parte anteriore/copertina rivolta verso di te. L'applicazione di una rotazione positiva di 90 gradi destrorsa rispetto all'asse Avanti fa sì che la parte superiore del libro sia ora rivolta a destra. Quindi, applicando una rotazione di 90 gradi attorno all'asse Sinistra, la parte anteriore del telefono è rivolta verso l'alto e la parte superiore del libro è rivolta verso destra.
Ora, applica le stesse rotazioni nell'ordine inverso. Applica una rotazione di 90 gradi attorno all'asse Sinistra in modo che la parte superiore del libro sia rivolta in avanti e la parte anteriore del libro rivolta verso l'alto. Quindi, applicando una rotazione di 90 gradi attorno all'asse Avanti, la parte superiore del libro è rivolta in avanti e la parte anteriore del libro è rivolta alla tua destra. Questo non è lo stesso orientamento dell'applicazione delle rotazioni nell'ordine opposto, a dimostrazione dell'importanza dell'ordine delle rotazioni.
Con questo in mente, se vuoi applicare due rotazioni R e R' a un vettore v, devi fare attenzione ad applicarle nell'ordine desiderato. Se vuoi applicare la rotazione R prima della rotazione R', l'ordine corretto è v' = v * R * R'.
Lo stesso principio si applica alle rotazioni stesse. Se hai una rotazione R e vuoi applicare una pre-rotazione PreR a R, che avviene prima della rotazione R e una post-rotazione PostR che avviene dopo la rotazione R, questo viene fatto nell'ordine PreR * R * PostR. Allo stesso modo, se vuoi applicare una pre-trasformazione PreT e una post-trasformazione PostT a una trasformazione T, l'operazione viene eseguita nell'ordine PreT * T * PostT. Successivamente, applicandoli a un vettore v per ottenere un nuovo vettore v' si procede come sopra, v' = v * PreR * R * PostR o v' = v * PreT * T * PostT.
Anche l'associatività delle trasformazioni e delle rotazioni è importante. Se vuoi applicare più operazioni su un vettore nella stessa riga di codice Verse, come una trasformazione seguita da una rotazione, l'associazione delle operazioni è importante. Ad esempio, puoi provare:
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 # compilesQuesto viene compilato correttamente poiché associa implicitamente operazioni come:
ResultantVector:vector3 = (ForwardVector * ForwardToLeftUpOne) * UpToForward # compiles
Ma se provi esplicitamente ad associare in modo diverso come:
ResultantVector:vector3 = ForwardVector * (ForwardToLeftUpOne * UpToForward) # error, no operator'*'(:transform,:rotation)
Ciò provoca un errore. Per evitare questi errori, associa esplicitamente la tua prima operazione tra un vettore e una trasformazione o un vettore e una rotazione.
ResultantVector:vector3 = (ForwardVector * ForwardToLeftUpOne) * UpToForward # explicitly associated
Modifiche alle operazioni di matematica spaziale
Rotazione e moltiplicazione della rotazione
RotateBy e UnrotateBy vengono rimossi e sostituiti con un operatore di moltiplicazione per due rotazioni.
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 handednessPer invertire una rotazione ("annulla rotazione"), prima inverti la rotazione, quindi moltiplica le rotazioni. Per ripristinare la rotazione UpToForward da UpToLeft, inverti la rotazione ForwardToLeft e applicala a destra alla rotazione UpToLeft. Di seguito viene illustrato come eseguire questa operazione passo dopo passo.
# 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 e moltiplicazione della rotazione
Allo stesso modo, Ruota e Annulla rotazione vengono rimossi e sostituiti con un operatore di moltiplicazione per un vector3 ruotato a destra da una rotazione.
ForwardVector:vector3 = vector3{Forward:=1.0}
ForwardToLeft:rotation = MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
LeftVector:vector3 = ForwardVector * ForwardToLeft # Rotate, correcting for handednessPer invertire una rotazione (annullare la rotazione), prima inverti la rotazione, quindi moltiplicala per il vettore. Per ripristinare ForwardVector da LeftVector, inverti la rotazione ForwardToLeft e applicala a destra a 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 e moltiplicazione della trasformazione
TransformVector e TransformVectorNoScale vengono rimossi e sostituiti con un operatore di moltiplicazione per un vector3 trasformato a destra da una trasformazione.
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 # TransformVectorPer eseguire una trasformazione senza ridimensionamento, TransformVectorNoScale, lascia il valore di scala predefinito sulla trasformazione che costruisci.
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