Flutter笔记 Matrix4矩阵改换及其事例


作者李俊才 (jcLee95)blog.csdn.net/qq_28550263
邮箱 : 291148484@163.com
本文地址blog.csdn.net/qq_28550263…


【简介】在3D计算机图形中,4×4矩阵最常见的用处是作为改换矩阵,这在各种 UI 框架中都十分常见,比如前端的 three.js 中也有相似方针。文本介绍 Flutter 中 Matrix4 矩阵改换的基础常识及其简单运用。本文涉及很一些学常识,不了解的读者能够参阅线性代数相关教材。

目 录* * *


1. 概述

Flutter中,矩阵改换是一种强壮的技能,它能够对方针方针进行各种改换,如缩放、平移和旋转。这种改换是经过运用Matrix4,一个表明4D矩阵的类,来完成的。这里的4D并不是指四维空间,而是指这个矩阵有 4 行 4 列。经过改动这个矩阵的元素,咱们能够完成对方针方针的各种改换。

Matrix4 的运用十分广泛,它能够用于各种图形和 3D 场景的改换。例如,咱们能够经过改动矩阵的元从来操控图形的缩放份额、平移间隔和旋转视点。这种改换方式的通用性使得咱们能够在各种不同的场景中运用它。

,矩阵改换是一种在 Flutter 中完成动画作用和交互作用的重要手段。经过了解和掌握 Matrix4 的运用,咱们能够在 Flutter 中创立出各种各样的动画和交互作用。

2. 矩阵改换基础

2.1 矩阵的概念和性质

矩阵是一种特殊的数表,由 m 行 n 列的数值组成,一般用大写字母表明。矩阵的行数和列数称为矩阵的维度。矩阵的每个数值称为矩阵的元素。矩阵的加法、减法和乘法都有特定的运算规则。特别的,矩阵的乘法不满足交换律,即 AB ≠ BA。

2.2 图形改换与 Matrix4 类

2.2.1 矩阵与改换

要讲清楚矩阵和改换,就需要提一提线性代数中中的一些常识。同济六版线性代数教材中有一个很重要的运用便是“正交二次型”,其几许意义便是将一个图形变为对应的正交图形,就像用一个扳手将一个斜着或歪着的图形扳正——于是这个时候读了大学的你开始回想,当年是如何求解将图形扳正的那个二次型的。但是实践上咱们除了能够运用二次型将图形“扳正”,其实也能够经过改换将一个图形“扳”成其它姿态,这便是线性改换的意义所在。

没有学过的也没事,我带大家过一遍。

1. 旋转改换

旋转改换是一种常见的线性改换,它能够将平面上的点或许空间中的点绕某一点旋转必定的视点。在二维平面上,一个点 (x, y) 绕原点旋转 视点后的新坐标 (x’, y’) 能够经过以下矩阵乘法得到:

Flutter笔记:Matrix4矩阵改换与事例

对应的旋转改换矩阵便是:

Flutter笔记:Matrix4矩阵改换与事例

在三维空间中,绕 z 轴旋转的旋转改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

2. 反射改换

反射改换是一种将平面上的点或许空间中的点关于某条直线或许某个平面进行翻转的改换。

在二维平面上,关于 x 轴的反射改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

对应的改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

别的一种状况是,关于y=x轴改换,能够得到对应的改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

假如是三维空间中,关于 xy 平面的反射改换,对应矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

3. 弹性改换

弹性改换是一种将平面上的点或许空间中的点在某个方向上进行拉伸或许压缩的改换。在二维平面上,沿 x 轴方向进行弹性的改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

4. 投影改换

投影改换是一种将空间中的点投影到某个平面上的改换。

Flutter笔记:Matrix4矩阵改换与事例

在三维空间中,将点投影到 xy 平面上的投影改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

5. 切变改换

切变改换是一种将平面上的点或许空间中的点在某个方向上进行错切的改换。在二维平面上:

平行x轴的切边改换:

Flutter笔记:Matrix4矩阵改换与事例

或许 平行y轴的切边改换:

Flutter笔记:Matrix4矩阵改换与事例

在三维空间中,沿 z 轴方向进行切变的改换矩阵为:

Flutter笔记:Matrix4矩阵改换与事例

(其它轴相似)

要了解和运用矩阵改换,这些很重要。实践上后续小节的内容中,假如需要精确操控改换,没有这些数学常识是做不到的。其间,在后面的4-3小节中,有一个详细的比如,叙述了是如何运用到详细开发中的。

5. 逆改换的概念

逆改换是线性代数中的一个重要概念。对于一个线性改换,假如存在另一个线性改换,使得这两个改换的组合是恒等改换(即任何向量经过这两个改换后依然坚持不变),那么咱们就说这两个改换是互逆的。

在矩阵表明的线性改换中,逆改换对应于矩阵的逆。给定一个矩阵 A,假如存在另一个矩阵 B,使得AB = BA = E(其间 E 是单位矩阵),那么咱们就说 B 是 A 的逆矩阵,记作
A^-1

逆矩阵的存在性并不是总建立的,只有当矩阵是可逆的(或许说是非奇异的)时,逆矩阵才存在。在实践运用中,咱们一般经过高斯消元法或许 LU 分解等办法来计算矩阵的逆。

逆改换在许多运用中都十分重要。例如,在解线性方程组时,咱们能够经过求解系数矩阵的逆来找到解。在计算机图形学中,逆改换能够用来吊销之前的改换,或许从方针状况计算出初始状况。

从几许意义上说,逆矩阵对应的是逆改换。一个改换让图形产生某个形变,那么一个对应的逆改换让改换后的图形还原本来的姿态。

2.2.2 Matrix4 类

3D图形的改换中,咱们一般运用 4×4 的矩阵,这种矩阵能够表明平移、缩放、旋转等改换,也能够表明这些改换的组合。在这个矩阵中,最终一列一般用于表明平移改换,其余部分用于表明缩放和旋转改换。

Flutter中,这种 4×4 矩阵由Matrix4类来表明。Matrix4类供给了一系列的办法,能够便利地创立和操作 4×4 矩阵完成3D图形改换。例如:

  • Matrix4.identity() 能够创立一个单位矩阵;
  • Matrix4.diagonal3Values() 能够创立一个对角矩阵;
  • Matrix4.compose() 能够创立一个表明组合改换的矩阵。

2.3 Flutter 中的坐标系统

对于手机屏幕来讲,坐标系的:

  • 原点在手机屏幕的左上角
  • 水平向右是 x 轴的正方向;
  • 竖直向下是 y 轴的正方向;
  • 垂直于屏幕的方向是 z 轴。

这种坐标系统的设计使得咱们能够便利地定位屏幕上的任何一个点,也便利咱们运用Matrix4进行图形的改换。

3. Matrix4 的根本操作

3.1 创立 Matrix4 方针

Flutter中,咱们能够运用多种方式创立Matrix4方针。最简单的方式是运用Matrix4的结构函数,这将创立一个全零的矩阵。假如咱们想创立一个单位矩阵,能够运用Matrix4.identity() 办法。此外,咱们还能够运用Matrix4.diagonal3Values() 办法创立一个对角矩阵,或许运用Matrix4.compose() 办法创立一个表明组合改换的矩阵。

Matrix4 matrix1 = Matrix4(); // 创立一个全零的矩阵
Matrix4 matrix2 = Matrix4.identity(); // 创立一个单位矩阵
Matrix4 matrix3 = Matrix4.diagonal3Values(1.0, 2.0, 3.0); // 创立一个对角矩阵

矩阵的实质是改换,在上面几个矩阵的示例中,代表了不同的改换:

  • Matrix4 matrix1 = Matrix4(); 创立的是一个全零矩阵。在大多数状况下,全零矩阵在图形改换中没有实践用处,由于它会将所有的点都映射到原点;
  • Matrix4 matrix2 = Matrix4.identity(); 创立的是一个单位矩阵。单位矩阵在改换中相当于“无操作”,由于任何向量与单位矩阵相乘都会得到原向量。它常用作改换矩阵的初始值,然后经过运用一系列的改换(如旋转、缩放等)来修正这个矩阵;
  • Matrix4 matrix3 = Matrix4.diagonal3Values(1.0, 2.0, 3.0); 创立的是一个对角矩阵。对角矩阵能够用来进行均匀或非均匀的缩放。例如,上述代码创立的矩阵会在 x 轴方向上坚持原巨细,在 y 轴方向上扩大 2 倍,在 z 轴方向上扩大 3 倍。

3.2 Matrix4 的根本办法

Matrix4 类供给了一系列的根本办法,能够用于获取和设置矩阵的元素,以及进行矩阵的根本运算。例如,咱们能够运用 [] 运算符获取和设置矩阵的元素,运用 和 – 运算符进行矩阵的加法和减法运算,运用 运算符进行矩阵的乘法运算。

double value = matrix1[0]; // 获取矩阵的元素
matrix1[0] = value; // 设置矩阵的元素
Matrix4 result1 = matrix1   matrix2; // 矩阵的加法运算
Matrix4 result2 = matrix1 - matrix2; // 矩阵的减法运算
Matrix4 result3 = matrix1 * matrix2; // 矩阵的乘法运算

3.3 Matrix4 的改换办法

Matrix4 类供给了一系列的改换办法,能够用于对矩阵进行平移、缩放、旋转等改换。这些办法都会改动矩阵的元素,然后完成对方针方针的改换。

matrix1.translate(10.0, 20.0, 30.0); // 平移改换
matrix1.scale(2.0, 3.0, 4.0); // 缩放改换
matrix1.rotateX(1.0); // 绕 x 轴旋转
matrix1.rotateY(1.0); // 绕 y 轴旋转
matrix1.rotateZ(1.0); // 绕 z 轴旋转

4. 根据 Matrix4 的平移、缩放和旋转改换

4.1 运用 Matrix4 进行平移改换

在 Flutter 中,咱们能够运用 Matrix4 的 translate 办法进行平移改换。这个办法承受三个参数,别离表明在 x、y 和 z 轴上的平移间隔。

Matrix4 matrix = Matrix4.identity();
matrix.translate(10.0, 20.0, 30.0); // 在 x、y 和 z 轴上别离平移 10、20 和 30 单位

这将会改动 Matrix4 方针的元素,使得它表明一个平移改换。咱们能够将这个矩阵运用到一个图形上,使得这个图形在 x、y 和 z 轴上别离平移 10、20 和 30 单位。

4.2 运用 Matrix4 进行缩放改换

咱们能够运用 Matrix4 的 scale 办法进行缩放改换。这个办法承受三个参数,别离表明在 x、y 和 z 轴上的缩放份额。

  Matrix4 matrix = Matrix4.identity();
  matrix.scale(2.0, 3.0, 4.0); // 在 x、y 和 z 轴上别离缩放 2、3 和 4 倍

这将会改动 Matrix4 方针的元素,使得它表明一个缩放改换。咱们能够将这个矩阵运用到一个图形上,使得这个图形在 x、y 和 z 轴上别离缩放 2、3 和 4 倍。

4.3 运用 Matrix4 进行旋转改换

Matrix4 类供给了 rotateX、rotateY 和 rotateZ 三个办法,能够用于进行旋转改换。这些办法承受一个参数,表明旋转的视点。

  Matrix4 matrix = Matrix4.identity();
  matrix.rotateX(1.0); // 绕 x 轴旋转 1 弧度
  matrix.rotateY(1.0); // 绕 y 轴旋转 1 弧度
  matrix.rotateZ(1.0); // 绕 z 轴旋转 1 弧度

这将会改动 Matrix4 方针的元素,使得它表明一个旋转改换。咱们能够将这个矩阵运用到一个图形上,使得这个图形别离绕 x、y 和 z 轴旋转 1 弧度。

实践上,要精确操控,仍是要回到之前的数学常识。结合之前解说的代数学常识,以绕x轴旋转为例。当绕x轴旋转时,旋转矩阵为:

[1000cos⁡−sin⁡0sin⁡cos⁡]begin{bmatrix} 1 & 0 & 0 \ 0 & costheta & -sintheta \ 0 & sintheta & costheta end{bmatrix}

对应的用于Matrix4的矩阵表明为:

[10000cos⁡−sin⁡00sin⁡cos⁡00001]begin{bmatrix} 1 & 0 & 0 & 0 \ 0 & costheta & -sintheta & 0 \ 0 & sintheta & costheta & 0 \ 0 & 0 & 0 & 1 end{bmatrix}

在这个基础上,以绕x轴正向旋转为例:

  1. 首要,咱们需要创立一个 Matrix4 实例。
  2. 然后,咱们能够运用 Matrix4 的 setEntry 办法来设置矩阵的元素。对于绕 x 轴旋转的改换,咱们需要设置的元素如下:
  • 第二行第二列的元素为 cos
  • 第二行第三列的元素为 -sin
  • 第三行第二列的元素为 sin
  • 第三行第三列的元素为 cos
  1. 最终,咱们能够运用这个 Matrix4 实例来对图形进行改换。
// 创立一个 Matrix4 实例
final matrix4 = Matrix4.identity();
// 设置旋转视点
final theta = math.pi / 4;  // 旋转 45 度
// 设置矩阵的元素
matrix4.setEntry(1, 1, math.cos(theta));
matrix4.setEntry(1, 2, -math.sin(theta));
matrix4.setEntry(2, 1, math.sin(theta));
matrix4.setEntry(2, 2, math.cos(theta));
// 运用 Matrix4 实例来对图形进行改换
final transformedWidget = Transform(
  transform: matrix4,
  child: /* 改换的组件 */,
);

上面的代码中,咱们首要创立了一个 Matrix4 实例,然后设置了旋转视点为 45 度,接着设置了矩阵的元素,最终运用这个 Matrix4 实例来对图形进行改换。

在实践运用中,咱们一般会先界说一个改换矩阵来表明改换,然后再将其运用到图形上。在 Flutter 中,咱们能够运用 Matrix4 的结构函数来直接创立一个表明特定改换的矩阵。

比如:

import 'dart:math' as math;
import 'package:flutter/widgets.dart';
// 设置旋转视点
final theta = math.pi / 4;  // 旋转 45 度
// 界说一个表明旋转改换的矩阵
final matrix4 = Matrix4(
  1, 0, 0, 0,
  0, math.cos(theta), -math.sin(theta), 0,
  0, math.sin(theta), math.cos(theta), 0,
  0, 0, 0, 1,
);
// 将 Matrix4 转换为 List<double>
final matrix4List = matrix4.storage.toList();
// 运用 Matrix4 实例来对图形进行改换
final transformedWidget = Transform(
  transform: matrix4,
  child: /* your widget */,
);

旋转45度是一个特例,咱们能够在了解的基础上进一步写成一个函数,用于绕 x 轴旋转,就像这样:

import 'dart:math' as math;
Matrix4 rotationMatrix(double angleInDegrees) {
  // 将视点转换为弧度
  final theta = angleInDegrees / 180.0 * math.pi;
  // 创立一个列表来表明矩阵
  final matrix = [
    [1, 0, 0, 0],
    [0, math.cos(theta), -math.sin(theta), 0],
    [0, math.sin(theta), math.cos(theta), 0],
    [0, 0, 0, 1],
  ];
  // 创立一个 Matrix4 实例
  final matrix4 = Matrix4.fromList(matrix.expand((i) => i).toList());
  return matrix4;
}

这个函数中,咱们首要将输入的视点转换为弧度,然后创立了一个列表来表明矩阵,最终将这个列表转换为 Matrix4 实例并回来。这样,咱们就能够经过调用这个函数来创立任意视点的绕 x 轴旋转矩阵了。这个列表 matrix ,就表明的是绕 x 轴旋转改换所用的改换矩阵。

仅举这个比如作为示范,其它的状况都是之前提到数学常识的运用,读者能够按照这个思路参阅得出。

5. 复合改换、逆改换和透视改换的完成

5.1 运用 Matrix4 进行复合改换

在 Flutter 中,咱们能够经过连续调用 Matrix4 的改换办法来完成复合改换。例如,咱们能够先进行平移改换,然后进行缩放改换,最终进行旋转改换。

Matrix4 matrix = Matrix4.identity();
matrix.translate(10.0, 20.0, 30.0); // 平移改换
matrix.scale(2.0, 3.0, 4.0); // 缩放改换
matrix.rotateZ(1.0); // 旋转改换

这将会改动 Matrix4 方针的元素,使得它表明一个复合改换。咱们能够将这个矩阵运用到一个图形上,使得这个图形先进行平移改换,然后进行缩放改换,最终进行旋转改换。

5.2 运用 Matrix4 进行逆改换

Matrix4 类供给了 invert 办法,能够用于计算矩阵的逆。逆改换能够用于吊销之前的改换。

  Matrix4 matrix = Matrix4.identity();
  matrix.translate(10.0, 20.0, 30.0); // 平移改换
  Matrix4 inverseMatrix = Matrix4.inverted(matrix); // 计算逆改换

这将会创立一个新的 Matrix4 方针,它表明的改换能够吊销本来的改换。咱们能够将这个矩阵运用到一个图形上,使得这个图形恢复到本来的状况。

5.3 运用 Matrix4 进行透视改换

Matrix4 类供给了 setEntry 办法,能够用于设置矩阵的元素。咱们能够经过设置矩阵的元从来完成透视改换。

Matrix4 matrix = Matrix4.identity();
matrix.setEntry(3, 2, 0.001); // 设置矩阵的元素,完成透视改换

这将会改动 Matrix4 方针的元素,使得它表明一个透视改换。咱们能够将这个矩阵运用到一个图形上,使得这个图形产生透视作用。

6. Matrix4 在动画和交互作用中的运用

6.1 运用 Matrix4 创立动画作用

在 Flutter 中,咱们能够运用 Matrix4 和动画操控器(AnimationController)一同创立动画作用。例如,咱们能够创立一个动画,使得一个图形在一段时间内进行平移、缩放和旋转改换。

  AnimationController controller = AnimationController(
    duration: const Duration(seconds: 2),
    vsync: this,
  );
  Matrix4 matrix = Matrix4.identity();
  controller.addListener(() {
    matrix.translate(controller.value * 10.0, controller.value * 20.0, controller.value * 30.0);
    matrix.scale(controller.value * 2.0, controller.value * 3.0, controller.value * 4.0);
    matrix.rotateZ(controller.value * 1.0);
  });
  controller.forward();

这将会创立一个动画,使得一个图形在 2 秒内进行平移、缩放和旋转改换。

6.2 运用 Matrix4 创立交互作用

咱们能够运用 Matrix4 和手势辨认器(GestureRecognizer)一同创立交互作用。例如,咱们能够创立一个交互作用,使得用户能够经过拖动来操控一个图形的平移改换。

  Matrix4 matrix = Matrix4.identity();
  double dx = 0.0, dy = 0.0;
  GestureDetector(
    onPanUpdate: (details) {
      dx  = details.delta.dx;
      dy  = details.delta.dy;
      matrix.setIdentity();
      matrix.translate(dx, dy);
    },
    child: Transform(
      transform: matrix,
      child: FlutterLogo(size: 100.0),
    ),
  );

这将会创立一个交互作用,使得用户能够经过拖动来操控一个图形的平移改换。

6.3 运用 Matrix4 创立 3D 作用

咱们能够运用 Matrix4 创立 3D 作用。例如,咱们能够创立一个作用,使得一个图形在 3D 空间中进行旋转。

  Matrix4 matrix = Matrix4.identity();
  matrix.setEntry(3, 2, 0.001); // 设置矩阵的元素,完成透视作用
  matrix.rotateY(1.0); // 绕 y 轴旋转
  Transform(
    transform: matrix,
    child: FlutterLogo(size: 100.0),
  );

这将会创立一个 3D 作用,使得一个图形在 3D 空间中进行旋转。