Advertisement
glados123123123123

Untitled

Dec 25th, 2023
1,005
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 33.16 KB | None | 0 0
  1. #if UNITY_WEBGL
  2. // No multithread
  3. #else
  4. #define ENABLE_MULTITHREAD
  5. #endif
  6.  
  7. using UnityEngine;
  8. using System.Collections.Generic;
  9. using System.Threading;
  10.  
  11. [AddComponentMenu("Dynamic Bone/Dynamic Bone")]
  12. public class DynamicBone : MonoBehaviour
  13. {
  14. #if UNITY_5_3_OR_NEWER
  15.     [Tooltip("The roots of the transform hierarchy to apply physics.")]
  16. #endif
  17.     public Transform m_Root = null;
  18.     public List<Transform> m_Roots = null;
  19.  
  20. #if UNITY_5_3_OR_NEWER
  21.     [Tooltip("Internal physics simulation rate.")]
  22. #endif
  23.     public float m_UpdateRate = 60.0f;
  24.  
  25.     public enum UpdateMode
  26.     {
  27.         Normal,
  28.         AnimatePhysics,
  29.         UnscaledTime,
  30.         Default
  31.     }
  32.     public UpdateMode m_UpdateMode = UpdateMode.Default;
  33.  
  34. #if UNITY_5_3_OR_NEWER
  35.     [Tooltip("How much the bones slowed down.")]
  36. #endif
  37.     [Range(0, 1)]
  38.     public float m_Damping = 0.1f;
  39.     public AnimationCurve m_DampingDistrib = null;
  40.  
  41. #if UNITY_5_3_OR_NEWER
  42.     [Tooltip("How much the force applied to return each bone to original orientation.")]
  43. #endif
  44.     [Range(0, 1)]
  45.     public float m_Elasticity = 0.1f;
  46.     public AnimationCurve m_ElasticityDistrib = null;
  47.  
  48. #if UNITY_5_3_OR_NEWER
  49.     [Tooltip("How much bone's original orientation are preserved.")]
  50. #endif
  51.     [Range(0, 1)]
  52.     public float m_Stiffness = 0.1f;
  53.     public AnimationCurve m_StiffnessDistrib = null;
  54.  
  55. #if UNITY_5_3_OR_NEWER
  56.     [Tooltip("How much character's position change is ignored in physics simulation.")]
  57. #endif
  58.     [Range(0, 1)]
  59.     public float m_Inert = 0;
  60.     public AnimationCurve m_InertDistrib = null;
  61.  
  62. #if UNITY_5_3_OR_NEWER
  63.     [Tooltip("How much the bones slowed down when collide.")]
  64. #endif
  65.     public float m_Friction = 0;
  66.     public AnimationCurve m_FrictionDistrib = null;
  67.  
  68. #if UNITY_5_3_OR_NEWER
  69.     [Tooltip("Each bone can be a sphere to collide with colliders. Radius describe sphere's size.")]
  70. #endif
  71.     public float m_Radius = 0;
  72.     public AnimationCurve m_RadiusDistrib = null;
  73.  
  74. #if UNITY_5_3_OR_NEWER
  75.     [Tooltip("If End Length is not zero, an extra bone is generated at the end of transform hierarchy.")]
  76. #endif
  77.     public float m_EndLength = 0;
  78.  
  79. #if UNITY_5_3_OR_NEWER
  80.     [Tooltip("If End Offset is not zero, an extra bone is generated at the end of transform hierarchy.")]
  81. #endif
  82.     public Vector3 m_EndOffset = Vector3.zero;
  83.  
  84. #if UNITY_5_3_OR_NEWER
  85.     [Tooltip("The force apply to bones. Partial force apply to character's initial pose is cancelled out.")]
  86. #endif
  87.     public Vector3 m_Gravity = Vector3.zero;
  88.  
  89. #if UNITY_5_3_OR_NEWER
  90.     [Tooltip("The force apply to bones.")]
  91. #endif
  92.     public Vector3 m_Force = Vector3.zero;
  93.  
  94. #if UNITY_5_3_OR_NEWER
  95.     [Tooltip("Control how physics blends with existing animation.")]
  96. #endif
  97.     [Range(0, 1)]
  98.     public float m_BlendWeight = 1.0f;
  99.  
  100. #if UNITY_5_3_OR_NEWER
  101.     [Tooltip("Collider objects interact with the bones.")]
  102. #endif
  103.     public List<DynamicBoneColliderBase> m_Colliders = null;
  104.  
  105. #if UNITY_5_3_OR_NEWER
  106.     [Tooltip("Bones exclude from physics simulation.")]
  107. #endif
  108.     public List<Transform> m_Exclusions = null;
  109.  
  110.     public enum FreezeAxis
  111.     {
  112.         None, X, Y, Z
  113.     }
  114. #if UNITY_5_3_OR_NEWER
  115.     [Tooltip("Constrain bones to move on specified plane.")]
  116. #endif 
  117.     public FreezeAxis m_FreezeAxis = FreezeAxis.None;
  118.  
  119. #if UNITY_5_3_OR_NEWER
  120.     [Tooltip("Disable physics simulation automatically if character is far from camera or player.")]
  121. #endif
  122.     public bool m_DistantDisable = false;
  123.     public Transform m_ReferenceObject = null;
  124.     public float m_DistanceToObject = 20;
  125.  
  126.     [HideInInspector]
  127.     public bool m_Multithread = true;
  128.  
  129.     Vector3 m_ObjectMove;
  130.     Vector3 m_ObjectPrevPosition;
  131.     float m_ObjectScale;
  132.  
  133.     float m_Time = 0;
  134.     float m_Weight = 1.0f;
  135.     bool m_DistantDisabled = false;
  136.     int m_PreUpdateCount = 0;
  137.  
  138.     class Particle
  139.     {
  140.         public Transform m_Transform;
  141.         public int m_ParentIndex;
  142.         public int m_ChildCount;
  143.         public float m_Damping;
  144.         public float m_Elasticity;
  145.         public float m_Stiffness;
  146.         public float m_Inert;
  147.         public float m_Friction;
  148.         public float m_Radius;
  149.         public float m_BoneLength;
  150.         public bool m_isCollide;
  151.         public bool m_TransformNotNull;
  152.  
  153.         public Vector3 m_Position;
  154.         public Vector3 m_PrevPosition;
  155.         public Vector3 m_EndOffset;
  156.         public Vector3 m_InitLocalPosition;
  157.         public Quaternion m_InitLocalRotation;
  158.  
  159.         // prepare data
  160.         public Vector3 m_TransformPosition;
  161.         public Vector3 m_TransformLocalPosition;
  162.         public Matrix4x4 m_TransformLocalToWorldMatrix;
  163.     }
  164.  
  165.     class ParticleTree
  166.     {
  167.         public Transform m_Root;
  168.         public Vector3 m_LocalGravity;
  169.         public Matrix4x4 m_RootWorldToLocalMatrix;
  170.         public float m_BoneTotalLength;
  171.         public List<Particle> m_Particles = new List<Particle>();
  172.  
  173.         // prepare data
  174.         public Vector3 m_RestGravity;
  175.     }
  176.  
  177.     List<ParticleTree> m_ParticleTrees = new List<ParticleTree>();
  178.  
  179.     // prepare data
  180.     float m_DeltaTime;
  181.     List<DynamicBoneColliderBase> m_EffectiveColliders;
  182.  
  183. #if ENABLE_MULTITHREAD
  184.     // multithread
  185.     bool m_WorkAdded = false;
  186.     static List<DynamicBone> s_PendingWorks = new List<DynamicBone>();
  187.     static List<DynamicBone> s_EffectiveWorks = new List<DynamicBone>();
  188.     static AutoResetEvent s_AllWorksDoneEvent;
  189.     static int s_RemainWorkCount;
  190.     static Semaphore s_WorkQueueSemaphore;
  191.     static int s_WorkQueueIndex;
  192. #endif
  193.  
  194.     static int s_UpdateCount;
  195.     static int s_PrepareFrame;
  196.  
  197.     void Start()
  198.     {
  199.         SetupParticles();
  200.     }
  201.  
  202.     void FixedUpdate()
  203.     {
  204.         if (m_UpdateMode == UpdateMode.AnimatePhysics)
  205.         {
  206.             PreUpdate();
  207.         }
  208.     }
  209.  
  210.     void Update()
  211.     {
  212.         if (m_UpdateMode != UpdateMode.AnimatePhysics)
  213.         {
  214.             PreUpdate();
  215.         }
  216.  
  217. #if ENABLE_MULTITHREAD
  218.         if (m_PreUpdateCount > 0 && m_Multithread)
  219.         {
  220.             AddPendingWork(this);
  221.             m_WorkAdded = true;
  222.         }
  223. #endif
  224.         ++s_UpdateCount;
  225.     }
  226.  
  227.     void LateUpdate()
  228.     {
  229.         if (m_PreUpdateCount == 0)
  230.             return;
  231.  
  232.         if (s_UpdateCount > 0)
  233.         {
  234.             s_UpdateCount = 0;
  235.             ++s_PrepareFrame;
  236.         }
  237.  
  238.         SetWeight(m_BlendWeight);
  239.  
  240. #if ENABLE_MULTITHREAD
  241.         if (m_WorkAdded)
  242.         {
  243.             m_WorkAdded = false;
  244.             ExecuteWorks();
  245.         }
  246.         else
  247. #endif
  248.         {
  249.             CheckDistance();
  250.             if (IsNeedUpdate())
  251.             {
  252.                 Prepare();
  253.                 UpdateParticles();
  254.                 ApplyParticlesToTransforms();
  255.             }
  256.         }
  257.  
  258.         m_PreUpdateCount = 0;
  259.     }
  260.  
  261.     void Prepare()
  262.     {
  263.         m_DeltaTime = Time.deltaTime;
  264. #if UNITY_5_3_OR_NEWER
  265.         if (m_UpdateMode == UpdateMode.UnscaledTime)
  266.         {
  267.             m_DeltaTime = Time.unscaledDeltaTime;
  268.         }
  269.         else if (m_UpdateMode == UpdateMode.AnimatePhysics)
  270.         {
  271.             m_DeltaTime = Time.fixedDeltaTime * m_PreUpdateCount;
  272.         }
  273. #endif
  274.  
  275.         m_ObjectScale = Mathf.Abs(transform.lossyScale.x);
  276.         m_ObjectMove = transform.position - m_ObjectPrevPosition;
  277.         m_ObjectPrevPosition = transform.position;
  278.  
  279.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  280.         {
  281.             ParticleTree pt = m_ParticleTrees[i];
  282.             pt.m_RestGravity = pt.m_Root.TransformDirection(pt.m_LocalGravity);
  283.  
  284.             for (int j = 0; j < pt.m_Particles.Count; ++j)
  285.             {
  286.                 Particle p = pt.m_Particles[j];
  287.                 if (p.m_TransformNotNull)
  288.                 {
  289.                     p.m_TransformPosition = p.m_Transform.position;
  290.                     p.m_TransformLocalPosition = p.m_Transform.localPosition;
  291.                     p.m_TransformLocalToWorldMatrix = p.m_Transform.localToWorldMatrix;
  292.                 }
  293.             }
  294.         }
  295.  
  296.         if (m_EffectiveColliders != null)
  297.         {
  298.             m_EffectiveColliders.Clear();
  299.         }
  300.  
  301.         if (m_Colliders != null)
  302.         {
  303.             for (int i = 0; i < m_Colliders.Count; ++i)
  304.             {
  305.                 DynamicBoneColliderBase c = m_Colliders[i];
  306.                 if (c != null && c.enabled)
  307.                 {
  308.                     if (m_EffectiveColliders == null)
  309.                     {
  310.                         m_EffectiveColliders = new List<DynamicBoneColliderBase>();
  311.                     }
  312.                     m_EffectiveColliders.Add(c);
  313.  
  314.                     if (c.PrepareFrame != s_PrepareFrame)       // colliders used by many dynamic bones only prepares once
  315.                     {
  316.                         c.Prepare();
  317.                         c.PrepareFrame = s_PrepareFrame;
  318.                     }
  319.                 }
  320.             }
  321.         }
  322.     }
  323.  
  324.     bool IsNeedUpdate()
  325.     {
  326.         return m_Weight > 0 && !(m_DistantDisable && m_DistantDisabled);
  327.     }
  328.  
  329.     void PreUpdate()
  330.     {
  331.         if (IsNeedUpdate())
  332.         {
  333.             InitTransforms();
  334.         }
  335.         ++m_PreUpdateCount;
  336.     }
  337.  
  338.     void CheckDistance()
  339.     {
  340.         if (!m_DistantDisable)
  341.             return;
  342.  
  343.         Transform rt = m_ReferenceObject;
  344.         if (rt == null && Camera.main != null)
  345.         {
  346.             rt = Camera.main.transform;
  347.         }
  348.  
  349.         if (rt != null)
  350.         {
  351.             float d2 = (rt.position - transform.position).sqrMagnitude;
  352.             bool disable = d2 > m_DistanceToObject * m_DistanceToObject;
  353.             if (disable != m_DistantDisabled)
  354.             {
  355.                 if (!disable)
  356.                 {
  357.                     ResetParticlesPosition();
  358.                 }
  359.                 m_DistantDisabled = disable;
  360.             }
  361.         }
  362.     }
  363.  
  364.     void OnEnable()
  365.     {
  366.         ResetParticlesPosition();
  367.     }
  368.  
  369.     void OnDisable()
  370.     {
  371.         InitTransforms();
  372.     }
  373.  
  374.     void OnValidate()
  375.     {
  376.         m_UpdateRate = Mathf.Max(m_UpdateRate, 0);
  377.         m_Damping = Mathf.Clamp01(m_Damping);
  378.         m_Elasticity = Mathf.Clamp01(m_Elasticity);
  379.         m_Stiffness = Mathf.Clamp01(m_Stiffness);
  380.         m_Inert = Mathf.Clamp01(m_Inert);
  381.         m_Friction = Mathf.Clamp01(m_Friction);
  382.         m_Radius = Mathf.Max(m_Radius, 0);
  383.  
  384.         if (Application.isEditor && Application.isPlaying)
  385.         {
  386.             if (IsRootChanged())
  387.             {
  388.                 InitTransforms();
  389.                 SetupParticles();
  390.             }
  391.             else
  392.             {
  393.                 UpdateParameters();
  394.             }
  395.         }
  396.     }
  397.  
  398.     bool IsRootChanged()
  399.     {
  400.         var roots = new List<Transform>();
  401.         if (m_Root != null)
  402.         {
  403.             roots.Add(m_Root);
  404.         }
  405.  
  406.         if (m_Roots != null)
  407.         {
  408.             foreach (var root in m_Roots)
  409.             {
  410.                 if (root != null && !roots.Contains(root))
  411.                 {
  412.                     roots.Add(root);
  413.                 }
  414.             }
  415.         }
  416.  
  417.         if (roots.Count != m_ParticleTrees.Count)
  418.             return true;
  419.  
  420.         for (int i = 0; i < roots.Count; ++i)
  421.         {
  422.             if (roots[i] != m_ParticleTrees[i].m_Root)
  423.                 return true;
  424.         }
  425.  
  426.         return false;
  427.     }
  428.  
  429.     void OnDidApplyAnimationProperties()
  430.     {
  431.         UpdateParameters();
  432.     }
  433.  
  434.     void OnDrawGizmosSelected()
  435.     {
  436.         if (!enabled)
  437.             return;
  438.  
  439.         if (Application.isEditor && !Application.isPlaying && transform.hasChanged)
  440.         {
  441.             //InitTransforms();
  442.             SetupParticles();
  443.         }
  444.  
  445.         Gizmos.color = Color.white;
  446.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  447.         {
  448.             DrawGizmos(m_ParticleTrees[i]);
  449.         }
  450.     }
  451.  
  452.     void DrawGizmos(ParticleTree pt)
  453.     {
  454.         for (int i = 0; i < pt.m_Particles.Count; ++i)
  455.         {
  456.             Particle p = pt.m_Particles[i];
  457.             if (p.m_ParentIndex >= 0)
  458.             {
  459.                 Particle p0 = pt.m_Particles[p.m_ParentIndex];
  460.                 Gizmos.DrawLine(p.m_Position, p0.m_Position);
  461.             }
  462.  
  463.             if (p.m_Radius > 0)
  464.             {
  465.                 Gizmos.DrawWireSphere(p.m_Position, p.m_Radius * m_ObjectScale);
  466.             }
  467.         }
  468.     }
  469.  
  470.     public void SetWeight(float w)
  471.     {
  472.         if (m_Weight != w)
  473.         {
  474.             if (w == 0)
  475.             {
  476.                 InitTransforms();
  477.             }
  478.             else if (m_Weight == 0)
  479.             {
  480.                 ResetParticlesPosition();
  481.             }
  482.             m_Weight = m_BlendWeight = w;
  483.         }
  484.     }
  485.  
  486.     public float GetWeight()
  487.     {
  488.         return m_Weight;
  489.     }
  490.  
  491.     void UpdateParticles()
  492.     {
  493.         if (m_ParticleTrees.Count <= 0)
  494.             return;
  495.  
  496.         int loop = 1;
  497.         float timeVar = 1;
  498.         float dt = m_DeltaTime;
  499.  
  500.         if (m_UpdateMode == UpdateMode.Default)
  501.         {
  502.             if (m_UpdateRate > 0)
  503.             {
  504.                 timeVar = dt * m_UpdateRate;
  505.             }
  506.         }
  507.         else
  508.         {
  509.             if (m_UpdateRate > 0)
  510.             {
  511.                 float frameTime = 1.0f / m_UpdateRate;
  512.                 m_Time += dt;
  513.                 loop = 0;
  514.  
  515.                 while (m_Time >= frameTime)
  516.                 {
  517.                     m_Time -= frameTime;
  518.                     if (++loop >= 3)
  519.                     {
  520.                         m_Time = 0;
  521.                         break;
  522.                     }
  523.                 }
  524.             }
  525.         }
  526.  
  527.         if (loop > 0)
  528.         {
  529.             for (int i = 0; i < loop; ++i)
  530.             {
  531.                 UpdateParticles1(timeVar, i);
  532.                 UpdateParticles2(timeVar);
  533.             }
  534.         }
  535.         else
  536.         {
  537.             SkipUpdateParticles();
  538.         }
  539.     }
  540.  
  541.     public void SetupParticles()
  542.     {
  543.         m_ParticleTrees.Clear();
  544.  
  545.         if (m_Root != null)
  546.         {
  547.             AppendParticleTree(m_Root);
  548.         }
  549.  
  550.         if (m_Roots != null)
  551.         {
  552.             for (int i = 0; i < m_Roots.Count; ++i)
  553.             {
  554.                 Transform root = m_Roots[i];
  555.                 if (root == null)
  556.                     continue;
  557.  
  558.                 if (m_ParticleTrees.Exists(x => x.m_Root == root))
  559.                     continue;
  560.  
  561.                 AppendParticleTree(root);
  562.             }
  563.         }
  564.  
  565.         m_ObjectScale = Mathf.Abs(transform.lossyScale.x);
  566.         m_ObjectPrevPosition = transform.position;
  567.         m_ObjectMove = Vector3.zero;
  568.  
  569.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  570.         {
  571.             ParticleTree pt = m_ParticleTrees[i];
  572.             AppendParticles(pt, pt.m_Root, -1, 0);
  573.         }
  574.  
  575.         UpdateParameters();
  576.     }
  577.  
  578.     void AppendParticleTree(Transform root)
  579.     {
  580.         if (root == null)
  581.             return;
  582.  
  583.         var pt = new ParticleTree();
  584.         pt.m_Root = root;
  585.         pt.m_RootWorldToLocalMatrix = root.worldToLocalMatrix;
  586.         m_ParticleTrees.Add(pt);
  587.     }
  588.  
  589.     void AppendParticles(ParticleTree pt, Transform b, int parentIndex, float boneLength)
  590.     {
  591.         var p = new Particle();
  592.         p.m_Transform = b;
  593.         p.m_TransformNotNull = b != null;
  594.         p.m_ParentIndex = parentIndex;
  595.  
  596.         if (b != null)
  597.         {
  598.             p.m_Position = p.m_PrevPosition = b.position;
  599.             p.m_InitLocalPosition = b.localPosition;
  600.             p.m_InitLocalRotation = b.localRotation;
  601.         }
  602.         else    // end bone
  603.         {
  604.             Transform pb = pt.m_Particles[parentIndex].m_Transform;
  605.             if (m_EndLength > 0)
  606.             {
  607.                 Transform ppb = pb.parent;
  608.                 if (ppb != null)
  609.                 {
  610.                     p.m_EndOffset = pb.InverseTransformPoint((pb.position * 2 - ppb.position)) * m_EndLength;
  611.                 }
  612.                 else
  613.                 {
  614.                     p.m_EndOffset = new Vector3(m_EndLength, 0, 0);
  615.                 }
  616.             }
  617.             else
  618.             {
  619.                 p.m_EndOffset = pb.InverseTransformPoint(transform.TransformDirection(m_EndOffset) + pb.position);
  620.             }
  621.             p.m_Position = p.m_PrevPosition = pb.TransformPoint(p.m_EndOffset);
  622.             p.m_InitLocalPosition = Vector3.zero;
  623.             p.m_InitLocalRotation = Quaternion.identity;
  624.         }
  625.  
  626.         if (parentIndex >= 0)
  627.         {
  628.             boneLength += (pt.m_Particles[parentIndex].m_Transform.position - p.m_Position).magnitude;
  629.             p.m_BoneLength = boneLength;
  630.             pt.m_BoneTotalLength = Mathf.Max(pt.m_BoneTotalLength, boneLength);
  631.             ++pt.m_Particles[parentIndex].m_ChildCount;
  632.         }
  633.  
  634.         int index = pt.m_Particles.Count;
  635.         pt.m_Particles.Add(p);
  636.  
  637.         if (b != null)
  638.         {
  639.             for (int i = 0; i < b.childCount; ++i)
  640.             {
  641.                 Transform child = b.GetChild(i);
  642.                 bool exclude = false;
  643.                 if (m_Exclusions != null)
  644.                 {
  645.                     exclude = m_Exclusions.Contains(child);
  646.                 }
  647.                 if (!exclude)
  648.                 {
  649.                     AppendParticles(pt, child, index, boneLength);
  650.                 }
  651.                 else if (m_EndLength > 0 || m_EndOffset != Vector3.zero)
  652.                 {
  653.                     AppendParticles(pt, null, index, boneLength);
  654.                 }
  655.             }
  656.  
  657.             if (b.childCount == 0 && (m_EndLength > 0 || m_EndOffset != Vector3.zero))
  658.             {
  659.                 AppendParticles(pt, null, index, boneLength);
  660.             }
  661.         }
  662.     }
  663.  
  664.     public void UpdateParameters()
  665.     {
  666.         SetWeight(m_BlendWeight);
  667.  
  668.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  669.         {
  670.             UpdateParameters(m_ParticleTrees[i]);
  671.         }
  672.     }
  673.  
  674.     void UpdateParameters(ParticleTree pt)
  675.     {
  676.         // m_LocalGravity = m_Root.InverseTransformDirection(m_Gravity);
  677.         pt.m_LocalGravity = pt.m_RootWorldToLocalMatrix.MultiplyVector(m_Gravity).normalized * m_Gravity.magnitude;
  678.  
  679.         for (int i = 0; i < pt.m_Particles.Count; ++i)
  680.         {
  681.             Particle p = pt.m_Particles[i];
  682.             p.m_Damping = m_Damping;
  683.             p.m_Elasticity = m_Elasticity;
  684.             p.m_Stiffness = m_Stiffness;
  685.             p.m_Inert = m_Inert;
  686.             p.m_Friction = m_Friction;
  687.             p.m_Radius = m_Radius;
  688.  
  689.             if (pt.m_BoneTotalLength > 0)
  690.             {
  691.                 float a = p.m_BoneLength / pt.m_BoneTotalLength;
  692.                 if (m_DampingDistrib != null && m_DampingDistrib.keys.Length > 0)
  693.                     p.m_Damping *= m_DampingDistrib.Evaluate(a);
  694.                 if (m_ElasticityDistrib != null && m_ElasticityDistrib.keys.Length > 0)
  695.                     p.m_Elasticity *= m_ElasticityDistrib.Evaluate(a);
  696.                 if (m_StiffnessDistrib != null && m_StiffnessDistrib.keys.Length > 0)
  697.                     p.m_Stiffness *= m_StiffnessDistrib.Evaluate(a);
  698.                 if (m_InertDistrib != null && m_InertDistrib.keys.Length > 0)
  699.                     p.m_Inert *= m_InertDistrib.Evaluate(a);
  700.                 if (m_FrictionDistrib != null && m_FrictionDistrib.keys.Length > 0)
  701.                     p.m_Friction *= m_FrictionDistrib.Evaluate(a);
  702.                 if (m_RadiusDistrib != null && m_RadiusDistrib.keys.Length > 0)
  703.                     p.m_Radius *= m_RadiusDistrib.Evaluate(a);
  704.             }
  705.  
  706.             p.m_Damping = Mathf.Clamp01(p.m_Damping);
  707.             p.m_Elasticity = Mathf.Clamp01(p.m_Elasticity);
  708.             p.m_Stiffness = Mathf.Clamp01(p.m_Stiffness);
  709.             p.m_Inert = Mathf.Clamp01(p.m_Inert);
  710.             p.m_Friction = Mathf.Clamp01(p.m_Friction);
  711.             p.m_Radius = Mathf.Max(p.m_Radius, 0);
  712.         }
  713.     }
  714.  
  715.     void InitTransforms()
  716.     {
  717.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  718.         {
  719.             InitTransforms(m_ParticleTrees[i]);
  720.         }
  721.     }
  722.  
  723.     void InitTransforms(ParticleTree pt)
  724.     {
  725.         for (int i = 0; i < pt.m_Particles.Count; ++i)
  726.         {
  727.             Particle p = pt.m_Particles[i];
  728.             if (p.m_TransformNotNull)
  729.             {
  730.                 p.m_Transform.localPosition = p.m_InitLocalPosition;
  731.                 p.m_Transform.localRotation = p.m_InitLocalRotation;
  732.             }
  733.         }
  734.     }
  735.  
  736.     void ResetParticlesPosition()
  737.     {
  738.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  739.         {
  740.             ResetParticlesPosition(m_ParticleTrees[i]);
  741.         }
  742.  
  743.         m_ObjectPrevPosition = transform.position;
  744.     }
  745.  
  746.     void ResetParticlesPosition(ParticleTree pt)
  747.     {
  748.         for (int i = 0; i < pt.m_Particles.Count; ++i)
  749.         {
  750.             Particle p = pt.m_Particles[i];
  751.             if (p.m_TransformNotNull)
  752.             {
  753.                 p.m_Position = p.m_PrevPosition = p.m_Transform.position;
  754.             }
  755.             else    // end bone
  756.             {
  757.                 Transform pb = pt.m_Particles[p.m_ParentIndex].m_Transform;
  758.                 p.m_Position = p.m_PrevPosition = pb.TransformPoint(p.m_EndOffset);
  759.             }
  760.             p.m_isCollide = false;
  761.         }
  762.     }
  763.  
  764.     void UpdateParticles1(float timeVar, int loopIndex)
  765.     {
  766.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  767.         {
  768.             UpdateParticles1(m_ParticleTrees[i], timeVar, loopIndex);
  769.         }
  770.     }
  771.  
  772.     void UpdateParticles1(ParticleTree pt, float timeVar, int loopIndex)
  773.     {
  774.         Vector3 force = m_Gravity;
  775.         Vector3 fdir = m_Gravity.normalized;
  776.         Vector3 pf = fdir * Mathf.Max(Vector3.Dot(pt.m_RestGravity, fdir), 0);  // project current gravity to rest gravity
  777.         force -= pf;    // remove projected gravity
  778.         force = (force + m_Force) * (m_ObjectScale * timeVar);
  779.  
  780.         Vector3 objectMove = loopIndex == 0 ? m_ObjectMove : Vector3.zero;      // only first loop consider object move
  781.  
  782.         for (int i = 0; i < pt.m_Particles.Count; ++i)
  783.         {
  784.             Particle p = pt.m_Particles[i];
  785.             if (p.m_ParentIndex >= 0)
  786.             {
  787.                 // verlet integration
  788.                 Vector3 v = p.m_Position - p.m_PrevPosition;
  789.                 Vector3 rmove = objectMove * p.m_Inert;
  790.                 p.m_PrevPosition = p.m_Position + rmove;
  791.                 float damping = p.m_Damping;
  792.                 if (p.m_isCollide)
  793.                 {
  794.                     damping += p.m_Friction;
  795.                     if (damping > 1)
  796.                     {
  797.                         damping = 1;
  798.                     }
  799.                     p.m_isCollide = false;
  800.                 }
  801.                 p.m_Position += v * (1 - damping) + force + rmove;
  802.             }
  803.             else
  804.             {
  805.                 p.m_PrevPosition = p.m_Position;
  806.                 p.m_Position = p.m_TransformPosition;
  807.             }
  808.         }
  809.     }
  810.  
  811.     void UpdateParticles2(float timeVar)
  812.     {
  813.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  814.         {
  815.             UpdateParticles2(m_ParticleTrees[i], timeVar);
  816.         }
  817.     }
  818.  
  819.     void UpdateParticles2(ParticleTree pt, float timeVar)
  820.     {
  821.         var movePlane = new Plane();
  822.  
  823.         for (int i = 1; i < pt.m_Particles.Count; ++i)
  824.         {
  825.             Particle p = pt.m_Particles[i];
  826.             Particle p0 = pt.m_Particles[p.m_ParentIndex];
  827.  
  828.             float restLen;
  829.             if (p.m_TransformNotNull)
  830.             {
  831.                 restLen = (p0.m_TransformPosition - p.m_TransformPosition).magnitude;
  832.             }
  833.             else
  834.             {
  835.                 restLen = p0.m_TransformLocalToWorldMatrix.MultiplyVector(p.m_EndOffset).magnitude;
  836.             }
  837.  
  838.             // keep shape
  839.             float stiffness = Mathf.Lerp(1.0f, p.m_Stiffness, m_Weight);
  840.             if (stiffness > 0 || p.m_Elasticity > 0)
  841.             {
  842.                 Matrix4x4 m0 = p0.m_TransformLocalToWorldMatrix;
  843.                 m0.SetColumn(3, p0.m_Position);
  844.                 Vector3 restPos;
  845.                 if (p.m_TransformNotNull)
  846.                 {
  847.                     restPos = m0.MultiplyPoint3x4(p.m_TransformLocalPosition);
  848.                 }
  849.                 else
  850.                 {
  851.                     restPos = m0.MultiplyPoint3x4(p.m_EndOffset);
  852.                 }
  853.  
  854.                 Vector3 d = restPos - p.m_Position;
  855.                 p.m_Position += d * (p.m_Elasticity * timeVar);
  856.  
  857.                 if (stiffness > 0)
  858.                 {
  859.                     d = restPos - p.m_Position;
  860.                     float len = d.magnitude;
  861.                     float maxlen = restLen * (1 - stiffness) * 2;
  862.                     if (len > maxlen)
  863.                     {
  864.                         p.m_Position += d * ((len - maxlen) / len);
  865.                     }
  866.                 }
  867.             }
  868.  
  869.             // collide
  870.             if (m_EffectiveColliders != null)
  871.             {
  872.                 float particleRadius = p.m_Radius * m_ObjectScale;
  873.                 for (int j = 0; j < m_EffectiveColliders.Count; ++j)
  874.                 {
  875.                     DynamicBoneColliderBase c = m_EffectiveColliders[j];
  876.                     p.m_isCollide |= c.Collide(ref p.m_Position, particleRadius);
  877.                 }
  878.             }
  879.  
  880.             // freeze axis, project to plane
  881.             if (m_FreezeAxis != FreezeAxis.None)
  882.             {
  883.                 Vector3 planeNormal = p0.m_TransformLocalToWorldMatrix.GetColumn((int)m_FreezeAxis - 1).normalized;
  884.                 movePlane.SetNormalAndPosition(planeNormal, p0.m_Position);
  885.                 p.m_Position -= movePlane.normal * movePlane.GetDistanceToPoint(p.m_Position);
  886.             }
  887.  
  888.             // keep length
  889.             Vector3 dd = p0.m_Position - p.m_Position;
  890.             float leng = dd.magnitude;
  891.             if (leng > 0)
  892.             {
  893.                 p.m_Position += dd * ((leng - restLen) / leng);
  894.             }
  895.         }
  896.     }
  897.  
  898.     void SkipUpdateParticles()
  899.     {
  900.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  901.         {
  902.             SkipUpdateParticles(m_ParticleTrees[i]);
  903.         }
  904.     }
  905.  
  906.     // only update stiffness and keep bone length
  907.     void SkipUpdateParticles(ParticleTree pt)
  908.     {
  909.         for (int i = 0; i < pt.m_Particles.Count; ++i)
  910.         {
  911.             Particle p = pt.m_Particles[i];
  912.             if (p.m_ParentIndex >= 0)
  913.             {
  914.                 p.m_PrevPosition += m_ObjectMove;
  915.                 p.m_Position += m_ObjectMove;
  916.  
  917.                 Particle p0 = pt.m_Particles[p.m_ParentIndex];
  918.  
  919.                 float restLen;
  920.                 if (p.m_TransformNotNull)
  921.                 {
  922.                     restLen = (p0.m_TransformPosition - p.m_TransformPosition).magnitude;
  923.                 }
  924.                 else
  925.                 {
  926.                     restLen = p0.m_TransformLocalToWorldMatrix.MultiplyVector(p.m_EndOffset).magnitude;
  927.                 }
  928.  
  929.                 // keep shape
  930.                 float stiffness = Mathf.Lerp(1.0f, p.m_Stiffness, m_Weight);
  931.                 if (stiffness > 0)
  932.                 {
  933.                     Matrix4x4 m0 = p0.m_TransformLocalToWorldMatrix;
  934.                     m0.SetColumn(3, p0.m_Position);
  935.                     Vector3 restPos;
  936.                     if (p.m_TransformNotNull)
  937.                     {
  938.                         restPos = m0.MultiplyPoint3x4(p.m_TransformLocalPosition);
  939.                     }
  940.                     else
  941.                     {
  942.                         restPos = m0.MultiplyPoint3x4(p.m_EndOffset);
  943.                     }
  944.  
  945.                     Vector3 d = restPos - p.m_Position;
  946.                     float len = d.magnitude;
  947.                     float maxlen = restLen * (1 - stiffness) * 2;
  948.                     if (len > maxlen)
  949.                     {
  950.                         p.m_Position += d * ((len - maxlen) / len);
  951.                     }
  952.                 }
  953.  
  954.                 // keep length
  955.                 Vector3 dd = p0.m_Position - p.m_Position;
  956.                 float leng = dd.magnitude;
  957.                 if (leng > 0)
  958.                 {
  959.                     p.m_Position += dd * ((leng - restLen) / leng);
  960.                 }
  961.             }
  962.             else
  963.             {
  964.                 p.m_PrevPosition = p.m_Position;
  965.                 p.m_Position = p.m_TransformPosition;
  966.             }
  967.         }
  968.     }
  969.  
  970.     static Vector3 MirrorVector(Vector3 v, Vector3 axis)
  971.     {
  972.         return v - axis * (Vector3.Dot(v, axis) * 2);
  973.     }
  974.  
  975.     void ApplyParticlesToTransforms()
  976.     {
  977.         Vector3 ax = Vector3.right;
  978.         Vector3 ay = Vector3.up;
  979.         Vector3 az = Vector3.forward;
  980.         bool nx = false, ny = false, nz = false;
  981.  
  982. #if !UNITY_5_4_OR_NEWER
  983.         // detect negative scale
  984.         Vector3 lossyScale = transform.lossyScale;
  985.         if (lossyScale.x < 0 || lossyScale.y < 0 || lossyScale.z < 0)
  986.         {
  987.             Transform mirrorObject = transform;
  988.             do
  989.             {
  990.                 Vector3 ls = mirrorObject.localScale;
  991.                 nx = ls.x < 0;
  992.                 if (nx)
  993.                     ax = mirrorObject.right;
  994.                 ny = ls.y < 0;
  995.                 if (ny)
  996.                     ay = mirrorObject.up;
  997.                 nz = ls.z < 0;
  998.                 if (nz)
  999.                     az = mirrorObject.forward;
  1000.                 if (nx || ny || nz)
  1001.                     break;
  1002.  
  1003.                 mirrorObject = mirrorObject.parent;
  1004.             }
  1005.             while (mirrorObject != null);
  1006.         }
  1007. #endif
  1008.  
  1009.         for (int i = 0; i < m_ParticleTrees.Count; ++i)
  1010.         {
  1011.             ApplyParticlesToTransforms(m_ParticleTrees[i], ax, ay, az, nx, ny, nz);
  1012.         }
  1013.     }
  1014.  
  1015.     void ApplyParticlesToTransforms(ParticleTree pt, Vector3 ax, Vector3 ay, Vector3 az, bool nx, bool ny, bool nz)
  1016.     {
  1017.         for (int i = 1; i < pt.m_Particles.Count; ++i)
  1018.         {
  1019.             Particle p = pt.m_Particles[i];
  1020.             Particle p0 = pt.m_Particles[p.m_ParentIndex];
  1021.  
  1022.             if (p0.m_ChildCount <= 1)       // do not modify bone orientation if has more then one child
  1023.             {
  1024.                 Vector3 localPos;
  1025.                 if (p.m_TransformNotNull)
  1026.                 {
  1027.                     localPos = p.m_Transform.localPosition;
  1028.                 }
  1029.                 else
  1030.                 {
  1031.                     localPos = p.m_EndOffset;
  1032.                 }
  1033.                 Vector3 v0 = p0.m_Transform.TransformDirection(localPos);
  1034.                 Vector3 v1 = p.m_Position - p0.m_Position;
  1035. #if !UNITY_5_4_OR_NEWER
  1036.                 if (nx)
  1037.                     v1 = MirrorVector(v1, ax);
  1038.                 if (ny)
  1039.                     v1 = MirrorVector(v1, ay);
  1040.                 if (nz)
  1041.                     v1 = MirrorVector(v1, az);
  1042. #endif
  1043.                 Quaternion rot = Quaternion.FromToRotation(v0, v1);
  1044.                 p0.m_Transform.rotation = rot * p0.m_Transform.rotation;
  1045.             }
  1046.  
  1047.             if (p.m_TransformNotNull)
  1048.             {
  1049.                 p.m_Transform.position = p.m_Position;
  1050.             }
  1051.         }
  1052.     }
  1053.  
  1054. #if ENABLE_MULTITHREAD
  1055.     static void AddPendingWork(DynamicBone db)
  1056.     {
  1057.         s_PendingWorks.Add(db);
  1058.     }
  1059.  
  1060.     static void AddWorkToQueue(DynamicBone db)
  1061.     {
  1062.         s_WorkQueueSemaphore.Release();
  1063.     }
  1064.  
  1065.     static DynamicBone GetWorkFromQueue()
  1066.     {
  1067.         int idx = Interlocked.Increment(ref s_WorkQueueIndex);
  1068.         return s_EffectiveWorks[idx];
  1069.     }
  1070.  
  1071.     static void ThreadProc()
  1072.     {
  1073.         while (true)
  1074.         {
  1075.             s_WorkQueueSemaphore.WaitOne();
  1076.  
  1077.             DynamicBone db = GetWorkFromQueue();
  1078.             db.UpdateParticles();
  1079.  
  1080.             if (Interlocked.Decrement(ref s_RemainWorkCount) <= 0)
  1081.             {
  1082.                 s_AllWorksDoneEvent.Set();
  1083.             }
  1084.         }
  1085.     }
  1086.  
  1087.     static void InitThreadPool()
  1088.     {
  1089.         s_AllWorksDoneEvent = new AutoResetEvent(false);
  1090.         s_WorkQueueSemaphore = new Semaphore(0, int.MaxValue);
  1091.  
  1092.         int threadCount = System.Environment.ProcessorCount;
  1093.  
  1094.         for (int i = 0; i < threadCount; ++i)
  1095.         {
  1096.             var t = new Thread(ThreadProc);
  1097.             t.IsBackground = true;
  1098.             t.Start();
  1099.         }
  1100.     }
  1101.  
  1102.     static void ExecuteWorks()
  1103.     {
  1104.         if (s_PendingWorks.Count <= 0)
  1105.             return;
  1106.  
  1107.         s_EffectiveWorks.Clear();
  1108.  
  1109.         for (int i = 0; i < s_PendingWorks.Count; ++i)
  1110.         {
  1111.             DynamicBone db = s_PendingWorks[i];
  1112.             if (db != null && db.enabled)
  1113.             {
  1114.                 db.CheckDistance();
  1115.                 if (db.IsNeedUpdate())
  1116.                 {
  1117.                     s_EffectiveWorks.Add(db);
  1118.                 }
  1119.             }
  1120.         }
  1121.  
  1122.         s_PendingWorks.Clear();
  1123.         if (s_EffectiveWorks.Count <= 0)
  1124.             return;
  1125.  
  1126.         if (s_AllWorksDoneEvent == null)
  1127.         {
  1128.             InitThreadPool();
  1129.         }
  1130.  
  1131.         int workCount = s_RemainWorkCount = s_EffectiveWorks.Count;
  1132.         s_WorkQueueIndex = -1;
  1133.  
  1134.         for (int i = 0; i < workCount; ++i)
  1135.         {
  1136.             DynamicBone db = s_EffectiveWorks[i];
  1137.             db.Prepare();
  1138.             AddWorkToQueue(db);
  1139.         }
  1140.  
  1141.         s_AllWorksDoneEvent.WaitOne();
  1142.  
  1143.         for (int i = 0; i < workCount; ++i)
  1144.         {
  1145.             DynamicBone db = s_EffectiveWorks[i];
  1146.             db.ApplyParticlesToTransforms();
  1147.         }
  1148.     }
  1149. #endif
  1150. }
  1151.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement