iOS_Core Animation UIView的transform属性
2015-12-30 18:20
369 查看
Transform 属性:
UIView有个transform的属性,通过设置该属性,我们可以实现调整该view在其superView中的大小和位置,具体来说,Transform(变化矩阵)是一种3×3的矩阵,通过这个矩阵我们可以对一个坐标系统进行缩放,平移,旋转以及这两者的任意组着操作。而且矩阵的操作不具备交换律,即矩阵的操作的顺序不同会导致不同的结果。
常用的三种实现选中的方式:
view.transform=CGAffineTransformScale(view.transform, 0.5, 0.5); // 实现的是放大和缩小 view.transform=CGAffineTransformRotate(view.transform, 0.2); //实现的是旋转 view.transform=CGAffineTransformTranslate(view.transform, 20, 20); //实现的是平移
由此可以发现屏幕旋转其实就是通过view的矩阵变化实现,当设备监测到旋转的时候,会通知当前程序,当前程序再通知程序中的window,window会通知它的rootViewController的,rootViewController对其view的transform进行设置,最终完成旋转。
顺便记录一些常量,以后用的着!
#define M_E 2.71828182845904523536028747135266250 e
#define M_LOG2E 1.44269504088896340735992468100189214 log
2e
#define M_LOG10E 0.434294481903251827651128918916605082 log
10e
#define M_LN2 0.693147180559945309417232121458176568 log
e2
#define M_LN10 2.30258509299404568401799145468436421 log
e10
#define M_PI 3.14159265358979323846264338327950288 pi
#define M_PI_2 1.57079632679489661923132169163975144 pi/2
#define M_PI_4 0.785398163397448309615660845819875721 pi/4
#define M_1_PI 0.318309886183790671537767526745028724 1/pi
#define M_2_PI 0.636619772367581343075535053490057448 2/pi
#define M_2_SQRTPI 1.12837916709551257389615890312154517 2/sqrt(pi)
#define M_SQRT2 1.41421356237309504880168872420969808 sqrt(2)
#define M_SQRT1_2 0.707106781186547524400844362104849039 1/sqrt(2)
我们可以用照相机的原理来阐释3D图形的绘制过程,想象一下,我们在摄影的时候都需要做哪些工作,大致可分为如下几个步骤
摆放好待拍摄的物品,或者人物。
调整好拍摄角度。
调整焦距。
拍摄。
好了,来分析一下,上面的第一步就相当于世界变换了,将一个模型置于一个公认的坐标系中,这里所谓的公认,也就是大家都遵守的,目的是保证待拍摄的物体和照相机在同一个坐标系。第二步相当于视图变换,这个过程是调整Camera到合适的位置以便拍摄,在3D程序中,也就是设置View Matrix了。第三步调整焦距,这就相当于3D编程中的投影变换。
View Transform的过程就是在世界坐标系中摆放Camera的过程,并将顶点由世界坐标系转换到Camera Space,在Camera Space中,观察者(Camera)位于坐标原点,观察方向指向Z轴正方向。
在world space中,camera并不一定位于坐标原点,并且观察方向不一定指向Z轴正方向,对于投影变换及其他的一些操作来说,如果不满足这两个条件,后续的的操作就会变得非常低效,所以为了提高效率,我们需要进行view transform。
View Transform主要有下面两个作用。
移动camera,使其位于world space的坐标原点
旋转camera,使其朝向z轴正方向,也就是视线由原点指向z轴正方向。
这两个过程,前一个实际上是平移,后一个实际上是旋转。你可以想象成Camera也有三个坐标轴x,y,z,视图变换的过程就是将Camera的坐标轴与世界坐标系的坐标轴对齐的过程。
注意:view transform中,所有位于world space中的models都随着camera一起变换,所以视野并未发生变化,具体过程见下图
![](http://pic002.cnblogs.com/img/zdd/201008/2010082410282456.png)
使用下面的D3D函数可以计算view matrix,第一个参数是输出参数,返回求得的视图矩阵,第二个参数是眼睛的位置,第三个参数是观察点中心,最后一个参数是向上向量。该函数的最后两个字母表示左手系(Left Hand)。
D3DXMatrixLookAtLH(&M, &eyePt, &lookCenter, &upVec) ;
手动求解View matrix并不是难事,一个camera一般有如下四个属性,
向前向量(direction),相当于Z轴
向上向量(up vector),相当于Y轴
向右向量(right vector),相当于X轴
位置(position)
其中前三个向量要求是相互垂直的。假设我们分别用d, u, v和p来表示这四个变量。并假设待求的视图矩阵为V,根据前面的介绍我们知道,V的作用就是将摄像机移动到原点,并将摄像机的三个向量分别与坐标轴对齐,d与z轴正方向对齐,u与y轴正方向对齐,r与x轴正方向对齐。假设将摄像机与坐标轴对齐的矩阵为V,那么V的推导过程如下。
![](http://pic002.cnblogs.com/images/2012/64257/2012062722473484.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012062722474754.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012062723245333.jpg)
通常在实际的编程中,只会给出如下三个量。至于d和r这两个量,只能通过计算求得。
摄像机(眼睛)的位置(eye point),相当于p
观察点中心(look at),假设为向量c
向上向量(up vector),相当于u
可以通过下面方法求得d, r和u。
d = c - p,下面第一幅图
r = d x u,下面第二幅图
u = r x d,下面第三幅图
![](http://pic002.cnblogs.com/images/2012/64257/2012071121341217.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012071121451564.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012071121454195.jpg)
注意上面的x是叉积运算(cross product),现在p,d,r,u四个量都已经知道,于是就可以根据上面的矩阵M求得视图变换矩阵了,对应的代码如下。该函数有三个参数,分别是摄像机位置p,向上向量u和视点中心lookAt。
注意事项,在求取View Matrix的时候有几点是需要注意的:
叉积满足右手法则。
叉积不满足交换律。 a x b = - b x a
DirectX使用左手系,满足左手法则。
只要最终求得的三个向量,up, right和d满足左手法则即可。如果应用了View Matrix之后发现模型左右或者上下颠倒了,那么就说明求取的时候没有满足左手系。
好了,矩阵求解完毕,赶快使用SetTransform(D3DTS_VIEW, &M) ;来试试吧,效果和使用函数D3DXMatrixLookAtLH是一样的!
Happy Coding!!!
作者:zdd
出处:http://www.cnblogs.com/graphics/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
UIView有个transform的属性,通过设置该属性,我们可以实现调整该view在其superView中的大小和位置,具体来说,Transform(变化矩阵)是一种3×3的矩阵,通过这个矩阵我们可以对一个坐标系统进行缩放,平移,旋转以及这两者的任意组着操作。而且矩阵的操作不具备交换律,即矩阵的操作的顺序不同会导致不同的结果。
常用的三种实现选中的方式:
view.transform=CGAffineTransformScale(view.transform, 0.5, 0.5); // 实现的是放大和缩小 view.transform=CGAffineTransformRotate(view.transform, 0.2); //实现的是旋转 view.transform=CGAffineTransformTranslate(view.transform, 20, 20); //实现的是平移
由此可以发现屏幕旋转其实就是通过view的矩阵变化实现,当设备监测到旋转的时候,会通知当前程序,当前程序再通知程序中的window,window会通知它的rootViewController的,rootViewController对其view的transform进行设置,最终完成旋转。
顺便记录一些常量,以后用的着!
#define M_E 2.71828182845904523536028747135266250 e
#define M_LOG2E 1.44269504088896340735992468100189214 log
2e
#define M_LOG10E 0.434294481903251827651128918916605082 log
10e
#define M_LN2 0.693147180559945309417232121458176568 log
e2
#define M_LN10 2.30258509299404568401799145468436421 log
e10
#define M_PI 3.14159265358979323846264338327950288 pi
#define M_PI_2 1.57079632679489661923132169163975144 pi/2
#define M_PI_4 0.785398163397448309615660845819875721 pi/4
#define M_1_PI 0.318309886183790671537767526745028724 1/pi
#define M_2_PI 0.636619772367581343075535053490057448 2/pi
#define M_2_SQRTPI 1.12837916709551257389615890312154517 2/sqrt(pi)
#define M_SQRT2 1.41421356237309504880168872420969808 sqrt(2)
#define M_SQRT1_2 0.707106781186547524400844362104849039 1/sqrt(2)
什么是View Transform
我们可以用照相机的原理来阐释3D图形的绘制过程,想象一下,我们在摄影的时候都需要做哪些工作,大致可分为如下几个步骤摆放好待拍摄的物品,或者人物。
调整好拍摄角度。
调整焦距。
拍摄。
好了,来分析一下,上面的第一步就相当于世界变换了,将一个模型置于一个公认的坐标系中,这里所谓的公认,也就是大家都遵守的,目的是保证待拍摄的物体和照相机在同一个坐标系。第二步相当于视图变换,这个过程是调整Camera到合适的位置以便拍摄,在3D程序中,也就是设置View Matrix了。第三步调整焦距,这就相当于3D编程中的投影变换。
View Transform的过程就是在世界坐标系中摆放Camera的过程,并将顶点由世界坐标系转换到Camera Space,在Camera Space中,观察者(Camera)位于坐标原点,观察方向指向Z轴正方向。
为什么要进行View Transform?
在world space中,camera并不一定位于坐标原点,并且观察方向不一定指向Z轴正方向,对于投影变换及其他的一些操作来说,如果不满足这两个条件,后续的的操作就会变得非常低效,所以为了提高效率,我们需要进行view transform。
View Transform的作用
View Transform主要有下面两个作用。移动camera,使其位于world space的坐标原点
旋转camera,使其朝向z轴正方向,也就是视线由原点指向z轴正方向。
这两个过程,前一个实际上是平移,后一个实际上是旋转。你可以想象成Camera也有三个坐标轴x,y,z,视图变换的过程就是将Camera的坐标轴与世界坐标系的坐标轴对齐的过程。
注意:view transform中,所有位于world space中的models都随着camera一起变换,所以视野并未发生变化,具体过程见下图
![](http://pic002.cnblogs.com/img/zdd/201008/2010082410282456.png)
如何求解View Matrix?
使用D3D函数
使用下面的D3D函数可以计算view matrix,第一个参数是输出参数,返回求得的视图矩阵,第二个参数是眼睛的位置,第三个参数是观察点中心,最后一个参数是向上向量。该函数的最后两个字母表示左手系(Left Hand)。D3DXMatrixLookAtLH(&M, &eyePt, &lookCenter, &upVec) ;
手动求解
手动求解View matrix并不是难事,一个camera一般有如下四个属性,向前向量(direction),相当于Z轴
向上向量(up vector),相当于Y轴
向右向量(right vector),相当于X轴
位置(position)
其中前三个向量要求是相互垂直的。假设我们分别用d, u, v和p来表示这四个变量。并假设待求的视图矩阵为V,根据前面的介绍我们知道,V的作用就是将摄像机移动到原点,并将摄像机的三个向量分别与坐标轴对齐,d与z轴正方向对齐,u与y轴正方向对齐,r与x轴正方向对齐。假设将摄像机与坐标轴对齐的矩阵为V,那么V的推导过程如下。
![](http://pic002.cnblogs.com/images/2012/64257/2012062722473484.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012062722474754.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012062723245333.jpg)
通常在实际的编程中,只会给出如下三个量。至于d和r这两个量,只能通过计算求得。
摄像机(眼睛)的位置(eye point),相当于p
观察点中心(look at),假设为向量c
向上向量(up vector),相当于u
可以通过下面方法求得d, r和u。
d = c - p,下面第一幅图
r = d x u,下面第二幅图
u = r x d,下面第三幅图
![](http://pic002.cnblogs.com/images/2012/64257/2012071121341217.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012071121451564.jpg)
![](http://pic002.cnblogs.com/images/2012/64257/2012071121454195.jpg)
注意上面的x是叉积运算(cross product),现在p,d,r,u四个量都已经知道,于是就可以根据上面的矩阵M求得视图变换矩阵了,对应的代码如下。该函数有三个参数,分别是摄像机位置p,向上向量u和视点中心lookAt。
D3DXMATRIX buildViewMatrix(D3DXVECTOR3& p, D3DXVECTOR3& u, D3DXVECTOR3& lookAt) { // Calculate d D3DXVECTOR3 d = lookAt - p; D3DXVec3Normalize(&d, &d); // Calculate r D3DXVECTOR3 r; D3DXVec3Cross(&r, &u, &d); D3DXVec3Normalize(&r, &r); // Calculate up D3DXVec3Cross(&u, &r, &d); D3DXVec3Normalize(&u, &u); // Fill in the view matrix entries. float x = -D3DXVec3Dot(&p, &r); float y = -D3DXVec3Dot(&p, &u); float z = -D3DXVec3Dot(&p, &d); D3DXMATRIX M; M(0,0) = r.x; M(1,0) = r.y; M(2,0) = r.z; M(3,0) = x; M(0,1) = u.x; M(1,1) = u.y; M(2,1) = u.z; M(3,1) = y; M(0,2) = d.x; M(1,2) = d.y; M(2,2) = d.z; M(3,2) = z; M(0,3) = 0.0f; M(1,3) = 0.0f; M(2,3) = 0.0f; M(3,3) = 1.0f; return M; }
注意事项,在求取View Matrix的时候有几点是需要注意的:
叉积满足右手法则。
叉积不满足交换律。 a x b = - b x a
DirectX使用左手系,满足左手法则。
只要最终求得的三个向量,up, right和d满足左手法则即可。如果应用了View Matrix之后发现模型左右或者上下颠倒了,那么就说明求取的时候没有满足左手系。
好了,矩阵求解完毕,赶快使用SetTransform(D3DTS_VIEW, &M) ;来试试吧,效果和使用函数D3DXMatrixLookAtLH是一样的!
Happy Coding!!!
作者:zdd
出处:http://www.cnblogs.com/graphics/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
相关文章推荐
- 使用UITableViewController注意事项
- 用request.files实现异文件上传(开放式上传)
- setValuesForKeysWithDictionary崩溃问题
- @PATHVARIABLE和@REQUESTPARAM的区别,@SESSIONATTRIBUTES
- 月try如同一条yui
- iOS中UIImageView 添加UITapGestureRecognizer后传参
- Interface Builder一些使用技巧
- iOS中UIKit——UIButton设置边框
- 扩展 easyui-tabs 插件 关闭标签页方法
- Java发邮件-QQ服务器认证(A secure connection is requiered(such as ssl))
- requireJS配置选项
- UITextField 限制字数与输入内容
- java 报错 the type JOptionPane is not accessible due to restriction on required library ×
- CAD 利用代码加载cui文件
- 最新Aria2控制前端WebUI客户端安装教程
- UIView的动画事务
- ios7上实现UIVisualEffectView效果
- js unique
- EasyUI 动态更新列
- EasyUI combogrid 赋多个值