虽然存在许多类型的矩阵,但我们感兴趣的是三维变换矩阵。这种矩阵由一个4x4方阵,共16个值组成。在JavaScript中,可以很方便的用数组表示矩阵。比如典型的单位矩阵。单位阵乘上一个点或者矩阵, 其结果保持不变。

var identityMatrix = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1
];

说到乘法,这种运算用于矩阵是什么样的呢?最简单的例子是矩阵乘一个点。你可能注意到,三维空间中的点和一个4x4矩阵并不匹配,为此我们加上了额外的第四维W。一般来说,把W设为1就可以了。W维度还有一些额外的用途超出本文的讨论范围。查看WebGL model view projection看它有哪些用途。

注意矩阵和点的对齐方式:

[1, 0, 0, 0,
 0, 1, 0, 0,
 0, 0, 1, 0,
 0, 0, 0, 1]

[4, 3, 2, 1]

定义相乘函数

我们在示例代码中定义了一个乘法函数 — multiplyMatrixAndPoint():

function multiplyMatrixAndPoint(matrix, point) {

  // 给矩阵的每一部分一个简单的变量名, 列数(c)与行数(r)
  var c0r0 = matrix[ 0], c1r0 = matrix[ 1], c2r0 = matrix[ 2], c3r0 = matrix[ 3];
  var c0r1 = matrix[ 4], c1r1 = matrix[ 5], c2r1 = matrix[ 6], c3r1 = matrix[ 7];
  var c0r2 = matrix[ 8], c1r2 = matrix[ 9], c2r2 = matrix[10], c3r2 = matrix[11];
  var c0r3 = matrix[12], c1r3 = matrix[13], c2r3 = matrix[14], c3r3 = matrix[15];

  // 定义点坐标
  var x = point[0];
  var y = point[1];
  var z = point[2];
  var w = point[3];

  // 点坐标和第一列对应相乘, 再求和
  var resultX = (x * c0r0) + (y * c0r1) + (z * c0r2) + (w * c0r3);

  // 点坐标和第二列对应相乘, 再求和
  var resultY = (x * c1r0) + (y * c1r1) + (z * c1r2) + (w * c1r3);

  // 点坐标和第三列对应相乘, 再求和
  var resultZ = (x * c2r0) + (y * c2r1) + (z * c2r2) + (w * c2r3);

  // 点坐标和第四列对应相乘, 再求和
  var resultW = (x * c3r0) + (y * c3r1) + (z * c3r2) + (w * c3r3);

  return [resultX, resultY, resultZ, resultW]
}

现在我们可以使用上面的函数将一个点乘上一个矩阵。乘以单位阵将会返回原值:

// identityResult等于[4,3,2,1]
var identityResult = multiplyMatrixAndPoint(identityMatrix, [4,3,2,1]);

返回同一个点并没有什么用处, 但还有一些其它的矩阵可以作用于点,返回有用的结果。接下来我们将演示其中一些矩阵。

两个矩阵相乘

除了把矩阵和点相乘,你也可以把两个矩阵相乘。之前的函数可以帮助我们简化这个过程:

function multiplyMatrices(matrixA, matrixB) {

  // 将第二个矩阵按列切片
  var column0 = [matrixB[0], matrixB[4], matrixB[8], matrixB[12]];
  var column1 = [matrixB[1], matrixB[5], matrixB[9], matrixB[13]];
  var column2 = [matrixB[2], matrixB[6], matrixB[10], matrixB[14]];
  var column3 = [matrixB[3], matrixB[7], matrixB[11], matrixB[15]];

  // 将每列分别和矩阵相乘
  var result0 = multiplyMatrixAndPoint( matrixA, column0 );
  var result1 = multiplyMatrixAndPoint( matrixA, column1 );
  var result2 = multiplyMatrixAndPoint( matrixA, column2 );
  var result3 = multiplyMatrixAndPoint( matrixA, column3 );

  // 把结果重新组合成矩阵
  return [
    result0[0], result1[0], result2[0], result3[0],
    result0[1], result1[1], result2[1], result3[1],
    result0[2], result1[2], result2[2], result3[2],
    result0[3], result1[3], result2[3], result3[3]
  ]
}

用法

让我们看一看实际使用:

var someMatrix = [
  4, 0, 0, 0,
  0, 3, 0, 0,
  0, 0, 5, 0,
  4, 8, 4, 1
]

var identityMatrix = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1
];

// 返回someMatrix的数组表示
var someMatrixResult = multiplyMatrices(identityMatrix, someMatrix);


参考: https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Matrix_math_for_the_web

6种图片灰度转换算法: https://github.com/aooy/blog/issues/4

7种图片灰度转换算法 https://tannerhelland.com/2011/10/01/grayscale-image-algorithm-vb6.html

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐