2016-07-23 01:18:44 +08:00
|
|
|
|
# Matrix基础篇
|
2016-06-06 17:39:12 +08:00
|
|
|
|
|
2016-07-20 06:10:39 +08:00
|
|
|
|
|
2016-07-23 01:31:39 +08:00
|
|
|
|
## 前言
|
|
|
|
|
|
|
|
|
|
|
|
前面讲了四篇 Path 相关的内容,经过长时间的拖更,终于要到了大家期盼已久的 Matrix, 一个与黑客帝国同名的东东,看名字就知道很不凡,接下来我们就看看这个 Matrix 到底是何方神圣。
|
2016-06-06 17:39:12 +08:00
|
|
|
|
|
2016-06-26 21:16:22 +08:00
|
|
|
|

|
2016-06-10 02:41:55 +08:00
|
|
|
|
|
2016-07-20 17:05:00 +08:00
|
|
|
|
|
2016-07-23 01:15:22 +08:00
|
|
|
|
******
|
|
|
|
|
|
|
|
|
|
|
|
## 一、Matrix简介
|
|
|
|
|
|
|
|
|
|
|
|
如题,本篇的主角是 Matrix,其实和黑客帝国并没有太大关系,它看起来大概是下面这样:
|
2016-07-22 04:01:04 +08:00
|
|
|
|
|
|
|
|
|
|

|
2016-06-10 02:41:55 +08:00
|
|
|
|
|
2016-07-23 01:15:22 +08:00
|
|
|
|
### Matrix概念: Matrix的翻译过来是矩阵,模型。和其释义相同,Matrix是一个矩阵,也一个控制视图状态的模型,主要功能是坐标映射,数值转换。
|
2016-06-06 17:39:12 +08:00
|
|
|
|
|
2016-07-23 01:05:12 +08:00
|
|
|
|
我的的手机屏幕作为物理设备,其坐标系是从左上角开始的,但我们在开发的时候通常不会使用这一坐标系,而是使用内容区的坐标系。
|
2016-07-22 03:54:40 +08:00
|
|
|
|
|
2016-07-23 01:05:12 +08:00
|
|
|
|
以下图为例,我们的内容区和屏幕坐标系还相差一个通知栏加一个标题栏的距离,所以两者是不重合的,我们在内容区的坐标系中的内容最终绘制的时候肯定要转换为实际的屏幕坐标系来绘制,Matrix在此处的作用就是转换这些数值。
|
2016-07-22 03:54:40 +08:00
|
|
|
|
|
2016-07-22 04:01:04 +08:00
|
|
|
|
>
|
|
|
|
|
|
假设通知栏高度为20像素,导航栏高度为40像素,那么我们在内容区的(0,0)位置绘制一个点,最终就要转化为在实际坐标系中的(0,60)位置绘制一个点。
|
2016-07-22 03:54:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
2016-07-24 02:13:56 +08:00
|
|
|
|
以上是仅以2D空间作为例子,然而我们在实际的软件开发过程中,为了有较好的空间层次感,可能都要求有一些3D效果,将3D效果的3维影像投影到2维的屏幕,也是依靠Matrix的转换。
|
2016-07-20 17:05:00 +08:00
|
|
|
|
|
2016-07-21 04:10:59 +08:00
|
|
|
|
## 二、Matrix基本原理
|
2016-06-27 19:55:23 +08:00
|
|
|
|
|
2016-07-19 03:47:11 +08:00
|
|
|
|
Matrix 本质是一个 3x3 的矩阵,里面有9个数值,分别用于控制视图的不同属性,大致如下:
|
|
|
|
|
|
|
2016-07-20 06:14:11 +08:00
|
|
|
|

|
2016-06-26 20:49:05 +08:00
|
|
|
|
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-20 02:46:31 +08:00
|
|
|
|
序号 | 名称 | 对应单词 | 摘要
|
|
|
|
|
|
-----|----------|-------------|--------------
|
|
|
|
|
|
0 | MSCALE_X | scale | 控制X坐标 缩放,旋转
|
|
|
|
|
|
1 | MSKEW_X | skew | 控制X坐标 错切,旋转
|
|
|
|
|
|
2 | MTRANS_X | transfer | 控制X坐标 位移
|
|
|
|
|
|
3 | MSKEW_Y | skew | 控制Y坐标 错切,旋转
|
|
|
|
|
|
4 | MSCALE_Y | scale | 控制Y坐标 缩放,旋转
|
|
|
|
|
|
5 | MTRANS_Y | transfer | 控制Y坐标 位移
|
|
|
|
|
|
6 | MPERSP_0 | perspective | 控制透视 (绕Y轴旋转)
|
|
|
|
|
|
7 | MPERSP_1 | perspective | 控制透视 (绕X轴旋转)
|
2016-07-23 04:17:12 +08:00
|
|
|
|
8 | MPERSP_2 | perspective | 控制透视 (齐次坐标标志位,通常为1)
|
2016-07-20 04:04:36 +08:00
|
|
|
|
|
2016-07-20 16:55:36 +08:00
|
|
|
|
从上表中可以看出一些内容,下面我们看一下2D画布中常用的四种操作(translate, scale, rotate, skew)都是由哪些参数控制的。
|
2016-07-20 04:04:36 +08:00
|
|
|
|
|
2016-07-20 16:48:25 +08:00
|
|
|
|

|
2016-07-22 23:21:08 +08:00
|
|
|
|

|
2016-07-20 04:04:36 +08:00
|
|
|
|
|
2016-07-20 16:52:48 +08:00
|
|
|
|
>
|
2016-07-21 03:09:37 +08:00
|
|
|
|
**从上图可以看到最后三个参数是控制透视的,这三个参数主要在3D效果中运用,通常为(0, 0, 1),不在本篇范围内,暂不过多叙述,会在之后对文章中详述其作用。**
|
2016-07-20 04:04:36 +08:00
|
|
|
|
|
2016-07-22 04:01:04 +08:00
|
|
|
|
### 常见误解
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-22 02:47:02 +08:00
|
|
|
|
在写本文之前,我翻阅很多介绍 Matrix 的文章和官方文档,但其中文的搜索结果令我很悲伤,大部分的中文文章对Matrix都存在误解,想当然的创造出一些错误的理论, 导致很多(抄袭)的文章都是这一错误的理论,不知道要坑害多少小白,常见的错误理论有:
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-21 04:14:15 +08:00
|
|
|
|
**1.认为Matrix最下面的一行的三个参数(MPERSP_0、MPERSP_1、MPERSP_2)没有什么太大的作用,在这里只是为了凑数。**
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-21 04:14:15 +08:00
|
|
|
|
> **实际上最后一行参数在3D变换中有着至关重要的作用,这一点会在后面中Camera一文中详细介绍。**
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-21 17:15:35 +08:00
|
|
|
|
**2.最后一个参数MPERSP_2被解释为scale**
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-21 04:14:15 +08:00
|
|
|
|
> **的确,更改MPERSP_2的值能够达到类似缩放的效果,但这是因为齐次坐标的缘故,并非这个参数的实际功能。**
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
|
|
|
|
|
|
2016-07-23 01:11:09 +08:00
|
|
|
|
## 三、Matrix详解
|
2016-07-22 07:26:20 +08:00
|
|
|
|
|
2016-07-23 01:11:09 +08:00
|
|
|
|
Matrix 是一个矩阵,肯定会涉及到一些比较麻烦的理论知识,我会尽量用通俗易懂的方式来帮助大家理解它。
|
2016-07-22 07:26:20 +08:00
|
|
|
|
|
2016-07-24 02:53:41 +08:00
|
|
|
|
我们先简单的理解几个概念和其作用。
|
2016-07-24 02:13:56 +08:00
|
|
|
|
|
2016-07-24 02:53:41 +08:00
|
|
|
|
### 1.齐次坐标系
|
2016-07-24 02:13:56 +08:00
|
|
|
|
|
2016-07-24 02:53:41 +08:00
|
|
|
|
* 作用: 方便区分坐标和向量,方便进行仿射变换。
|
2016-07-24 02:13:56 +08:00
|
|
|
|
* 摘要: 在数学中我们的点和向量都是这样表示的(x, y),两者看起来一样,我们人可以根据上下文信息区分这是点还是向量,而计算机则无法区分,为此我们增加了一个标志位来让计算机也可以区分它们,增加时候看起来是这样: <br/>
|
2016-07-24 02:33:08 +08:00
|
|
|
|
**点(x : y : 1) - 向量(x : y : 0)**<br/>
|
2016-07-24 02:53:41 +08:00
|
|
|
|
你可能注意到了,我将分隔符换成了冒号,这是因为齐次坐标具有等比的性质,(2:3:1)、(4:6:2)...(2N,3N,N)表示的均是(2,3)这一个点。(**这也是为什么会产生将MPERSP_2解释为scale这一误解了**)
|
|
|
|
|
|
|
|
|
|
|
|
### 2.仿射变换
|
|
|
|
|
|
|
|
|
|
|
|
* 作用: 仿射变换其实是线性变换和平移变换的叠加,其实我们之前了解过的缩放,错切,旋转本质上都属于线性变换。对于我们android开发者而言,仿射变换对应的就是常见的四种画布操作(平移,旋转,缩放,错切)。
|
|
|
|
|
|
|
|
|
|
|
|
### 3.线性变换
|
|
|
|
|
|
|
|
|
|
|
|
#### a.缩放
|
2016-07-24 02:33:08 +08:00
|
|
|
|
|
2016-07-22 07:26:20 +08:00
|
|
|
|
|
2016-07-23 01:11:09 +08:00
|
|
|
|
### 四大常用操作
|
2016-07-22 02:47:02 +08:00
|
|
|
|
|
2016-07-22 03:54:40 +08:00
|
|
|
|
我们之前在 [Canvas之画布操作](https://github.com/GcsSloop/AndroidNote/blob/master/CustomView/Advance/%5B3%5DCanvas_Convert.md) 中讲解过的四种画布操作(translate, scale, rotate, skew),这些操作的核心就是改变Matrix的数值,接下来我们看看这四种操作都会影响到哪些数值。
|
2016-07-22 03:42:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 02:47:02 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-21 04:09:29 +08:00
|
|
|
|
|
2016-07-20 17:05:00 +08:00
|
|
|
|
|
2016-07-20 04:04:36 +08:00
|
|
|
|
|
2016-07-20 01:45:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-21 03:09:37 +08:00
|
|
|
|
## Matrix方法表
|
|
|
|
|
|
|
2016-07-21 04:09:29 +08:00
|
|
|
|
Matrix 有很多常用和不常用的方法,
|
2016-07-21 03:09:37 +08:00
|
|
|
|
|
|
|
|
|
|
方法类别 | 相关API | 摘要
|
|
|
|
|
|
-----------|---------------------------------------------------------|------------------------
|
|
|
|
|
|
基本方法 | equals hashCode toString toShortString | 比较、 获取哈希值、 转换为字符串
|
2016-07-23 00:58:04 +08:00
|
|
|
|
数值操作 | set reset setValues getValues | 设置、 重置、 设置数值、 获取数值
|
|
|
|
|
|
数值计算 | mapPoints mapRadius mapRect mapVectors | 计算变换后的数值
|
2016-07-21 03:09:37 +08:00
|
|
|
|
设置(set) | setConcat setRotate setScale setSkew setTranslate | 设置变换
|
|
|
|
|
|
前乘(pre) | preConcat preRotate preScale preSkew preTranslate | 前乘变换
|
|
|
|
|
|
后乘(post) | postConcat postRotate postScale postSkew postTranslate | 后乘变换
|
|
|
|
|
|
特殊方法 | setPolyToPoly setRectToRect rectStaysRect setSinCos | 一些特殊操作
|
|
|
|
|
|
矩阵相关 | invert isAffine isIdentity | 求逆矩阵、 是否为仿射矩阵、 是否为单位矩阵 ...
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-13 17:01:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-11 21:46:30 +08:00
|
|
|
|
|
|
|
|
|
|
|