BBC Micro Elite

# Orientation vectors

```The three vectors that determine a ship's orientation in space
--------------------------------------------------------------
References: MVEIT (Part 1 of 9), INWK, K%, TIDY, MVS4, MVS5
Each ship in the Elite universe has its own set of three orientation vectors,
which determine its orientation in space. There are three different vectors -
nosev, roofv and sidev - with each of them pointing along one of the ship's
main axes, like this:

* nosev points forward out of the nose of the ship

* roofv points up out of the ship's sunroof... or it would if it had one

* sidev points out of the ship's right view

(Note that there are five ships that have slightly different orientations to
this standard model, namely Thargoids, Thargons, space stations, cargo
canisters and asteroids. These orientations are described below.)

It might help to think of these vectors from the point of view of the ship's
cockpit. From this perspective, the orientation vectors always look like this,
with our ship at the origin:

roofv
^
|
|
|
|    nosev
|   /
|  /
| /
|/
+-----------------------> sidev

Every ship out there has its own set of orientation vectors, with nosev
pointing out of that ship's nose, roofv pointing out of that ship's roof, and
sidev out of that ship's right side. The orientation vectors are used in lots
of places, for example:

* When we draw the ship on screen, we take the shape as defined by its
blueprint, and rotate it so that it aligns with its orientation vectors,
so the ship we draw on screen points the right way

* If an enemy ship is firing its lasers at us, we use that ship's nosev
vector to work out whether it is pointing towards us, and therefore
whether it can hit us

* When enemy ships pitch or roll, we can apply these movements by rotating
their orientation vectors

Our ship doesn't have its own set of orientation vectors - at least, not
explicitly. This is because our own ship's orientation vectors always align
with the main coordinate axes: sidev aligns with the x-axis, which always
points to the right from the point of view of our cockpit, while roofv aligns
with the y-axis and points up, and nosev aligns with the z-axis, which always
points into the screen.

Storing the vectors in the ship data block
------------------------------------------
The three vectors are stored in bytes #9-26 of the ship's data block, so when
we copy a ship's data into the internal workspace INWK, the vectors live in
INWK+9 to INWK+26. Each vector coordinate is stored as a 16-bit sign-magnitude
number, like this:

[ INWK(10 9)  ]           [ INWK(16 15) ]           [ INWK(22 21) ]
nosev = [ INWK(12 11) ]   roofv = [ INWK(18 17) ]   sidev = [ INWK(24 23) ]
[ INWK(14 13) ]           [ INWK(20 19) ]           [ INWK(26 25) ]

We can refer to these three vectors in various ways, such as these variations
for the nosev vector:

nosev = (nosev_x, nosev_y, nosev_z)

= [ nosev_x nosev_y nosev_z ]

[ nosev_x ]
= [ nosev_y ]
[ nosev_z ]

[ (nosev_x_hi nosev_x_lo) ]
= [ (nosev_y_hi nosev_y_lo) ]
[ (nosev_z_hi nosev_z_lo) ]

Orthonormal vectors
-------------------
The three orientation vectors are orthonormal, which means they are orthogonal
(i.e. they are perpendicular to each other), and normal (i.e. each of the
vectors has length 1).

We can rotate a ship about its centre by rotating these vectors, as in the
MVS4 routine (see the deep dive on "Pitching and rolling" for more about
this). However, because we use the small angle approximation to rotate in
space, and it is not completely accurate, the three vectors tend to get a bit
stretched over time, so periodically we have to tidy the vectors with the TIDY
routine to ensure they remain as orthonormal as possible.

Initialisation
--------------
When a new ship is spawned, its vectors are initialised in ZINF as follows:

sidev = (1,  0,  0)
roofv = (0,  1,  0)
nosev = (0,  0, -1)

So new ships are spawned facing out of the screen, as their nosev vectors
point in a negative direction along the z-axis, which is positive into the
screen and negative out of the screen.

Internally, we store a vector value of 1 as 96, to support fractional values,
and the orientation vectors are stored as 16-bit sign-magnitude numbers. 96 is
&60, and &60 with bit 7 set is &E0, so we store the above vectors like this:

sidev = (&6000, 0, 0)
roofv = (0, &6000, 0)
nosev = (0, 0, &E000)

so nosev_z_hi = &E0 = -96, sidev_x_hi = &60 = 96 and so on.

Rotation matrices and axes
--------------------------
Sometimes we might refer to the orientation vectors as a matrix, with sidev
as the first row, roofv as the second row, and nosev as the third row, like
this:

[ sidev_x sidev_y sidev_z ]
[ roofv_x roofv_y roofv_z ]
[ nosev_x nosev_y nosev_z ]

though generally we talk about the individual vectors, because that's easier
to understand. See the deep dive on "Calculating vertex coordinates" for an
example of the above matrix in use.

For the mathematically inclined, the three orientation vectors can be thought
of as axes that define the 3D coordinate space orientated around the other
ship - they form the basis for this space. To put it yet another way, the
matrix above is a rotation matrix that transforms the axes of our ship into
the axes of the other ship.

Finally, the orientation vectors define a left-handed universe, with the thumb
as roofv, index finger as nosev, and middle finger as sidev.

Non-standard orientations
-------------------------
The following ships don't have a standard orientation (all other ships follow
the logical nose-roof-side pattern).

* Thargoid mothership:

* nosev points out of one side of the mothership

* roofv points out of the other side of the mothership

* sidev points out of the roof of the mothership

* Thargon:

* nosev points out of the Thargon's nose

* roofv points out of the side of the Thargon

* sidev points out of the roof of the Thargon

* Space station:

* nosev points forward out of the docking slot

* roofv points out of the side of the space station in a direction that is
parallel to the horizontal line of the slot

* sidev points out of the side of the space station in a direction that is
perpendicular to the horizontal line of the slot

* Cargo canister:

* nosev points out of the side of the canister, avoiding the apexes of the
pentagonal cross-section and at right-angles to roofv

* roofv points out of the side of the canister, through one of the apexes
of the pentagonal cross-section

* sidev points out of one end of the canister

The asteroid also follows its own orientation, but I'm not even going to try
to describe which features appear to be the the nose, roof and side, as they
all just look like bumps to me.

One interesting (and presumably intentional) effect of the Thargoid and
Thargon orientations can be seen when they pitch and roll. A pitching Thargoid
actually spins like a traditional flying saucer (i.e. like a spinning top) as
its roofv vector points out of its side (though a rolling Thargoid tilts back
and forth as expected). When fighting Thargoids, you often find yourself
orientating your ship to get them vertically aligned in your sights, which is
because you can then track their sideways pitching with your own vertical
pitching movement. This is different to the other ships, which expose their
soft underbellies to your lasers when they try to pitch out of your way.

That's Thargoids for you. Different... and deadly.

```