//****************************************************************************//
//************** Arbitrary Rotations - January 23rd, 2019 ********************//
//**************************************************************************//

- "Greg recommends using matrices to implement projection and mapping to the screen - true or false?"
    - The fools. The answer is obviously C, conveniently hidden on the backside of the paper
    - "...but really, don't use matrices. They're great for most stuff, but noooooo, they're just too annoying to deal with for a first-time projection assignment"
-----------------------------------------------------------

- So, the goal for today is to move away from just doing "axis-aligned" rotations, and instead to learn how to rotate around any vector we want
    - "The math here is actually pretty elegant, and will come in handy when we need to deal with 3D cameras"

- First off, some quick pieces of math we'll need to recover from the past:
    - VECTOR NORMALIZATION - to make a vector unit-length, we just take the vector and divide all of its components by its magnitude/length!
        - Remember, the magnitude/length of a vector is just sqrt(x^2 + y^2 + z^2 + ...)
    - Now, the dot product between 2 identical unit-length vectors is always 1
        - On the other hand, the dot product between any 2 perpendicular vectors is 0
    - ...and additionally, there's this operation you might remember called the CROSS-PRODUCT, where we multiply 2 vectors and get a 3rd vector that's orthogonal to both of the original ones
        - I won't derive it here, but to remind you, the cross-product equation looks like this:

            V1 x V2 = (y1*z2 - y2*z1, z1*x2 - z2*x1, x1*y2 - x2*y1)

- Hopefully that was just review for all of you, but what're we aiming towards?
    - Well, let's suppose we're back in 2D land, and there's a unit-length vector A pointing off in the first quadrant. Here's a puzzle: if we want to rotate A to line up with the X axis, how can we do that?
        - Sure, we could do something with a rotation matrix and arctangents and so forth, but there's a really neat solution that's simpler:

            1) Create another unit vector "B" perpendicular to A, such that:

                    B = (-ay, ax)

                - Is this always perpendicular? Well, yes!

                    A*B = a1*b1 + a2*b2 = ax*-ay + ay*ax = 0

                - In 2D, there's also another perpendicular vector that would also work - this would give us the same answer (although it might possibly flip something?)

            2) Create a rotation matrix as the following:

                    R = [ax ay 0] = [ax  ay 0]
                        [bx by 0]   [-ay ax 0]
                        [0  0  1]   [0   0  1]

                - "For the positive and negatives, think of ax replacing cosine and ay replacing sine"
                    - Why is the negative sign in the wrong place, then? Because this time we're rotating CLOCKWISE onto the x-axis, instead of counter-clockwise like we're used to
                - So, what does this get us when we multiply A by this matrix?

                    R*A = [ax  ay 0]   |ax|
                          [-ax ay 0] * |ay|
                          [0   0  1]   | 1|

                        = |ax^2 + ay^2 =  1|   |1|
                          |-ay*ax+ax*ay = 0| = |0|
                          |1               |   |1|

                - So, we get a unit vector pointing along the x-axis - which is what we wanted!
            - But here's a question: if we multiply B by this matrix, what would we get?
                - Well, it turns out that we'd rotate B onto the Y axis!
        - So, that's all we had to do - it's almost magically simple!

- "That's all well and good, Professor Turk, but how does it help us with rotations?" Well, let's try looking at this in 3D!
    - Let's say that A is now a 3D vector |ax, ay, az|, pointing off in space somewhere, and we want to rotate a point around A - how can we do it?
    - Well, we're not going to - INSTEAD, we're going to break this down into 3 simpler problems:
        1) We're going to rotate A onto the X-axis
        2) We're going to rotate about the X-axis (which we know how to do)
        3) We're going to rotate A back to its original positions
    - So, how do we do step 1?
        - Well, very similarly to what we did in the 2D case, we need to find  2 perpendicular vectors to A; to do this, we'll need:
            - A itself
            - N (some other vector that's not parallel to A - pretend we have an easy way to find this)
            - B: the CROSS PRODUCT of AxN that's been normalized, and therefore perpendicular to both of them!
            - and C, the cross-product of AxB (which should be unit-length if we've normalized B)
        - So, we now have 3 orthogonal vectors A, B, and C - which we can now use to create the following rotation matrix:

            R = [ax ay az 0]
                [bx by bz 0]
                [cx cy cz 0]
                [0  0  0  1]

            - Will this really rotate A onto the X axis? Well, yes!
                - The x-coordinate of R*A will be one (dot product with itself)
                - The z/y coordinates of R*A will be 0 (dot product of A with perpendicular vectors)

    - For step 2, then, we'll just rotate about the X axis, which we already know how to do!
    - ...but then, for step 3, we need to undo our first rotation. How do we do that?
        - Well, we need the inverse of our first matrix! "But it's a 4x4 matrix - wouldn't that be annoying to solve?"
            - Normally, yes, it would be - but in the very special case of an ORTHONORMAL matrix like we've got here, it turns out that the matrix's transpose IS its inverse!

            R^-1 = Rt = [ax bx cx 0]
                        [ay by cy 0]
                        [az bz cz 0]
                        [0  0  0  1]

    - SO, our final rotation matrix around some arbitrary vector A looks just like this:

            Ra = Rt * Rx * R

- A quick side-note: an easy way to find N, given our starting vector A, is the following:

        getN(vector A):
            if (ax == 0):
                N = (1, 0, 0)
            else
                N = (0, 1, 0)

    - "Every method I've seen for finding this vector N has some sort of if-statement, implicit or otherwise. This confused me for awhile, but then it dawned on me: it's just a special case of the hairy ball theorem from topology (which basically says a vector field on a ball has to have a pole somewhere)...which I don't expect ANY of you to know for tests or anything, but that was the epiphany I had."

- Here's a problem that seems unrelated, but is actually very tied to this rotation stuff: how do we put a camera in our 3D scene at any position, pointed in any direction?
    - We've learned how to deal with projections and camera stuff when we're at the origin, pointed down a single axis - but sometimes life gets boring, and we want to see the world from other angles
    - As it turns out, specifying the camera's position really does just take 3 numbers: x, y, and z. It's just a point in space
    - ...but how do we specify which way we're pointing? Well, the most obvious thing would be to have another 3D vector for which way we're facing...
        - ...but that's actually more than we need! Remember a globe? We can specify ANY direction on that globe using just latitude and longitude, since we don't need to care about the vector's length!
            - For the same reason, a unit vector technically carries more information than we need - if we wanted to, we could figure out where it was with just 2 things
    - For a camera, we'll call these values the AZIMUTH and ELEVATION
- We also need a 6th number: the "orientation" number, that basically just tells us which direction/axis is "up" in our world
    - But many graphics libraries require us to give up to NINE numbers! What gives? Well, skipping some of the details, it's for convenience sake so that we don't have to calculate the azimuth/elevation when passing them to the functions

- On Friday, we'll dig a bit deeper into HOW we're going to implement this - in the meantime, read the textbook for the camera sections, and I'll see you then!