脚本宝典收集整理的这篇文章主要介绍了重新实现unity3d的Mecanim动画混合 (2) 2D Freeform Cartesian,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
2D Freeform的两个方式在计算开销上要比Simple大一些。其中Cartesian算法比较简单,Directional的方法要基于Cartesian,所以本篇先讨论这个算法。
2D Freeform的两个算法是可以在网上找到参考资料的,它们基于一篇论文[http://runevision.com/thesis]的章节6.3。
基础程序框架:
我们依然沿用之前的那个场景,代码框架稍微有一些变化。
[ExecuteInEditMode]
public class SampleNode : MonoBehaviour
{
public BlendNode[] Nodes;
private Vector3 mLastPosition;
void Start ()
{
Nodes = FindObjectsOfType<BlendNode>();
}
void Update ()
{
var pos = transform.position;
if(mLastPosition == pos) return;
mLastPosition = pos;
UpdateWeights();
}
[ContextMenu("Update Weights")]
void UpdateWeights()
{
for (int i = 0; i < Nodes.Length; ++i) Nodes[i].Weight = 0;
CalcWeightsFreeformCartesian();
NormalizeWeights();
}
void CalcWeightsFreeformCartesian()
{
}
void NormalizeWeights()
{
float totalWeight = 0;
foreach (var node in Nodes)
{
totalWeight += node.Weight;
}
if(totalWeight == 0) return;
foreach (var node in Nodes)
{
node.Weight = node.Weight / totalWeight;
}
}
}
算法思路
这个算法的思考方向是,想象为任意一个节点生成一个影响力图,那么该影响力必然从这个节点的位置向周围各个方向逐渐递减。
对任一个方向而言,影响力在这个方向上遇到的第一个其它节点时会降到零。
使用1维来理解这件事,看下图。
有两个节点pi和pj,对于采样点在位置p,那么个pi的影响值应该是多少呢?
我们可以看点p在直线pipj上的投影,这个投影点到pi的距离L0与pi到pj的距离L1,刚好能用来计算这个概念。
使I=1-L0/L1
,那么可以满足当p接近pi时,I趋近于1,当p接近pj时,I趋近于0。
根据向量点乘的特性,可以很容易的计算出来投影的长度。
L0=cosθ|pip→|=pip→⋅pipj→|pipj→|
所以
Iij=1−L0|pipj→|=1−pip→⋅pipj→|pipj→|2
每个节点的最终影响力取它到所有其它节点的影响力中的最小值,至此我们得到了论文中的公式(6.6):
hi(p)=minj=1n(1−pip→⋅pipj→|pipj→|2)
最后,对所有节点的影响力进行归一化,就能得到它们各自的权重。
代码实现
void CalcWeightsFreeformCartesian()
{
var posS = mInputPosition;
// 为每一个动画节点计算影响值
foreach (var node0 in Nodes)
{
var influence = float.MaxValue;
var pos0 = node0.transform.position;
// 计算当前节点针对每一个其它节点的影响值,并取最小的一个
for (int i = 0; i < Nodes.Length; ++i)
{
var node1 = Nodes[i];
if (node0 == node1) continue;
var pos1 = node1.transform.position;
var vec0S = posS - pos0;
var vec01 = pos1 - pos0;
// 影响值相当于0S在01上的投影的归一化
var h = Mathf.Clamp01(1 - Vector3.Dot(vec0S, vec01) / vec01.sqrMagnitude);
// 保留影响值中最小的
influence = Mathf.Min(influence, h);
}
node0.Weight = influence;
}
}
大功告成
预览影响力图的功能在文章中没有提及,但包含在完整代码中。
点此下载完整代码
以上是脚本宝典为你收集整理的重新实现unity3d的Mecanim动画混合 (2) 2D Freeform Cartesian全部内容,希望文章能够帮你解决重新实现unity3d的Mecanim动画混合 (2) 2D Freeform Cartesian所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。