transform的結(jié)構(gòu)如下:
struct CATransform3D{
CGFloat m11, m12, m13, m14;
CGFloat m21, m22, m23, m24;
CGFloat m31, m32, m33, m34;
CGFloat m41, m42, m43, m44;};
首先要實(shí)現(xiàn)view(layer)的透視效果(就是近大遠(yuǎn)胁蛐汀)崔赌,是通過設(shè)置m34的:CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;rotationAndPerspectiveTransform.m34 = 1.0 / -500;m34負(fù)責(zé)z軸方向的translation(移動(dòng))作煌,m34= -1/D, 默認(rèn)值是0茄厘,也就是說D無窮大靶剑,這意味layer in projection plane(投射面)和layer in world coordinate重合了。D越小透視效果越明顯。所謂的D警绩,是eye(觀察者)到投射面的距離。
一.概述
在iOS中使用CATransform3D這個(gè)結(jié)構(gòu)體來表示三維的齊次坐標(biāo)變換矩陣. 齊次坐標(biāo)是一種坐標(biāo)的表示方法盅称,n維空間的坐標(biāo)需要用n+1個(gè)元素的坐標(biāo)元組來表示,在Quartz 2D Transform中就有關(guān)于齊次坐標(biāo)的應(yīng)用,那邊是關(guān)于二維空間的變換肩祥,其某點(diǎn)的齊次坐標(biāo)的最后一個(gè)元素始終設(shè)置為1。使用齊次坐標(biāo)而不是簡單的數(shù)學(xué)坐標(biāo)是為了方便圖形進(jìn)行仿射變換缩膝,仿射變換可以通過仿射變換矩陣來實(shí)現(xiàn)混狠,3D的仿射變換可以實(shí)現(xiàn)諸如 平移(translation),旋轉(zhuǎn)(rotation),縮放(scaling),切變(shear)等變換疾层。如果不用齊次坐標(biāo)那么進(jìn)行坐標(biāo)變換可能就涉及到兩種運(yùn)算了将饺,加法(平移)和乘法(旋轉(zhuǎn),縮放)痛黎,而使用齊次坐標(biāo)以及齊次坐標(biāo)變換矩陣后只需要矩陣乘法就可以完成一切了予弧。上面的這些如果需要深入了解就需要去學(xué)習(xí)一下圖形變換的相關(guān)知識(shí),自己對(duì)矩陣的乘法進(jìn)行演算湖饱。
iOS中的CALayer的3D本質(zhì)上并不能算真正的3D(其視點(diǎn)即觀察點(diǎn)或者所謂的照相機(jī)的位置是無法變換的),而只是3D在二維平面上的投影掖蛤,投影平面就是手機(jī)屏幕也就是xy軸組成的平面(注意iOS中為左手坐標(biāo)系),那么視點(diǎn)的位置是如何確定的呢井厌?可以通過CATransform3D中的m34來間接指定蚓庭, m34 = -1/z,其中z為觀察點(diǎn)在z軸上的值,而Layer的z軸的位置則是通過anchorPoint來指定的致讥,所謂的anchorPoint(錨點(diǎn))就是在變換中保持不變的點(diǎn),也就是某個(gè)Layer在變換中的原點(diǎn),xyz三軸相交于此點(diǎn)器赞。在iOS中垢袱,Layer的anchorPoint使用unit coordinate space來描述,unit coordinate space無需指定具體真實(shí)的坐標(biāo)點(diǎn)而是使用layer bounds中的相對(duì)位置港柜,下圖展示了一個(gè)Layer中的幾個(gè)特殊的錨點(diǎn),
m34 = -1/z中惶桐,當(dāng)z為正的時(shí)候,是我們?nèi)搜塾^察現(xiàn)實(shí)世界的效果潘懊,即在投影平面上表現(xiàn)出近大遠(yuǎn)小的效果,z越靠近原點(diǎn)則這種效果越明顯贿衍,越遠(yuǎn)離原點(diǎn)則越來越不明顯授舟,當(dāng)z為正無窮大的時(shí)候,則失去了近大遠(yuǎn)小的效果贸辈,此時(shí)投影線垂直于投影平面释树,也就是視點(diǎn)在無窮遠(yuǎn)處,CATransform3D中m34的默認(rèn)值為0擎淤,即視點(diǎn)在無窮遠(yuǎn)處.
還有一個(gè)需要說明一下的就是齊次坐標(biāo)到數(shù)學(xué)坐標(biāo)的轉(zhuǎn)換 通用的齊次坐標(biāo)為 (a, b, c, h),其轉(zhuǎn)換成數(shù)學(xué)坐標(biāo)則為 (a/h, b/h, c/h).
二.代數(shù)解釋
假設(shè)一個(gè)Layer anchorPoint為默認(rèn)的 (0.5, 0.5 ), 其三維空間中一個(gè)A點(diǎn) (6, 0, 0)奢啥,m34 = -1/1000.0, 則此點(diǎn)往z軸負(fù)方向移動(dòng)10個(gè)單位之后,則在投影平面上看到的點(diǎn)的坐標(biāo)是多少呢嘴拢?
A點(diǎn)使用齊次坐標(biāo)表示為 (6, 0, 0, 1)
QuartzCore框架為我們提供了函數(shù)來算出所需要的矩陣桩盲,
CATransform3D transform = CATransform3DIdentity; transform.m34 = -1/1000.0; transform = CATransform3DTranslate(transform, 0, 0, -10);
計(jì)算出來的矩陣為
{ 1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, -0.001; 0, 0, -10, 1.01; }
其實(shí)上面的變換矩陣本質(zhì)上是兩個(gè)矩陣相乘得到的 變換矩陣 * 投影矩陣 變換矩陣為
{1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, -10, 1; }
投影矩陣為
{1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, -0.001; 0, 0, 0, 1; }
上面的兩個(gè)矩陣相乘則會(huì)得到最終的變換矩陣(如果忘記矩陣乘法的可以去看下線性代數(shù)復(fù)習(xí)下),所以一個(gè)矩陣就可以完成變換和投影席吴。
將A點(diǎn)坐標(biāo)乘上最終的變換矩陣赌结,則得到 {6, 0 , -10, 1.01}, 轉(zhuǎn)換成數(shù)學(xué)坐標(biāo)點(diǎn)為 {6/1.01, 0, 10/1.01},則可以知道其在投影平面上的投影點(diǎn)為 {6/1.01, 0, 0} 也就是我們看到的變換后的點(diǎn)。其比之前較靠近原點(diǎn)孝冒。越往z軸負(fù)方向移動(dòng)柬姚,則在投影平面上越靠近原點(diǎn)。
三.幾何解釋
將上面的例子使用幾何的方式來進(jìn)行解釋分析庄涡,當(dāng)我們沿著y軸的正方向向下看時(shí)候量承,可以得到如下的景象
虛線為投影線,其和x軸的交點(diǎn)即為A點(diǎn)的投影點(diǎn)穴店。 由相似三角形的定理我們很容易算出投影的點(diǎn)撕捍,
1000/(1000 + 10) = x/6,則x = 6*1000/1010 = 6/1.01