Flutter 45: 图解矩阵变换 Transform 类 (二)

      小菜刚学习了 Transform 类,其核心部分在于矩阵变换,而矩阵变换是由 Matrix4 处理的,且无论是如何的平移旋转等操作,根本上还是一个四阶矩阵操作的;接下来小菜学习一下 Matrix4 的基本用法;

基本构造

Matrix4(double arg0, ... double arg15)

      Matrix4 默认构造函数由 16 个参数,从左到右从上到下依此排列为一个四阶矩阵;

transform: Matrix4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0),

Matrix4.identity()

      Matrix4.identity() 会初始化一个如上的 Matrix4,可在此基础上进行其他矩阵操作;

transform: Matrix4.identity(),
transform: Matrix4.identity()..rotateZ(pi / 4),

Matrix4.zero()

      Matrix4.zero() 会初始化一个所有参数值为 0 的空矩阵,在此基础上设置具体的变化矩阵;查看源码所有的初始化都是从 Matrix4.zero() 开始的;

transform: Matrix4.zero(),
transform: Matrix4.zero()..setIdentity(),

Matrix4.fromList()

      Matrix4.fromList()List<double> 列表中数据赋值进入 Matrix4(double arg0, ... double arg15) 类似;

List<double> list = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0];
transform: Matrix4.fromList(list),

Matrix4.copy()

      Matrix4.copy() 拷贝一个已有的 Matrix4

transform: Matrix4.copy(Matrix4.identity()),

Matrix4.columns()

      Matrix4.columns() 由四个 4D 列向量组成;

import 'package:vector_math/vector_math_64.dart' as v;

transform: Matrix4.columns(
    v.Vector4(1.0, 0.0, 0.0, 0.0),
    v.Vector4(0.0, 1.0, 0.0, 0.0),
    v.Vector4(0.0, 0.0, 1.0, 0.0),
    v.Vector4(0.0, 0.0, 0.0, 1.0)),

Matirx4.inverted()

      Matrix4.inverted() 为逆向矩阵,与原 Matrix4 矩阵相反(矩阵坐标沿着左对角线对称);

transform: Matrix4.inverted(Matrix4.fromList(list)),

Matrix4.outer()

      Matrix4.outer() 为两个四阶矩阵的合并乘积,注意两个四阶矩阵的先后顺序决定最终合并后的矩阵数组;

transform: Matrix4.outer(v.Vector4(1.0, 1.0, 1.0, 1.20), v.Vector4.identity()),
transform: Matrix4.outer(v.Vector4.identity(), v.Vector4(1.0, 1.0, 1.0, 1.20)),

Scale 缩放构造方法

Matrix4.diagonal3()

      Matrix4.diagonal3() 通过 Vector3 设置缩放矩阵;

transform: Matrix4.diagonal3(v.Vector3(2.0, 1.0, 1.0)),
transform: Matrix4.diagonal3(v.Vector3.array([2.0, 2.0, 2.0])),

      分析 Vector3 两种构造方法,三个参数分别对应 x / y /z 轴方向缩放;

factory Vector3(double x, double y, double z) =>
      new Vector3.zero()..setValues(x, y, z);
      
factory Vector3.array(List<double> array, [int offset = 0]) =>
      new Vector3.zero()..copyFromArray(array, offset);

Matirx4.diagonal3Values()

      Matrix4.diagonal3Values() 类似于将上述构造方法提取出来,直接对三个参数进行缩放赋值;

transform: Matrix4.diagonal3Values(2.0, 1.0, 1.0),

      分析 diagonal3Values 源码,发现 Matrix4 矩阵中坐对角线上的值分别对应 x / y / z 轴方向的缩放;

factory Matrix4.diagonal3Values(double x, double y, double z) =>
    new Matrix4.zero()
      .._m4storage[15] = 1.0
      .._m4storage[10] = z
      .._m4storage[5] = y
      .._m4storage[0] = x;

Transform 平移构造方法

Matrix4.translation()

      Matrix4.translation 同样通过 Vector3 构造方法的各参数设置矩阵平移量;水平向右为 x 轴正向,竖直向下为 y 轴正向;

transform: Matrix4.translation(v.Vector3(10.0, 10.0, 10.0)),
transform: Matrix4.translation(v.Vector3.array([-10.0, -10.0, 10.0])),

Matrix4.translationValues()

      Matrix4.translationValues() 将矩阵平移量直接赋值展示;

transform: Matrix4.translationValues(10.0, 10.0, 10.0),

      分析 translationValues 源码,Matirx4 四阶矩阵中第四行前三列分别对应 x / y / z 轴方向的偏移量;

factory Matrix4.translationValues(double x, double y, double z) =>
    new Matrix4.zero()
      ..setIdentity()
      ..setTranslationRaw(x, y, z);

void setTranslationRaw(double x, double y, double z) {
  _m4storage[14] = z;
  _m4storage[13] = y;
  _m4storage[12] = x;
}

Rotation 旋转构造方法

Matrix4.rotationX()

      Matrix4.rotationX() 沿 x 轴方向旋转;

transform: Matrix4.rotationX(pi / 3),

      分析源码,四阶矩阵中,index5/6/9/10 共同操作旋转弧度;

void setRotationX(double radians) {
    final double c = math.cos(radians);
    final double s = math.sin(radians);
    _m4storage[0] = 1.0;  _m4storage[1] = 0.0;
    _m4storage[2] = 0.0;  _m4storage[4] = 0.0;
    _m4storage[5] = c;    _m4storage[6] = s;
    _m4storage[8] = 0.0;  _m4storage[9] = -s;
    _m4storage[10] = c;   _m4storage[3] = 0.0;
    _m4storage[7] = 0.0;  _m4storage[11] = 0.0;
}

Matrix4.rotationY()

      Matrix4.rotationY() 沿 y 轴方向旋转;

transform: Matrix4.rotationY(pi / 3),

      分析源码,四阶矩阵中,index0/2/8/10 共同操作旋转弧度;

void setRotationY(double radians) {
    final double c = math.cos(radians);
    final double s = math.sin(radians);
    _m4storage[0] = c;    _m4storage[1] = 0.0;
    _m4storage[2] = -s;   _m4storage[4] = 0.0;
    _m4storage[5] = 1.0;  _m4storage[6] = 0.0;
    _m4storage[8] = s;    _m4storage[9] = 0.0;
    _m4storage[10] = c;   _m4storage[3] = 0.0;
    _m4storage[7] = 0.0;  _m4storage[11] = 0.0;
}

Matrix4.rotationZ()

      Matrix4.rotationZ() 沿 z 轴方向旋转;

transform: Matrix4.rotationZ(pi / 3),

      分析源码,四阶矩阵中,index0/1/4/5 共同操作旋转弧度;

void setRotationZ(double radians) {
    final double c = math.cos(radians);
    final double s = math.sin(radians);
    _m4storage[0] = c;
    _m4storage[1] = s;
    _m4storage[2] = 0.0;   _m4storage[4] = -s;
    _m4storage[5] = c;     _m4storage[6] = 0.0;
    _m4storage[8] = 0.0;   _m4storage[9] = 0.0;
    _m4storage[10] = 1.0;  _m4storage[3] = 0.0;
    _m4storage[7] = 0.0;   _m4storage[11] = 0.0;
}

Skew 斜切

Matrix4.skewX()

      上一篇博客稍稍介绍过,skewX() 是沿 x 轴方向斜切;

transform: Matrix4.skewX(pi / 6),

      分析源码,四阶矩阵中,第二行第一列元素对应斜切值,即三角函数中 tan

factory Matrix4.skewX(double alpha) {
    final Matrix4 m = new Matrix4.identity();
    m._m4storage[4] = math.tan(alpha);
    return m;
}

Matrix4.skewY()

      skewY() 是沿 y 轴方向斜切;

transform: Matrix4.skewY(pi / 6),

      分析源码,四阶矩阵中,第一行第二列元素对应斜切值,即三角函数中 tan

factory Matrix4.skewY(double beta) {
    final Matrix4 m = new Matrix4.identity();
    m._m4storage[1] = math.tan(beta);
    return m;
}

Matrix4.skew()

      skew() 是沿 x / y 轴方向斜切;

transform: Matrix4.skew(pi / 6, pi / 6),

      分析源码,四阶矩阵中,将上述两个元素结合展示效果;

factory Matrix4.skew(double alpha, double beta) {
    final Matrix4 m = new Matrix4.identity();
    m._m4storage[1] = math.tan(beta);
    m._m4storage[4] = math.tan(alpha);
    return m;
}

组合构造

Matrix4.compose()

      Matrix4.compose() 可以将平移/旋转/缩放共同组合操作绘制;

transform: Matrix4.compose(v.Vector3(10.0, 10.0, 10.0), v.Quaternion.random(math.Random(10)), v.Vector3(1.5, 1.0, 1.0)),

      分析源码,三个参数分别对应平移量/旋转量/缩放量;旋转量用到了欧拉旋转,小菜还不是很理解,只是在测试中用了 v.Quaternion.random() 的一个构造方法,还有待深入探索;

factory Matrix4.compose(
        Vector3 translation, Quaternion rotation, Vector3 scale) =>
    new Matrix4.zero()
      ..setFromTranslationRotationScale(translation, rotation, scale);

      Matirx4 涉及的范围很广泛,还有很多方法小菜没有研究到,只是尝试了一些常用的构造方法,若有错误的地方请多多指导!

来源:阿策小和尚

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容