OpenGL Mathematics (GLM) library for Python providing comprehensive vector and matrix manipulation capabilities for graphics programming.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Efficient 3D rotation representation using quaternions. Quaternions provide smooth interpolation, avoid gimbal lock, and offer compact storage for rotations in 3D graphics and physics applications.
PyGLM provides quaternion types in different precisions for various performance and accuracy requirements.
class quat:
"""
Single-precision quaternion for 3D rotations.
Components: w (scalar), x, y, z (vector)
"""
w: float # Scalar component
x: float # X vector component
y: float # Y vector component
z: float # Z vector component
def __init__(self): ... # Identity quaternion (0, 0, 0, 1)
def __init__(self, w: float, x: float, y: float, z: float): ... # From components
def __init__(self, v: vec3): ... # From Euler angles
def __init__(self, m: mat3): ... # From rotation matrix
def __init__(self, m: mat4): ... # From transformation matrix
class dquat:
"""
Double-precision quaternion for high-accuracy rotations.
Components: w (scalar), x, y, z (vector)
"""
w: float # Scalar component (double precision)
x: float # X vector component (double precision)
y: float # Y vector component (double precision)
z: float # Z vector component (double precision)
def __init__(self): ... # Identity quaternion
def __init__(self, w: float, x: float, y: float, z: float): ...
def __init__(self, v: vec3): ... # From Euler angles
def __init__(self, m: mat3): ... # From rotation matrix
def __init__(self, m: mat4): ... # From transformation matrixFunctions for creating quaternions from various rotation representations.
def angleAxis(angle, axis):
"""
Create a quaternion from an angle and rotation axis.
Args:
angle: Rotation angle in radians
axis: Rotation axis vector (vec3, should be normalized)
Returns:
Quaternion representing the rotation
Example:
q = glm.angleAxis(glm.radians(45), glm.vec3(0, 1, 0)) # 45° around Y-axis
"""
def quatLookAt(direction, up):
"""
Create a quaternion that rotates to look in a specific direction.
Args:
direction: Direction to look toward (vec3, will be normalized)
up: Up vector (vec3, will be normalized)
Returns:
Quaternion representing the look-at rotation
"""
def euler(angles):
"""
Create a quaternion from Euler angles.
Args:
angles: Euler angles in radians (vec3: pitch, yaw, roll)
Returns:
Quaternion representing the combined rotation
Example:
q = glm.euler(glm.vec3(glm.radians(15), glm.radians(30), glm.radians(45)))
"""Core quaternion mathematics including arithmetic, normalization, and conjugation.
def normalize(q):
"""
Normalize a quaternion to unit length.
Args:
q: Quaternion to normalize
Returns:
Normalized quaternion (unit quaternion)
Note:
Unit quaternions represent pure rotations
"""
def conjugate(q):
"""
Calculate the conjugate of a quaternion.
Args:
q: Input quaternion
Returns:
Conjugate quaternion (negated vector part)
Note:
For unit quaternions, conjugate equals inverse
"""
def inverse(q):
"""
Calculate the inverse of a quaternion.
Args:
q: Input quaternion
Returns:
Inverse quaternion
"""
def length(q):
"""
Calculate the length (magnitude) of a quaternion.
Args:
q: Input quaternion
Returns:
Scalar length of the quaternion
"""
def dot(q1, q2):
"""
Calculate the dot product of two quaternions.
Args:
q1: First quaternion
q2: Second quaternion
Returns:
Scalar dot product
"""Smooth interpolation functions for animation and smooth transitions between rotations.
def slerp(x, y, a):
"""
Spherical linear interpolation between two quaternions.
Args:
x: Start quaternion
y: End quaternion
a: Interpolation factor (0.0 = x, 1.0 = y)
Returns:
Interpolated quaternion with constant angular velocity
Note:
SLERP provides the shortest rotation path between quaternions
"""
def lerp(x, y, a):
"""
Linear interpolation between two quaternions.
Args:
x: Start quaternion
y: End quaternion
a: Interpolation factor (0.0 = x, 1.0 = y)
Returns:
Linearly interpolated quaternion (requires normalization)
Note:
Faster than SLERP but doesn't maintain constant angular velocity
"""
def mix(x, y, a):
"""
Alias for lerp - linear interpolation between quaternions.
Args:
x: Start quaternion
y: End quaternion
a: Interpolation factor
Returns:
Linearly interpolated quaternion
"""Functions for converting between quaternions and rotation matrices.
def mat3_cast(q):
"""
Convert a quaternion to a 3×3 rotation matrix.
Args:
q: Quaternion to convert
Returns:
3×3 rotation matrix equivalent to the quaternion
Example:
rotation_matrix = glm.mat3_cast(quaternion)
"""
def mat4_cast(q):
"""
Convert a quaternion to a 4×4 transformation matrix.
Args:
q: Quaternion to convert
Returns:
4×4 transformation matrix with rotation and identity translation
Example:
transform_matrix = glm.mat4_cast(quaternion)
"""
def quat_cast(m):
"""
Convert a rotation matrix to a quaternion.
Args:
m: 3×3 or 4×4 rotation matrix
Returns:
Quaternion equivalent to the matrix rotation
Example:
quaternion = glm.quat_cast(rotation_matrix)
"""Functions for converting between quaternions and Euler angle representations.
def eulerAngles(q):
"""
Extract Euler angles from a quaternion.
Args:
q: Input quaternion
Returns:
vec3 containing Euler angles in radians (pitch, yaw, roll)
Example:
angles = glm.eulerAngles(quaternion)
pitch = angles.x
yaw = angles.y
roll = angles.z
"""
def pitch(q):
"""
Extract the pitch angle from a quaternion.
Args:
q: Input quaternion
Returns:
Pitch angle in radians (rotation around X-axis)
"""
def yaw(q):
"""
Extract the yaw angle from a quaternion.
Args:
q: Input quaternion
Returns:
Yaw angle in radians (rotation around Y-axis)
"""
def roll(q):
"""
Extract the roll angle from a quaternion.
Args:
q: Input quaternion
Returns:
Roll angle in radians (rotation around Z-axis)
"""
def angle(q):
"""
Extract the rotation angle from a quaternion.
Args:
q: Input quaternion
Returns:
Rotation angle in radians
"""
def axis(q):
"""
Extract the rotation axis from a quaternion.
Args:
q: Input quaternion
Returns:
vec3 representing the normalized rotation axis
"""All quaternion types support standard arithmetic operations through operator overloading:
q1 + q2 - Component-wise additionq1 - q2 - Component-wise subtractionq1 * q2 - Quaternion multiplication (composition of rotations)q * scalar - Scale quaternion components-q - Component-wise negationq1 == q2, q1 != q2 - Component-wise equalityfrom pyglm import glm
import math
# === Basic Quaternion Creation ===
# Identity quaternion (no rotation)
identity_quat = glm.quat()
# From explicit components (w, x, y, z)
explicit_quat = glm.quat(0.707, 0.0, 0.707, 0.0) # 90° around Y-axis
# From angle and axis
angle = glm.radians(45)
axis = glm.vec3(0, 1, 0) # Y-axis
angle_axis_quat = glm.angleAxis(angle, axis)
# From Euler angles (pitch, yaw, roll)
euler_angles = glm.vec3(glm.radians(15), glm.radians(30), glm.radians(45))
euler_quat = glm.euler(euler_angles)
# === Quaternion Operations ===
# Normalize quaternion (essential for rotations)
normalized_quat = glm.normalize(angle_axis_quat)
# Quaternion multiplication (combines rotations)
q1 = glm.angleAxis(glm.radians(30), glm.vec3(1, 0, 0)) # 30° around X
q2 = glm.angleAxis(glm.radians(45), glm.vec3(0, 1, 0)) # 45° around Y
combined_rotation = q2 * q1 # Apply q1 first, then q2
# Conjugate (inverse for unit quaternions)
inverse_rotation = glm.conjugate(normalized_quat)
# === Quaternion Interpolation for Animation ===
# SLERP for smooth rotation animation
start_quat = glm.angleAxis(glm.radians(0), glm.vec3(0, 1, 0))
end_quat = glm.angleAxis(glm.radians(90), glm.vec3(0, 1, 0))
# Animate from 0° to 90° over time
animation_time = 0.5 # 50% through animation
interpolated_quat = glm.slerp(start_quat, end_quat, animation_time)
# === Matrix Conversion ===
# Convert quaternion to rotation matrix
rotation_quat = glm.angleAxis(glm.radians(45), glm.vec3(0, 0, 1))
rotation_matrix_3x3 = glm.mat3_cast(rotation_quat)
rotation_matrix_4x4 = glm.mat4_cast(rotation_quat)
# Convert matrix back to quaternion
recovered_quat = glm.quat_cast(rotation_matrix_3x3)
# === Euler Angle Extraction ===
# Get Euler angles from quaternion
quaternion = glm.angleAxis(glm.radians(45), glm.vec3(1, 1, 0))
euler_angles = glm.eulerAngles(quaternion)
pitch_degrees = glm.degrees(euler_angles.x)
yaw_degrees = glm.degrees(euler_angles.y)
roll_degrees = glm.degrees(euler_angles.z)
# Extract individual components
pitch_rad = glm.pitch(quaternion)
yaw_rad = glm.yaw(quaternion)
roll_rad = glm.roll(quaternion)
# Extract angle and axis
rotation_angle = glm.angle(quaternion)
rotation_axis = glm.axis(quaternion)
# === Practical 3D Graphics Example ===
# Create a first-person camera rotation system
class FirstPersonCamera:
def __init__(self):
self.orientation = glm.quat() # Identity quaternion
self.sensitivity = 0.002 # Mouse sensitivity
def rotate(self, mouse_delta_x, mouse_delta_y):
# Yaw rotation (around world Y-axis)
yaw_rotation = glm.angleAxis(-mouse_delta_x * self.sensitivity, glm.vec3(0, 1, 0))
# Pitch rotation (around local X-axis)
pitch_rotation = glm.angleAxis(-mouse_delta_y * self.sensitivity, glm.vec3(1, 0, 0))
# Apply rotations: pitch first (local), then yaw (world)
self.orientation = yaw_rotation * self.orientation * pitch_rotation
self.orientation = glm.normalize(self.orientation)
def get_view_matrix(self, position):
# Convert quaternion to rotation matrix
rotation_matrix = glm.mat4_cast(glm.conjugate(self.orientation))
# Apply translation
view_matrix = glm.translate(rotation_matrix, -position)
return view_matrix
# Usage
camera = FirstPersonCamera()
camera.rotate(0.1, 0.05) # Simulate mouse movement
view_matrix = camera.get_view_matrix(glm.vec3(0, 2, 5))
# === Character Animation Example ===
# Smooth rotation between two orientations
old_facing = glm.angleAxis(glm.radians(0), glm.vec3(0, 1, 0)) # North
new_facing = glm.angleAxis(glm.radians(90), glm.vec3(0, 1, 0)) # East
# Smoothly rotate character over 2 seconds
animation_duration = 2.0
current_time = 0.75 # 0.75 seconds into animation
t = current_time / animation_duration
current_facing = glm.slerp(old_facing, new_facing, t)
character_transform = glm.mat4_cast(current_facing)
# === Look-At Quaternion ===
target_position = glm.vec3(10, 0, 0)
current_position = glm.vec3(0, 0, 0)
up_vector = glm.vec3(0, 1, 0)
look_direction = glm.normalize(target_position - current_position)
look_at_quat = glm.quatLookAt(look_direction, up_vector)
look_at_matrix = glm.mat4_cast(look_at_quat)Install with Tessl CLI
npx tessl i tessl/pypi-pyglm