Example #1
0
    void AppendBone(Transform bone, BoneParticle parendBone, Vector3 extraEndBoneOffset = default(Vector3))
    {
        BoneParticle particle = new BoneParticle();

        if (bone != null)
        {
            particle.position = particle.prevPosition = bone.position;
        }
        else
        {
            //虚结点,应该不会出现虚结点没有父节点的情况……
            particle.position = particle.prevPosition = parendBone.position + extraEndBoneOffset;
        }

        if (parendBone != null)
        {
        }

        bones.Add(particle);

        if (bone != null)
        {
            int childCount = bone.childCount;
            if (childCount > 0)
            {
                for (int i = 0; i < childCount; ++i)
                {
                    if (!InExcludtion(bone.GetChild(i)))
                    {
                        AppendBone(bone.GetChild(i), particle);
                    }
                }
            }
            else
            {
                //虚结点
                switch (extraEndPointType)
                {
                case ExtraEndParticle.Length:
                    AppendBone(null, particle, Vector3.Normalize(particle.position - parendBone.position) * extraEndPointDist);
                    break;

                case ExtraEndParticle.Offset:
                    AppendBone(null, particle, extraEndPointOffset);
                    break;

                default:
                    //do nothing no extra end bone appended;
                    break;
                }
            }
        }
    }
Example #2
0
    private void CrateChildBoneParticle(BoneParticle root)
    {
        int childCount = root.BoneTransform.childCount;

        if (childCount > 0)
        {
            Transform    child       = root.BoneTransform.GetChild(0);
            BoneParticle newParticle = new BoneParticle(child.gameObject, false, _boneList.Count, root);
            _boneList.Add(newParticle);
            CrateChildBoneParticle(newParticle);
        }
    }
    void Constraint()
    {
        for (int iter = 0; iter < 10; ++iter)
        {
//			for (int i = 0; i < bones.Count; ++i)
//			{
//				//pos restraints
//			}

            for (int i = 1; i < bones.Count; ++i)
            {
                BoneParticle parentBone = bones [i - 1];
                BoneParticle bone       = bones [i];

                Vector3 originOffset = bone.position - parentBone.position;
                float   originLength = Mathf.Sqrt(Vector3.Dot(originOffset, originOffset));


                //需要保持原形状
                //Stiffness_Bend,弯曲刚性
                //弯曲刚性应该不影响长度,只影响方向,正常的算法是需要acos的,不过这里用两步来趋近
                Matrix4x4 parentLocalToWorld = parentBone.transform.localToWorldMatrix;
                parentLocalToWorld.SetColumn(3, parentBone.position);                 //parent的位置可能是有变化的,修正坐标转换矩阵

                //				Vector3 restPos = parentLocalToWorld.MultiplyPoint3x4 (bone.boneInitOffset);
                Vector3 restPos             = parentLocalToWorld.MultiplyPoint3x4(bone.initLocalPosition);
                Vector3 bendStiffnessVector = restPos - bone.position;
                bone.position += bendStiffnessVector * bone.stiffnessBend;
                //此时两个particle之间的距离已经发生了变化,在计算线性刚性之前要修正一下,这个修正只影响子节点就可以
                Vector3 bended       = bone.position - parentBone.position;
                float   bendedLength = Mathf.Sqrt(Vector3.Dot(bended, bended));
                bone.position += bended * (originLength - bendedLength) / bendedLength;

                //Stiffness_Strecth,线性刚性
                //维持长度,将骨骼长度修复回原长度
                Vector3 delta       = bone.position - parentBone.position;
                float   deltaLength = Mathf.Sqrt(Vector3.Dot(delta, delta));
                float   diff        = (deltaLength - bone.boneInitLength) / (deltaLength * (parentBone.InvMass + bone.InvMass));
                diff *= bone.stiffnessStretch;

                parentBone.position += diff * delta * parentBone.InvMass;
                bone.position       -= diff * delta * bone.InvMass;

//				bone.boneCurLength = Vector3.Distance (bone.position, parentBone.position);

                //				float diff = (Vector3.Dot (delta, delta) - bone.boneInitDelta.magnitude * bone.boneInitDelta.magnitude) / (Vector3.Dot (delta, delta) - bone.boneInitDelta.magnitude * bone.boneInitDelta.magnitude);
                //				diff = diff / (parentBone.invMass + bone.invMass);
                //				parentBone.position += diff * delta * parentBone.invMass;
                //				bone.position -= diff * delta * bone.invMass;
            }
        }
    }
Example #4
0
    private void SetBoneToDefaultPos()
    {
        for (int i = 0; i < _boneList.Count; i++)
        {
            BoneParticle bp = _boneList[i];
            if (bp.IsRoot)
            {
                bp.TargetPos = bp.BoneTransform.position;
                continue;
            }

            bp.BoneTransform.localRotation = bp.DefaultRotate;
            bp.BoneTransform.localPosition = bp.DefaultLocalPos;
            bp.TargetPos = bp.BoneTransform.position;
        }
    }
Example #5
0
    public BoneParticle(GameObject obj, bool isRoot, int boneIdx = 0, BoneParticle parentBone = null)
    {
        GO              = obj;
        IsRoot          = isRoot;
        BoneTransform   = obj.transform;
        CurrPos         = TargetPos = BoneTransform.position;
        DefaultLocalPos = BoneTransform.localPosition;
        BoneIdx         = boneIdx;
        ParentBone      = parentBone;

        if (parentBone != null)
        {
            DefaultDisToParent = Vector3.Distance(BoneTransform.position, parentBone.BoneTransform.position);
        }

        DefaultRotate = BoneTransform.localRotation;
    }
Example #6
0
    private void LateUpdate()
    {
        SetBoneToDefaultPos();
        for (int i = 0; i < _boneList.Count; i++)
        {
            BoneParticle bp = _boneList[i];
            if (bp.IsRoot)
            {
                bp.CurrPos = bp.BoneTransform.position;
                continue;
            }

            Vector3 X              = bp.BoneTransform.right;
            Vector3 forceDir       = bp.TargetPos - bp.CurrPos;
            float   distanceToOPos = forceDir.magnitude;

            forceDir = forceDir.normalized;
            float sprint   = 50.0f;
            float forceStr = sprint / bp.BoneIdx * distanceToOPos;
            float mass     = 3.0f;

            Vector3 parentToThisDir = (bp.CurrPos - bp.ParentBone.CurrPos).normalized;
            //parentToThisDir = (bp.CurrPos - bp.ParentBone.CurrPos).normalized;
            //bp.CurrPos = bp.ParentBone.CurrPos + parentToThisDir * bp.DefaultDisToParent;
            forceDir = Vector3.Cross(parentToThisDir, forceDir).normalized;
            forceDir = Vector3.Cross(forceDir, parentToThisDir).normalized;
            Vector3 accelerate = (forceStr / mass) * forceDir;

            bp.Velocity += accelerate * Time.deltaTime;
            bp.Velocity  = Vector3.Dot(bp.Velocity, forceDir) * 0.99f * forceDir;

            Vector3 dynamicPos = bp.CurrPos + bp.Velocity * Time.deltaTime;
            parentToThisDir = (dynamicPos - bp.ParentBone.CurrPos).normalized;
            bp.CurrPos      = bp.ParentBone.CurrPos + parentToThisDir * bp.DefaultDisToParent;


            bp.BoneTransform.position = bp.CurrPos; //bp.CurrPos;
            //bp.BoneTransform.LookAt(bp.ParentBone.CurrPos, _rootBone.BoneTransform.forward);
            Vector3 lookDir = (bp.CurrPos - bp.ParentBone.CurrPos).normalized;
            //lookDir = Vector3.Cross(bp.BoneTransform.right, lookDir);

            bp.BoneTransform.rotation = QuaternionLookRotation(lookDir, X);
        }
    }
    void Verlet(float deltaTime)
    {
        BoneParticle particle = null;
        Vector3      posCache;

        //TODO 第一个节点需要特殊处理
        for (int i = 0; i < bones.Count; ++i)
        {
            particle = bones [i];
            if (particle.kinematic)
            {
                particle.prevPosition = particle.position;
                particle.position     = particle.transform.position;
            }
            else
            {
                posCache              = particle.position;
                particle.position    += (particle.position - particle.prevPosition) * (1 - particle.damp) + particle.force * deltaTime * deltaTime / particle.Mass;
                particle.prevPosition = posCache;
            }
        }
    }
    void AppendBone(Transform bone, BoneParticle parentBone, Vector3 extraEndBoneOffset = default(Vector3))
    {
        BoneParticle particle = new BoneParticle();

        if (bone != null)
        {
            particle.position          = particle.prevPosition = bone.position;
            particle.transform         = bone;
            particle.initLocalPosition = bone.localPosition;
        }
        else
        {
            //虚结点,应该不会出现虚结点没有父节点的情况……
            particle.position          = particle.prevPosition = parentBone.position + extraEndBoneOffset;
            particle.initLocalPosition = parentBone.transform.InverseTransformPoint(particle.position);
        }


        if (parentBone != null)
        {
            particle.boneInitLength = Vector3.Distance(particle.position, parentBone.position);
            particle.Mass           = 1;  //HACK 先将质量都设成1
        }
        else
        {
            //第一个骨骼这个节点是
            particle.kinematic = true;
        }
        particle.damp             = damp;
        particle.stiffnessBend    = stiffnessBend;
        particle.stiffnessStretch = stiffnessStretch;

        bones.Add(particle);
        if (bone != null)
        {
            int childCount = bone.childCount;
            if (childCount > 0)
            {
                for (int i = 0; i < childCount; ++i)
                {
                    if (!InExcludtion(bone.GetChild(i)))
                    {
                        AppendBone(bone.GetChild(i), particle);
                    }
                }
            }
            else
            {
                //虚结点
                switch (extraEndPointType)
                {
                case ExtraEndParticle.Length:
                    AppendBone(null, particle, Vector3.Normalize(particle.position - parentBone.position) * extraEndPointDist);
                    break;

                case ExtraEndParticle.Offset:
                    AppendBone(null, particle, extraEndPointOffset);
                    break;

                default:
                    //do nothing no extra end bone appended;
                    break;
                }
            }
        }
    }
Example #9
0
 private void Awake()
 {
     _rootBone = new BoneParticle(this.gameObject, true, 0);
     _boneList.Add(_rootBone);
     CrateChildBoneParticle(_rootBone);
 }