Skip to navigation

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.