As3 Matrix 理解与应用

TheMatrixWallpaper800

一、介绍

Matrix 字面意思是矩阵, 是一个数学概念。这个词在本科线性代数里有详细说明,它是数的一个排列,支持好多种数学运算!在flash里,在3D运算中,矩阵 真的是无处不在。flash中,你要使一个可显示对象(DisplayObject )旋转,倾斜,调位置你都可以通过矩阵来完成,虽然你还有其他更简单的方法,就是通过修改rotation, x, y 等值来达到同样的目的。在每个显示对象中,都有一个属性:transform. 这里就包含了显示对象的各种变换,其中一项,就是matrix! 可见matrix在flash中也有重要的作用。

二、为什么是矩阵

矩阵对于很多数学恐惧者来说,很让人无法直视, 真的很让人头痛!但是它却在计算机图形学里起着很重要的作用。我们从简单说起!

2.1 坐标系统

在我们的学习中,就已经深刻的学习了坐标系统的概念,要分析空间物体及其对应关系,就离不开坐标系这个概念!我们最熟悉的是笛卡尔坐标系, 直角坐标系!在坐标系里又可以找到很多概念,这些概念对于我们理解这矩阵有着很重要的作用。 比如说,物体坐标系, 旋转坐标系,世界坐标系等。

世界坐标系,简单来说,它是空间里处于全局位置,永远不变的坐标系。举个例子,我们要研究小猫在房间里的运动路径,这时我们可以选择房间里的一个角落来作为我们的世界坐标系。 物体坐标系,就是以处于世界坐标系下的一个物体上的某一点构成的坐标系,假如我们选择小猫正常站立形态下后脚作为原点建立一个直角坐标系,那么,这个坐标系就是小猫的物体坐标系,这个物体坐标系相对世界坐标系而言,它会随着猫的运动而运动!

2.2 物体变换

我们选定了物体坐标系, 小猫一天中会在房间里各处走动,或跑,或跳,或睡觉等,那么,这时的小猫就相对世界坐标系而言,它发生了一些变换,可能包括:平移,旋转,当然还可能包括缩放(缩着身子)。 假如小猫在进食时在身上沾了一粒米,那么,在小猫在世界坐标系里进行变换时,这粒米相对相对世界坐标系又是怎么一个情形呢? 这就相当于在数学上一个物体从一个坐标系变换到另一个坐标系下,如何确定其位置的问题,对于这个问题,用矩阵可以很好的来解决这个问题!

在flash里,矩阵matrix也是一样用于处理坐标变换的问题。相信大家可能曾经会想过一个问题。 一个显示对象有宽,有高,那么对于这些内容是如何分层次的画出来的,又如何确定物体内部每个点在舞台上的位置的呢? 没错,就是通过坐标变换来实现的!

三、矩阵

flash里 矩阵用于将点从一个坐标系转换到另一个坐标系, 使用下面的方程:

clip_image002

其中P代表变换后的坐标点, N代表变换前坐标点(都是以列向量的形式)。

显示对象的transform属性的matrix就是这个M, 它用于将物体坐标系里的点变换到显示对象父坐标中。

image

这个M是一个3维矩阵,如下所示:

Matrix class properties in matrix notation showing    assumed values for u, v, and w

转换过程如下:

clip_image002[4]

其中a, d 影响显示对象的缩放, c, d 影响显示对象的倾斜, a, b, c, d同时影响显示对象的旋转。 tx, ty 代表显示对象相对于父对象的位置偏移!如果clip_image002[6] 都为0 的话,

那么clip_image002[8]就是 clip_image002[10] 所以说, tx, ty 就是显示对象的坐标。

四、应用

1. 获取对象里某一点在父对象中的位置。

var p:Point = new Point( x0, y0 );
p = displayObject.transform.matrix.transformPoint( p );

2. 绘制渐变图

代码示例略

3. 中心旋转

public function rotateAroundCenter (ob:DisplayObject, angleDegrees:Number):void
{
    var matrix:Matrix = ob.transform.matrix; 

    var rect:Rectangle = ob.getBounds(ob.parent); 

    matrix.translate(- (rect.left + (rect.width/2)), - (rect.top + (rect.height/2))); 

    matrix.rotate((angleDegrees/180)*Math.PI); 

    matrix.translate(rect.left + (rect.width / 2), rect.top + (rect.height / 2));

    ob.transform.matrix = matrix;
}

4. 绕点旋转

// get matrix object from your MovieClip (mc)
var m:Matrix = mc.transform.matrix;

// set the point around which you want to rotate your MovieClip (relative to the MovieClip position)
var point:Point = new Point(10, 10);

// get the position of the MovieClip related to its origin and the point around which it needs to be rotated
point = m.transformPoint(point);
// set it
m.translate( -point.x, -point.y);

// rotate it of 30°
m.rotate(30 * (Math.PI / 180));

// and get back to its "normal" position
m.translate(point.x, point.y);

// finally, to set the MovieClip position, use this
mc.transform.matrix = m;

// or this
mc.x = m.tx;
mc.y = m.ty;
mc.rotation += 30;

值得注意的是, 你通过Matrix的rotate方法旋转得到的效果与你通过显示对象的rotation属性得到的是不样的!这是因为 matrix.rotate 以父对象的原点为旋转中心,旋转的是物体坐标系, 所以,通过rotate是会改变tx, ty的。 如下图所示:

image

希望本文章能够帮到你!转载请注明梦溪笔记!

基于THREE JS的 JSON 模型格式 理解

THREE.js 是一个开源的基于WebGL的渲染引擎,提供了很多方便有用的类与方法,为我们使用WebGL提供了大大的便利,简化了我们的学习成本,让你只要专注于项目本身,而不会花太多时间留在WebGL的技术实现细节。当你在处理3D网络应用或项目时,你就会遇到一个问题,选择一个适合的模型格式就会摆在你的案头。obj, 3ds, dae还是其他什么呢?对于那些以二进制进行数据保存的格式而已,网络加载是一个问题,js处理二进制也是一个问题, 所以,如果有一个可以完美支持JS特性的格式,那真是令人高兴的事情,JSON Model Format 就是这样一种模式格式。

JSON Model Format 的基本格式如下:

{
	"metadata": { "formatVersion" : 3 },	

	"materials": [ {
		"DbgColor" : 15658734, // => 0xeeeeee
		"DbgIndex" : 0,
		"DbgName" : "dummy",
		"colorDiffuse" : [ 1, 0, 0 ],
	} ],

	"vertices": [ 0,0,0, 0,0,1, 1,0,1, 1,0,0, ... ],
	"normals":  [ 0,1,0, ... ],
	"colors":   [ 1,0,0, 0,1,0, 0,0,1, 1,1,0, ... ],
	"uvs":      [ [ 0,0, 0,1, 1,0, 1,1 ], ... ],

	"faces": 	[43, 0, 4, 5, 1, 0, 0, 1, 2, 3, 0, 1, 2, 3]
}

其中Metadata 中包含formatVersion 用于指示当前文件所用的格式版本号,这将决定于解析器如何解析下面的文件内容。

接下来另一个重要的域是Materials, 指定该模型所用到的素材,一个模型可能用到多个素材,所以,Materials是一个数组,每一项都是material对象。每个Material对象都包括DbgIndex 指示该Material的索引,DbgName显示Matrial的名字。

接下来的一个域是vertices, 也就是顶点了,顶点以三个数为一组,每三个数组成一个顶点坐标,x, y, z. Normals用于保存法线坐标,跟顶点一样,每三个数组成一个法线向量。 Colors是顶点颜色, THREE.js 允许给每个顶点指定颜色。 uvs是贴图坐标,faces是模型的面了,我们都知道模型是由三角面、四角面或多边形面组成的, faces就是用来保存这个面的信息。

一个面可以包括多个信息,比如说,他是三角面还是四边形面或是其他?每个顶点是不是有颜色?是不是只有一个面法线还是有面顶点法线?要区分并保存这些信息,faces是如何做的吗?其他他的格式是这样的,基本上可以看做是流式。以一个标志为开头,后面跟一系列的数据说明。例如:

[ 43, 0, 4, 5, 1, 0, 0, 1, 2, 3, 0, 1, 2, 3 ]

第一个数, 43 就是这个标志. 把这个标志表示成二进制,它的每个二进制位都代表着不同的意思。43 表示成二进制如下:

00 10 10 11

43 表示成一个字节,8个二进制位,每个位都有特定含意,如果这个位为1(置位),表示这个位在后续的数据流中有表示,如果为0,则说明后续的数据流中没有该位所代表的特定含意的数据表示。那么这8个位都表示什么意思呢?

二进制位

含意

0

面的类型。如果为0,表示三角面,为1表示四边形面

1

指示该面是否有素材,0表示没有,1表示有

2

指示该面是否有贴图坐标,0表示没有,1表示有

3

指示该面是否有顶点贴图坐标,0表示没有,1表示有

4

指示该面是否有面法线,0表示没有,1表示有

5

指示该面是否有顶点法线,0表示没有,1表示有

6

指示是否为面指定了颜色,0表示没有,1表示有

7

指示是否有顶点颜色,0表示没有,1表示有

 

后面的数据是按照从小大到的顺序排列的。 例如如果标志为43的话,表示 四边形面,有素材,有顶点贴图坐标,有顶点法线。所以,43后面跟着的四位数:0, 4, 5, 1 就是对应顶点的索引。 那么接下来的 0 就表示当前面的素材索引为 0, 然后接下来的 0, 1, 2, 3, 表示顶点贴图坐标的索引,最后的0, 1, 2, 3 则是顶点法线的索引。.

以上说的是大部分模型都会有的数据。有些特殊的模型还会有别的域,比如说

 "morphTargets" : [{ "name": "animation_000000", "vertices": [ ... ] }, ... { "name": "animation_000000", "vertices": [ ... ]}],
 "bones" : [],
 "skinIndices" : [],
 "skinWeights" : [],
 "animation" : {}

morphTargets存在表示模型存在变形动画,后面跟着的都是每帧的顶点数据。 bones用于保存骨骼信息,animation用于保存动画信息。

以上是基本的对JSON Model Format 的说明与解析,希望能对你有所帮助。

本文为原创,如果你想转载,请注明“梦溪笔记”出品!

3D-Book