# Celx Scripting: Rotation

## rotation

A CELX "rotation" object is internally a Quaternion, which is one possibility to mathematically describe a rotation in 3 dimensions (i.e. it can be converted to a rotation matrix). A rotation can also be used to describe the orientation of objects or the observer (i.e. where the observer is looking to, and where "up" is).

Within a CELX script, the rotation methods need to be prefixed with the obtained "rotation" object, separated with a colon.

The following methods can be used to obtain a "rotation" object:

## Methods

This chapter contains a list of all available rotation methods, which can be used on "rotation" objects.

### imag

vector rotation:imag()

Return the X, Y and Z values of this rotation as a "vector" object.

Notes:

1. A CELX "vector" object is a geometric object that has both a length and direction [X, Y, Z] in a 3 dimensional coordinate system.
2. The vector methods can be used on a CELX "vector" object. "Vector" objects can also be used in other methods, requiring a "vector" object as an argument.

Example:

```obs = celestia:getobserver()
rot1 = obs:getorientation()
vector = rot1:imag()
```

### real

number rotation:real()

Return the W value of this rotation as a number.

Example:

```obs = celestia:getobserver()
rot1 = obs:getorientation()
number = rot1:real()
```

### transform

vector rotation:transform(vector:vec)

Transform a "vector" object by applying the rotation to that vector and return the result in a new "vector" object.

Arguments:

vec
The vector the rotation will be applied to. Must be a "vector" object.

Notes:

1. A CELX "vector" object is a geometric object that has both a length and direction [X, Y, Z] in a 3 dimensional coordinate system.
2. The vector methods can be used on a CELX "vector" object. "Vector" objects can also be used in other methods, requiring a "vector" object as an argument.

Example:
Goto a position at the actual dark side of Earth.

```obs = celestia:getobserver()
-- Set frame of reference to "universal".
obs:setframe(celestia:newframe("universal"))
-- Find the Sun and Earth and get their actual positions
earth = celestia:find("Sol/Earth")
sun = celestia:find("Sol")
now = celestia:gettime()
earthpos = earth:getposition(now)
sunpos = sun:getposition(now)
-- Get vector from Earth to the Sun
vector1 = earthpos:vectorto(sunpos)
-- Transform that vector over a rotation of 180 degrees = math.pi
up_v = celestia:newvector(0,1,0)
opposite = celestia:newrotation(up_v, math.pi)
vector2 = opposite:transform(vector1)
-- Adjust the length of the opposite vector
vector2 = 0.0003 * vector2
-- Goto new position and center Earth.
newpos = earthpos + vector2
obs:goto(newpos, 0.0)
wait(0.0)
obs:center(earth, 0.0)
wait(0.0)
```

### setaxisangle

rotation:setaxisangle(vector:vec, number:angle)

Set axis and angle, as defined in the vector and angle for this rotation.

Arguments:

vec
Vector describing the [X,Y,Z] axis for this rotation. Must be a "vector" object.
angle
The angle in radians for this rotation. Must be a number.

Notes:

1. Angles in CELX are defined in radians instead of degrees. 180 degrees (half a circle) is the same as π radians = 3.14159265 radians = math.pi radians (LUA). You can convert degrees to radians and vice versa as follows:
• radians = math.rad( number:degrees ) = ( number:degrees / 180 * math.pi) = ( number:degrees / 180 * 3.14159265).
• degrees = math.deg( number:radians ) = ( number:radians * 180 / math.pi) = ( number:radians * 180 / 3.14159265).
2. This method is equivalent to celestia:newrotation(axis-angle) method. Only by using this method, the "rotation" object needs to be present first, instead of being created by the method. To obtain such a "rotation" object, the celestia:newrotation() method can be used instead, or you can use an already existing "rotation" object, previously defined within your script.

Example:
Change the current observer view by 180 degrees (like a rear-view mirror).

```obs = celestia:getobserver()
-- Create a rotation object from all zero numbers.
rot1 = celestia:newrotation(0, 0, 0, 0)
-- Define the axis for the rotation as a vector
up_vec = celestia:newvector(0, 1, 0)
rot1:setaxisangle(up_vec, math.pi)
obs:rotate(rot1)
wait(0.0)
```

### slerp

rotation:rot3 rotation:slerp(rotation:rot2, number:percent)

Return an interpolation of this rotation and another "rotation" object (rot2), using number to indicate how much of each rotation should be used. Return the result in a new "rotation" object (rot3).

Arguments:

rot2
Second rotation that will be used for the interpolation. Must be a "rotation" object.
percent
The percent number used to interpolate between the two rotations. Must be a number between 0 and 1.
• If percent is 0, this rotation is returned in rotation:rot3.
• If percent is 1, the second rotation (rot2) is returned in rotation:rot3.

Notes:

1. A CELX "rotation" object is internally a Quaternion, which is one possibility to mathematically describe a rotation in 3 dimensions (i.e. it can be converted to a rotation matrix). A rotation can also be used to describe the orientation of objects or the observer (i.e. where the observer is looking to, and where "up" is).
2. The rotation methods can be used on a CELX "rotation" object. "Rotation" objects can also be used in other methods, requiring a "rotation" object as an argument.

Example:
Goto a position in the Earth-Moon system and set the observer orientation to the middle of the Earth-Moon positions.

```obs = celestia:getobserver()
-- Set frame of reference to "universal".
obs:setframe(celestia:newframe( "universal"))
-- Find the actual position of the Earth.
earth = celestia:find("Sol/Earth")
earthpos = earth:getposition()
-- Find the actual position of the Moon.
moon = celestia:find("Sol/Earth/Moon")
moonpos = moon:getposition()
-- Calculate new position to goto
newpos = earthpos + 0.5 * (moonpos - earthpos)
newpos = newpos + celestia:newvector(0, 0, 0.075)
obs:goto(newpos, 0.0)
wait(0.0)
-- Orientation from this position towards Earth
orient_earth = newpos:orientationto(earthpos, celestia:newvector(0, 1, 0))
-- Orientation from this position towards Moon
orient_moon = newpos:orientationto(moonpos, celestia:newvector(0, 1, 0))
-- Interpolate new observer orientation (middle)
orientation = orient_earth:slerp(orient_moon, 0.5)
obs:setorientation(orientation)
```