20th December 2024 -
22nd January 2025
PGABLE extension for MATLAB
C++
Git
Github
CMake
At DAE, I was one of the first students in the world that had the opportunity to be taught
Plane-based Projective Geometric Algebra (PPGA). Using translations and rotations in PPGA, we had to create a small game to show our understanding of the topic. 'In Plane Sight' was born.
If you're interested in PPGA, bivector.net is a great source.
In PPGA you start with four basis element, four planes.
e1, e2, e3 and e0 which is called 'the vanishing plane'. Think of it as the sky: it's all around you, but when you look at it, it looks like a plane because it's infinitely far away. These four planes create 10 more basis elements as you can see on the left. With the additional scalar and I4 (same as e0123 a.k.a. the entirety of space) elements you have 16 basis elements that are fundamental to start using PPGA.
It is important to note that every element is oriented, even points.
Scalar: 1
Planes: e1, e2, e3
Vanishing Plane: e0
Lines: e23, e31, e12
Vanishing Lines: e01, e02, e03
Point (Origin): e123
Vanishing Points: e013, e021, e032
Pseudo-Scalar: I4 or e0123
! The Images use 2D. If I talk about planes, they are represented as lines on the images. !
Every transformation is actually a result from reflecting the object over multiple planes. Yes, you can also reflect over lines and points.
A point-reflection is namely a reflection over 3 planes.
You can define a reflection by applying the 'sandwich operation' on a specific object:
x' = -p * x * inverse(p)
A multiplication between geometric objects is called the 'geometric product':
m*n = m.n + m^n
(dot product + wedge product)
In case of 2 parallel planes, we can translate our object. We use the same approach as with rotations: x' = M * x * inverse(M)
Two reflections reserve the orientation of the object, just positioned somewhere else.
The actual distance by which the object translates is equal to the distance between the two planes multiplied by 2.
By reviewing the internal formula, you can create an alternative translation Motor:
M = 1 - 0.5 * p * (-e0)
This means that you can specify the translate distance for a Motor! A plane's components can be multiplied by a scalar, similar to a vector. By normalizing the plane 'p', you can specify your distance:
M = 1 - 0.5 * (p * (-e0))
M = 1 - 0.5 * vLine
M = 1 - 0.5 * |vLine| * (vLine/|vLine|)
M = 1 - 0.5 * |p| * (vLine/|vLine|)
M = 1 - 0.5 * Distance * (vLine/|vLine|)
Notice that the distance gets halfed by the formula. This is exactly what we want, since the distance between the Motor's two planes is always half of the translation distance.
Fun fact:
Intersecting parallel planes results in the vanishing line at infinity!
The cool thing about a translation in PPGA, is that it is equivalent to a rotation around the vanishing line made from the 2 reflection planes.
We can rotate by reflecting our object over 2 non-parallel planes.
The fact that we need to reflect 2 times, means we need to apply a sandwich operation on a sandwich operation:
x' = -p2 * (-p1 * x * inverse(p1)) * inverse(p2)
Following the rules of PPGA, we can simplify this to:
x' = (p2*p1) * x * inverse(p2*p1)
This product (p2*p1), can be called a 'Motor' M or in this case more specifically a 'Rotor'.
x' = M * x * inverse(M)
In PPGA, you can get the perpendicular distance from a point to a plane by 'joining' (V operator) them.
By creating a box that owns four planes for the walls, you can check the distance towards those planes. If the distance is smaller than 0, the point is on the other side of the plane and thus outside the box.
To translate the correct amount into the correct direction, you can create the translation vanishing line: (-e0) ^ boxWall
By providing the translation distance, the translation Motor can be created to translate the object.
When you want your player to move in all directions, normalizing the direction in linear algebra can get lengthy for such a small requirement.
In PPGA however, you can specify the direction first, determined by the pressed keys in this example. The direction is just a vanishing line, no length or size exists. Afterwards, you translate with the needed speed along the vanishing line. No need to calculate the correct speed based on the direction!
Bonus: if you press 2 opposite keys, the direction gets cancelled out by PPGA itself!
In the game, there are four different Units to place around the level. The Teleport Unit just applies a point-reflection on the projectile when it's inside the box.
The black holes slowly apply a downwards translation. The Booster Unit boosts the projectile over the black holes.
The Phase Unit phases the projectiles through fences
The Rotator Unit rotates the projectile around the center line (goes into the screen). The area in which the projectiles can rotate are blocked off with 2 planes. To check whether the projectiles are in the area, I use the same aproach as with the collision box; join the point with the plane.
If a projectile is rotating while the Unit gets picked up, it needs to know what the current direction was. By joining the center line with the projectile, you get a plane that connects that line and point. Intersect the plane with the vanishing plane (-e0) and you got your vanishing direction line.
vLine = (-e0) ^ (Line V Point)