vector_math for Dart
repository·master·Indexed 43 days ago
https://github.com/google/vector_math.dartA high-performance vector math library for 2D and 3D applications in Dart. It provides essential types for graphics and physics, including vectors, matrices, quaternions, and collision detection primitives like Aabb2. The library supports GLSL-style swizzled getters and setters and offers both 32-bit and 64-bit float precision (via vector_math_64.dart). It is used by major projects such as Flutter and Flame.
What's inside vector_math
- A high-performance vector math library for Dart designed for 2D and 3D applications. It provides essential types for graphics and physics, including vectors, matrices, quaternions, and collision detection primitives. It is heavily optimized and used by major projects like Flutter and Flame.
Use the Quaternion class for rotations
masterThe
Quaternionclass provides a four-dimensional vector implementation designed for efficient rotation calculations. Quaternions are preferred over Euler rotations for interpolating between rotations and for avoiding the gimbal lock problem.Key capabilities include:
- Constructing rotations from axis-angles, rotation matrices, or Euler angles (yaw, pitch, roll).
- Rotating vectors in 3D space.
- Performing quaternion arithmetic (addition, subtraction, multiplication/composition).
- Converting to and from
Matrix3rotation matrices.
// Example: Creating a rotation and rotating a vector final rotation = Quaternion.axisAngle(Vector3(0, 1, 0), math.pi / 2); // 90 deg around Y final point = Vector3(1, 0, 0); final rotatedPoint = rotation.rotated(point);Invert a matrix
masterThe library provides methods to invert a
Matrix4entirely usinginvert(), or to invert only the rotation component usinginvertRotation().import 'dart:math'; import 'package:vector_math/vector_math.dart'; void main() { // Rotation of 90 degrees around the Y axis followed by a // translation of (5.0, 2.0, 3.0). Matrix4 T = Matrix4.rotationY(PI * 0.5)..translate(5.0, 2.0, 3.0); // Invert T. T.invert(); // Invert just the rotation in T. T.invertRotation(); }Transform a vector using a matrix
masterYou can apply transformations (like rotation and translation) to a
Vector3using aMatrix4via thetransform3method.import 'dart:math'; import 'package:vector_math/vector_math.dart'; void main() { // Rotation of PI/2 degrees around the Y axis followed by a // translation of (5.0, 2.0, 3.0). Matrix4 T = Matrix4.rotationY(PI * 0.5)..translate(5.0, 2.0, 3.0); // A point. Vector3 position = Vector3(1.0, 1.0, 1.0); // Transform position by T. T.transform3(position); }Rotate a vector using a Quaternion
masterTo rotate a
Vector3around an arbitrary axis, create aQuaternionusingQuaternion.axisAngle(axis, angle)and then callrotate(vector).import 'dart:math'; import 'package:vector_math/vector_math.dart'; void main() { // The X axis. Vector3 axis = Vector3(1.0, 0.0, 0.0); // 90 degrees. double angle = PI / 2.0; // Quaternion encoding a 90 degree rotation along the X axis. Quaternion q = Quaternion.axisAngle(axis, angle); // A point. Vector3 point = Vector3(1.0, 1.0, 1.0); // Rotate point by q. q.rotate(point); }Perform Ray-Sphere intersection detection
masterTo find where a
Rayintersects aSphere, useray.intersectsWithSphere(sphere). This returns the distance from the ray origin to the intersection point, ornullif no intersection occurs. Useray.at(distance)to retrieve the exactVector3position of the intersection.import 'package:vector_math/vector_math.dart'; void main() { // Define a ray starting at the origin and going into positive x-direction. Ray ray = Ray.originDirection(Vector3.zero(), Vector3(1.0, 0.0, 0.0)); // Defines a sphere with the center (5.0 0.0 0.0) and a radius of 2. Sphere sphere = Sphere.centerRadius(Vector3(5.0, 0.0, 0.0), 2.0); // Checks if the ray intersect with the sphere and returns the distance of the // intersection from the origin of the ray. Would return null if no intersection // is found. double distanceFromOrigin = ray.intersectsWithSphere(sphere); // Evaluate the position of the intersection, in this case (3.0 0.0 0.0). Vector3 position = ray.at(distanceFromOrigin); }Work with colors
masterColors are handled as
Vector4types. TheColorsutility class provides methods for common operations:Colors.toGrayscale(source, destination)Colors.fromHexString(hexString, destination)Colors.rgbToHsl(source, destination)Colors.hslToRgb(source, destination)
import 'package:vector_math/vector_math.dart'; void main() { // Access a build-in color, colors are stored in 4-dimensional vectors. Vector4 red = Colors.red; Vector4 gray = Vector4.zero(); // Convert the red color to a grayscaled color. Colors.toGrayscale(red, gray); // Parse a blue color from a hex string. Vector4 blue = Vector4.zero(); Colors.fromHexString('#0000FF', blue); // Convert the blue color from RGB to HSL. Colors.rgbToHsl(blue, blue); // Reduce the lightness of the color by 50%. blue.z *= 0.5; // Convert the HSL color back to RGB. Colors.hslToRgb(blue, blue); }Use GLSL-style getters and setters
masterThe library supports flexible, swizzled-style getters and setters similar to GLSL. This allows you to assign multiple components of one vector to multiple components of another in a single operation using component names like
x,y,z,w,r,g,b, etc.import 'package:vector_math/vector_math.dart'; void main() { Vector3 x = Vector3.zero(); // Zero vector Vector4 y = Vector4.all(4.0); // Vector with 4.0 in all lanes x.zyx = y.xzz; // Sets z,y,x the values in x,z,z }Perform AABB collision detection
masterUse
Aabb2(Axis-Aligned Bounding Box) to check for intersections between two boxes usingintersectsWithAabb2. You can also usehullPointto expand a box to include a specific point.import 'package:vector_math/vector_math.dart'; void main() { // Define the first box with a minimum and a maximum. Aabb2 aabbOne = Aabb2.minMax(Vector2.zero(), Vector2(4.0, 4.0)); // Define the second box Aabb2 aabbTwo = Aabb2.minMax(Vector2(5.0, 5.0), Vector2(6.0, 6.0)); // Extend the second box to contain a point aabbTwo.hullPoint(Vector2(3.0, 3.0)); // Check if the two boxes intersect, returns true in this case. bool intersect = aabbOne.intersectsWithAabb2(aabbTwo); }Use 64-bit float precision
masterIf your application requires 64-bit float precision instead of the default 32-bit, import
package:vector_math/vector_math_64.dartinstead of the standard library. The API and types remain identical, but they use 64-bit storage.// Use different import statement. // Which is a drop-in replacement for 'package:vector_math/vector_math.dart' import 'package:vector_math/vector_math_64.dart'; void main() { // Types work the same, but using 64 bit storage. Vector3 x = Vector3.zero(); Matrix4 m = Matrix4.identity(); }Use Vector3 geometric operations
masterPerform common 3D geometric calculations with these methods:
dot(other): Computes the dot product (inner product) of two vectors.cross(other): Computes the cross product, returning a newVector3.crossInto(other, out): Computes the cross product and stores the result in the providedoutvector.reflect(normal): Reflects the vector across a given normal in-place.reflected(normal): Returns a new reflectedVector3.applyAxisAngle(axis, angle): Rotates the vector using an axis and an angle.applyQuaternion(quaternion): Rotates the vector using aQuaternion.
var v1 = Vector3(1, 0, 0); var v2 = Vector3(0, 1, 0); // Cross product (result should be [0, 0, 1]) var cp = v1.cross(v2); // Dot product double d = v1.dot(v2); // 0.0Clamp and transform vectors
masterUse these methods for bounding and geometric transformations:
clamp(min, max): Clamps each component of the vector within the ranges defined by theminandmaxvectors.clampScalar(min, max): Clamps each component within a scalar range.reflect(normal): Reflects the vector across a givennormalvector.reflected(normal): Returns a new reflected copy of the vector.postmultiply(matrix): Transforms this vector as a row vector, postmultiplied by aMatrix2.scaleOrthogonalInto(scale, out): Rotates the vector 90 degrees and scales it, storing the result inout.
var v = Vector2(10, 10); var min = Vector2(0, 0); var max = Vector2(5, 5); v.clamp(min, max); // v is now [5.0, 5.0] var normal = Vector2(1, 0); var v2 = Vector2(-1, 1); v2.reflect(normal); // v2 is now [1.0, 1.0]