diff --git a/agb/src/display/affine.rs b/agb/src/display/affine.rs index 8fd23f73..e05ce53c 100644 --- a/agb/src/display/affine.rs +++ b/agb/src/display/affine.rs @@ -7,16 +7,79 @@ //! Affine matricies are used in two places on the GBA, for affine backgrounds //! and for affine objects. //! -//! # Linear Algebra basics -//! As a matrix, they can be manipulated using linear algebra, although you -//! shouldn't need to know linear algebra to use this apart from a few things +//! # Linear Algebra +//! As a matrix, they can be manipulated using linear algebra. The short version +//! of this section is to beware that the matrix is the inverse of the normal +//! transformation matricies. //! -//! If `A` and `B` are matricies, then matrix `C = A * B` represents the -//! transformation `A` performed on `B`, or alternatively `C` is transformation -//! `B` followed by transformation `A`. +//! One quick thing to point out at the start as it will become very relevant is +//! that matrix-matrix multiplication is not commutative, meaning swapping the +//! order changes the result, or **A** × **B** ≢ **B** × **A**. However, +//! matricies are, at least in the case they are used here, associative, meaning +//! (**AB**)**C** = **A**(**BC**). //! -//! Additionally matrix multiplication is not commutative, meaning swapping the -//! order changes the result, or `A * B ≢ B * A`. +//! ## Normal (wrong on GBA!) transformation matricies +//! +//! As a start, normal transformation matricies will transform a shape from it's +//! original position to it's new position. Generally when people talk about +//! transformation matricies they are talking about them in this sense. +//! +//! > If **A** and **B** are transformation matricies, then matrix **C** = **A** +//! > × **B** represents the transformation **A** performed on **B**, or +//! > alternatively **C** is transformation **B** followed by transformation +//! > **A**. +//! +//! This is not what they represent on the GBA! If you are looking up more +//! information about tranformation matricies bear this in mind. +//! +//! ## Correct (on GBA) transformation matricies +//! +//! On the GBA, the affine matrix works the other way around. The GBA wants to +//! know for each pixel what colour it should render, to do this it applies the +//! affine transformation matrix to the pixel it is rendering to lookup correct +//! pixel in the texture. +//! +//! This describes the inverse of the previously given transformation matricies. +//! +//! Above I described the matrix **C** = **A** × **B**, but what the GBA wants +//! is the inverse of **C**, or **C**-1 = (**AB**)-1 = +//! **B**-1 × **A**-1. This means that if we have the +//! matricies **I** and **J** in the form the GBA expects then +//! +//! > Transformation **K** = **I** × **J** is the transformation **I** followed +//! > by the transformation **J**. +//! +//! Beware if you are used to the other way around! +//! +//! ## Example, rotation around the center +//! +//! To rotate something around its center, you will need to move the thing such +//! that the center is at (0, 0) and then you can rotate it. After that you can +//! move it where you actually want it. +//! +//! These can be done in the order I stated, **A** = **Move To Origin** × +//! **Rotate** × **Move to Final Position**. Or in code, +//! +//! ```rust,no_run +//! # #![no_std] +//! # #![no_main] +//! use agb::fixnum::{Vector2D, Num, num}; +//! use agb::display::affine::AffineMatrix; +//! +//! # fn foo(_gba: &mut agb::Gba) { +//! // size of our thing is 10 pixels by 10 pixels +//! let size_of_thing: Vector2D> = (10, 10).into() +//! // rotation by a quarter turn +//! let rotation: Num = num!(0.25); +//! // the final position +//! let position: Vector2D> = (100, 100).into(); +//! +//! // now lets calculate the final transformation matrix! +//! let a = AffineMatrix::from_translation(-size_of_thing / 2) +//! * AffineMatrix::from_rotation(rotation) +//! * AffineMatrix::from_translation(position); +//! # } +//! ``` use core::{ convert::TryFrom,