咱們看看這幾步操做後,咱們獲得了那些數據:
1.每一個皮膚頂點的初始世界座標。
2.每一個骨骼關節頂點的初始世界座標。
3.每一個頂點被骨骼頂點的影響信息。
4.骨骼如何移動。git
核心: 經過骨骼帶動皮膚運動,也就是經過骨骼的移動動態計算mesh上的點的位置github
1.將mesh上的點轉換爲骨骼空間上的點。
骨骼空間就是以關節爲原點肯定的空間,並非一個實體。
2.經過縮放、旋轉、平移將骨骼移動到新的位置。
3.根據骨骼的新位置計算mesh頂點新世界座標(骨骼移動,但mesh頂點與骨骼的相對位置不變,因此產生了頂點隨骨骼移動的感受),若一個頂點被多個骨骼影響,則要進行頂點混合計算新世界座標。ide
初始位置(綁定姿式):
骨骼移動後的位置:
1.計算小臂上一點S在小臂空間中的位置。
這個就要根據初始的骨骼位置和mesh上頂點的位置來計算了,也就是常說的綁定姿式狀態。
先說一下該例中每一個座標的意義:
(x1,y1,z1):左肩關節SL的世界座標。
(x2,y2,z2):左肘關節在以左肩關節爲原點的座標系本地座標。
(x3,y3,z3):附着於左小臂上的皮膚上的一點S的世界座標。
這裏爲了簡單,假設全部的關節都沒有通過旋轉和縮放。
先將S轉換到經過SL肯定的空間中,也就是大臂UAL空間,直接減去SL的座標便可(x3-x1,y3-y1,z3-z1)。
再將S點在大臂UAL空間中的座標轉換到小臂LA空間中,直接減去EL的座標便可(x3-x1-x2,y3-y1-y2,z3-z1-z2)。動畫
以上只是一個簡單的說明,而實際的使用中,初始的骨骼位置多是經過縮放、旋轉、平移後獲得的,通常會經過矩陣的方式來表示這一系列變換。
關於OpenGL中的座標轉換能夠參考這個連接的說明LearnOpenGL CN。
看完這個咱們就應該知道如何將一個子座標空間的點轉化爲世界座標了。下面再使用該例子進行舉例。
先計算模型矩陣再求模型矩陣的逆矩陣:
或者直接將求模型矩陣的運算反過來也能夠:
獲得World→EL矩陣後就可應直接經過矩陣運算直接將世界座標上的一點轉化爲EL空間上的一點了。
注意:
1.注意矩陣的運算順序,由於矩陣運算是不知足交換率的,若是順序錯了,結果極可能也就錯了。
2.矩陣EL→World通常叫作EL空間的模型(model)矩陣,矩陣World→EL通常叫作EL空間的綁定姿式矩陣(bindpose)
3.有時存儲的Mesh頂點信息不是直接的世界座標,而是一個有層次結構的mesh,但這並不影響流程,只要在運算時增長一步將這些頂點轉化爲世界座標的操做便可。
2.計算EL順時針旋轉90°後S點的位置。
直接經過左肩SL,左肘關節EL的縮放、旋轉、平移信息計算小臂LA空間的模型矩陣,使用上一步算出的小臂LA空間座標乘以該模型矩陣即算出了該點收到骨骼移動的影響後的位置。
3.頂點混合
有一些頂點不必定只受一個骨骼的影響,可能受多個骨骼的影響,此時就要經過頂點混合計算該點的新座標。
如今假設點S同時受SL,EL的影響且影響權重分別爲0.4,0.6。
①分別計算點S在SL、EL空間中的本地座標。
②分別計算點S在SL、EL移動後的世界座標。
③根據SL、EL對點S的影響權重混合座標,得到新的世界座標。
這裏舉例的是受兩個骨骼影響的狀況,受3個、4個時原理也是相同的,只不過運算量會更大一些。3d
1.空間的平移、旋轉、縮放均可以用矩陣來表示,並且這些矩陣也能夠結合在一塊兒成爲一個矩陣,多層空間結構的變換也同樣能夠組合爲一個矩陣。
2.如今看來骨骼動畫的核心其實就是幾個矩陣乘法的問題,大概就是這樣:
其中model矩陣隨着動畫的播放不停的變化,也就實現了骨骼帶動皮膚的功能。
假設一個頂點受多個骨骼影響,那麼就再根據權重混合一下。
3.mesh的初始位置、bindpose、影響因素都是經過製做該骨骼動畫模型時肯定的,能夠參考第一小節制做骨骼動畫的過程。code
咱們這裏以一個Mixamo上的免費資源Samba Dancing爲例。orm
直接將資源拖入Unity中便可,能夠看到在Unity中生成了一個文件夾和一個預製件。
htm
1.把模型prefab拖入場景中。
2.而後將mixamo.com動畫拖到場景中的Samba Dancing中,Unity會自動生成對應的Animator Controller。
blog
直接點擊運行便可。ci
左邊是每一幀變化的骨骼,右邊是每一個骨骼關鍵幀的平移,旋轉,縮放信息。
Cast Shadows:是否投射陰影。
Receive Shadows:是否接收陰影。
Materials:材質。
Use Light Probes:是否使用光探針。
Reflection Probes:反射探針設置。
Anchor Override:網格錨點。
Lightmap Parameters:光照烘培參數。
Quality:每一個頂點最多收到的骨骼影響數量。
Update When Offscreen:當mesh在屏幕外時是否更新,依據RootBone和Bounds判斷。
Mesh:Mesh信息。
mesh信息包含了每一個頂點的位置信息,受骨骼影響的權重信息、切線、法線、UV映射信息。
RootBone:根骨骼,有兩個做用。
1.做爲mesh在屏幕外時是否更新的依據。
2.進行座標計算時的Root空間。
在Unity中計算mesh上一點位置的流程大概是這樣的:
先經過上述一系列計算獲得點在RootBone空間中的位置,上述過程對開發者時不可見的。而後將接下來的步驟交給Material中的Shader解決。查看Shader文件能夠看到,在頂點着色其中第一步會給輸入的點乘以一個MVP矩陣獲取該點在屏幕上的位置,其中的M就是RootBone的模型矩陣。
以Unity 5.37的Standard Shader爲例,截取其使用的頂點着色器的一部分
VertexOutputForwardBase vertForwardBase (VertexInput v) { UNITY_SETUP_INSTANCE_ID(v); VertexOutputForwardBase o; UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o); UNITY_TRANSFER_INSTANCE_ID(v, o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); float4 posWorld = mul(unity_ObjectToWorld, v.vertex); #if UNITY_REQUIRE_FRAG_WORLDPOS #if UNITY_PACK_WORLDPOS_WITH_TANGENT o.tangentToWorldAndPackedData[0].w = posWorld.x; o.tangentToWorldAndPackedData[1].w = posWorld.y; o.tangentToWorldAndPackedData[2].w = posWorld.z; #else o.posWorld = posWorld.xyz; #endif #endif
能夠看到,經過posWorld = mul(unity_ObjectToWorld, v.vertex);對頂點以RootBone空間爲基礎作了轉換。
Bounds:根骨骼的邊界。
若是有什麼錯誤,但願各位在博客下留言指正,我會盡快改正。