请教unity中mesh.unity tangentt是什么作用,一般用在什么地方

您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
Unity3D中文脚本使用手册(重新排版整理过).doc 450页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:150 &&
你可能关注的文档:
········
Unity3D中文脚本使用手册一、 脚本概览这是一个关于Unity内部脚本如何工作的简单概览.Unity内部的脚本,是通过附加自定义脚本对象到游戏物体组成的.在脚本对象内部不同志的函数被特定的事件调用.最常用的列在下面:Update:这个函数在渲染一帧之前被调用,这里是大部分游戏行为代码被执行的地方,除了物理代码.FixedUpdate:这个函数在每个物理时间步被调用一次,这是处理基于物理游戏的地方.在任何函数之外的代码:在任何函数之外的代码在物体被加载的时候运行,这个可以用来初始化脚本状态.注意:文档的这个部份假设你是用Javascript,参考用C#编写获取如何使用C#和Boo编写脚本的信息.你也能定义事件句柄,它们的名称都以On开始,(例如OnCollisionEnter),为了查看完整的预定义事件的列表,参考MonoBehaviour文档.概览:常用操作大多数游戏物体的操作是通过游戏物体的Transform或Rigidbody来做的,在行为脚本内部它们可以分别通过transform和rigidbody访问,因此如果你想绕着Y轴每帧旋转5度,你可以如下写:functionUpdate(){transform.Rotate(0,5,0);}如果你想向前移动一个物体,你应该如下写:functionUpdate(){transform.Translate(0,0,2);}概览:跟踪时间Time类包含了一个非常重要的类变量,称为deltaTime,这个变量包含从上一次调用Update或FixedUpdate(根据你是在Update函数还是在FixedUpdate函数中)到现在的时间量.所以对于上面的例子,修改它使这个物体以一个恒定的速度旋转而不依赖于帧率:functionUpdate(){transform.Rotate(0,5*Time.deltaTime,0);}移动物体:functionUpdate(){transform.Translate(0,,0,2*Time.deltaTime);}如果你加或是减一个每帧改变的值,你应该将它与Time.deltaTime相乘.当你乘以Time.deltaTime时,你实际的表达:我想以10米/秒移动这个物体不是10米/帧.这不仅仅是因为你的游戏将独立于帧而运行,同时也是因为运动的单位容易理解.(米/秒)另一个例子,如果你想随着时间增加光照的范围.下面的表达式,以2单位/秒改变半径.functionUpdate(){light.range+=2.0*Time.deltaT}当通过力处理刚体的时候,你通常不必用Time.deltaTime,因为引擎已经为你考虑到了这一点.概览:访问其他组件组件被附加到游戏物体,附加Renderer到游戏物体使它在场景中渲染,附加一个Camera使它变为相机物体,所有的脚本都是组件,因为它们能被附加到游戏物体.最常用的组件可以作为简单成员变量访问:Component可如下访问TransformtransformRigidbodyrigidbodyRendererrendererCameracamera(onlyoncameraobjects)Lightlight(onlyonlightobjects)AnimationanimationCollidercollider…等等.对于完整的预定义成员变量的列表.查看Component,Behaviour和MonnoBehaviour类文档.如果游戏物体没有你想取的相同类型的组件,上面的变量将被设置为null.任何附加到一个游戏物体的组件或脚本都可以通过GetComponent访问.transform.Translate(0,3,0);//等同于GetComponent(Transform).Translate(0,1,0);注意transfom和Transform之间大小写的区别,前者是变量(小写),后者是类或脚本名称(大写).大小写不同使你能够从类和脚本名中区分变量.应用我们所学,你可以使用GetComponent找到任何附加在同一游戏物体上的脚本和组件,请注意要使用下面的例子能够工作,你需要有一个名为OtherScript的脚本,其中包含一个DoSomething函数.OtherScript脚本必须与下面的脚本附加到相同的物体上.//这个在同一游戏物体桑找到名为OtherScript的脚本//并调用它上加的DoSomethingfunctionUpdate(){otherScript=GetComponent(OtherScript);otherScript.DoSomething();}概览:访问其它游戏物体大多数高级的代码不仅需要操作一个物体,Unity脚本接口有各种方法来找到并访问其他游戏物
正在加载中,请稍后...在商店看到这样一个例子,表示很有兴趣,他们说是用UGUI做的。我想,像这种可以随便变形的图形,我第一个就想到了网格变形。
细心的朋友应该会发现,每个UGUI可见元素,都有一个&Canvas Render'组件,就跟3D世界模型有'Mesh Render'以及2D Sprite
有&Sprite Render'一样,UGUI的UI元素也需要一个Render渲染出来,那么第一时间想到的就是修改Render的Mesh。
private CanvasR
void Update()
Mesh mesh = new Mesh();
mesh.SetVertices();      // 设置顶点,这里缩略没写出顶点数组
mesh.SetUVs();         // 同上
mesh.SetTriangles();     
render = GetComponent&CanvasRenderer&();
render.SetMesh(mesh);
不过不知道为何,这种做法失败了,不知道是哪里出错,待我再研究下。
本来想直接获取render的mesh,然后在此mesh的基础上修改顶点的,可惜render并没有获取mesh的方法,或许是我还未发现。
刚刚试了下,又成功了,不过在Start里还是失败,我是放到Update里才成功的。
还有,获取顶点的方法:
1 OnPopulateMesh(UI.VertexHelper vh)
2 List&UIVertex& stream = new List&UIVertex&();
2 vh.GetUIVertexStream(stream);&
然后我想到UGUI是开源的,然后就跑去看源码,研究Image控件的实现原理,发现了Image是继承Graphic,
而Graphic里有OnPopulateMesh这个函数,查官方API:
protected void&OnPopulateMesh(vh);
Description
Callback function when a UI element needs to generate vertices.
Used by&,&, and&&for example to generate vertices specific to their use case.
说的是当该控件(例如Text,Image,RawImage)需要改变顶点的时候,就会自动调用。
在传入的vh参数里修改顶点,三角形,UV等,同样可以达到修改mesh的目的。
不过该函数是只有在该Craphic组件需要修改的时候才会调用,比如你修改Image的大小,或者它加载的时候才会。
这样就导致我们没法及时看到我们对mesh的修改,比如用是将一张Image的四个角分别用四个对象表示,这四个对象的
移动,会让这种Image发生形变。但是没法及时更新就没办法了。
还好有SetNativeSize()这个方法,其实跟刷新差不多。
// 自己手动刷新
&void Update()&{
  SetNativeSize();&}
protected override void OnPopulateMesh(VertexHelper vh)
Color32 color32 =
vh.Clear();     // 这里我用5对GameObject的坐标来与该Image对象的五个顶点绑定起来     // AddVert的最后一个参数是UV值
vh.AddVert(pos[0].position, color32, new Vector2(0f, 0f));
vh.AddVert(pos[1].position, color32, new Vector2(0f, 1f));
vh.AddVert(pos[2].position, color32, new Vector2(1f, 1f));
vh.AddVert(pos[3].position, color32, new Vector2(1f, 0f));
vh.AddVert(pos[4].position, color32, new Vector2(0.5f, 0f));
vh.AddTriangle(0, 1, 2);
vh.AddTriangle(2, 3, 4);
vh.AddTriangle(2, 4, 0);
想起我之前为了让Text实现渐变效果写的一个扩展方法,就是创建一个组件脚本,这个组件继承BaseMeshEffect,
然后在里面覆写ModifyMesh(Mesh mesh)方法,在该方法内部实现修改mesh即可。
最新的5.3版已经将该方法改成ModifyMesh(VertexHelper vh)(又TM改,我印象中这是第三次改了)
作用以及写法几乎与第二点一样,只是不用继承Graphic组件,这样可以实现比较好的扩展性。把效果做成Effect,
然后所有Graphic组件都可以通过添加该组件来实现扩展。
阅读(...) 评论()请教unity+Oculus开发问题【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:71,710贴子:
请教unity+Oculus开发问题收藏
我用unity + Oculus DK2 开发,请教两个问题:1,怎么才能让 电脑桌面 和 DK2眼镜同时显示画面内容?2,如何去掉 开始时的 警告 提示?
unity3d千锋VR培训0元入学,「高薪」就业!「预约申请2周免费试学」.火爆预约中!千锋VR培训,招生限大专以上学历,年龄30岁以下,符合条件即可报名,入学即签订就业协议!
高大上的东西,不懂
问题1已解决,谢谢
怎么用unity打包出来那种kd2 的包?
下了那个插件打包出来还是不行啊
请问具体该怎么弄
手机怎么和显示器同步啊?
我也遇到了这2个问题,怎么解决了?
请问Unity怎么自动检测到头盔的 为什么我运行后没用?UNITY5.4据说已经封装了OculusRift的接口,只用在playersetting里勾选virtual reality supported,进入play模式就可以直接使用虚拟现实头盔。但是我使用了oculus runtime 0.8,unity 5.4f1,添加了插件vr_unity_utilities_1.6.0 ,但是在勾选virtual reality supported以后,并没有在dk2中看到东西,而且dk2的信号灯依然为橙色,想问下这个应该怎么解决下呢?
解决了吗 我也是同样的问题
登录百度帐号推荐应用2936人阅读
Unity(3)
3、&(这个是京东地址)
4、维基百科(文中的数学概念出处)
& & & & 坐标系的定义是:对于一个n维系统,能够使每一个点和一组(n个)标量构成一一对应的系统。
& & & &&我们的出发点是三维欧几里得空间,或三维实内积空间。对于这样的三维空间,最常见的坐标系就是笛卡尔坐标系,指定了三个互相垂直的向量x、y、z,这样每个空间中的点就可以表示成
& & & &&考虑原点的存在,则对点V有:
& & & &&这里的x、y、z,就是三维实数空间的一组标准正交基。
& & & &&原点和基,就唯一的定义了一个坐标系。
& & & &&如果要展开讨论数学概念实在是太难懂,我们下面直接看unity中的各种坐标系来讨论各种情况。本文中讨论的unity坐标系有以下几个:
本地坐标系。local space世界坐标系。world space相机坐标系(观察坐标系)。view space投影坐标系。projection space切线坐标系。tangent space
& & & &&这几个坐标系将在下面逐个讨论。
二、本地坐标系
<span style="color:#、shader中的本地坐标系,与 Editor中的本地坐标系
& & & &&在unity中,有一个肉&#30524;可见的本地坐标系,当你选中一个物体时,就会显示出其本地坐标系。
图1、Editor中的本地坐标系
& & & &&那么问题来了,这个坐标系,是shader中的本地坐标系吗?
& & & &&产生这样的疑问是自然的,3ds max中建立模型使用的坐标系是右手坐标系,而unity editor中显示的本地坐标系是左手坐标系,显然是不一样的:
图2、3ds Max 中的本地坐标系
& & & &&我们这里不对3dmax中的轴做任何修改,并在导出时选择z向上(即和在3dmax中看到的一样),则导入到unity中,并将旋转等reset,看到的是这样的:
图3、导入unity后的本地坐标系
& & & &&注意此时方向已经和在3dsmax中不一样了。
& & & &&那么在shader中的坐标系到底是哪个坐标系呢?我们使用下面这样的shader来观察以下:
Shader &Custom/TestCoordShader& {
SubShader{
Tags{ &RenderType& = &Opaque& }
#pragma vertex
#pragma fragment frag
#include &UnityCG.cginc&
struct v2f {
float4 pos : SV_POSITION;
float4 col : COLOR;
v2f vert(appdata_base v) {
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.col = v.
float4 frag(v2f i) : COLOR{
return i.col.x; // i.col.y; //i.col.z;
//FallBack &Diffuse&
}& & & &&将 fragment 中的颜色&#20540;分别修改为 x y z,就可以得到下面的结果:
图4、shader中本地坐标系的x、y、z方向
& & & &&可以看到vertex的x、y、z方向和editor中显示的坐标轴向一致,且更仔细的观察的话,会发现原点位置也一致。因此我们可以得出结论:shader中的本地坐标系,就是在editor中看到的本地坐标系。
<span style="color:#、本地坐标系:左手坐标系
& & & &&这里需要注意的是,本地坐标系是一个左手坐标系系统。
图5、左手坐标系和右手坐标系
& & & &&这里不展开讨论左右手坐标系的问题,在后面会再探讨这个东西。
三、世界坐标系
<span style="color:#、世界坐标系的形态
图6、位于原点的正方体
& & & &&和各自为政的本地坐标系不同,在unity中,每个scene都有唯一存在的一个世界坐标系。同样的,世界坐标系也是一个左手坐标系。一般常见的用法,是使得x正方向为正右方,y正方向为正上方,z正方向为正前方(常用而已),如图6中所示。
<span style="color:#、从本地坐标系转换到世界坐标系
& & & &&现在要将本地坐标系的点、向量等转换到世界坐标系中。
1)不移动原点的坐标系变换
& & & &&考虑我们上面对于坐标系的要素描述:原点和基。这里的本地坐标系和世界坐标系的不同就在于这两点。
& & & &&首先不考虑原点的变化,先假定本地坐标系和世界坐标系共原点O。
& & & &&而在基的方面,本地坐标系和世界坐标系是同一个三维线性空间中选取两组不同的基构成的坐标系,分为称为 local 基 和 world 基。
& & & &&容易看出,从 local 基到 world 基是一个线性变换(反之亦然),参考《矩阵理论》中对过渡矩阵和坐标系一节的讨论,可以知道,任意点 p 在世界坐标系下的位置,可以用其在本地坐标系下的位置,左乘&&local 基 到 world 基的过渡矩阵的逆矩阵得到。而这个逆矩阵,实际上就是&world& 基 到 local&基的过渡矩阵。因此有:
公式1、不移动原点时,本地坐标系到世界坐标系的坐标轴变换和点变换
& & & &&注意到&world 基的正交特性,不失一般性的,令&X_world = (1, 0, 0),Y_world = (0, 1, 0),Z_world = (0, 0, 1),带入到上面的坐标轴变换公式,可以求出M_local-&world,则(其中 X_local_in_world 是指该local 基在世界坐标系下的表示):
公式2、坐标系变换与坐标轴的关系
& & & &&这个结论是可以推广的,即:点P在坐标系V下的坐标,相当于其在坐标系U下的坐标,左乘矩阵T,其中T为 坐标系U的三个基(列向量)在坐标系V下的坐标构成的矩阵。
& & & &&将这个矩阵记做 p 从本地坐标系变换到世界坐标系的变换矩阵 Trans:
公式3、本地坐标系变换到世界坐标系的变换矩阵 Trans
2)不移动原点的坐标系变换——举例
图7、本地坐标系到世界坐标系变换举例
& & & &&以这个cube的本地坐标系为例,其坐标轴在世界坐标系下的表示分别为:
& & & &&这样就可以得到过渡矩阵
3)仿射变换——考虑原点的移动
& & & &&前面的推导都是基于原点不移动得到的,这样假设的原因在于线性变换并不能够表示原点的移动。那么如果现在需要考虑这一变化,则需要引入仿射变换。
& & & &&所谓仿射变换,就是线性变换加平移,其实就是在刚才的线性变换的基础上再加上原点的移动。
& & & &&由于已经不是线性变换,那么使用线性变换矩阵就无法表示了,也就是说,现在已经无法写成 p' = T * p 的形式。因此,引入齐次线性空间的概念,即增加第4维w,用来辅助表示移动。
& & & &&考虑这样的仿射变换,首先保持原点不变,进行线性变换,其线性变换矩阵为A,再将原点平移b,则在该仿射变换下,任意点P有:
公式4、仿射变换
& & & &&关于齐次变换的更多细节,可以参考之前的(这篇文章较老,冲突的概念以本文为准)。
& & & &&仔细考虑这个表示平移的b向量,会发现他是转换后的线性空间V的原点所在位置,在原线性空间U下的坐标
图8、仿射变换的原点变换
& & & & 现在回到本地坐标系向世界坐标系的变换过程中,则可以得到齐次变换下的变换矩阵:
公式4、仿射变换矩阵与坐标轴和原点
& & & &&考虑到齐次空间的特性,点的w分量为1,向量的w分量为0,则可以进一步写为:
4)在unity中获得这个转换矩阵
& & & & Unity中已经提供了获得这个矩阵的方便形式,在script中使用
gameObject.transform.localToWorldMatrix& & & &&在shader中使用如下的矩阵:
_Object2World
5)转换法线
& & & &&将点或者普通的向量从本地坐标系转换到世界坐标系,只要按照上面说的,用该转换矩阵左乘原坐标&#20540;就可以了,但是对于法线,还需要一些特殊的处理。
& & & &&为什么?
& & & &&回答这个问题,就需要搬出法线的定义:三维平面的法线是垂直于该平面的三维向量。曲面在某点P处的法线为垂直于该点切平面的向量。所以,在转换之后,还需要保持原有的垂直关系。
& & & &&按照上面举例中的变换矩阵,假定某条法线为(1,1,0),与之垂直的一个向量(1,-1,0)。如果左乘变换矩阵,则法线变为(3.5,3.5,-0.7),向量变为(0.7,-3.5,-3.5)。变换之后的内积为 -7,即已经不再垂直。
& & & &&其实从数学上看这是显然的:
公式5、使用变换矩阵变换法线——不再垂直
& & & &&而从直观上,原因是这样的:
图9、使用变换矩阵变换法线——不再垂直
& & & &&因此要正确的进行法线的变换,要使得保持 V 和 N 的内积为0,因此要让 N 左乘 Trans的逆转置矩阵,这样有:
公式6、用逆转置矩阵转换法线
6)获取逆转置矩阵的捷径——mul的秘密
& & & &&上面提到要转换法线,需要使用从本地坐标系到世界坐标系的仿射变换矩阵 (即 _Object2World) 的逆转置矩阵,即应该使用 _World2Object 的转置矩阵。
& & & &&那么在shader中完成这个变换,应有:
float4 worldPos
= mul(_Object2World, v.vertex);
float4 worldNorm = mul(transpose(_World2Object), v.normal);& & & &&但在实际使用中,常常见到这样的写法:
float4 worldPos
= mul(_Object2World, v.vertex);
float4 worldNorm = mul(v.normal, _World2Object);
& & & &&这两种写法的结果是一样的吗?是的,这里就必须说明 mul 的用法了()。
& & & &&简单来说,如果 mul 的第一个参数是矩阵 M,第二个参数是向量 V,则结果 Out 为(以vector4为例):
& & & & 如果第一个参数是向量 V,第二个参数是矩阵 M,则结果 Out 为
& & & &&则可以进行如下推导:
公式7、mul与转置矩阵
& & & &&注意到输出的vector4,在数据&#26684;式上,转置与不转置实际上并没有区别,(shader中,转置实际上只对矩阵有效果)。因此,mul(V, M) 就相当于 mul( tranpose(M), V )更进一步的,对于正交矩阵,其转置矩阵等于逆矩阵,那么通过这个方法,还可以得到他的逆矩阵,这个特性我们后面还会看到。
四、观察坐标系
<span style="color:#、观察坐标系的形态
& & & & View space是观察者&#30524;中的世界,可以认为是观察者的本地坐标系,以观察者的位置为原点。但在中可以看到,观察坐标系又与 editor 中看到的 camera 的本地坐标系有本质的区别:它是右手坐标系
& & & &&其形态如下所示:
图10、观察坐标系
<span style="color:#、左手坐标系和右手坐标系的互相转换——数学运算的独立性
& & & &&在考虑如何从世界坐标系转换到观察坐标系之前,我们要先思考一个问题:上一节的转换公式是在世界坐标系和本地坐标系——两个都是左手坐标系——的情况下推导的,那么现在要在左手坐标系和右手坐标系之间进行转换了,那么之前的推导是否仍然有效?
& & & &&这里就要展开来谈谈矩阵运算与左右手规则的关系了。
1)线性变换定理与左右手无关
& & & &&上一节讨论的线性变换,是从一组基变换到另一组基,对基本身没有任何要求,他们甚至可以不满足互相正交的特性,到底构成的是左手坐标系还是右手坐标系,容易看到,对定理本身是完全没有影响的。
2)矩阵乘法 mul 与左右手无关
& & & &&矩阵乘法的本质实际上就是对点或向量进行变换,即更换基向量,从线性变换定理与左右手无关也容易看出 mul 也不挑剔他所在的线性空间。
3)点积与左右手无关
& & & &&点积需要在实内积空间中进行,要使得下面的点积计算方式生效,需要 a 和 b 在同一个线性空间内,且基向量两两正交。
公式8、点积
& & & &&注意到unity中使用的左手坐标系和右手坐标系中的基向量都是满足正交条件的,因此点积都可以正常进行。
4)叉乘与左右手规则的关系
& & & &&叉乘是唯一需要注意的。其数学公式如下:
公式8、叉乘的数学计算方法
& & & &&可以看到,其本身也是与基向量的形态独立的,因此计算公式本身(例如,cross函数本身)并不因左右手坐标系的变化而变化。
& & & &&但是,计算叉乘还有一个方法(以下这段出自):
公式9、叉乘
& & & &&这里方向向量 n 的确定,通常会介绍右手规则。但实际上,右手规则仅适用于右手坐标系下的情况,在左手坐标系中,需要使用左手规则。总结来说,就是叉乘的数学表达式是独立于左右手坐标系的。但如果使用X手判定准则来进行方向的判断,则在左手坐标系中应使用左手准则,在右手坐标系中使用右手准则。
<span style="color:#、从世界坐标系变换到观察坐标系
& & & &&经过了上面的讨论,我们可以放心大胆的说,可以按照本地坐标系变换到世界坐标系的思路,再从世界坐标系变换到观察坐标系。
& & & &&在 Script 中获得这个变换矩阵的方法是:
Camera.worldToCameraMatrix& & & &&在shader中,这一步的单独的矩阵是:
UNITY_MATRIX_V
& & & &&综合从本地坐标系到观察坐标系的变换矩阵:
UNITY_MATRIX_MV
4、&#20540;得注意的 z 分量和 w 分量
& & & &&到目前为止,无论是本地坐标系到世界坐标系的变换,还是世界坐标系到观察坐标系的变换,都不影响点(或向量)的 w 分量,仍然保持为 1 (或0,对于向量)。
另外,可以注意下 z 分量,可以看到,由于 z 的正方向的缘故,所以观察者可见的所有点的 z 分量都小于0,且距离越远,负的&#20540;越大。
五、投影坐标系
<span style="color:#、投影坐标系的形态
& & & &&投影坐标系是将观察者&#30524;中的世界进行截取和归一得到的(比较详细的讨论可以参考),首先截取世界中,camera的平截体包含的部分,然后又再次变为一个左手坐标系(对透视投影来说,坐标系的概念可能已经拓展)
图11、投影坐标系:正投影和透视投影
& & & &&这就产生了问题,为什么前面也是左手坐标系(本地坐标系,世界坐标系),后面也是左手坐标系(投影坐标系),中间为什么要费力的插一个右手坐标系呢(观察坐标系)?实际上,在Opengl中,本地坐标系和世界坐标系都是右手坐标系,也就是说,直到投影空间中才变换为左手。而unity中的本地坐标系和世界坐标系是左手系统,所以显得观察坐标系比较的特别。
<span style="color:#、正投影
& & & &&正投影见第一张图,在从观察坐标系变换到投影坐标系之后,点 (x,y,z)的取&#20540;范围有:
& & & &&其变换矩阵可以参考我的坐标系那篇博客:
公式10、正投影的投影变换矩阵
<span style="color:#、透视投影
& & & &&透视投影的情况要复杂的多,在这一步,w &#20540;开始正式发挥作用。
& & & &&先直接来看变换矩阵(关于求法仍建议阅读坐标系一文)
公式11、透视投影的投影变换矩阵
& & & &&对原观察坐标系下点P,变换到投影坐标系下坐标P’为:
公式12、透视投影变换下点的变换情况
& & & &&如果只考虑(x,y,z),那么和正投影是相同的,但是多了第四维w,使得 z 坐标轴的指向产生了弯曲
图12、透视坐标系
<span style="color:#、从观察坐标系到投影坐标系——获取变换矩阵
& & & &&自己想要计算的话,可以用上面提供的公式计算,unity本身也为我们提供了获取这个变换矩阵的方式。
& & & &&在shader中,这一步单独的变换矩阵:
UNITY_MATRIX_P
& & & &&在script中,如果使用&camera.projectionMatrix ,可能会发现与 shader 中的这个矩阵有些差异,这是由于,在我的电脑上(目前不清楚是否和显卡有关),实际使用的变换矩阵,最终会使得 z 的取&#20540;范围为 [0, 1],和上面公式略有不同。
& & & &&因此在script中,需要使用下面的代码来获取投影变换矩阵:
GL.GetGPUProjectionMatrix(c.projectionMatrix, false)
<span style="color:#、&#20540;得注意的w分量
& & & & 之前的 w 分量一直为1,现在终于有了作用。在正投影变换后,w的&#20540;仍然是1;但是在透视投影变换之后,w的&#20540;等于观察坐标系下的 -z。另外,在透视坐标系中,在 shader 中实际应该使用的 x、y、z分量应当是 P 在变换后的坐标&#20540;的 Px、Py、Pz分量除以 w 来获取。
& & & & 一说到除以就必须当心0除问题,w有可能是0吗?答案是不可能,这是由于透视投影的camera的视锥体中的点,其z的取&#20540;范围是 [-ZFar, -ZNear],不会取&#20540;到0。
六、切线空间
<span style="color:#、切线空间的形态
& & & &&在做 bump map的时候,会提到切线空间 tangent space。切线空间的具体意义这里不展开讨论(关于这个问题,解释的最清楚的是),这里主要讨论坐标系变换问题。
& & & &&切线空间的坐标轴分别为:
X轴——切线 tangentY轴——副切线 biTangentZ轴——法线 normal
& & & &&其中,法线即我们平时所说的法线:
& & & &&切线选取的是,与法线垂直的,沿着贴图uv的u变量增长方向的向量:
& & & &&副切线则选取与这两个向量都垂直的,一般通过叉乘得到。从而构成坐标系:
& & & &&需要注意的是,unity中,实际获得的 B 向量,可能与这张图中的 B 向量反向。
<span style="color:#、在unity中获得和使用切空间变换矩阵
& & & &&在unity中,有这样一个宏&TANGENT_SPACE_ROTATION,可以获得变换到切线空间
#define TANGENT_SPACE_ROTATION \
float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w; \
float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal )
& & & &&使用的时候,可以这样用:
TANGENT_SPACE_ROTATION;
o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
& & & &&这个变换矩阵有很多细节&#20540;得说明,我们下面一个一个来看。
<span style="color:#、这是个什么样的矩阵?
& & & &&这个问题换个问法就是,float3x3如何构造?
& & & &&实际上,float3x3是行优先填充元素的,可以看。所以,这个矩阵是:
& & & &&注意,这个矩阵作为变换矩阵是非常奇怪的。回忆我们在&第三节世界坐标系 中,第2小节的结论:
点P在坐标系V下的坐标,相当于其在坐标系U下的坐标,左乘矩阵T,其中T为 坐标系U的三个基(列向量)在坐标系V下的坐标构成的矩阵。
& & & &&因此变换矩阵应当是一个由三个列向量构成的矩阵,而现在却是三个行向量,这是为什么?
<span style="color:#、转置与逆矩阵
& & & &&现在回答前面的问题:原因在于,实际上这是一个逆矩阵。
& & & &&首先,可以注意到,三个基向量(T,B,N)都是单位向量,且两两正交。则其构成的矩阵是一个正交矩阵。对于正交矩阵,其转置矩阵就是他的逆矩阵,因此有:
& & & &&注意看后面的这个矩阵,他显然满足前面的结论,T、B、N都是在本地坐标系下的&#20540;,因此这个列向量构成的 [T B N] 矩阵,是将点从切线坐标系变换到本地坐标系的变换矩阵。&那么这个矩阵的逆矩阵,就是将点从本地坐标系变换到切线坐标系的变换矩阵。而由于正交,其逆矩阵就是其转置矩阵,所以从本地坐标系变换到切线坐标系的变换矩阵,就是我们在第2小节里面看到的情况。
<span style="color:#、左手坐标系?右手坐标系?
& & & &&由于 B 向量是叉乘得到的,那么一个&#20540;得关注的问题就是,这个坐标系到底是左手规则还是右手规则?这就牵涉到之前的另外一个结论:对于叉乘,在左手坐标系中使用左手规则,在右手坐标系中使用右手规则,但是无论使用哪个规则,其数学计算表达式并不会有任何不同。
& & & &&而现在,N、T都是在本地坐标系中的向量,而本地坐标系是一个左手坐标系,所以 N 和 T 的叉乘使用左手规则,那么在没有其他变数的情况下,T、B、N应该如下,构成一个左手坐标系:
& & & &&但是现在还有一个变量 tangent.w,他的取&#20540;为 1 或 -1。如果为1,则上面的结论不变,如果为-1,则B则会反向,从而构成一个右手坐标系。
这个变量的存在是由于B 向量通常还代表着 uv 中 v 增长的方向,所以需要调整 B 轴使得他和 v 增长的方向一致。(这里可参考)
& & & &&至此,对于坐标系的讨论基本就告一段落了。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:88681次
积分:1190
积分:1190
排名:千里之外
原创:28篇
评论:35条
(1)(3)(1)(2)(2)(4)(1)(2)(3)(7)(5)

我要回帖

更多关于 unity nav mesh agent 的文章

 

随机推荐