or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

3d-models.mdapp-clock.mdaudio-video.mdgraphics-rendering.mdgui.mdimages-textures.mdindex.mdinput-devices.mdmath.mdopengl.mdresource-management.mdsprites-shapes.mdtext-rendering.mdwindowing.md
IMPROVEMENTS.md

math.mddocs/

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