Showing posts with label Vector Maths. Show all posts
Showing posts with label Vector Maths. Show all posts

Wednesday, January 16, 2019

Sample Problem: Rotating a 2D Character

The Problem
In a top down shooter, there is a scripted in game cutscene where an explosion happens and the player must turn to face the explosion. The turn to face the explosion must be a smoothed transition and since the cutscene can be triggered in a variety of ways, the initial direction of the player can be different between playthroughs. We need to know the angle the player needs to rotate and whether the direction they need to rotate is clockwise or anticlockwise.

The Variables
The current variables we have access to is the initial direction the player is facing (Vector C) , the position of the player (P) and the position of the explosion (E).

The Solution
The first step is to calculate the direction towards the explosion from the player, which can be done by subtracting P from E. This gives us Vector N and since we don't care about the distance between the two positions, we can normalise Vector N.

Since we now have two unit vectors (Vector N and Vector C), we can calculate the angle between them by using the dot product calculation. So the angle is equal to arccos(dotProduct(Vector C, Vector N)). However, this doesn't tell us if the direction we need to rotate is clockwise or anti clockwise.

This can be done with the cross product. However, since both vectors are in 2D space, they need to be converted into 3D vectors. Once the cross product is calculated we can determine the direction of the rotation needed. If the z component of the resultant vector is positive then the rotation is anti clockwise, which means if the z component is negative then the rotation is clockwise.

Cross Product

Using the cross product via two vectors, a third vector is calculated. There is a single plane that contains both vectors and so the third vector is the normal to that plane or perpendicular to the plane. Since the cross product returns a normal to a plane, it only works in 3D, however, it can work with 2D vectors after they have been converted into 3D vectors by adding a zeroed z component.

The formula for the cross product is simply Vector C = Vector A * Vector B
However, this gets extended to
Vector C = (Vector A.y * Vector B.z - Vector A.z * Vector B.y, Vector A.z * Vector B.x - Vector A.x * Vector B.z, Vector A.x * Vector B.y - Vector A.y * Vector B.x)

This can be hard to remember but there is a mnemonic that reminds you of the order for the subscipts for the x component of the cross product vector, which is "xyzzy". Combine this with the base equation of c = a*b - a*b and you have the first component.

Vector C.x = Vector A.y * Vector B.z - Vector A.z * Vector B.y

You can figure out the y and z components of the cross product vector by rotating the subscripts in the following manner: x -> y -> z -> x

Vector C.y = Vector A.z * Vector B.x - Vector A.x * Vector B.z
Vector C.z = Vector A.x * Vector B.y - Vector A.y * Vector B.x

It should also be noted that the cross product is anti commutatuve, so Vector A * Vector B = -Vector B * Vector A. Another note is that if the cross product returns a vector where all three components have a value of 0 then both input vectors are collinear, which means they lie on the same line. This means a plane cannot be formed and so there is no normal for the cross product to return.

Special Usage
Since a triangle is always on a single plane, we can calculate its normal by coverting two sides of the triange to vectors, then using those vectors and the cross product we can calculate the normal. If we only care about the direction and not the magnitude of the vector then we can normalise the vector afterwards.

Sunday, January 13, 2019

Vector Math

Vector Addition
  • Can be imagined as chaining vectors
  • Vector C points to the position that vector A points to after being displaced by vector B

2D: Vector C = (Vector A.x + Vector B.x, Vector A.y + Vector B.y)
3D: Vector C = (Vector A.x + Vector B.x, Vector A.y + Vector B.y, Vector A.z + Vector B.z)

Vector Subtraction
  • Can be seen as adding a negative vector

2D: Vector C = (Vector A.x - Vector B.x, Vector A.y - Vector B.y)
3D: Vector C = (Vector A.x - Vector B.x, Vector A.y - Vector B.y, Vector A.z - Vector B.z)

Vector Scaling
  • Multiply each component of a vector by a scalar value
  • Scaling only affect the length and not the direction

2D: Vector B = (Vector A.x * i, Vector A.y * i)
3D: Vector B = (Vector A.x * i, Vector A.y * i, Vector A.z * i)

Vector Division
  • Same as vector scaling but you divide each component by a divisor

2D: Vector B = (Vector A.x / i, Vector A.y / i)
3D: Vector B = (Vector A.x / i, Vector A.y / i, Vector A.z / i)

Vector Length
  • Calculates the magnitude of the vector
2D: Length = square root(Vector A.x^2 + Vector A.y^2)
3D: Length = square root (Vector A.x^2 + Vector A.y^2 + Vector A.z^2)

Unit Vector
  • Is any vector with a length of 1
  • Also known as normalisation
  • Can be calculated by dividing each component by the vectors length
2D: Unit Vector = (Vector A.x / ||Vector A||, Vector A.y / ||Vector A||)
3D: Unit Vector = (Vector A.x / ||Vector A||, Vector A.y / ||Vector A||, Vector A.z / ||Vector A||)

Friday, January 11, 2019

Sample Problem: Vector Reflection

Say we have a scenario, where a ball is moving towards a wall, if the ball hits a wall then it will reflect off of it. If the wall is parallel to an axis then this is fairly simple, we just invert the velocity of the ball in the axis perpendicular to the walls axis. For example, if the wall is on the x axis we would invert the velocity of the ball in the y axis. However, its not that simple should the wall not be parallel.

The formula to solve this is: Vi = Vo - 2n(Vo * n)
where Vi is the final velocity after the ball has been reflected, Vo is the initial velocity before the ball has been reflected and n is the normal of the wall that the ball will reflect on. All of which are vectors.

How this formula is derived

At the start of the problem we know two variables, the inital velocity and the normal of the wall, which is a unit vector. If we had a vector that started at the tail of the inital velocity and ended at the head of the final velocity, then we could use vector subtraction to figure out what the final velocity is. The parallel vector that shows the distance the ball will travel from its inital point to the wall is s and we can presume that it will travel the same after the bounce therefore our vector we need for the subtraction is 2s. This means we need to find s.

So currently Vi = 2s - Vo

To find s we would need to extend n so that it would reach the head of the s vector. This can be achieved by using vector projection and inverting the inital velocity to find the distance. Doing so gives us -Vo * n. As n is a unit vector we can multiply n by the scalar distance we just found. This gives us extended n = n *  (-Vo * n). Then by using vector addition we can find s, so s = Vo + n * (-Vo * n).

Now that we have the value of s we can subsitute that value into our original equation and then simplfy.

Vi = 2(Vo + n * (-Vo * n)) - Vo

Vi = 2Vo + 2n * (-Vo * n) - V0

Vi = Vo + 2n * (-Vo * n)

Vi = Vo - 2n * (Vo * n)

Below are diagrams to help explain the process.













Thursday, January 10, 2019

Dot Product

The dot product describes the relation between two vectors with a single number. The single number can mean three possible things about the angle between the two vectors.

  • If the value was 0 then the angle between the two vectors is 90°
  • If the value is positive so greater than 0, then the angle between the two vectors is less than 90°
  • If the value is negative so less than 0, then the angle between the two vectors is greater than 90°
Pseudo code
float DotProduct(Vector2 _vectorA, Vector2 _vectorB)
{
    return _vectorA.x * _vectorB.x + _vectorA.y * _vectorB.y;
}

The dot product can be used for more though as using the dot product with the unit vectors of any two given vectors can result in the actual angle between the two vectors.

  1. First find the unit vector of both given vectors
  2. Calculate the dot product of the two unit vectors
  3. Use arc cosine (dot product) to calculate the angle in radians
  4. Convert angle to degrees if needed

Also the dot product of two vectors that are the same equals the length of the vector squared. This can be used for geometric calculations. Another side note if you have a unit vector and a non unit vector you can perform scalar projects, which returns the length of the extended unit vector (Unit Vector * Non Unit Vector).