Cross-platform windowing and multimedia library for Python with OpenGL graphics, event handling, and audio/video playback
Vector and matrix operations for 2D/3D graphics and transformations.
from pyglet.math import Vec2, Vec3, Vec4, Mat3, Mat4, Quaternion
# Vectors (immutable)
v = Vec3(1, 2, 3)
length = v.mag
normalized = v.normalize()
dot = v1.dot(v2)
cross = v1.cross(v2) # Vec3 only
# Matrices
mat = Mat4() # Identity
mat = Mat4.from_translation(Vec3(10, 20, 0))
mat = Mat4.from_rotation(45, Vec3(0, 0, 1))
mat = Mat4.from_scale(Vec3(2, 2, 2))
# Projection
proj = Mat4.perspective_projection(aspect=16/9, z_near=0.1, z_far=100, fov=60)
view = Mat4.look_at(position=Vec3(0,0,10), target=Vec3(0,0,0), up=Vec3(0,1,0))
# Quaternions
q = Quaternion.from_axis_angle(Vec3(0, 1, 0), 45)class pyglet.math.Vec2:
"""2D vector (immutable)"""
__init__(x=0, y=0)
x, y: float
# Properties
mag: float # Length
heading: float # Angle in radians
# Methods
def dot(other: Vec2) -> float
def normalize() -> Vec2
def clamp(min_val, max_val) -> Vec2
def lerp(other: Vec2, alpha: float) -> Vec2
def distance(other: Vec2) -> float
def from_polar(mag, angle) -> Vec2 # Class method
# Operators
# +, -, *, /, //, %, abs(), -vecclass pyglet.math.Vec3:
"""3D vector (immutable)"""
__init__(x=0, y=0, z=0)
x, y, z: float
# Properties
mag: float
# Methods
def dot(other: Vec3) -> float
def cross(other: Vec3) -> Vec3
def normalize() -> Vec3
def clamp(min_val, max_val) -> Vec3
def lerp(other: Vec3, alpha: float) -> Vec3
def distance(other: Vec3) -> float
# Operators
# +, -, *, /, //, %, abs(), -vecclass pyglet.math.Vec4:
"""4D vector (immutable)"""
__init__(x=0, y=0, z=0, w=0)
x, y, z, w: float
mag: float
# Methods
def dot(other: Vec4) -> float
def normalize() -> Vec4
def clamp(min_val, max_val) -> Vec4
def lerp(other: Vec4, alpha: float) -> Vec4
def distance(other: Vec4) -> floatclass pyglet.math.Mat3:
"""3x3 matrix (immutable, column-major)"""
__init__() # Identity
# Class methods (create matrices)
@classmethod
def from_rotation(angle: float) -> Mat3
@classmethod
def from_scale(scale: Vec2) -> Mat3
@classmethod
def from_translation(vec: Vec2) -> Mat3
# Instance methods
def __matmul__(other: Mat3 | Vec2) -> Mat3 | Vec2 # Matrix/vector multiply
def __invert__() -> Mat3 # Inverse
def transpose() -> Mat3class pyglet.math.Mat4:
"""4x4 matrix (immutable, column-major)"""
__init__() # Identity
# Transform creation
@classmethod
def from_translation(vec: Vec3) -> Mat4
@classmethod
def from_rotation(angle: float, axis: Vec3) -> Mat4
@classmethod
def from_scale(vec: Vec3) -> Mat4
# View matrices
@classmethod
def look_at(position: Vec3, target: Vec3, up: Vec3) -> Mat4
@classmethod
def look_at_direction(position: Vec3, direction: Vec3, up: Vec3) -> Mat4
# Projection matrices
@classmethod
def perspective_projection(aspect: float, z_near: float, z_far: float, fov: float = 60) -> Mat4
@classmethod
def orthogonal_projection(left: float, right: float, bottom: float, top: float,
z_near: float, z_far: float) -> Mat4
# Instance methods
def __matmul__(other: Mat4 | Vec4) -> Mat4 | Vec4 # Matrix/vector multiply
def __invert__() -> Mat4
def transpose() -> Mat4
# Utility
def __getitem__(index) -> tuple # Get column
def __iter__() # Iterate columnsclass pyglet.math.Quaternion:
"""Quaternion for rotations (immutable)"""
__init__(w=1, x=0, y=0, z=0)
w, x, y, z: float
# Creation
@classmethod
def from_axis_angle(axis: Vec3, angle: float) -> Quaternion
@classmethod
def from_euler(heading: float, attitude: float, bank: float) -> Quaternion
# Methods
def conjugate() -> Quaternion
def dot(other: Quaternion) -> float
def normalize() -> Quaternion
def slerp(other: Quaternion, alpha: float) -> Quaternion
# Conversion
def as_matrix() -> Mat4
# Operators
def __matmul__(other: Quaternion | Vec3) -> Quaternion | Vec3# Rotate point around origin
angle = math.radians(45)
rotation_mat = Mat3.from_rotation(angle)
point = Vec2(10, 0)
rotated = rotation_mat @ point # @ is matrix multiply# Combine transformations
translation = Mat4.from_translation(Vec3(10, 5, 0))
rotation = Mat4.from_rotation(45, Vec3(0, 0, 1))
scale = Mat4.from_scale(Vec3(2, 2, 2))
# Order: scale, then rotate, then translate
transform = translation @ rotation @ scale
# Apply to vertex
vertex = Vec4(1, 0, 0, 1)
transformed = transform @ vertex# Projection matrix
aspect_ratio = window.width / window.height
proj = Mat4.perspective_projection(aspect=aspect_ratio, z_near=0.1, z_far=100, fov=60)
# View matrix
camera_pos = Vec3(0, 5, 10)
look_at = Vec3(0, 0, 0)
up = Vec3(0, 1, 0)
view = Mat4.look_at(camera_pos, look_at, up)
# Pass to shader
shader['projection'] = proj
shader['view'] = view# Distance
dist = pos1.distance(pos2)
# Normalize
direction = (target_pos - current_pos).normalize()
# Lerp (interpolation)
new_pos = current_pos.lerp(target_pos, alpha=0.1) # Move 10% toward target
# Dot product (for angle check)
dot = forward.dot(to_target)
if dot > 0:
print("Target is in front")# Create rotation
axis = Vec3(0, 1, 0) # Y-axis
angle = math.radians(45)
quat = Quaternion.from_axis_angle(axis, angle)
# Apply to vector
v = Vec3(1, 0, 0)
rotated = quat @ v
# Interpolate rotations
q1 = Quaternion.from_axis_angle(Vec3(0,1,0), 0)
q2 = Quaternion.from_axis_angle(Vec3(0,1,0), math.radians(90))
interpolated = q1.slerp(q2, 0.5) # Halfway rotationclass OrbitCamera:
def __init__(self):
self.distance = 10
self.angle = 0
self.target = Vec3(0, 0, 0)
def update(self, angle_delta):
self.angle += angle_delta
x = self.distance * math.cos(self.angle)
z = self.distance * math.sin(self.angle)
position = Vec3(x, 5, z)
return Mat4.look_at(position, self.target, Vec3(0, 1, 0))velocity = Vec2(0, 0)
position = Vec2(100, 100)
acceleration = 500 # pixels/sec^2
max_speed = 200 # pixels/sec
def update(dt):
global velocity, position
# Apply input
if keys[key.LEFT]:
velocity -= Vec2(acceleration * dt, 0)
if keys[key.RIGHT]:
velocity += Vec2(acceleration * dt, 0)
# Clamp speed
if velocity.mag > max_speed:
velocity = velocity.normalize() * max_speed
# Update position
position += velocity * dt
# Apply friction
velocity *= 0.95Install with Tessl CLI
npx tessl i tessl/pypi-pyglet