new Matrix4(column0Row0, column1Row0, column2Row0, column3Row0, column0Row1, column1Row1, column2Row1, column3Row1, column0Row2, column1Row2, column2Row2, column3Row2, column0Row3, column1Row3, column2Row3, column3Row3)
A 4x4 matrix, indexable as a column-major order array. Constructor parameters are in row-major order for code readability.
Name | Type | Default | Description |
---|---|---|---|
column0Row0 |
Number |
0.0
|
optional
The value for column 0, row 0. |
column1Row0 |
Number |
0.0
|
optional
The value for column 1, row 0. |
column2Row0 |
Number |
0.0
|
optional
The value for column 2, row 0. |
column3Row0 |
Number |
0.0
|
optional
The value for column 3, row 0. |
column0Row1 |
Number |
0.0
|
optional
The value for column 0, row 1. |
column1Row1 |
Number |
0.0
|
optional
The value for column 1, row 1. |
column2Row1 |
Number |
0.0
|
optional
The value for column 2, row 1. |
column3Row1 |
Number |
0.0
|
optional
The value for column 3, row 1. |
column0Row2 |
Number |
0.0
|
optional
The value for column 0, row 2. |
column1Row2 |
Number |
0.0
|
optional
The value for column 1, row 2. |
column2Row2 |
Number |
0.0
|
optional
The value for column 2, row 2. |
column3Row2 |
Number |
0.0
|
optional
The value for column 3, row 2. |
column0Row3 |
Number |
0.0
|
optional
The value for column 0, row 3. |
column1Row3 |
Number |
0.0
|
optional
The value for column 1, row 3. |
column2Row3 |
Number |
0.0
|
optional
The value for column 2, row 3. |
column3Row3 |
Number |
0.0
|
optional
The value for column 3, row 3. |
- Matrix4.fromColumnMajorArray
- Matrix4.fromRowMajorArray
- Matrix4.fromRotationTranslation
- Matrix4.fromTranslationQuaternionRotationScale
- Matrix4.fromTranslationRotationScale
- Matrix4.fromTranslation
- Matrix4.fromScale
- Matrix4.fromUniformScale
- Matrix4.fromRotation
- Matrix4.computePerspectiveFieldOfView
- Matrix4.computeOrthographicOffCenter
- Matrix4.computePerspectiveOffCenter
- Matrix4.computeInfinitePerspectiveOffCenter
- Matrix4.computeViewportTransformation
- Matrix4.computeView
See:
Members
static constant Matrix4.IDENTITY : Matrix4
An immutable Matrix4 instance initialized to the identity matrix.
static constant Matrix4.ZERO : Matrix4
An immutable Matrix4 instance initialized to the zero matrix.
Methods
clone(result) → Matrix4
Duplicates the provided Matrix4 instance.
Name | Type | Description |
---|---|---|
result |
Matrix4 |
optional
The object onto which to store the result. |
Returns:
The modified result parameter or a new Matrix4 instance if one was not provided.
Compares this matrix to the provided matrix componentwise and returns
true
if they are equal, false
otherwise.
Name | Type | Description |
---|---|---|
right |
Matrix4 |
optional
The right hand side matrix. |
Returns:
true
if they are equal, false
otherwise.
Compares this matrix to the provided matrix componentwise and returns
true
if they are within the provided epsilon,
false
otherwise.
Name | Type | Default | Description |
---|---|---|---|
right |
Matrix4 |
optional
The right hand side matrix. |
|
epsilon |
Number |
0
|
optional
The epsilon to use for equality testing. |
Returns:
true
if they are within the provided epsilon, false
otherwise.
Computes a string representing this Matrix with each row being on a separate line and in the format '(column0, column1, column2, column3)'.
Returns:
A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1, column2, column3)'.
static Matrix4.clone(matrix, result) → Matrix4
Duplicates a Matrix4 instance.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to duplicate. |
result |
Matrix4 |
optional
The object onto which to store the result. |
Returns:
The modified result parameter or a new Matrix4 instance if one was not provided. (Returns undefined if matrix is undefined)
static Matrix4.computePerspectiveFieldOfView(fovY, aspectRatio, near, far, result) → Matrix4
Computes a Matrix4 instance representing a perspective transformation matrix.
Name | Type | Description |
---|---|---|
fovY |
Number |
The field of view along the Y axis in radians. |
aspectRatio |
Number |
The aspect ratio. |
near |
Number |
The distance to the near plane in meters. |
far |
Number |
The distance to the far plane in meters. |
result |
Matrix4 |
The object in which the result will be stored. |
Returns:
The modified result parameter.
Throws:
-
DeveloperError :
fovY must be in (0, PI].
-
DeveloperError :
aspectRatio must be greater than zero.
-
DeveloperError :
near must be greater than zero.
-
DeveloperError :
far must be greater than zero.
static Matrix4.computeView(position, direction, up, right, result) → Matrix4
Computes a Matrix4 instance that transforms from world space to view space.
Name | Type | Description |
---|---|---|
position |
Cartesian3 |
The position of the camera. |
direction |
Cartesian3 |
The forward direction. |
up |
Cartesian3 |
The up direction. |
right |
Cartesian3 |
The right direction. |
result |
Matrix4 |
The object in which the result will be stored. |
Returns:
The modified result parameter.
Compares the provided matrices componentwise and returns
true
if they are equal, false
otherwise.
Name | Type | Description |
---|---|---|
left |
Matrix4 |
optional
The first matrix. |
right |
Matrix4 |
optional
The second matrix. |
Returns:
true
if left and right are equal, false
otherwise.
Example:
//compares two Matrix4 instances
// a = [10.0, 14.0, 18.0, 22.0]
// [11.0, 15.0, 19.0, 23.0]
// [12.0, 16.0, 20.0, 24.0]
// [13.0, 17.0, 21.0, 25.0]
// b = [10.0, 14.0, 18.0, 22.0]
// [11.0, 15.0, 19.0, 23.0]
// [12.0, 16.0, 20.0, 24.0]
// [13.0, 17.0, 21.0, 25.0]
if(Matrix4.equals(a,b)) {
console.log("Both matrices are equal");
} else {
console.log("They are not equal");
}
//Prints "Both matrices are equal" on the console
Compares the provided matrices componentwise and returns
true
if they are within the provided epsilon,
false
otherwise.
Name | Type | Default | Description |
---|---|---|---|
left |
Matrix4 |
optional
The first matrix. |
|
right |
Matrix4 |
optional
The second matrix. |
|
epsilon |
Number |
0
|
optional
The epsilon to use for equality testing. |
Returns:
true
if left and right are within the provided epsilon, false
otherwise.
Example:
//compares two Matrix4 instances
// a = [10.5, 14.5, 18.5, 22.5]
// [11.5, 15.5, 19.5, 23.5]
// [12.5, 16.5, 20.5, 24.5]
// [13.5, 17.5, 21.5, 25.5]
// b = [10.0, 14.0, 18.0, 22.0]
// [11.0, 15.0, 19.0, 23.0]
// [12.0, 16.0, 20.0, 24.0]
// [13.0, 17.0, 21.0, 25.0]
if(Matrix4.equalsEpsilon(a,b,0.1)){
console.log("Difference between both the matrices is less than 0.1");
} else {
console.log("Difference between both the matrices is not less than 0.1");
}
//Prints "Difference between both the matrices is not less than 0.1" on the console
static Matrix4.fromColumnMajorArray(values, result) → Matrix4
Computes a Matrix4 instance from a column-major order array.
Name | Type | Description |
---|---|---|
values |
Array.<Number> |
The column-major order array. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
static Matrix4.fromRotation(rotation, result) → Matrix4
Creates a rotation matrix.
Name | Type | Description |
---|---|---|
rotation |
Matrix3 |
The rotation matrix. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
static Matrix4.fromRotationTranslation(rotation, translation, result) → Matrix4
Computes a Matrix4 instance from a Matrix3 representing the rotation and a Cartesian3 representing the translation.
Name | Type | Default | Description |
---|---|---|---|
rotation |
Matrix3 |
The upper left portion of the matrix representing the rotation. |
|
translation |
Cartesian3 |
Cartesian3.ZERO
|
optional
The upper right portion of the matrix representing the translation. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
static Matrix4.fromRowMajorArray(values, result) → Matrix4
Computes a Matrix4 instance from a row-major order array. The resulting matrix will be in column-major order.
Name | Type | Description |
---|---|---|
values |
Array.<Number> |
The row-major order array. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
static Matrix4.fromScale(scale, result) → Matrix4
Computes a Matrix4 instance representing a non-uniform scale.
Name | Type | Description |
---|---|---|
scale |
Cartesian3 |
The x, y, and z scale factors. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
Example:
// Creates
// [7.0, 0.0, 0.0, 0.0]
// [0.0, 8.0, 0.0, 0.0]
// [0.0, 0.0, 9.0, 0.0]
// [0.0, 0.0, 0.0, 1.0]
const m = Matrix4.fromScale(new Cartesian3(7.0, 8.0, 9.0));
static Matrix4.fromTranslation(translation, result) → Matrix4
Creates a Matrix4 instance from a Cartesian3 representing the translation.
Name | Type | Description |
---|---|---|
translation |
Cartesian3 |
The upper right portion of the matrix representing the translation. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
- Matrix4.multiplyByTranslation
See:
static Matrix4.fromTranslationQuaternionRotationScale(translation, rotation, scale, result) → Matrix4
Computes a Matrix4 instance from a translation, rotation, and scale (TRS) representation with the rotation represented as a quaternion.
Name | Type | Description |
---|---|---|
translation |
Cartesian3 |
The translation transformation. |
rotation |
Quaternion |
The rotation transformation. |
scale |
Cartesian3 |
The non-uniform scale transformation. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
Example:
const result = Matrix4.fromTranslationQuaternionRotationScale(
new Cartesian3(1.0, 2.0, 3.0), // translation
Quaternion.IDENTITY, // rotation
new Cartesian3(7.0, 8.0, 9.0), // scale
result);
static Matrix4.fromTranslationRotationScale(translationRotationScale, result) → Matrix4
Creates a Matrix4 instance from a TranslationRotationScale
instance.
Name | Type | Description |
---|---|---|
translationRotationScale |
TranslationRotationScale |
The instance. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
static Matrix4.fromUniformScale(scale, result) → Matrix4
Computes a Matrix4 instance representing a uniform scale.
Name | Type | Description |
---|---|---|
scale |
Number |
The uniform scale factor. |
result |
Matrix4 |
optional
The object in which the result will be stored, if undefined a new instance will be created. |
Returns:
The modified result parameter, or a new Matrix4 instance if one was not provided.
Example:
// Creates
// [2.0, 0.0, 0.0, 0.0]
// [0.0, 2.0, 0.0, 0.0]
// [0.0, 0.0, 2.0, 0.0]
// [0.0, 0.0, 0.0, 1.0]
const m = Matrix4.fromUniformScale(2.0);
static Matrix4.getColumn(matrix, index, result) → Cartesian4
Retrieves a copy of the matrix column at the provided index as a Cartesian4 instance.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
index |
Number |
The zero-based index of the column to retrieve. |
result |
Cartesian4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Throws:
-
DeveloperError :
index must be 0, 1, 2, or 3.
Examples:
//returns a Cartesian4 instance with values from the specified column
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
//Example 1: Creates an instance of Cartesian
const a = Matrix4.getColumn(m, 2, new Cartesian4());
//Example 2: Sets values for Cartesian instance
const a = new Cartesian4();
Matrix4.getColumn(m, 2, a);
// a.x = 12.0; a.y = 16.0; a.z = 20.0; a.w = 24.0;
static Matrix4.getMatrix3(matrix, result) → Matrix3
Gets the upper left 3x3 matrix of the provided matrix.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
result |
Matrix3 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Example:
// returns a Matrix3 instance from a Matrix4 instance
// m = [10.0, 14.0, 18.0, 22.0]
// [11.0, 15.0, 19.0, 23.0]
// [12.0, 16.0, 20.0, 24.0]
// [13.0, 17.0, 21.0, 25.0]
const b = new Matrix3();
Matrix4.getMatrix3(m,b);
// b = [10.0, 14.0, 18.0]
// [11.0, 15.0, 19.0]
// [12.0, 16.0, 20.0]
static Matrix4.getRotation(matrix, result) → Matrix4
Extracts the rotation matrix assuming the matrix is an affine transformation.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix. |
result |
Matrix3 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.getRow(matrix, index, result) → Cartesian4
Retrieves a copy of the matrix row at the provided index as a Cartesian4 instance.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
index |
Number |
The zero-based index of the row to retrieve. |
result |
Cartesian4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Throws:
-
DeveloperError :
index must be 0, 1, 2, or 3.
Examples:
//returns a Cartesian4 instance with values from the specified column
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
//Example 1: Returns an instance of Cartesian
const a = Matrix4.getRow(m, 2, new Cartesian4());
//Example 2: Sets values for a Cartesian instance
const a = new Cartesian4();
Matrix4.getRow(m, 2, a);
// a.x = 18.0; a.y = 19.0; a.z = 20.0; a.w = 21.0;
static Matrix4.getScale(matrix, result) → Cartesian3
Extracts the non-uniform scale assuming the matrix is an affine transformation.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix. |
result |
Cartesian3 |
The object onto which to store the result. |
Returns:
The modified result parameter
- Matrix4.multiplyByScale
- Matrix4.multiplyByUniformScale
- Matrix4.fromScale
- Matrix4.fromUniformScale
- Matrix4.setScale
- Matrix4.setUniformScale
See:
static Matrix4.getTranslation(matrix, result) → Cartesian3
Gets the translation portion of the provided matrix, assuming the matrix is an affine transformation matrix.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
result |
Cartesian3 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.inverse(matrix, result) → Matrix4
Computes the inverse of the provided matrix using Cramers Rule. If the determinant is zero, the matrix can not be inverted, and an exception is thrown.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to invert. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Throws:
-
Error :
matrix is not invertible because its determinate is zero.
static Matrix4.inverseTranspose(matrix, result) → Matrix4
Computes the inverse transpose of a matrix.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to transpose and invert. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.multiply(left, right, result) → Matrix4
Computes the product of two matrices.
Name | Type | Description |
---|---|---|
left |
Matrix4 |
The first matrix. |
right |
Matrix4 |
The second matrix. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.multiplyByMatrix3(matrix, rotation, result) → Matrix4
Multiplies a transformation matrix (with a bottom row of [0.0, 0.0, 0.0, 1.0]
)
by a 3x3 rotation matrix. This is an optimization
for Matrix4.multiply(m, Matrix4.fromRotationTranslation(rotation), m);
with less allocations and arithmetic operations.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix on the left-hand side. |
rotation |
Matrix3 |
The 3x3 rotation matrix on the right-hand side. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Example:
// Instead of Matrix4.multiply(m, Matrix4.fromRotationTranslation(rotation), m);
Matrix4.multiplyByMatrix3(m, rotation, m);
static Matrix4.multiplyByPoint(matrix, cartesian, result) → Cartesian3
Computes the product of a matrix and a Cartesian3
. This is equivalent to calling Matrix4.multiplyByVector
with a Cartesian4
with a w
component of 1, but returns a Cartesian3
instead of a Cartesian4
.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix. |
cartesian |
Cartesian3 |
The point. |
result |
Cartesian3 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Example:
const p = new Cartesian3(1.0, 2.0, 3.0);
const result = Matrix4.multiplyByPoint(matrix, p, new Cartesian3());
static Matrix4.multiplyByPointAsVector(matrix, cartesian, result) → Cartesian3
Computes the product of a matrix and a Cartesian3
. This is equivalent to calling Matrix4.multiplyByVector
with a Cartesian4
with a w
component of zero.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix. |
cartesian |
Cartesian3 |
The point. |
result |
Cartesian3 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Example:
const p = new Cartesian3(1.0, 2.0, 3.0);
const result = Matrix4.multiplyByPointAsVector(matrix, p, new Cartesian3());
// A shortcut for
// Cartesian3 p = ...
// Matrix4.multiplyByVector(matrix, new Cartesian4(p.x, p.y, p.z, 0.0), result);
static Matrix4.multiplyByVector(matrix, cartesian, result) → Cartesian4
Computes the product of a matrix and a column vector.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix. |
cartesian |
Cartesian4 |
The vector. |
result |
Cartesian4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.setColumn(matrix, index, cartesian, result) → Matrix4
Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian4 instance.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
index |
Number |
The zero-based index of the column to set. |
cartesian |
Cartesian4 |
The Cartesian whose values will be assigned to the specified column. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Throws:
-
DeveloperError :
index must be 0, 1, 2, or 3.
Example:
//creates a new Matrix4 instance with new column values from the Cartesian4 instance
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
const a = Matrix4.setColumn(m, 2, new Cartesian4(99.0, 98.0, 97.0, 96.0), new Matrix4());
// m remains the same
// a = [10.0, 11.0, 99.0, 13.0]
// [14.0, 15.0, 98.0, 17.0]
// [18.0, 19.0, 97.0, 21.0]
// [22.0, 23.0, 96.0, 25.0]
static Matrix4.setRotation(matrix, rotation) → Matrix4
Sets the rotation assuming the matrix is an affine transformation.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix. |
rotation |
Matrix3 |
The rotation matrix. |
Returns:
The modified result parameter.
static Matrix4.setRow(matrix, index, cartesian, result) → Matrix4
Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian4 instance.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
index |
Number |
The zero-based index of the row to set. |
cartesian |
Cartesian4 |
The Cartesian whose values will be assigned to the specified row. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Throws:
-
DeveloperError :
index must be 0, 1, 2, or 3.
Example:
//create a new Matrix4 instance with new row values from the Cartesian4 instance
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
const a = Matrix4.setRow(m, 2, new Cartesian4(99.0, 98.0, 97.0, 96.0), new Matrix4());
// m remains the same
// a = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [99.0, 98.0, 97.0, 96.0]
// [22.0, 23.0, 24.0, 25.0]
static Matrix4.setScale(matrix, scale, result) → Matrix4
Computes a new matrix that replaces the scale with the provided scale. This assumes the matrix is an affine transformation.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
scale |
Cartesian3 |
The scale that replaces the scale of the provided matrix. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.setTranslation(matrix, translation, result) → Matrix4
Computes a new matrix that replaces the translation in the rightmost column of the provided matrix with the provided translation. This assumes the matrix is an affine transformation.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
translation |
Cartesian3 |
The translation that replaces the translation of the provided matrix. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.setUniformScale(matrix, scale, result) → Matrix4
Computes a new matrix that replaces the scale with the provided uniform scale. This assumes the matrix is an affine transformation.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to use. |
scale |
Number |
The uniform scale that replaces the scale of the provided matrix. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
static Matrix4.transpose(matrix, result) → Matrix4
Computes the transpose of the provided matrix.
Name | Type | Description |
---|---|---|
matrix |
Matrix4 |
The matrix to transpose. |
result |
Matrix4 |
The object onto which to store the result. |
Returns:
The modified result parameter.
Example:
//returns transpose of a Matrix4
// m = [10.0, 11.0, 12.0, 13.0]
// [14.0, 15.0, 16.0, 17.0]
// [18.0, 19.0, 20.0, 21.0]
// [22.0, 23.0, 24.0, 25.0]
const a = Matrix4.transpose(m, new Matrix4());
// m remains the same
// a = [10.0, 14.0, 18.0, 22.0]
// [11.0, 15.0, 19.0, 23.0]
// [12.0, 16.0, 20.0, 24.0]
// [13.0, 17.0, 21.0, 25.0]