segunda-feira, 2 de janeiro de 2012

Usando Rotators em UnrealScript

Em UnrealScript a rotação de objetos 3D é feita através do uso de uma estrutura chamada Rotator que está definida na classe Object da seguinte forma:
struct immutable Rotator
{
    var() int Pitch, Yaw, Roll;
};

Cada uma das variáveis inteiras Pitch (arfada), Yaw (guinada) e Roll (rolamento), representa a rotação ao redor de um eixo. A palavra chave "immutable" é um modificador de estrutura usado para otimizar a serialização das variáveis do tipo Rotator.

A Unreal Engine utiliza os valores inteiros entre -32768 e +32767 para representar os ângulos em graus entre -180 e 180, ou 0 a 65535 para os ângulos de 0 a 360º. Essa faixa de valores corresponde a capacidade de uma variável inteira de 16 bits e deve ser uma herança da 1ª versão da Unreal Engine, pois antigamente as operações matemáticas feitas com inteiros eram muito mais rápidas do que as operações feitas com números fracionários.

Para facilitar a conversão de ângulos entre Graus, Radianos e Unreal Rotation, foram definidas algumas constantes na classe Object:
const Pi = 3.1415926535897932;
const RadToDeg = 57.295779513082321600;    // 180 / Pi
const DegToRad = 0.017453292519943296;    // Pi / 180
const UnrRotToRad = 0.00009587379924285;// Pi / 32768
const RadToUnrRot = 10430.3783504704527;// 32768 / Pi
const DegToUnrRot = 182.0444;
const UnrRotToDeg = 0.00549316540360483;

Para utilizar essas constantes basta multiplicar pelo valor desejado. Por exemplo, se quisermos descobrir quanto é 90 graus em Unreal Rotation, faça assim:
unreal90Degree = 90 * DegToUnrRot;

A classe Actor possui uma variável do tipo Rotator chamada Rotation definida assim:
/** The actor's rotation; use SetRotation to change. */
var(Movement) const rotator    Rotation;

Essa variável é definida como const (constante) indicando que seu conteúdo não pode ser alterado. Para modificarmos a rotação de um Actor é preciso usar a função SetRotation:
native(299) final function bool SetRotation( rotator NewRotation );

A palavra chave native indica que esta função está sendo implementada em C++, sendo assim não podemos ver o seu código fonte, pois no UDK só vem o código fonte UnrealScript. A palavra chave final significa que esta função não pode ser sobrescrita em uma subclasse.

Fiz um exemplo para demonstrar o uso do Rotator. Uso uma nave do Unreal Tournament e faço um movimento composto de rotação ao redor de cada um dos eixos.
class TesteRotacao extends Actor
      placeable;
    
var float velRotacao;

event Tick(float DeltaTime)
{
   local float deltaRotacao;
   local Rotator novaRotacao;
   
   deltaRotacao = velRotacao * DeltaTime; 
   
   novaRotacao = Rotation;
   
   novaRotacao.Pitch += deltaRotacao;
   novaRotacao.Yaw  += deltaRotacao;   
   novaRotacao.Roll  += deltaRotacao;   

   SetRotation( novaRotacao );       
}

defaultproperties
{
    velRotacao=5000
   
    Begin Object Class=DynamicLightEnvironmentComponent Name=LightEnvironmentComp
        bEnabled = true
    End Object    
    Components.add( LightEnvironmentComp )
    
    Begin Object Class=SkeletalMeshComponent Name=SVehicleMesh
        SkeletalMesh=SkeletalMesh'VH_Cicada.Mesh.SK_VH_Cicada'
        AnimTreeTemplate=AnimTree'VH_Cicada.Anims.AT_VH_Cicada'
        PhysicsAsset=PhysicsAsset'VH_Cicada.Mesh.SK_VH_Cicada_Physics'
        AnimSets.Add(AnimSet'VH_Cicada.Anims.VH_Cicada_Anims')
        LightEnvironment = LightEnvironmentComp
    End Object
    Components.add( SVehicleMesh )        
}