0
# Vector and Matrix Math
1
2
Vector and matrix operations for 2D/3D graphics and transformations.
3
4
## Quick Reference
5
6
```python
7
from pyglet.math import Vec2, Vec3, Vec4, Mat3, Mat4, Quaternion
8
9
# Vectors (immutable)
10
v = Vec3(1, 2, 3)
11
length = v.mag
12
normalized = v.normalize()
13
dot = v1.dot(v2)
14
cross = v1.cross(v2) # Vec3 only
15
16
# Matrices
17
mat = Mat4() # Identity
18
mat = Mat4.from_translation(Vec3(10, 20, 0))
19
mat = Mat4.from_rotation(45, Vec3(0, 0, 1))
20
mat = Mat4.from_scale(Vec3(2, 2, 2))
21
22
# Projection
23
proj = Mat4.perspective_projection(aspect=16/9, z_near=0.1, z_far=100, fov=60)
24
view = Mat4.look_at(position=Vec3(0,0,10), target=Vec3(0,0,0), up=Vec3(0,1,0))
25
26
# Quaternions
27
q = Quaternion.from_axis_angle(Vec3(0, 1, 0), 45)
28
```
29
30
## Vec2
31
32
```python
33
class pyglet.math.Vec2:
34
"""2D vector (immutable)"""
35
__init__(x=0, y=0)
36
37
x, y: float
38
39
# Properties
40
mag: float # Length
41
heading: float # Angle in radians
42
43
# Methods
44
def dot(other: Vec2) -> float
45
def normalize() -> Vec2
46
def clamp(min_val, max_val) -> Vec2
47
def lerp(other: Vec2, alpha: float) -> Vec2
48
def distance(other: Vec2) -> float
49
def from_polar(mag, angle) -> Vec2 # Class method
50
51
# Operators
52
# +, -, *, /, //, %, abs(), -vec
53
```
54
55
## Vec3
56
57
```python
58
class pyglet.math.Vec3:
59
"""3D vector (immutable)"""
60
__init__(x=0, y=0, z=0)
61
62
x, y, z: float
63
64
# Properties
65
mag: float
66
67
# Methods
68
def dot(other: Vec3) -> float
69
def cross(other: Vec3) -> Vec3
70
def normalize() -> Vec3
71
def clamp(min_val, max_val) -> Vec3
72
def lerp(other: Vec3, alpha: float) -> Vec3
73
def distance(other: Vec3) -> float
74
75
# Operators
76
# +, -, *, /, //, %, abs(), -vec
77
```
78
79
## Vec4
80
81
```python
82
class pyglet.math.Vec4:
83
"""4D vector (immutable)"""
84
__init__(x=0, y=0, z=0, w=0)
85
86
x, y, z, w: float
87
mag: float
88
89
# Methods
90
def dot(other: Vec4) -> float
91
def normalize() -> Vec4
92
def clamp(min_val, max_val) -> Vec4
93
def lerp(other: Vec4, alpha: float) -> Vec4
94
def distance(other: Vec4) -> float
95
```
96
97
## Mat3
98
99
```python
100
class pyglet.math.Mat3:
101
"""3x3 matrix (immutable, column-major)"""
102
__init__() # Identity
103
104
# Class methods (create matrices)
105
@classmethod
106
def from_rotation(angle: float) -> Mat3
107
@classmethod
108
def from_scale(scale: Vec2) -> Mat3
109
@classmethod
110
def from_translation(vec: Vec2) -> Mat3
111
112
# Instance methods
113
def __matmul__(other: Mat3 | Vec2) -> Mat3 | Vec2 # Matrix/vector multiply
114
def __invert__() -> Mat3 # Inverse
115
def transpose() -> Mat3
116
```
117
118
## Mat4
119
120
```python
121
class pyglet.math.Mat4:
122
"""4x4 matrix (immutable, column-major)"""
123
__init__() # Identity
124
125
# Transform creation
126
@classmethod
127
def from_translation(vec: Vec3) -> Mat4
128
@classmethod
129
def from_rotation(angle: float, axis: Vec3) -> Mat4
130
@classmethod
131
def from_scale(vec: Vec3) -> Mat4
132
133
# View matrices
134
@classmethod
135
def look_at(position: Vec3, target: Vec3, up: Vec3) -> Mat4
136
@classmethod
137
def look_at_direction(position: Vec3, direction: Vec3, up: Vec3) -> Mat4
138
139
# Projection matrices
140
@classmethod
141
def perspective_projection(aspect: float, z_near: float, z_far: float, fov: float = 60) -> Mat4
142
@classmethod
143
def orthogonal_projection(left: float, right: float, bottom: float, top: float,
144
z_near: float, z_far: float) -> Mat4
145
146
# Instance methods
147
def __matmul__(other: Mat4 | Vec4) -> Mat4 | Vec4 # Matrix/vector multiply
148
def __invert__() -> Mat4
149
def transpose() -> Mat4
150
151
# Utility
152
def __getitem__(index) -> tuple # Get column
153
def __iter__() # Iterate columns
154
```
155
156
## Quaternion
157
158
```python
159
class pyglet.math.Quaternion:
160
"""Quaternion for rotations (immutable)"""
161
__init__(w=1, x=0, y=0, z=0)
162
163
w, x, y, z: float
164
165
# Creation
166
@classmethod
167
def from_axis_angle(axis: Vec3, angle: float) -> Quaternion
168
@classmethod
169
def from_euler(heading: float, attitude: float, bank: float) -> Quaternion
170
171
# Methods
172
def conjugate() -> Quaternion
173
def dot(other: Quaternion) -> float
174
def normalize() -> Quaternion
175
def slerp(other: Quaternion, alpha: float) -> Quaternion
176
177
# Conversion
178
def as_matrix() -> Mat4
179
180
# Operators
181
def __matmul__(other: Quaternion | Vec3) -> Quaternion | Vec3
182
```
183
184
## Examples
185
186
### 2D Rotation
187
```python
188
# Rotate point around origin
189
angle = math.radians(45)
190
rotation_mat = Mat3.from_rotation(angle)
191
point = Vec2(10, 0)
192
rotated = rotation_mat @ point # @ is matrix multiply
193
```
194
195
### 3D Transform Combination
196
```python
197
# Combine transformations
198
translation = Mat4.from_translation(Vec3(10, 5, 0))
199
rotation = Mat4.from_rotation(45, Vec3(0, 0, 1))
200
scale = Mat4.from_scale(Vec3(2, 2, 2))
201
202
# Order: scale, then rotate, then translate
203
transform = translation @ rotation @ scale
204
205
# Apply to vertex
206
vertex = Vec4(1, 0, 0, 1)
207
transformed = transform @ vertex
208
```
209
210
### Camera Setup
211
```python
212
# Projection matrix
213
aspect_ratio = window.width / window.height
214
proj = Mat4.perspective_projection(aspect=aspect_ratio, z_near=0.1, z_far=100, fov=60)
215
216
# View matrix
217
camera_pos = Vec3(0, 5, 10)
218
look_at = Vec3(0, 0, 0)
219
up = Vec3(0, 1, 0)
220
view = Mat4.look_at(camera_pos, look_at, up)
221
222
# Pass to shader
223
shader['projection'] = proj
224
shader['view'] = view
225
```
226
227
### Vector Operations
228
```python
229
# Distance
230
dist = pos1.distance(pos2)
231
232
# Normalize
233
direction = (target_pos - current_pos).normalize()
234
235
# Lerp (interpolation)
236
new_pos = current_pos.lerp(target_pos, alpha=0.1) # Move 10% toward target
237
238
# Dot product (for angle check)
239
dot = forward.dot(to_target)
240
if dot > 0:
241
print("Target is in front")
242
```
243
244
### Quaternion Rotation
245
```python
246
# Create rotation
247
axis = Vec3(0, 1, 0) # Y-axis
248
angle = math.radians(45)
249
quat = Quaternion.from_axis_angle(axis, angle)
250
251
# Apply to vector
252
v = Vec3(1, 0, 0)
253
rotated = quat @ v
254
255
# Interpolate rotations
256
q1 = Quaternion.from_axis_angle(Vec3(0,1,0), 0)
257
q2 = Quaternion.from_axis_angle(Vec3(0,1,0), math.radians(90))
258
interpolated = q1.slerp(q2, 0.5) # Halfway rotation
259
```
260
261
## Performance Tips
262
263
1. **Vectors/matrices are immutable**: Operations create new objects
264
2. **Reuse matrices**: Cache frequently used transforms
265
3. **Matrix order matters**: Read right-to-left (TRS = translate @ rotate @ scale)
266
4. **Use quaternions for rotations**: Avoid gimbal lock, smooth interpolation
267
5. **Normalize sparingly**: Only when needed, has performance cost
268
269
## Common Patterns
270
271
### Orbit Camera
272
```python
273
class OrbitCamera:
274
def __init__(self):
275
self.distance = 10
276
self.angle = 0
277
self.target = Vec3(0, 0, 0)
278
279
def update(self, angle_delta):
280
self.angle += angle_delta
281
x = self.distance * math.cos(self.angle)
282
z = self.distance * math.sin(self.angle)
283
position = Vec3(x, 5, z)
284
return Mat4.look_at(position, self.target, Vec3(0, 1, 0))
285
```
286
287
### Velocity-Based Movement
288
```python
289
velocity = Vec2(0, 0)
290
position = Vec2(100, 100)
291
acceleration = 500 # pixels/sec^2
292
max_speed = 200 # pixels/sec
293
294
def update(dt):
295
global velocity, position
296
297
# Apply input
298
if keys[key.LEFT]:
299
velocity -= Vec2(acceleration * dt, 0)
300
if keys[key.RIGHT]:
301
velocity += Vec2(acceleration * dt, 0)
302
303
# Clamp speed
304
if velocity.mag > max_speed:
305
velocity = velocity.normalize() * max_speed
306
307
# Update position
308
position += velocity * dt
309
310
# Apply friction
311
velocity *= 0.95
312
```
313