Пример #1
0
                // for BoingBehavior & BoingReactor
                public void PrepareExecute(ref Params p, Vector3 position, Quaternion rotation, float scale, bool accumulateEffectors)
                {
                    PositionTarget     =
                        PositionOrigin = position;

                    RotationTarget     =
                        RotationOrigin = QuaternionUtil.ToVector4(rotation);

                    if (accumulateEffectors)
                    {
                        // make relative
                        PositionTarget = Vector3.zero;
                        RotationTarget = Vector4.zero;

                        m_numEffectors = 0;
                        m_upWs         =
                            p.Bits.IsBitSet(ReactorFlags.GlobalReactionUpVector)
              ? p.RotationReactionUp
              : rotation *VectorUtil.NormalizeSafe(p.RotationReactionUp, Vector3.up);

                        m_scale = scale;
                    }
                    else
                    {
                        m_numEffectors = -1;
                        m_upWs         = Vector3.zero;
                    }
                }
Пример #2
0
        public Quaternion TrackDampingRatio(Vector4 targetValueVec, float angularFrequency, float dampingRatio, float deltaTime)
        {
            if (angularFrequency < MathUtil.Epsilon)
            {
                VelocityVec = QuaternionUtil.ToVector4(Quaternion.identity);
                return(QuaternionUtil.FromVector4(ValueVec));
            }

            // keep in same hemisphere for shorter track delta
            if (Vector4.Dot(ValueVec, targetValueVec) < 0.0f)
            {
                targetValueVec = -targetValueVec;
            }

            Vector4 delta = targetValueVec - ValueVec;

            float   f      = 1.0f + 2.0f * deltaTime * dampingRatio * angularFrequency;
            float   oo     = angularFrequency * angularFrequency;
            float   hoo    = deltaTime * oo;
            float   hhoo   = deltaTime * hoo;
            float   detInv = 1.0f / (f + hhoo);
            Vector4 detX   = f * ValueVec + deltaTime * VelocityVec + hhoo * targetValueVec;
            Vector4 detV   = VelocityVec + hoo * delta;

            VelocityVec = detV * detInv;
            ValueVec    = detX * detInv;

            if (VelocityVec.magnitude < MathUtil.Epsilon && delta.magnitude < MathUtil.Epsilon)
            {
                VelocityVec = Vector4.zero;
                ValueVec    = targetValueVec;
            }

            return(QuaternionUtil.FromVector4(ValueVec));
        }
Пример #3
0
        public Quaternion TrackExponential(Quaternion targetValue, float halfLife, float deltaTime)
        {
            if (halfLife < MathUtil.Epsilon)
            {
                VelocityVec = QuaternionUtil.ToVector4(Quaternion.identity);
                ValueVec    = QuaternionUtil.ToVector4(targetValue);
                return(targetValue);
            }

            float angularFrequency = 0.6931472f / halfLife;
            float dampingRatio     = 1.0f;

            return(TrackDampingRatio(targetValue, angularFrequency, dampingRatio, deltaTime));
        }
Пример #4
0
        public Quaternion TrackHalfLife(Quaternion targetValue, float frequencyHz, float halfLife, float deltaTime)
        {
            if (halfLife < MathUtil.Epsilon)
            {
                VelocityVec = QuaternionUtil.ToVector4(Quaternion.identity);
                ValueVec    = QuaternionUtil.ToVector4(targetValue);
                return(targetValue);
            }

            float angularFrequency = frequencyHz * MathUtil.TwoPi;
            float dampingRatio     = 0.6931472f / (angularFrequency * halfLife);

            return(TrackDampingRatio(targetValue, angularFrequency, dampingRatio, deltaTime));
        }
Пример #5
0
                public void EndAccumulateTargets(ref Params p)
                {
                    if (m_numEffectors > 0)
                    {
                        PositionTarget *= m_scale / m_numEffectors;
                        PositionTarget += PositionOrigin;

                        RotationTarget /= m_numEffectors;
                        RotationTarget  = QuaternionUtil.ToVector4(QuaternionUtil.FromVector4(RotationTarget) * QuaternionUtil.FromVector4(RotationOrigin));
                    }
                    else
                    {
                        PositionTarget = PositionOrigin;
                        RotationTarget = RotationOrigin;
                    }
                }
Пример #6
0
                // for BoingReactorFied
                public void PrepareExecute(ref Params p, Vector3 gridCenter, Quaternion gridRotation, Vector3 cellOffset)
                {
                    PositionOrigin = gridCenter + cellOffset;
                    RotationOrigin = QuaternionUtil.ToVector4(Quaternion.identity);

                    // make relative
                    PositionTarget = Vector3.zero;
                    RotationTarget = Vector4.zero;

                    m_numEffectors = 0;
                    m_upWs         =
                        p.Bits.IsBitSet(ReactorFlags.GlobalReactionUpVector)
            ? p.RotationReactionUp
            : gridRotation *VectorUtil.NormalizeSafe(p.RotationReactionUp, Vector3.up);

                    m_scale = 1.0f;
                }
Пример #7
0
                public void PullResults(BoingBones bones)
                {
                    for (int iChain = 0; iChain < bones.BoneData.Length; ++iChain)
                    {
                        var chain = bones.BoneChains[iChain];
                        var aBone = bones.BoneData[iChain];

                        if (aBone == null)
                        {
                            continue;
                        }

                        // must cache before manipulating bone transforms
                        // otherwise, we'd cache delta propagated down from parent bones
                        foreach (var bone in aBone)
                        {
                            bone.CachedPositionWs = bone.Transform.position;
                            bone.CachedPositionLs = bone.Transform.localPosition;
                            bone.CachedRotationWs = bone.Transform.rotation;
                            bone.CachedRotationLs = bone.Transform.localRotation;
                        }

                        // blend bone position
                        for (int iBone = 0; iBone < aBone.Length; ++iBone)
                        {
                            var bone = aBone[iBone];

                            // skip fixed root
                            if (iBone == 0 && !chain.LooseRoot)
                            {
                                bone.BlendedPositionWs = bone.CachedPositionWs;
                                continue;
                            }

                            bone.BlendedPositionWs =
                                Vector3.Lerp
                                (
                                    bone.Instance.PositionSpring.Value,
                                    bone.CachedPositionWs,
                                    bone.AnimationBlend
                                );
                        }

                        // rotation delta back-propagation
                        if (bones.EnableRotationEffect)
                        {
                            for (int iBone = 0; iBone < aBone.Length; ++iBone)
                            {
                                var bone = aBone[iBone];

                                // skip fixed root
                                if (iBone == 0 && !chain.LooseRoot)
                                {
                                    bone.BlendedRotationWs = bone.CachedRotationWs;
                                    continue;
                                }

                                if (bone.ChildIndices == null)
                                {
                                    if (bone.ParentIndex >= 0)
                                    {
                                        var parentBone = aBone[bone.ParentIndex];
                                        bone.BlendedRotationWs = parentBone.BlendedRotationWs * (parentBone.RotationInverseWs * bone.CachedRotationWs);
                                    }

                                    continue;
                                }

                                Vector3    bonePos        = bone.CachedPositionWs;
                                Vector3    boneBlendedPos = bone.BlendedPositionWs;
                                Quaternion boneRot        = bone.CachedRotationWs;
                                Quaternion boneRotInv     = Quaternion.Inverse(boneRot);

                                Vector4 childRotDeltaPsVecAccumulator = Vector3.zero;
                                float   totalWeight = 0.0f;
                                foreach (int iChild in bone.ChildIndices)
                                {
                                    var childBone = aBone[iChild];

                                    Vector3 childPos         = childBone.CachedPositionWs;
                                    Vector3 childPosDelta    = childPos - bonePos;
                                    Vector3 childPosDeltaDir = VectorUtil.NormalizeSafe(childPosDelta, Vector3.zero);

                                    Vector3 childBlendedPos         = childBone.BlendedPositionWs;
                                    Vector3 childBlendedPosDelta    = childBlendedPos - boneBlendedPos;
                                    Vector3 childBlendedPosDeltaDir = VectorUtil.NormalizeSafe(childBlendedPosDelta, Vector3.zero);

                                    Quaternion childRotDelta   = Quaternion.FromToRotation(childPosDeltaDir, childBlendedPosDeltaDir);
                                    Quaternion childRotDeltaPs = boneRotInv * childRotDelta;

                                    Vector4 childRotDeltaPsVec = QuaternionUtil.ToVector4(childRotDeltaPs);
                                    float   weight             = Mathf.Max(MathUtil.Epsilon, chain.MaxLengthFromRoot - childBone.LengthFromRoot);
                                    childRotDeltaPsVecAccumulator += weight * childRotDeltaPsVec;
                                    totalWeight += weight;
                                }

                                if (totalWeight > 0.0f)
                                {
                                    Vector4 avgChildRotDeltaPsVec = childRotDeltaPsVecAccumulator / totalWeight;
                                    bone.RotationBackPropDeltaPs = QuaternionUtil.FromVector4(avgChildRotDeltaPsVec);
                                    bone.BlendedRotationWs       = (boneRot * bone.RotationBackPropDeltaPs) * boneRot;
                                }
                                else if (bone.ParentIndex >= 0)
                                {
                                    var parentBone = aBone[bone.ParentIndex];
                                    bone.BlendedRotationWs = parentBone.BlendedRotationWs * (parentBone.RotationInverseWs * bone.CachedRotationWs);
                                }
                            }
                        }

                        // write blended position & adjusted rotation into final transforms
                        for (int iBone = 0; iBone < aBone.Length; ++iBone)
                        {
                            var bone = aBone[iBone];

                            // skip fixed root
                            if (iBone == 0 && !chain.LooseRoot)
                            {
                                bone.Instance.PositionSpring.Reset(bone.CachedPositionWs);
                                bone.Instance.RotationSpring.Reset(bone.CachedRotationWs);
                                continue;
                            }

                            bone.Transform.position   = bone.BlendedPositionWs;
                            bone.Transform.rotation   = bone.BlendedRotationWs;
                            bone.Transform.localScale = bone.BlendedScaleLs;
                        }
                    }
                }
Пример #8
0
                public void AccumulateTarget(ref Params p, ref BoingEffector.Params effector)
                {
                    Vector3 effectRefPos =
                        effector.Bits.IsBitSet(BoingWork.EffectorFlags.ContinuousMotion)
              ? VectorUtil.GetClosestPointOnSegment(PositionOrigin, effector.PrevPosition, effector.CurrPosition)
              : effector.CurrPosition;

                    Vector3 deltaPos = PositionOrigin - effectRefPos;

                    Vector3 deltaPos3D = deltaPos;

                    if (p.Bits.IsBitSet(ReactorFlags.TwoDDistanceCheck))
                    {
                        switch (p.TwoDPlane)
                        {
                        case TwoDPlaneEnum.XY: deltaPos.z = 0.0f; break;

                        case TwoDPlaneEnum.XZ: deltaPos.y = 0.0f; break;

                        case TwoDPlaneEnum.YZ: deltaPos.x = 0.0f; break;
                        }
                    }

                    bool inRange =
                        Mathf.Abs(deltaPos.x) <= effector.Radius &&
                        Mathf.Abs(deltaPos.y) <= effector.Radius &&
                        Mathf.Abs(deltaPos.z) <= effector.Radius &&
                        deltaPos.sqrMagnitude <= effector.Radius * effector.Radius;

                    if (!inRange)
                    {
                        return;
                    }

                    float deltaDist  = deltaPos.magnitude;
                    float tDeltaDist =
                        effector.Radius - effector.FullEffectRadius > MathUtil.Epsilon
            ? 1.0f - Mathf.Clamp01((deltaDist - effector.FullEffectRadius) / (effector.Radius - effector.FullEffectRadius))
            : 1.0f;

                    Vector3 upWsPos     = m_upWs;
                    Vector3 upWsRot     = m_upWs;
                    Vector3 deltaDirPos = VectorUtil.NormalizeSafe(deltaPos3D, m_upWs);
                    Vector3 deltaDirRot = deltaDirPos;

                    if (p.Bits.IsBitSet(ReactorFlags.TwoDPositionInfluence))
                    {
                        switch (p.TwoDPlane)
                        {
                        case TwoDPlaneEnum.XY: deltaDirPos.z = 0.0f; upWsPos.z = 0.0f; break;

                        case TwoDPlaneEnum.XZ: deltaDirPos.y = 0.0f; upWsPos.y = 0.0f; break;

                        case TwoDPlaneEnum.YZ: deltaDirPos.x = 0.0f; upWsPos.x = 0.0f; break;
                        }

                        if (upWsPos.sqrMagnitude < MathUtil.Epsilon)
                        {
                            switch (p.TwoDPlane)
                            {
                            case TwoDPlaneEnum.XY: upWsPos = Vector3.up; break;

                            case TwoDPlaneEnum.XZ: upWsPos = Vector3.forward; break;

                            case TwoDPlaneEnum.YZ: upWsPos = Vector3.up; break;
                            }
                        }
                        else
                        {
                            upWsPos.Normalize();
                        }

                        deltaDirPos = VectorUtil.NormalizeSafe(deltaDirPos, upWsPos);
                    }

                    if (p.Bits.IsBitSet(ReactorFlags.TwoDRotationInfluence))
                    {
                        switch (p.TwoDPlane)
                        {
                        case TwoDPlaneEnum.XY: deltaDirRot.z = 0.0f; upWsRot.z = 0.0f; break;

                        case TwoDPlaneEnum.XZ: deltaDirRot.y = 0.0f; upWsRot.y = 0.0f; break;

                        case TwoDPlaneEnum.YZ: deltaDirRot.x = 0.0f; upWsRot.x = 0.0f; break;
                        }

                        if (upWsRot.sqrMagnitude < MathUtil.Epsilon)
                        {
                            switch (p.TwoDPlane)
                            {
                            case TwoDPlaneEnum.XY: upWsRot = Vector3.up;      break;

                            case TwoDPlaneEnum.XZ: upWsRot = Vector3.forward; break;

                            case TwoDPlaneEnum.YZ: upWsRot = Vector3.up;      break;
                            }
                        }
                        else
                        {
                            upWsRot.Normalize();
                        }

                        deltaDirRot = VectorUtil.NormalizeSafe(deltaDirRot, upWsRot);
                    }

                    if (p.Bits.IsBitSet(ReactorFlags.EnablePositionEffect))
                    {
                        Vector3 moveVec = tDeltaDist * p.MoveReactionMultiplier * effector.MoveDistance * deltaDirPos;
                        PositionTarget += moveVec;

                        PositionSpring.Velocity += tDeltaDist * p.LinearImpulseMultiplier * effector.LinearImpulse * effector.LinearVelocityDir;
                    }

                    if (p.Bits.IsBitSet(ReactorFlags.EnableRotationEffect))
                    {
                        Vector3 rotAxis = VectorUtil.NormalizeSafe(Vector3.Cross(upWsRot, deltaDirRot), VectorUtil.FindOrthogonal(upWsRot));
                        Vector3 rotVec  = tDeltaDist * p.RotationReactionMultiplier * effector.RotateAngle * rotAxis;
                        RotationTarget += QuaternionUtil.ToVector4(QuaternionUtil.FromAngularVector(rotVec));

                        Vector3 angularImpulseDir     = VectorUtil.NormalizeSafe(Vector3.Cross(effector.LinearVelocityDir, deltaDirRot - 0.01f * Vector3.up), rotAxis);
                        float   angularImpulseMag     = tDeltaDist * p.AngularImpulseMultiplier * effector.AngularImpulse;
                        Vector4 angularImpulseDirQuat = QuaternionUtil.ToVector4(QuaternionUtil.FromAngularVector(angularImpulseDir));
                        RotationSpring.VelocityVec += angularImpulseMag * angularImpulseDirQuat;
                    }

                    ++m_numEffectors;
                }
Пример #9
0
 public Quaternion TrackDampingRatio(Quaternion targetValue, float angularFrequency, float dampingRatio, float deltaTime)
 {
     return(TrackDampingRatio(QuaternionUtil.ToVector4(targetValue), angularFrequency, dampingRatio, deltaTime));
 }
Пример #10
0
 public void Reset(Quaternion initValue, Quaternion initVelocity)
 {
     ValueVec    = QuaternionUtil.ToVector4(initValue);
     VelocityVec = QuaternionUtil.ToVector4(initVelocity);
 }
Пример #11
0
 public void Reset(Quaternion initValue)
 {
     ValueVec    = QuaternionUtil.ToVector4(initValue);
     VelocityVec = Vector4.zero;
 }
Пример #12
0
 public void Reset()
 {
     ValueVec    = QuaternionUtil.ToVector4(Quaternion.identity);
     VelocityVec = Vector4.zero;
 }