Matrix and Vector Math
Modern OpenGL depends on matrixes for projection, translation, and other things. To
provide out-of-the-box functionality, pyglet’s math
module includes
the necessary Matrix and Vector types to cover common use cases. Provided types are:
Vec2
, Vec3
, Vec4
,
Mat3
, and Mat4
.
See the math
API documentation for a full list of methods and operations
that these objects support.
Note
Matrix and Vector types are tuple
subclasses. They are therefore
immutable - all operations return a new object; they are not updated in-place.
Creating a Matrix
A Matrix can be created with no arguments, or by passing the initial values:
my_matrix = Mat4()
# or
my_matrix = Mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0)
If no arguments are given on creation, an “identity” matrix will be created by default. (1.0 on the main diagonal, as shown here).
More conveniently, you can also create matrixes from one of their helper class methods.
Matrix Helper Methods
When working with 3D graphics in OpenGL, A common operation is setting a perspective
projection matrix. The Mat4
class includes a helper method for this task. The arguments
are similar to what you will find in popular OpenGL math libraries:
# Perspective (3D) projection matrix:
projection = Mat4.perspective_projection(aspect_ratio, z_near=0.1, z_far=255, fov=60)
For setting a projection matrix on the current OpenGL context, pyglet Windows have
a projection
property. This points to a projection matrix used by all of pyglet’s
built-in classes, and can be set as follows:
my_matrix = Mat4.perspective_projection(aspect_ratio, z_near=0.1, z_far=255)
window.projection = my_matrix
For working with 2D graphics, a helper method also exists for creating orthogonal projection matrixes, which is created and set in a similar way:
# Orthographic (2D) projection matrix:
my_matrix = Mat4.orthogonal_projection(0, width, 0, height, z_near=-255, z_far=255)
window.projection = my_matrix
By default, pyglet is already set up with an orthographic projection matrix. It automatically
updates this 2D matrix whenever a Window is created or resized. This is done inside of the
Window’s on_resize
event handler. If you plan to set your own 3D or 2D projection matrix,
a useful pattern is to override the default on_resize
event handler with your own:
@window.event
def on_resize(width, height):
# window.viewport = (0, 0, width, height)
window.projection = Mat4.perspective_projection(window.aspect_ratio, z_near=0.1, z_far=255)
return pyglet.event.EVENT_HANDLED # Don't call the default handler
In addition to the projection
property, pyglet Windows also contain a view
property that
points to another matrix that is used internally by pyglet’s built-in classes. The view matrix
gets multiplied with the projection matrix, controlling the final positioning and rendering of
pyglet’s built-in objects like Sprites, Shapes, and text. Unlike the projection matrix the view
matrix defaults to an indentity matrix, and therefore has no effect initially. This makes it useful
for users to set their own matrix on it, and controll zooming or translating (panning) a “camera”.
The Mat4
class contains helper methods for creating these types of matrixes:
# translate the camera +100 on the X axis:
view_matrix = Mat4.from_translation(vector=Vec3(x=100, y=0, z=0))
# or scale by 2X (be careful of the Z values):
view_matrix = Mat4.from_scale(vector=Vec3(x=2.0, y=2.0, z=1.0))
window.view = view_matrix
You can of course create multiple matrixes and multiply them together, such as to zoom and then translate, or translate and then zoom, etc. Be careful of multiplication order, as matrix multiplication is non-commutative.
See the math
API documentation for a full list of helper class methods.
Matrix Multiplication
Matrix classes in pyglet use the Python matmul
(@
) operator for matrix multiplication.
The star
operator (*
) is not allowed, and will raise an exception. For example:
new_matrix = rotation_matrix @ translation_matrix
Creating Vectors
pyglet includes classes for 2D, 3D, and 4D vectors: Vec2
,
Vec3
and Vec4
. These Vec types support
most mathematical operations, and implement helper methods for most common vector operations.
Vecs are created with their values.
myvec2 = Vec2() # same as Vec(x=0.0, y=0.0) myvec2 = Vec2(-4.5, 3.0) myvec3 = Vec3(100.0, 400.0, 1.0)
Vector Operations
TBD