A partir da versão 36.00, O UEFN usa o sistema de coordenadas LUF para o editor e todas as transformações do módulo /Verse.org. As transformações do módulo /UnrealEngine.com e /Fortnite.com usam o sistema de coordenadas XYZ.
Apresentando o Sistema de Coordenadas LUF
Todas as principais ferramentas de criação de conteúdo 3D usam um sistema de coordenadas Cartesianas (X, Y e Z) para posicionar e girar objetos. No entanto, as interpretações específicas para quais eixos (X, Y e Z) representam quais direções (como esquerda/direita, cima/baixo e frente/trás) são diferentes entre as ferramentas. Além disso, a maneira como as rotações são modeladas — conceito conhecido como lateralidade do sistema de coordenadas — também varia entre as diferentes ferramentas.
Para alinhar melhor a linguagem Verse e o UEFN com os padrões recentes na criação de conteúdo 3D e outros conjuntos de ferramentas importantes, estamos fazendo mudanças fundamentais na apresentação do nosso sistema de coordenadas.
Em primeiro lugar, em vez de rotular os eixos de coordenadas com X, Y e Z, estamos introduzindo nomes de eixo mais descritivos:
Esquerdo (era -Y)
Para cima (era Z)
Para frente (era X)
A alteração do XYZ e FRU anteriores para o LUF corresponde, portanto, a uma alteração da lateralidade nos eixos de um sistema de coordenadas para a esquerda (XYZ e FRU) para um sistema de coordenadas para a direita (LUF).
Em segundo lugar, as cores do gizmo da janela de visualização do UEFN mudaram para se alinhar a outros softwares de criação de conteúdo 3D:
À esquerda: vermelho (era verde)
Para cima: verde (era azul)
Para a frente: azul (era vermelho)
Em terceiro lugar, muitas melhorias foram feitas no módulo/Verse.org/SpatialMath:
As funções do módulo de matemática espacial do Verse agora são operações para a direita. Como resultado, todas as funções com variantes explícitas de rotação para a direita foram removidas e substituídas por versões que usam operações para a direita como padrão, e os indicadores de rotação para a direita foram removidos dos nomes das funções. Para obter mais informações, consulte a seção Sistema de Coordenadas com Mão Direita desta página abaixo.
As funções de rotação que envolvem um parâmetro de ângulo ou retornam um valor agora têm versões que aceitam ou retornam radianos ou graus e são sufixadas com
RadianosouGrauspara a respectiva variante.RotateBy,UnrotateBye todas as funções(:rotation).Apply*foram removidas em favor de um operador de multiplicação que compõe duasrotaçõesda esquerda para a direita. Para obter mais informações, consulte a seção [Ordem de multiplicação de transformação e rotação]() desta página.RotateVectoreUnrotateVectorforam removidos em favor de um operador de multiplicação que gira umvector3usando umarotation, nessa ordem. Para obter mais informações, consulte a seção Alterações na operação de matemática espacial desta página.TransformVectoreTransformVectorNoScaleforam removidos em favor de um operador de multiplicação que transforma umvector3usando umatransformna seguinte ordem: escala, rotação, translação. Para obter mais informações, consulte a seção Alterações na operação de matemática espacial desta página.
Em quarto lugar, as importações padrão de malhas do esqueleto de FBX agora usam a opção de alinhar os eixos para cima e para a frente, de modo que todas as malhas do esqueleto importadas fiquem voltadas para o eixo para a frente.
O que isso afeta
Essa alteração no sistema de coordenadas afeta qualquer pessoa que use o UEFN ou as transformações no módulo /Verse.org, em particular vários aspectos do UEFN e do Verse, que incluem:
Painel Detalhes do UEFN
Janela de visualização e gizmo do UEFN
Transformação Verse
Você não precisa alterar o código ou o conteúdo para que suas ilhas publicadas funcionem corretamente com o LUF.
Painel Detalhes do UEFN
As transformações no Painel Detalhes do UEFN agora exibem as coordenadas em termos do sistema LUF.
Janela de visualização do UEFN
O mapeamento entre os eixos e as cores do gizmo foi alterado na janela de visualização do UEFN.
Transformações Verse
As transformações do módulo /Verse.org usam o sistema LUF . A transformação de módulo /UnrealEngine.com usando o sistema de coordenadas XYZ ainda existe e é usada como a transformação padrão nos módulos /UnrealEngine.com e /Fortnite.com.
Como ambos os módulos contêm tipos de transformação, tenha em mente o seguinte:
Se estiver usando funções da API que usam transformações de módulo
/Verse.orge transformações do módulo/UnrealEngine.comno mesmo arquivo, os nomes dos tipos precisam ser qualificados por seu caminho para que se evite ambiguidade entre os dois módulos. Isso é mostrado no trecho de código abaixo.VerseNomes de tipos qualificados por caminhousing { /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{}O Scene Graph usa transformações do módulo
/Verse.org. Ou seja, o Scene Graph agora usa apenas o sistema de coordenadas LUF.O Verse Digest usa identificadores Verse totalmente qualificados para desambiguar entre os tipos de transform definidos nos módulos UnrealEngine.com/Temporary/SpatialMath eVerse.org/SpatialMath.
Para saber mais sobre o sistema de coordenadas da Unreal Engine, consulte Sistema de coordenadas e espaços na Unreal Engine.
Como converter de XYZ para LUF
Se você estiver usando quaisquer funções da API existentes que tenham sido alteradas para as transformações de módulo /Verse.org (LUF), você precisará converter suas transformações /UnrealEngine.com definidas pelo usuário (XYZ) para usar o LUF ou usar as funções de conversão FromTransform recém-criadas. Nesta sessão, você pode encontrar vários possíveis problemas de conversão e as soluções para eles.
Ambiguidade de tipo constante ou variável
Com as alterações recentes na API do Verse, /UnrealEngine.com/Temporary/SpatialMath e /Verse.org/SpatialMath definem os tipos vector3, rotation e transform. Como resultado, uma ambiguidade de tipo surgirá se você incluir ambos os domínios no arquivo Verse.
Exemplo de ambiguidade de tipo
O arquivo Verse a seguir importa ambos os caminhos de módulo /UnrealEngine.com/Temporary/SpatialMath e /Verse.org/SpatialMath, e a classe definida pelo usuário usa o tipo não qualificado 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.vector3Como resultado, a ambiguidade de tipo causa um erro de compilação se você tentar compilar este arquivo, pois o compilador não sabe se deve compilar MyVectorOne e MyVectorTwo como um tipo /UnrealEngine.com vector3 ou como um tipo /Verse.org vector3. O usuário não forneceu ao compilador informações suficientes para que ele saiba qual tipo é indicado.
Para resolver esse erro de compilação, você deve qualificar o caminho do tipo de vector3 que cada variável usa. Há várias maneiras diferentes de qualificar o caminho dessas constantes para resolver o erro:
Você pode qualificar totalmente qualquer constante ou variável do tipo vector3, conforme mostrado no trecho de código abaixo.
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{}Você pode qualificar uma constante ou variável no módulo /Verse.org, conforme mostrado no trecho de código abaixo.
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 submoduleVocê pode qualificar uma constante ou variável no módulo /UnrealEngine.com, conforme mostrado no trecho de código abaixo:
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{}Alteração do tipo de Scene Graph
Se você estiver usando as APIs do Scene Graph nos seus arquivos Verse e não estiver usando outras APIs que usam matemática espacial, poderá alterar os tipos de matemática espacial no código Verse alterando o módulo de matemática espacial importado com a palavra-chave using. Por exemplo, se você tiver o seguinte código:
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{}Você pode alterá-lo para:
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 vector2A única exceção é que quaisquer tipos vector2 devem ser removidos ou convertidos para usar vector3, pois o módulo Verse.org não define atualmente o tipo vector2.
Disparidade de tipo de função
Outro cenário em que você pode precisar qualificar tipos de caminho ou converter seu código é quando:
Uma função chamada ou uma variável atribuída espera um tipo do módulo
UnrealEngine.com, mas é fornecido um tipo do móduloVerse.org.Uma função chamada ou uma variável atribuída espera um tipo do módulo
Verse.org, mas é fornecido um tipo do móduloUnrealEngine.com.
Exemplo de disparidade de tipo de função
Os dois arquivos Verse a seguir existem no mesmo projeto. FileOne.verse define uma função para imprimir uma transformação do módulo /UnrealEngine.com/Temporary/SpatialMath . FileTwo.verse define um transform constante do módulo /Verse.org/SpatialMath e uma função para imprimir esse valor que chama a função de 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.Isso resulta em um erro de compilação devido aos tipos de transform que se referem a dois tipos de transform diferentes definidos em módulos diferentes.
Para corrigir esse erro de compilação, você deve converter o tipo de transform para o tipo de transform correto do módulo apropriado. Edite o código em FileTwo.verse para usar a função FromTransform, que converte um transform de /Verse.org/SpatialMath em um transform de /UnrealEngine.com/Temporary/SpatialMath.
Para obter uma lista completa de funções de conversão disponíveis, consulte a próxima seção.
# 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 moduleConversão dos tipos vector, rotation e transform
O módulo /UnrealEngine.com fornece várias novas funções de conversão para converter entre os tipos possivelmente ambíguos definidos no módulo /UnrealEngine.com e no módulo /Verse.org.
Da matemática espacial da Unreal Engine para a matemática espacial de 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
Da matemática espacial de Verse para a matemática espacial da Unreal Engine
# 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
Operações e funções matemáticas espaciais do Verse
Sistema de coordenadas com a mão direita
As funções do módulo de matemática espacial do Verse agora são operações para a direita. Como resultado, todas as funções com variantes de lateralidade explícitas foram removidas e substituídas por versões que usam operações para a direita, e os indicadores de lateralidade foram retirados dos nomes das funções. Todas as operações em que há uma escolha de lateralidade, como a multiplicação de um vector3 por uma rotation ou a multiplicação de um vector3 por uma transform, são operações para a direita.
Por exemplo, o código a seguir ilustra que construir uma rotação de 90 graus positivos em torno do eixo para cima e aplicar essa rotação a um vetor unitário para a frente resulta em um vetor unitário para a esquerda:
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}
Ordem de multiplicação de transformação e rotação
Você pode pensar nas rotações como sendo representadas internamente por uma Matrix. Quando uma rotação R é aplicada a um vetor v, ela é aplicada na ordem de multiplicação entre linha e vetor. Ou seja, o vetor v é um vetor de linha e, quando um vetor é girado, a multiplicação é aplicada à direita para obter o resultado, v' = v * R. Aqui, o vetor resultante v' é um novo vetor linha. Isso funciona de forma semelhante para aplicar uma transformação T a um vetor v, v' = v * T, e o vetor resultante v' é outro vetor linha.
A ordem importa ao aplicar rotações e transformações a vetores. Segure um objeto, como um livro, na mão com a parte superior voltada para cima e a frente/capa voltada para você. Aplicar uma rotação positiva de 90 graus para a direita em torno do eixo para a frente faz com que o topo do livro fique voltado para a direita. Em seguida, aplicando uma rotação de 90 graus sobre o eixo esquerdo, a frente do telefone fica voltada para cima e a parte superior do livro fica voltada para a sua direita.
Agora, aplique as mesmas rotações na ordem inversa. Aplique uma rotação de 90 graus em torno do eixo esquerdo, resultando na parte superior do livro voltada para a frente e a frente do livro voltada para cima. Em seguida, aplicar uma rotação de 90 graus sobre o eixo para a frente faz com que o topo do livro fique voltado para a frente e a frente do livro fique voltada para a direita. Essa não é a mesma orientação que aplicar as rotações na outra ordem, ilustrando que a ordem das rotações é importante.
Com isso em mente, se você quiser aplicar duas rotações R e R' a um vetor v, deverá tomar cuidado para aplicá-las na ordem desejada. Se quiser aplicar a rotação R antes da rotação R', a ordem correta é v' = v * R * R'.
O mesmo princípio se aplica às próprias rotações. Se você tiver uma rotação R e quiser aplicar uma pré-rotação PreR a R, que ocorre antes da rotação R, e uma pós-rotação PostR que ocorre após a rotação R, isso é feito na ordem PreR * R * PostR. Da mesma forma, se você quiser aplicar uma pré-transformação PreT e uma pós-transformação PostT a uma transformação T, isso é feito na ordem PreT * T * PostT. Em seguida, a aplicação delas a um vetor v para obter um novo vetor v' é feita conforme acima, v' = v * PreR * R * PostR ou v' = v * PreT * T * PostT.
A associatividade de transformações e rotações também é importante. Se você deseja aplicar múltiplas operações em um vetor na mesma linha de código Verse, como uma transformação seguida por uma rotação, a associação das operações importa. Por exemplo, você pode tentar:
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 # compilesIsso compila bem, pois está associando implicitamente operações como:
ResultantVector:vector3 = (ForwardVector * ForwardToLeftUpOne) * UpToForward # compiles
Mas se você tentar associar explicitamente de forma diferente como:
ResultantVector:vector3 = ForwardVector * (ForwardToLeftUpOne * UpToForward) # error, no operator'*'(:transform,:rotation)
Isso resulta em um erro. Para evitar esses erros, associe explicitamente sua primeira operação entre um vetor e uma transformação ou um vetor e uma rotação.
ResultantVector:vector3 = (ForwardVector * ForwardToLeftUpOne) * UpToForward # explicitly associated
Alterações na operação de matemática espacial
Rotação e multiplicação de rotação
RotateBy e UnrotateBy são removidos e substituídos por um operador de multiplicação para duas rotações.
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 handednessPara reverter uma rotação ("unrotation"), primeiro inverta a rotação e, em seguida, multiplique as rotações. Para recuperar a rotação UpToForward de UpToLeft, inverta a rotação ForwardToLeft e aplique-a à direita da rotação UpToLeft. O código a seguir mostra como isso é feito, passo a 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 multiplicação de rotação
Da mesma forma, Rotate e Unrotate são removidos e substituídos por um operador de multiplicação para um vector3 girado à direita por uma rotação.
ForwardVector:vector3 = vector3{Forward:=1.0}
ForwardToLeft:rotation = MakeRotationFromEulerDegrees(0.0, 90.0, 0.0)
LeftVector:vector3 = ForwardVector * ForwardToLeft # Rotate, correcting for handednessPara reverter uma rotação (cancelar a rotação), primeiro inverta a rotação e, em seguida, multiplique a rotação pelo vetor. Para recuperar o ForwardVector de LeftVector, inverta a rotação de ForwardToLeft e aplique-a à direita de 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 multiplicação de transformação
TransformVector e TransformVectorNoScale são removidos e substituídos por um operador de multiplicação para um vector3 transformado à direita por uma transformação.
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 # TransformVectorPara executar uma transformação sem dimensionamento, TransformVectorNoScale, deixe o valor de escala padrão na transform que você construir.
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