Unity 3Dwpf 触摸屏滑动相册,单指左右滑动360°旋转物体,上线旋转限制在60°之内,欧拉选转后还会恢复原来的角度

没有更多推荐了,
不良信息举报
举报内容:
Unity 中的旋转
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!【Unity编程】Unity中的欧拉旋转
欧拉角的定义
在写这篇博客之前,我搜索了网上很多关于欧拉角的定义,发现大部分引用自维基百科的定义,我这里也引述一下:
维基百科定义
莱昂哈德·欧拉用欧拉角来描述刚体在三维欧几里得空间的取向。对于任何参考系,一个刚体的取向,是依照顺序,从这参考系,做三个欧拉角的旋转而设定的。所以,刚体的取向可以用三个基本旋转矩阵来决定。换句话说,任何关于刚体旋转的旋转矩阵是由三个基本旋转矩阵复合而成的。
对于在三维空间里的一个参考系,任何坐标系的取向,都可以用三个欧拉角来表现。参考系又称为实验室参考系,是静止不动的。而坐标系则固定于刚体,随着刚体的旋转而旋转。参阅下图。设定xyz-轴为参考系的参考轴。三个欧拉角: (αβγ),蓝色的轴是xyz-轴,红色的轴是XYZ-坐标轴。称xy-平面与XY-平面的相交为交点线(绿色),用英文字母(N)代表。
zxz顺规的欧拉角可以静态地这样定义:
α是x-轴与交点线的夹角,
β是z-轴与Z-轴的夹角,
γ是交点线与X-轴的夹角。
很可惜地,对于夹角的顺序和标记,夹角的两个轴的指定,并没有任何常规。科学家对此从未达成共识。每当用到欧拉角时,我们必须明确的表示出夹角的顺序,指定其参考轴。
实际上,有许多方法可以设定两个坐标系的相对取向。欧拉角方法只是其中的一种。此外,不同的作者会用不同组合的欧拉角来描述,或用不同的名字表示同样的欧拉角。因此,使用欧拉角前,必须先做好明确的定义。
在经典力学里,时常用zxz顺规来设定欧拉角;照着第二个转动轴的轴名,简称为x顺规。另外,还有别种欧拉角组。合法的欧拉角组中,唯一的限制是,任何两个连续的旋转,必须绕着不同的转动轴旋转。因此,一共有12种顺规。例如,y顺规,第二个转动轴是y-轴,时常用在量子力学、核子物理学、粒子物理学。另外,还有一种顺规,xyz顺规,是用在航空航天工程学;参阅泰特-布莱恩角。
以上两部分均来自维基百科,我之所以把顺规特殊挑选出来,是因为第一段定义中使用的顺规与Unity中使用的顺规是不一样的,如果不理顺这一点,很容易造成混淆,这会将那些学Unity而查看欧拉角、万向节死锁之类文章的人带向误区。
Unity中的定义
以下内容来自Unity文档中Transform.eulerAngles的定义,本身是一个Vector3,就是一个三维矢量,
分别含有xyz三个参数。
The x, y, and z angles represent a rotation z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis (in that order).
Only use this variable to read and set the angles to absolute values. Don't increment them, as it will fail when the angle exceeds 360 degrees. Use Transform.Rotate instead.
意思就是说:
xyz代表了三个角度,它们定义了一组有序的旋转,即围绕z轴旋转z度,然后围绕x轴旋转x度,然后围绕y轴旋转y度。
你应该只去读取或者直接设置这些数值,不要增加它们,因为当角度超过360度将会失败。应该使用Transform.Rotate去替代执行旋转操作。
由于Unity内部使用四元数去执行旋转,不会存储欧拉角的累计值,因此它说超过360度会失败是可以理解的,它用四元数执行完运算之后,会更新最后对应的欧拉角数值,而这个结果欧拉角只是代表了等值的旋转变化结果,却无法代表中间过程,由于欧拉角旋转Z轴361度与1度有一样的结果,它便最后只存储了1度,以便于我们观察和使用。
Unity中的顺规
特别注意的是,上述文档中说明了Unity使用zxy的顺规,这与维基百科定义是不同的,因此不能使用上面那张图片中的旋转来理解。那么我们尝试来了解一下,Unity中的欧拉旋转究竟是如何的。
欧拉旋转的小实验
这里,我使用Unity制作了一个小实验,可以指定在x+,x-,y+,y-,z+,z-这些轴向来旋转一个箭头,见下图。
RotateXX按钮代表旋转指定的轴向XX
Applied Angles代表累计的欧拉旋转角
Result Angles代表Unity经过四元数计算之后输出的结果欧拉角
Slider控制旋转的速度
左边居中的空白框用来显示待旋转的执行项,每次使用RotateXX按钮都会产生一个旋转待执行项。
Rest用来重置
Allow Excute代表是都允许执行当前的待执行项。
Once All代表是按顺序执行这些可执行项还是所有执行项一起执行。
红绿蓝(RGB)三色分别代表XYZ轴,靠近箭头的三个轴是局部坐标轴,有圆球的一端代表轴的正向。远离箭头的上下左右前后断开的6个半截轴代表了世界坐标轴。轴的正向与局部坐标相同。这便是一切最初始的状态,物体的全局坐标和局部坐标下的欧拉角都是(0,0,0),也就是没有任何旋转的状态。
这个小程序可以参见我的Github中的页面,自己尝试一下就可以理解这些按钮的作用,注意需要使用支持WebGL的浏览器打开,比如或者Firefox(360极速浏览器8.7版本以上貌似也是支持的)。文件较大,网速慢的稍等一小会儿。
需要注意的是,我在写小程序的时候,刻意使用了累加计算的欧拉角(小程序中的Applied Angles),也就是说,你所执行的每次旋转都被累加到一个Vector3中,最后被设置到箭头的当前欧拉角,相当于箭头被复位之后,重新执行了最新的欧拉角累计值。举例来说,累加计算的欧拉角(90,90,90)所对应的结果都是一样的,无论你是按照什么顺序点击三个旋转按钮。这样,这个小程序可以模拟从初始状态经历过当前累计的欧拉旋转。
欧拉旋转的旋转轴
前述一直没有明确的一个问题,就是我们在围绕哪一个轴进行旋转?在Unity的官方文档上也没有说清楚这个问题。
准确地说,Unity中每次执行欧拉旋转,都是使用“当前轴”。
比如在Transform的文档中:
public void Rotate(Vector3 eulerAngles, Space relativeTo = Space.Self);
Description
Applies a rotation of eulerAngles.z degrees around the z axis, eulerAngles.x degrees around the x axis, and eulerAngles.y degrees around the y axis (in that order).
if relativeTo is left out or set to Space.Self the rotation is applied around the transform’s local axes. (The x, y and z axes shown when selecting the object inside the Scene View.) If relativeTo is Space.World the rotation is applied around the world x, y, z axes.
这个函数提供了一个可选的相对空间坐标系参数:
Space.Self
局部坐标系,意味着本次欧拉旋转以物体当前的局部坐标朝向为基础出发执行旋转。
Space.World 世界坐标系,意味着本次欧拉旋转以物体当前的世界坐标朝向为基础出发执行旋转。
最重要的倒不是它有可选的世界坐标系,一般而言,常用的旋转都是相对当前局部坐标系执行的。
最重要的是:在本次欧拉旋转过程中,它的相对轴是始终不变的,不变的,不变的…
比如我们可以指定一组欧拉旋转(90,60,30),通过前述的顺规我们知道,先绕Z轴旋转30度,再绕X轴旋转90度,再绕Y轴旋转60度,虽然有这样的顺序,但是Z旋转后相对X轴、Y轴,都是执行本组欧拉旋转前的那个轴向,它没有发生变动,所以我称它为“当前轴”。在Unity中的欧拉旋转就是这样定义的,不排除其它学术中欧拉旋转有不一样的定义方式。因此,执行:
Transform.Rotate(new Vector3(90,60,30))
Transform.Rotate(new Vector3(0,0,30));
Transform.Rotate(new Vector3(90,0,0));
Transform.Rotate(new Vector3(0,60,0));
的结果是不一样的。第一种情况,只执行了一组欧拉旋转,第二种情况,执行了三组欧拉旋转,后两组欧拉旋转的相对轴在旋转时已经发生了变动。
使用小程序验证旋转轴
上面的小程序执行的始终只有一组欧拉旋转,它每次累计欧拉角变化之后,都相当于从初始状态重新执行累计欧拉角的旋转。因此它很容易来验证相对的旋转轴向。
假设我们设定一组欧拉旋转(90,90,90),其最后的旋转结果朝向如下图A。
那么,我们按照Unity定义的顺规,先执行Z轴旋转90度。
它的旋转轴是初始的+z轴,轨迹记录了本次旋转划过的位置。接着是绕X轴旋转90度。
它的旋转轴也是初始的+X轴,接着是绕Y轴旋转90度。
它的旋转轴也是初始的+Y轴。最终我们得到了(90,90,90)这一组欧拉旋转的最终结果,与图A的结果相同。可以看出,它的确是沿着初始的固定轴向在进行按Z、X、Y顺序的旋转。
最后,我们总结一下Unity中的欧拉旋转。它是沿着Z、X、Y顺规执行的旋转,一组欧拉旋转过程中,相对的轴向不会发生变化。Transform.Rotate(new Vector3(90,60,30)),代表执行了一组欧拉旋转,它相对的是旋转前的局部坐标朝向。
正是这种顺规和轴向的定义,它导致了“万向节死锁”的自然形成。
且听下回分解…
没有更多推荐了,
不良信息举报
举报内容:
【Unity编程】Unity中的欧拉旋转
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!【Unity3D】物体、材质的设置、物体位移与旋转
Unity3D和Flash一样,甚至可以说是和C#一样,拖完组件,再写一系列的脚本,完成编程,甚至可以说,就是带编程脚本的3DSMAX。那么如何完成最基本的物体、材质的设置、物体位移与旋转呢?下面用一个简单的Unity3D说明这个问题,如下图所示:
在一个面板上面有一个可以控制的立方体与不可以控制的球体和立方体各2个,然后可以控制立方体的位移与旋转。概念的东西就不写了,具体步骤如下。
一、场景设置
1、如下图所示,在GameObject里面,选择需要的东西,在场景一拖就可以创建相应的物体了。
除了默认自带的摄像机和光源,我们要设置3个立方体,2个球,1个地面。
在设置的时候,还可以像画图、Flash、C#那样用CTRL+C、CTRL+V复制、粘贴物体。
2、之后,点击任意一个物体,再右边的Inspector就可以设置相应的属性。这和C#设置控件的基本控件,和Flash设置资源的属性不就是同一个意思吗?
不过由于在3D界面不像2D那样好控制组件的位置,基本上我们是需要在Inspector界面的Transform项,直接输入坐标控制物体的位置。
如下图所示(在没有设置材质之前,这些东西应该都是白色的),默认情况下,Y是上下方向,XZ是平面的纵横,这就是公认的三维笛卡儿坐标系设置,没什么好说的。
各个组件的坐标Position,旋转Rotation和缩放Scale如下图所示。Position指坐标,物体中心点所处的位置,所以如果物体要放在Plane上面,则要处于Y轴0.5的位置,Rotation指的是物体绕哪一轴旋转的角度,Scale则是单位物体的XYZ轴半径沿此轴拓宽的多少。
理论上,刚才GameObject中所有单位的立体靠各种坐标偏移,角度偏移与形变能表示三维世界的所有东西,就像二维世界的所有东西,是由点、直线、曲线所组成。
3、物体设置好之后,我们则要给各个物体上色,也就是给各个物体贴上材质。这里不要有windows自带颜色版的惯性思维,“颜色”也就是材质,不是说有就有,直接能在Inspector中设置的,是需要我们自己新建的,具体如下:
以上只是设置简单的纯色材质。材质的设置在3D领域同样是一种学问,就像如何用HTML+CSS的颜色配搭弄好一个网页一样。
这里设置材质,只是基本的入门,未来这个方面肯定可以深究一番。
现在游戏美工缺,高收入也就是因为如此,材质可以说是2D美工的3D版。
言归正传,如图设置黑色材质给予地板,蓝色材质给予预设为不能动的物理,红色材质设定给我们中间的主角。
4、至此,场景终于布置完毕,如下图所示,选择各个物体(2个球体、3个立方体),【Component】-&【Physics】-&【Rigidbody】,将所有物体设置为刚体,用于真实的物理碰撞之后,则可以进行脚本的编写。
二、脚本编写
显然按钮是通过脚本创建的。
如何新建脚本在《【Unity3D】Helloworld》()说过了,这里就不再赘述了。
给予如下的脚本给中间的红色立方体。
using System.C
using System.Collections.G
using UnityEngine.SceneM//重新开始游戏,切换场景SceneManager.LoadScene("Scene1");需要。
using UnityE
public class script : MonoBehaviour
// Use this for initialization
void Start()
// Update is called once per frame
void Update()
//初始化变换方法。
void Awake()
transform = this.GetComponent&Transform&();
float moveSpeed = 20;//物体移动速度
void OnGUI()//OnGUI用于画面绘制
//这里的rect就是指在左上角坐标(10,10)这个100x30像素的区域位置。
if (GUI.Button(new Rect(10, 10, 100, 30), "向左旋转30度"))//GUI.Button用于创建按钮
transform.Rotate(-Vector3.up * 30);//30就是指30度
if (GUI.Button(new Rect(110, 10, 100, 30), "向右旋转30度"))
transform.Rotate(Vector3.up * 30);
if (GUI.Button(new Rect(210, 10, 100, 30), "重新开始"))
SceneManager.LoadScene("Scene1");//Application下的方法已经被标识过期
if (GUI.Button(new Rect(10, 50, 100, 30), "向上移动"))
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
if (GUI.Button(new Rect(110, 50, 100, 30), "向下移动"))
transform.Translate(-Vector3.forward * moveSpeed * Time.deltaTime);//Time.deltaTime指一帧时间,这样据说可以平滑视觉差
if (GUI.Button(new Rect(210, 50, 100, 30), "向左移动"))
transform.Translate(-Vector3.right * moveSpeed * Time.deltaTime);
if (GUI.Button(new Rect(310, 50, 100, 30), "向右移动"))
transform.Translate(Vector3.right * moveSpeed * Time.deltaTime);
GUI.Label(new Rect(10, 100, 400, 30), "模型位置" + transform.position);//transform.position可以获取模型位置
具体请看注释。
Unity3D里面没有向后移动和像左移动,统一用负的.forward和负的.right实现。
Vector3直接可以使用,无须初始化,一般是指给赋予脚本的对象。
SceneManager.LoadScene("Scene1");在Unity3D内部调试时候,灯光会因场景重置变暗,但发布成exe之后不会有这样的问题。
没有更多推荐了,
不良信息举报
举报内容:
【Unity3D】物体、材质的设置、物体位移与旋转
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 wpf 触摸屏滑动相册 的文章

 

随机推荐