Monday, January 2, 2012

Using Rotators in UnrealScript

In UnrealScript the rotation of 3D objects is done through the use of a structure called Rotator that is defined in the Object class as follows:
struct immutable Rotator
{
    var() int Pitch, Yaw, Roll;
};

Each of the integer variables Pitch, Yaw and Roll, represents the rotation around an axis. The keyword "immutable" is a structure modifier used to optimize the serialization of Rotator variables.

The Unreal Engine uses integer values between -32768 and +32767 to represent the angle in degrees between -180 and 180, or 0 to 65535 for the angles of 0 to 360 degrees. This range of values corresponds to the capacity of a 16-bit integer variable and maybe is an inheritance from the 1st version of the Unreal Engine, because at this time the mathematical operations with integers were much faster than the operations done with float numbers.

To help in the conversion of angles between degrees, radians and Unreal Rotation, some constants are defined in the Object class:
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;

To use these constants just multiply by the desired value. For example, if we want to find out how much is 90 degrees in Unreal Rotation, do as follows:
unreal90Degree = 90 * DegToUnrRot;

The Actor class has a variable called Rotation of type Rotator defined as follows:
/** The actor's rotation; use SetRotation to change. */
var(Movement) const rotator    Rotation;

This variable is defined as const (constant) indicating that its contents can not be changed. To change the rotation of an Actor you must use the SetRotation function:
native(299) final function bool SetRotation( rotator NewRotation );

The native keyword indicates that this function is implemented in C++, so we can not see its source code, because in the UDK only comes UnrealScript source code. The final keyword means that this function can not be overridden in a subclass.

I made an example to demonstrate the use of the Rotator. I use a ship of Unreal Tournament and did a movement of rotation around each axis.
class TestRotator extends Actor
      placeable;
    
var float velRotation;

event Tick(float DeltaTime)
{
   local float deltaRotation;
   local Rotator newRotation;
   
   deltaRotation = velRotation * DeltaTime; 
   
   newRotation = Rotation;
   
   newRotation.Pitch += deltaRotation;
   newRotation.Yaw  += deltaRotation;   
   newRotation.Roll  += deltaRotation;   

   SetRotation( newRotation );       
}

defaultproperties
{
    velRotation=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 )        
}