using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using Thousandto.Core.Base;
using Thousandto.Core.Support;
///
/// 骨骼布料化 -- 动作柔化
///
public class BoneCloth : MonoBehaviour
{
public Transform m_srcRoot = null;
public Transform m_dstRoot = null;
public Particle[] m_particles = null;
//父改变
private bool m_parentChanged = false;
#region//重写MonoBehaviour方法
//每帧更新最后
private void LateUpdate()
{
if (m_parentChanged)
{
m_parentChanged = false;
ResetPose();
}
if (m_particles != null)
{
for (int i = 0; i < m_particles.Length; ++i)
{
var p = m_particles[i];
if (p.pfactor < 0.99f)
{
//根据参数进行位置插值计算
p.pos = Vector3.Lerp(p.pos, p.src.position, FixFactor(p.pfactor));
p.dst.position = p.pos;
var src_parent = p.src.parent;
var dst_parent = p.dst.parent;
if (src_parent != null && dst_parent != null)
{
//计算当前位置与父的位置距离
var src_dis = Vector3.Distance(src_parent.position, p.src.position);
var dst_dis = Vector3.Distance(dst_parent.position, p.dst.position);
if (src_dis != 0 && dst_dis != 0)
{
//计算目标位置相对父位置的方向,并根据方向重新计算目标的位置
var dst_dir = Vector3.Normalize(p.dst.position - dst_parent.position);
p.dst.position = dst_parent.position + dst_dir * (src_dis * 0.4f + dst_dis * 0.6f);
}
}
}
else
{
p.dst.position = p.src.position;
}
//对旋转信息进行插值计算
p.rot = Quaternion.Slerp(p.rot, p.src.rotation, FixFactor(p.rfactor));
p.dst.rotation = p.rot;
}
}
}
#endregion
#region//公共接口
//恢复原始位置
public void ResetPose()
{
if (m_particles != null)
{
for (int i = 0; i < m_particles.Length; ++i)
{
var p = m_particles[i];
p.pos = p.dst.position;
p.rot = p.dst.rotation;
p.src.position = p.pos;
p.src.rotation = p.rot;
}
}
}
//进行恢复处理
public void DoReset()
{
m_particles = null;
if (m_srcRoot != null && m_dstRoot != null)
{
var particles = new List();
UnityHierarchyUtils.WalkHierarchy(
m_srcRoot,
t =>
{
if (t.name.StartsWith("weiba", StringComparison.CurrentCultureIgnoreCase))
{
var p = new Particle();
p.src = t;
var root = m_srcRoot;
if (root != t)
{
var h = UnityUtils.GetTransPathFrom(t, root);
var depth = UnityUtils.GetHierarchyDepthFrom(t, root);
var a = Math.Min(depth, depth_pfactors.Length - 1);
var b = Math.Min(depth, depth_rfactors.Length - 1);
p.dst = m_dstRoot.Find(h);
p.pfactor = depth_pfactors[a];
p.rfactor = depth_rfactors[b];
}
else
{
p.dst = m_dstRoot;
p.pfactor = 1.0f;
p.rfactor = 1.0f;
}
if (p.dst != null)
{
t.position = p.dst.position;
t.rotation = p.dst.rotation;
p.pos = t.position;
p.rot = t.rotation;
particles.Add(p);
}
}
return true;
}
);
m_particles = particles.ToArray();
}
}
#endregion
#region//私有函数
private void OnTransformParentChanged()
{
m_parentChanged = true;
}
#endregion
#region//静态函数与方法
//位置参数--层次越深跟随的参数就越小
private static float[] depth_pfactors = new float[] { 1.0f, 0.5f, 0.3f, 0.2f, };
//旋转参数--层次越深跟随的参数就越小
private static float[] depth_rfactors = new float[] { 1.0f, 0.75f, 0.2f, 0.1f, };
//基础参数
private static float BaseFactor = 45;
//根据时间进行参数修正
private static float FixFactor(float factor)
{
#if UNITY_EDITOR
if (Application.isPlaying)
{
return factor * Time.deltaTime * BaseFactor;
}
else
{
return factor;
}
#else
return factor * Time.deltaTime * BaseFactor;
#endif
}
#endregion
#region//子类定义
///
/// 每一个部分
///
[Serializable]
public class Particle
{
public Transform src = null;
public Transform dst = null;
public Vector3 pos = Vector3.zero;
public Quaternion rot = Quaternion.identity;
[Range(0.1f, 1.0f)]
public float pfactor = 0.1f;
[Range(0.1f, 1.0f)]
public float rfactor = 0.1f;
}
#endregion
}