transform的结构如下:
struct CATransform3D
{
  CGFloat m11, m12, m13, m14;
  CGFloat m21, m22, m23, m24;
  CGFloat m31, m32, m33, m34;
  CGFloat m41, m42, m43, m44;
};

首先要实现view(layer)的透视效果(就是近大远小),是通过设置m34的:

CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -500;

m34负责z轴方向的translation(移动),m34= -1/D,  默认值是0,也就是说D无穷大,这意味layer in projection plane(投射面)和layer in world coordinate重合了。

D越小透视效果越明显。

所谓的D,是eye(观察者)到投射面的距离。

概述

在iOS中使用CATransform3D这个结构体来表示三维的齐次坐标变换矩阵. 齐次坐标是一种坐标的表示方法,n维空间的坐标需要用n+1个元素的坐标元组来表示,在Quartz 2D Transform中就有关于齐次坐标的应用,那边是关于二维空间的变换,其某点的齐次坐标的最后一个元素始终设置为1。使用齐次坐标而不是简单的数学坐标是为了方便图形进行仿射变换,仿射变换可以通过仿射变换矩阵来实现,3D的仿射变换可以实现诸如 平移(translation),旋转(rotation),缩放(scaling),切变(shear)等变换。如果不用齐次坐标那么进行坐标变换可能就涉及到两种运算了,加法(平移)和乘法(旋转,缩放),而使用齐次坐标以及齐次坐标变换矩阵后只需要矩阵乘法就可以完成一切了。上面的这些如果需要深入了解就需要去学习一下图形变换的相关知识,自己对矩阵的乘法进行演算。

iOS中的CALayer的3D本质上并不能算真正的3D(其视点即观察点或者所谓的照相机的位置是无法变换的),而只是3D在二维平面上的投影,投影平面就是手机屏幕也就是xy轴组成的平面(注意iOS中为左手坐标系),那么视点的位置是如何确定的呢?可以通过CATransform3D中的m34来间接指定, m34 = -1/z,其中z为观察点在z轴上的值,而Layer的z轴的位置则是通过anchorPoint来指定的,所谓的anchorPoint(锚点)就是在变换中保持不变的点,也就是某个Layer在变换中的原点,xyz三轴相交于此点。在iOS中,Layer的anchorPoint使用unit coordinate space来描述,unit coordinate space无需指定具体真实的坐标点而是使用layer bounds中的相对位置,下图展示了一个Layer中的几个特殊的锚点, 

m34 = -1/z中,当z为正的时候,是我们人眼观察现实世界的效果,即在投影平面上表现出近大远小的效果,z越靠近原点则这种效果越明显,越远离原点则越来越不明显,当z为正无穷大的时候,则失去了近大远小的效果,此时投影线垂直于投影平面,也就是视点在无穷远处,CATransform3D中m34的默认值为0,即视点在无穷远处.

还有一个需要说明一下的就是齐次坐标到数学坐标的转换 通用的齐次坐标为 (a, b, c, h),其转换成数学坐标则为 (a/h, b/h, c/h).

代数解释

假设一个Layer anchorPoint为默认的 (0.5, 0.5 ), 其三维空间中一个A点 (6, 0, 0),m34 = -1/1000.0, 则此点往z轴负方向移动10个单位之后,则在投影平面上看到的点的坐标是多少呢?

A点使用齐次坐标表示为 (6, 0, 0, 1)

QuartzCore框架为我们提供了函数来算出所需要的矩阵,

    CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1/1000.0;
transform = CATransform3DTranslate(transform, 0, 0, -10);

计算出来的矩阵为


{ 1, 0, 0, 0;
0, 1, 0, 0;
0, 0, 1, -0.001;
0, 0, -10, 1.01;
}

其实上面的变换矩阵本质上是两个矩阵相乘得到的 变换矩阵 * 投影矩阵 变换矩阵为

{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;
}

上面的两个矩阵相乘则会得到最终的变换矩阵(如果忘记矩阵乘法的可以去看下线性代数复习下),所以一个矩阵就可以完成变换和投影。

将A点坐标乘上最终的变换矩阵,则得到 {6, 0 , -10, 1.01}, 转换成数学坐标点为 {6/1.01, 0, 10/1.01},则可以知道其在投影平面上的投影点为 {6/1.01, 0, 0} 也就是我们看到的变换后的点。其比之前较靠近原点。越往z轴负方向移动,则在投影平面上越靠近原点。

几何解释

将上面的例子使用几何的方式来进行解释分析,当我们沿着y轴的正方向向下看时候,可以得到如下的景象

虚线为投影线,其和x轴的交点即为A点的投影点。 由相似三角形的定理我们很容易算出投影的点,

1000/(1000 + 10) = x/6,则x = 6*1000/1010 = 6/1.01

iOS动画 三维透视投影 m34的更多相关文章

  1. 简析iOS动画原理及实现——Core Animation

    本文转载至 http://www.tuicool.com/articles/e2qaYjA 原文  https://tech.imdada.cn/2016/06/21/ios-core-animati ...

  2. 解析 iOS 动画原理与实现

    这篇文章不会教大家如何实现一个具体的动画效果,我会从动画的本质出发,来说说 iOS 动画的原理与实现方式. 什么是动画 动画,顾名思义,就是能“动”的画.人的眼睛对图像有短暂的记忆效应,所以当眼睛看到 ...

  3. (转)iOS动画Core Animation

    文章转载:http://blog.sina.com.cn/s/blog_7b9d64af0101b8nh.html 在iOS中动画实现技术主要是:Core Animation. Core Animat ...

  4. IOS动画隐式,显式,翻页

    //  ViewController.m //  IOS动画0817 // //  Created by 张艳锋 on 15/8/17. //  Copyright (c) 2015年 张艳锋. Al ...

  5. iOS动画原理

    1. iOS动画原理 本质:动画对象(这里是UIView)的状态,基于时间变化的反应 分类:可以分为显式动画(关键帧动画和逐帧动画)和隐式动画 关键帧和逐帧总结:关键帧动画的实现方式,只需要修改某个属 ...

  6. iOS 动画基础

    原文:http://www.cnblogs.com/lujianwenance/p/5733846.html   今天说一下有关动画的基础,希望能帮助到一些刚接触iOS动画或者刚开始学习iOS的同学, ...

  7. ios 动画效果CATransition笔记

    初学ios开发,很多概念还不清楚,所以只有边学边做例子.又怕学了后面忘了前面,因此用自己的博客来纪录自己的学习历程,也是对自己学习不要懈怠做个监督. 刚学ios做动画效果.因为ios封装得很好,实现i ...

  8. IOS动画总结

    IOS动画总结   一.基本方式:使用UIView类的UIViewAnimation扩展 + (void)beginAnimations:(NSString *)animationID context ...

  9. ios 动画学习的套路 (二)

    有它们俩你就够了! 说明:下面有些概念我说的不怎么详细,网上实在是太多了,说了我觉得也意义不大了!但链接都给大家了,可以自己去看,重点梳理学习写动画的一个过程和一些好的博客! (一) 说说这两个三方库 ...

随机推荐

  1. 关于 MySQL 的 boolean 和 tinyint(1) (转)

    boolean类型MYSQL保存BOOLEAN值时用1代表TRUE,0代表FALSE,boolean在MySQL里的类型为tinyint(1),MySQL里有四个常量:true,false,TRUE, ...

  2. git 常用命令 (git did not exit cleanly)

    Git常用操作命令收集: git clonegit git remote -v git remote add [name] [url] git remote rm [name] git remote ...

  3. ubuntu14.04 wifi驱动安装

    重装linux后,一直搜不到wlan0,无法启动wifi,经过重重努力,终于成功,在此简单记录一下. 1. 查看网卡类型: ~$ lspci -nn -d 14e4: :]: Broadcom Cor ...

  4. lable标签透明

    方法1: pictureBox1.Controls.Add(lable1);    //或 this.label1.Parent=pictureBox1;   lable1.BackColor=Col ...

  5. vim扩展配置

    在用户根目录下新建 “.vimrc”文件,键入一下代码: set syntax=on "高亮语法 set fenc=utf- "设定默认解码 set fencs=utf-,usc- ...

  6. 打开FTP服务器上的文件夹时发生错误,请检查是否有权限访问该文件夹

    打开FTP服务器上的文件夹时发生错误,请检查是否有权限访问 在win98,winme,win2000,win2003下都能正常上传文件夹,但在winxp+sp2下同样的文件夹就可能出现问题 1. 打开 ...

  7. 20145305 《Java程序设计》第2周学习总结

    教材学习内容总结 1.boolean类型可表示true与false 2.储存值超类型范围会出现溢值 3.变量在命名时不可以使用数字作为开头,不可以使用一些特殊字符,不可以与JAVA关键词同名,不可以与 ...

  8. Delphi Alpha皮肤控件使用方法

    //用于刷新控件颜色. FsSkinManager.BeginUpdate; FsSkinManager.EndUpdate(True); //动态选择皮肤 begin if not FIsswitc ...

  9. 使用jaxp对比xml进行SAX解析

    package cn.itcast.sax; import java.io.IOException; import javax.xml.parsers.ParserConfigurationExcep ...

  10. 4.1.1 A - Calendar(简单线性表)(日期查找)(数组应用)

    Description A calendar is a system for measuring time, from hours and minutes, to months and days, a ...