• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / vector_math.dart / 17181727464

04 Aug 2025 07:19PM UTC coverage: 26.702% (+0.3%) from 26.388%
17181727464

push

github

web-flow
Bump min SDK to 3.7, update dependencies, reformat (#348)

496 of 1182 new or added lines in 55 files covered. (41.96%)

18 existing lines in 8 files now uncovered.

4463 of 16714 relevant lines covered (26.7%)

1.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.77
/lib/src/vector_math/opengl.dart
1
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
2
// All rights reserved. Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
part of '../../vector_math.dart';
6

7
/// Constructs a rotation matrix in [rotationMatrix].
8
///
9
/// Sets [rotationMatrix] to a rotation matrix built from
10
/// [forwardDirection] and [upDirection]. The right direction is
11
/// constructed to be orthogonal to [forwardDirection] and
12
/// [upDirection].
13
///
14
/// [forwardDirection] specifies the direction of the forward vector.
15
/// [upDirection] specifies the direction of the up vector.
16
///
17
/// Use case is to build the per-model rotation matrix from vectors
18
/// [forwardDirection] and [upDirection]. See sample code below for
19
/// a context.
20
///
21
///     class Model {
22
///       Vector3 _center = new Vector3.zero();        // per-model translation
23
///       Vector3 _scale = new Vector3(1.0, 1.0, 1.0); // per-model scaling
24
///       Matrix4 _rotation = new Matrix4.identity();  // per-model rotation
25
///       Matrix4 _MV = new Matrix4.identity();        // per-model model-view
26
///
27
///       void updateModelViewUniform(RenderingContext gl, UniformLocation u_MV,
28
///         Vector3 camPosition, camFocusPosition, camUpDirection) {
29
///
30
///         // V = View (inverse of camera)
31
///         // T = Translation
32
///         // R = Rotation
33
///         // S = Scaling
34
///         setViewMatrix(_MV, camPosition, camFocusPosition, camUpDirection); // MV = V
35
///         _MV.translate(_center); // MV = V*T
36
///         _MV.multiply(_rotation); // MV = V*T*R
37
///         // _rotation is updated with setRotationMatrix(_rotation, forward, up);
38
///         _MV.scale(_scale); // MV = V*T*R*S
39
///
40
///         gl.uniformMatrix4fv(u_MV, false, _MV.storage);
41
///       }
42
///     }
43
void setRotationMatrix(
×
44
  Matrix4 rotationMatrix,
45
  Vector3 forwardDirection,
46
  Vector3 upDirection,
47
) {
UNCOV
48
  setModelMatrix(rotationMatrix, forwardDirection, upDirection, 0.0, 0.0, 0.0);
×
49
}
50

51
/// Constructs an OpenGL model matrix in [modelMatrix].
52
/// Model transformation is the inverse of the view transformation.
53
/// Model transformation is also known as "camera" transformation.
54
/// Model matrix is commonly used to compute a object location/orientation into
55
/// the full model-view stack.
56
///
57
/// [forwardDirection] specifies the direction of the forward vector.
58
/// [upDirection] specifies the direction of the up vector.
59
/// [tx],[ty],[tz] specifies the position of the object.
60
void setModelMatrix(
1✔
61
  Matrix4 modelMatrix,
62
  Vector3 forwardDirection,
63
  Vector3 upDirection,
64
  double tx,
65
  double ty,
66
  double tz,
67
) {
68
  final right = forwardDirection.cross(upDirection)..normalize();
2✔
69
  final c1 = right;
70
  final c2 = upDirection;
71
  final c3 = -forwardDirection;
1✔
72
  modelMatrix.setValues(
1✔
73
    c1[0],
1✔
74
    c1[1],
1✔
75
    c1[2],
1✔
76
    0.0,
77
    c2[0],
1✔
78
    c2[1],
1✔
79
    c2[2],
1✔
80
    0.0,
81
    c3[0],
1✔
82
    c3[1],
1✔
83
    c3[2],
1✔
84
    0.0,
85
    tx,
86
    ty,
87
    tz,
88
    1.0,
89
  );
90
}
91

92
/// Constructs an OpenGL view matrix in [viewMatrix].
93
/// View transformation is the inverse of the model transformation.
94
/// View matrix is commonly used to compute the camera location/orientation into
95
/// the full model-view stack.
96
///
97
/// [cameraPosition] specifies the position of the camera.
98
/// [cameraFocusPosition] specifies the position the camera is focused on.
99
/// [upDirection] specifies the direction of the up vector (usually, +Y).
100
void setViewMatrix(
1✔
101
  Matrix4 viewMatrix,
102
  Vector3 cameraPosition,
103
  Vector3 cameraFocusPosition,
104
  Vector3 upDirection,
105
) {
106
  final z = (cameraPosition - cameraFocusPosition)..normalize();
2✔
107
  final x = upDirection.cross(z)..normalize();
2✔
108
  final y = z.cross(x)..normalize();
2✔
109

110
  final rotatedEyeX = -x.dot(cameraPosition);
2✔
111
  final rotatedEyeY = -y.dot(cameraPosition);
2✔
112
  final rotatedEyeZ = -z.dot(cameraPosition);
2✔
113

114
  viewMatrix.setValues(
1✔
115
    x[0],
1✔
116
    y[0],
1✔
117
    z[0],
1✔
118
    0.0,
119
    x[1],
1✔
120
    y[1],
1✔
121
    z[1],
1✔
122
    0.0,
123
    x[2],
1✔
124
    y[2],
1✔
125
    z[2],
1✔
126
    0.0,
127
    rotatedEyeX,
128
    rotatedEyeY,
129
    rotatedEyeZ,
130
    1.0,
131
  );
132
}
133

134
/// Constructs a new OpenGL view matrix.
135
///
136
/// [cameraPosition] specifies the position of the camera.
137
/// [cameraFocusPosition] specifies the position the camera is focused on.
138
/// [upDirection] specifies the direction of the up vector (usually, +Y).
139
Matrix4 makeViewMatrix(
1✔
140
  Vector3 cameraPosition,
141
  Vector3 cameraFocusPosition,
142
  Vector3 upDirection,
143
) {
144
  final r = Matrix4.zero();
1✔
145
  setViewMatrix(r, cameraPosition, cameraFocusPosition, upDirection);
1✔
146
  return r;
147
}
148

149
/// Constructs an OpenGL perspective projection matrix in [perspectiveMatrix].
150
///
151
/// [fovYRadians] specifies the field of view angle, in radians, in the y
152
/// direction.
153
/// [aspectRatio] specifies the aspect ratio that determines the field of view
154
/// in the x direction. The aspect ratio of x (width) to y (height).
155
/// [zNear] specifies the distance from the viewer to the near plane
156
/// (always positive).
157
/// [zFar] specifies the distance from the viewer to the far plane
158
/// (always positive).
159
void setPerspectiveMatrix(
2✔
160
  Matrix4 perspectiveMatrix,
161
  double fovYRadians,
162
  double aspectRatio,
163
  double zNear,
164
  double zFar,
165
) {
166
  final height = math.tan(fovYRadians * 0.5);
4✔
167
  final width = height * aspectRatio;
2✔
168
  final near_minus_far = zNear - zFar;
2✔
169

170
  perspectiveMatrix
171
    ..setZero()
2✔
172
    ..setEntry(0, 0, 1.0 / width)
4✔
173
    ..setEntry(1, 1, 1.0 / height)
4✔
174
    ..setEntry(2, 2, (zFar + zNear) / near_minus_far)
6✔
175
    ..setEntry(3, 2, -1.0)
4✔
176
    ..setEntry(2, 3, (2.0 * zNear * zFar) / near_minus_far);
8✔
177
}
178

179
/// Constructs a new OpenGL perspective projection matrix.
180
///
181
/// [fovYRadians] specifies the field of view angle, in radians, in the y
182
/// direction.
183
/// [aspectRatio] specifies the aspect ratio that determines the field of view
184
/// in the x direction. The aspect ratio of x (width) to y (height).
185
/// [zNear] specifies the distance from the viewer to the near plane
186
/// (always positive).
187
/// [zFar] specifies the distance from the viewer to the far plane
188
/// (always positive).
189
Matrix4 makePerspectiveMatrix(
2✔
190
  double fovYRadians,
191
  double aspectRatio,
192
  double zNear,
193
  double zFar,
194
) {
195
  final r = Matrix4.zero();
2✔
196
  setPerspectiveMatrix(r, fovYRadians, aspectRatio, zNear, zFar);
2✔
197
  return r;
198
}
199

200
/// Constructs an OpenGL infinite projection matrix in [infiniteMatrix].
201
/// [fovYRadians] specifies the field of view angle, in radians, in the y
202
/// direction.
203
/// [aspectRatio] specifies the aspect ratio that determines the field of view
204
/// in the x direction. The aspect ratio of x (width) to y (height).
205
/// [zNear] specifies the distance from the viewer to the near plane
206
/// (always positive).
207
void setInfiniteMatrix(
1✔
208
  Matrix4 infiniteMatrix,
209
  double fovYRadians,
210
  double aspectRatio,
211
  double zNear,
212
) {
213
  final height = math.tan(fovYRadians * 0.5);
2✔
214
  final width = height * aspectRatio;
1✔
215

216
  infiniteMatrix
217
    ..setZero()
1✔
218
    ..setEntry(0, 0, 1.0 / width)
2✔
219
    ..setEntry(1, 1, 1.0 / height)
2✔
220
    ..setEntry(2, 2, -1.0)
2✔
221
    ..setEntry(3, 2, -1.0)
2✔
222
    ..setEntry(2, 3, -2.0 * zNear);
3✔
223
}
224

225
/// Constructs a new OpenGL infinite projection matrix.
226
///
227
/// [fovYRadians] specifies the field of view angle, in radians, in the y
228
/// direction.
229
/// [aspectRatio] specifies the aspect ratio that determines the field of view
230
/// in the x direction. The aspect ratio of x (width) to y (height).
231
/// [zNear] specifies the distance from the viewer to the near plane
232
/// (always positive).
233
Matrix4 makeInfiniteMatrix(
1✔
234
  double fovYRadians,
235
  double aspectRatio,
236
  double zNear,
237
) {
238
  final r = Matrix4.zero();
1✔
239
  setInfiniteMatrix(r, fovYRadians, aspectRatio, zNear);
1✔
240
  return r;
241
}
242

243
/// Constructs an OpenGL perspective projection matrix in [perspectiveMatrix].
244
///
245
/// [left], [right] specify the coordinates for the left and right vertical
246
/// clipping planes.
247
/// [bottom], [top] specify the coordinates for the bottom and top horizontal
248
/// clipping planes.
249
/// [near], [far] specify the coordinates to the near and far depth clipping
250
/// planes.
251
void setFrustumMatrix(
2✔
252
  Matrix4 perspectiveMatrix,
253
  double left,
254
  double right,
255
  double bottom,
256
  double top,
257
  double near,
258
  double far,
259
) {
260
  final two_near = 2.0 * near;
2✔
261
  final right_minus_left = right - left;
2✔
262
  final top_minus_bottom = top - bottom;
2✔
263
  final far_minus_near = far - near;
2✔
264
  perspectiveMatrix
265
    ..setZero()
2✔
266
    ..setEntry(0, 0, two_near / right_minus_left)
4✔
267
    ..setEntry(1, 1, two_near / top_minus_bottom)
4✔
268
    ..setEntry(0, 2, (right + left) / right_minus_left)
6✔
269
    ..setEntry(1, 2, (top + bottom) / top_minus_bottom)
6✔
270
    ..setEntry(2, 2, -(far + near) / far_minus_near)
8✔
271
    ..setEntry(3, 2, -1.0)
4✔
272
    ..setEntry(2, 3, -(two_near * far) / far_minus_near);
8✔
273
}
274

275
/// Constructs a new OpenGL perspective projection matrix.
276
///
277
/// [left], [right] specify the coordinates for the left and right vertical
278
/// clipping planes.
279
/// [bottom], [top] specify the coordinates for the bottom and top horizontal
280
/// clipping planes.
281
/// [near], [far] specify the coordinates to the near and far depth clipping
282
/// planes.
283
Matrix4 makeFrustumMatrix(
2✔
284
  double left,
285
  double right,
286
  double bottom,
287
  double top,
288
  double near,
289
  double far,
290
) {
291
  final view = Matrix4.zero();
2✔
292
  setFrustumMatrix(view, left, right, bottom, top, near, far);
2✔
293
  return view;
294
}
295

296
/// Constructs an OpenGL orthographic projection matrix in [orthographicMatrix].
297
///
298
/// [left], [right] specify the coordinates for the left and right vertical
299
/// clipping planes.
300
/// [bottom], [top] specify the coordinates for the bottom and top horizontal
301
/// clipping planes.
302
/// [near], [far] specify the coordinates to the near and far depth clipping
303
/// planes.
304
void setOrthographicMatrix(
1✔
305
  Matrix4 orthographicMatrix,
306
  double left,
307
  double right,
308
  double bottom,
309
  double top,
310
  double near,
311
  double far,
312
) {
313
  final rml = right - left;
1✔
314
  final rpl = right + left;
1✔
315
  final tmb = top - bottom;
1✔
316
  final tpb = top + bottom;
1✔
317
  final fmn = far - near;
1✔
318
  final fpn = far + near;
1✔
319
  orthographicMatrix
320
    ..setZero()
1✔
321
    ..setEntry(0, 0, 2.0 / rml)
2✔
322
    ..setEntry(1, 1, 2.0 / tmb)
2✔
323
    ..setEntry(2, 2, -2.0 / fmn)
3✔
324
    ..setEntry(0, 3, -rpl / rml)
3✔
325
    ..setEntry(1, 3, -tpb / tmb)
3✔
326
    ..setEntry(2, 3, -fpn / fmn)
3✔
327
    ..setEntry(3, 3, 1.0);
1✔
328
}
329

330
/// Constructs a new OpenGL orthographic projection matrix.
331
///
332
/// [left], [right] specify the coordinates for the left and right vertical
333
/// clipping planes.
334
/// [bottom], [top] specify the coordinates for the bottom and top horizontal
335
/// clipping planes.
336
/// [near], [far] specify the coordinates to the near and far depth clipping
337
/// planes.
338
Matrix4 makeOrthographicMatrix(
1✔
339
  double left,
340
  double right,
341
  double bottom,
342
  double top,
343
  double near,
344
  double far,
345
) {
346
  final r = Matrix4.zero();
1✔
347
  setOrthographicMatrix(r, left, right, bottom, top, near, far);
1✔
348
  return r;
349
}
350

351
/// Returns a transformation matrix that transforms points onto
352
/// the plane specified with [planeNormal] and [planePoint].
353
Matrix4 makePlaneProjection(Vector3 planeNormal, Vector3 planePoint) {
×
NEW
354
  final v = Vector4(
×
NEW
355
    planeNormal.storage[0],
×
NEW
356
    planeNormal.storage[1],
×
NEW
357
    planeNormal.storage[2],
×
358
    0.0,
359
  );
360
  final outer = Matrix4.outer(v, v);
×
361
  var r = Matrix4.zero();
×
362
  r = r - outer;
×
363
  final scaledNormal = planeNormal.scaled(dot3(planePoint, planeNormal));
×
NEW
364
  final T = Vector4(
×
NEW
365
    scaledNormal.storage[0],
×
NEW
366
    scaledNormal.storage[1],
×
NEW
367
    scaledNormal.storage[2],
×
368
    1.0,
369
  );
UNCOV
370
  r.setColumn(3, T);
×
371
  return r;
372
}
373

374
/// Returns a transformation matrix that transforms points by reflecting
375
/// them through the plane specified with [planeNormal] and [planePoint].
376
Matrix4 makePlaneReflection(Vector3 planeNormal, Vector3 planePoint) {
×
NEW
377
  final v = Vector4(
×
NEW
378
    planeNormal.storage[0],
×
NEW
379
    planeNormal.storage[1],
×
NEW
380
    planeNormal.storage[2],
×
381
    0.0,
382
  );
383
  final outer = Matrix4.outer(v, v)..scaleByDouble(2.0, 2.0, 2.0, 1.0);
×
384
  var r = Matrix4.zero();
×
385
  r = r - outer;
×
386
  final scale = 2.0 * planePoint.dot(planeNormal);
×
387
  final scaledNormal = planeNormal.scaled(scale);
×
NEW
388
  final T = Vector4(
×
NEW
389
    scaledNormal.storage[0],
×
NEW
390
    scaledNormal.storage[1],
×
NEW
391
    scaledNormal.storage[2],
×
392
    1.0,
393
  );
UNCOV
394
  r.setColumn(3, T);
×
395
  return r;
396
}
397

398
/// On success, Sets [pickWorld] to be the world space position of
399
/// the screen space [pickX], [pickY], and [pickZ].
400
///
401
/// The viewport is specified by ([viewportX], [viewportWidth]) and
402
/// ([viewportY], [viewportHeight]).
403
///
404
/// [cameraMatrix] includes both the projection and view transforms.
405
///
406
/// [pickZ] is typically either 0.0 (near plane) or 1.0 (far plane).
407
///
408
/// Returns false on error, for example, the mouse is not in the viewport
409
bool unproject(
1✔
410
  Matrix4 cameraMatrix,
411
  num viewportX,
412
  num viewportWidth,
413
  num viewportY,
414
  num viewportHeight,
415
  num pickX,
416
  num pickY,
417
  num pickZ,
418
  Vector3 pickWorld,
419
) {
420
  viewportX = viewportX.toDouble();
1✔
421
  viewportWidth = viewportWidth.toDouble();
1✔
422
  viewportY = viewportY.toDouble();
1✔
423
  viewportHeight = viewportHeight.toDouble();
1✔
424
  pickX = pickX.toDouble();
1✔
425
  pickY = pickY.toDouble();
1✔
426
  pickX = pickX - viewportX;
1✔
427
  pickY = pickY - viewportY;
1✔
428
  pickX = (2.0 * pickX / viewportWidth) - 1.0;
3✔
429
  pickY = (2.0 * pickY / viewportHeight) - 1.0;
3✔
430
  pickZ = (2.0 * pickZ) - 1.0;
2✔
431

432
  // Check if pick point is inside unit cube
433
  if (pickX < -1.0 ||
2✔
434
      pickY < -1.0 ||
2✔
435
      pickX > 1.0 ||
1✔
436
      pickY > 1.0 ||
1✔
437
      pickZ < -1.0 ||
2✔
438
      pickZ > 1.0) {
1✔
439
    return false;
440
  }
441

442
  // Copy camera matrix.
443
  final invertedCameraMatrix = Matrix4.copy(cameraMatrix);
1✔
444
  // Invert the camera matrix.
445
  invertedCameraMatrix.invert();
1✔
446
  // Determine intersection point.
447
  final v = Vector4(pickX.toDouble(), pickY.toDouble(), pickZ.toDouble(), 1.0);
4✔
448
  invertedCameraMatrix.transform(v);
1✔
449
  if (v.w == 0.0) {
2✔
450
    return false;
451
  }
452
  final invW = 1.0 / v.w;
2✔
453
  pickWorld
454
    ..x = v.x * invW
3✔
455
    ..y = v.y * invW
3✔
456
    ..z = v.z * invW;
3✔
457

458
  return true;
459
}
460

461
/// On success, [rayNear] and [rayFar] are the points where
462
/// the screen space [pickX], [pickY] intersect with the near and far
463
/// planes respectively.
464
///
465
/// The viewport is specified by ([viewportX], [viewportWidth]) and
466
/// ([viewportY], [viewportHeight]).
467
///
468
/// [cameraMatrix] includes both the projection and view transforms.
469
///
470
/// Returns false on error, for example, the mouse is not in the viewport.
471
bool pickRay(
×
472
  Matrix4 cameraMatrix,
473
  num viewportX,
474
  num viewportWidth,
475
  num viewportY,
476
  num viewportHeight,
477
  num pickX,
478
  num pickY,
479
  Vector3 rayNear,
480
  Vector3 rayFar,
481
) {
482
  bool r;
483

NEW
484
  r = unproject(
×
485
    cameraMatrix,
486
    viewportX,
487
    viewportWidth,
488
    viewportY,
489
    viewportHeight,
490
    pickX,
NEW
491
    viewportHeight - pickY,
×
492
    0.0,
493
    rayNear,
494
  );
495
  if (!r) {
496
    return false;
497
  }
498

NEW
499
  return unproject(
×
500
    cameraMatrix,
501
    viewportX,
502
    viewportWidth,
503
    viewportY,
504
    viewportHeight,
505
    pickX,
NEW
506
    viewportHeight - pickY,
×
507
    1.0,
508
    rayFar,
509
  );
510
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc