CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyglet

Cross-platform windowing and multimedia library for Python with OpenGL graphics, event handling, and audio/video playback

Overview
Eval results
Files

math.mddocs/

Vector and Matrix Math

Vector and matrix operations for 2D/3D graphics and transformations.

Quick Reference

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)

Vec2

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(), -vec

Vec3

class 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(), -vec

Vec4

class 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) -> float

Mat3

class 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() -> Mat3

Mat4

class 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 columns

Quaternion

class 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

Examples

2D Rotation

# 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

3D Transform Combination

# 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

Camera Setup

# 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

Vector Operations

# 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")

Quaternion Rotation

# 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 rotation

Performance Tips

  1. Vectors/matrices are immutable: Operations create new objects
  2. Reuse matrices: Cache frequently used transforms
  3. Matrix order matters: Read right-to-left (TRS = translate @ rotate @ scale)
  4. Use quaternions for rotations: Avoid gimbal lock, smooth interpolation
  5. Normalize sparingly: Only when needed, has performance cost

Common Patterns

Orbit Camera

class 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-Based Movement

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.95

Install with Tessl CLI

npx tessl i tessl/pypi-pyglet

docs

3d-models.md

app-clock.md

audio-video.md

graphics-rendering.md

gui.md

images-textures.md

index.md

input-devices.md

math.md

opengl.md

resource-management.md

sprites-shapes.md

text-rendering.md

windowing.md

tile.json