Skip to navigation

Elite on the BBC Micro and NES

Calculating vertex coordinates

Determining whether a ship's vertex is visible or hidden from us

To understand the following, you'll probably want to have a look through the deep dive on back-face culling, which describes how we can work out whether or not a ship's face is visible.

As part of the back-face cull, we projected the vector [x y z] onto the orientation vector space like this:

  [x y z] projected onto sidev = [x y z] . sidev
  [x y z] projected onto roofv = [x y z] . roofv
  [x y z] projected onto nosev = [x y z] . nosev

We can express this exact same calculation in terms of matrix multiplication:

  [ sidev ]   [ x ]
  [ roofv ] . [ y ]
  [ nosev ]   [ z ]

or, expanding it out fully:

                      [ sidev_x sidev_y sidev_z ]   [ x ]
  projected [x y z] = [ roofv_x roofv_y roofv_z ] . [ y ]
                      [ nosev_x nosev_y nosev_z ]   [ z ]

This is just a different way of expressing the exact same equation as we used in part 5 of LL9, just with a matrix instead of individual dot products.

Transposing the rotation matrix
-------------------------------

So the inverse matrix will map vectors in the orientation vector space back into normal ship space. The inverse of a rotation matrix is its transpose (as long as it is a unit matrix), so this is the calculation:

                      [ sidev_x roofv_x nosev_x ]   [ x ]
  projected [x y z] = [ sidev_y roofv_y nosev_y ] . [ y ]
                      [ sidev_z roofv_z nosev_z ]   [ z ]

This takes a vector, which goes from the ship's centre to the vertex and is expressed in terms of the ship's axes (i.e. its orientation vectors), and instead expresses it in terms of our ship's axes (i.e. our orientation vectors).

Given this new vector, we can add the vector from our ship to the other ship, to get the vector from us to the vertex, expressed in our ship's coordinates:

                     [ sidev_x roofv_x nosev_x ]   [ x ]   [ x ]
  vector to vertex = [ sidev_y roofv_y nosev_y ] . [ y ] + [ y ]
                     [ sidev_z roofv_z nosev_z ]   [ z ]   [ z ]

The code to calculate this equation takes up part 6 and part 7 of LL9. It's in two parts because there are two small subroutines that have rudely inserted themselves just before the big reveal. These are used by part 8 and don't play a part in this calculation (except to make it harder to follow).