Exemple #1
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));
        }
Exemple #2
0
        public Quaternion TrackExponential(Vector4 targetValueVec, float halfLife, float deltaTime)
        {
            if (halfLife < MathUtil.Epsilon)
            {
                VelocityVec = Vector4.zero;
                ValueVec    = targetValueVec;
                return(QuaternionUtil.FromVector4(targetValueVec));
            }

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

            return(TrackDampingRatio(targetValueVec, angularFrequency, dampingRatio, deltaTime));
        }
Exemple #3
0
        public Quaternion TrackHalfLife(Vector4 targetValueVec, float frequencyHz, float halfLife, float deltaTime)
        {
            if (halfLife < MathUtil.Epsilon)
            {
                VelocityVec = Vector4.zero;
                ValueVec    = targetValueVec;
                return(QuaternionUtil.FromVector4(targetValueVec));
            }

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

            return(TrackDampingRatio(targetValueVec, angularFrequency, dampingRatio, deltaTime));
        }
        public void SampleFromField()
        {
            m_objPosition = transform.position;
            m_objRotation = transform.rotation;

            if (ReactorField == null)
            {
                return;
            }

            var comp = ReactorField.GetComponent <BoingReactorField>();

            if (comp == null)
            {
        #if UNITY_EDITOR
                if (!s_warnedComponent)
                {
                    Debug.LogWarning("The assigned ReactorField game object must have a BoingReactorField component for BoingReactorFieldCpuSampler components to sample from.");
                    s_warnedComponent = true;
                }
        #endif

                return;
            }

            if (comp.HardwareMode != BoingReactorField.HardwareModeEnum.CPU)
            {
        #if UNITY_EDITOR
                if (!s_warnedHardwareMode)
                {
                    Debug.LogWarning("The BoingReactorField component needs to be set to CPU hardware mode for BoingReactorFieldCpuSampler components to sample from.");
                    s_warnedHardwareMode = true;
                }
        #endif

                return;
            }

            Vector3 positionOffset;
            Vector4 rotationOffset;
            if (!comp.SampleCpuGrid(transform.position, out positionOffset, out rotationOffset))
            {
                return;
            }

            transform.position = m_objPosition + positionOffset * PositionSampleMultiplier;
            transform.rotation = QuaternionUtil.Pow(QuaternionUtil.FromVector4(rotationOffset), RotationSampleMultiplier) * m_objRotation;
        }
Exemple #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;
                    }
                }
Exemple #6
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;
                        }
                    }
                }
Exemple #7
0
                public void Execute(ref Params p, float dt)
                {
                    bool useAccumulatedEffectors = (m_numEffectors >= 0);

                    bool positionSpringNeedsUpdate =
                        useAccumulatedEffectors
            ? (PositionSpring.Velocity.sqrMagnitude > MathUtil.Epsilon ||
               (PositionSpring.Value - PositionTarget).sqrMagnitude > MathUtil.Epsilon)
            : p.Bits.IsBitSet(ReactorFlags.EnablePositionEffect);
                    bool rotationSpringNeedsUpdate =
                        useAccumulatedEffectors
            ? (RotationSpring.VelocityVec.sqrMagnitude > MathUtil.Epsilon ||
               (RotationSpring.ValueVec - RotationTarget).sqrMagnitude > MathUtil.Epsilon)
            : p.Bits.IsBitSet(ReactorFlags.EnableRotationEffect);

                    if (m_numEffectors == 0)
                    {
                        bool earlyOut = true;

                        if (positionSpringNeedsUpdate)
                        {
                            earlyOut = false;
                        }
                        else
                        {
                            PositionSpring.Reset(PositionTarget);
                        }

                        if (rotationSpringNeedsUpdate)
                        {
                            earlyOut = false;
                        }
                        else
                        {
                            RotationSpring.Reset(QuaternionUtil.FromVector4(RotationTarget));
                        }

                        if (earlyOut)
                        {
                            return;
                        }
                    }

                    if (m_instantAccumulation != 0)
                    {
                        PositionSpring.Value    = PositionTarget;
                        RotationSpring.ValueVec = RotationTarget;
                        m_instantAccumulation   = 0;
                    }
                    else
                    {
                        if (positionSpringNeedsUpdate)
                        {
                            switch (p.PositionParameterMode)
                            {
                            case ParameterMode.Exponential:
                                PositionSpring.TrackExponential(PositionTarget, p.PositionExponentialHalfLife, dt);
                                break;

                            case ParameterMode.OscillationByHalfLife:
                                PositionSpring.TrackHalfLife(PositionTarget, p.PositionOscillationFrequency, p.PositionOscillationHalfLife, dt);
                                break;

                            case ParameterMode.OscillationByDampingRatio:
                                PositionSpring.TrackDampingRatio(PositionTarget, p.PositionOscillationFrequency * MathUtil.TwoPi, p.PositionOscillationDampingRatio, dt);
                                break;
                            }
                        }

                        if (rotationSpringNeedsUpdate)
                        {
                            switch (p.RotationParameterMode)
                            {
                            case ParameterMode.Exponential:
                                RotationSpring.TrackExponential(RotationTarget, p.RotationExponentialHalfLife, dt);
                                break;

                            case ParameterMode.OscillationByHalfLife:
                                RotationSpring.TrackHalfLife(RotationTarget, p.RotationOscillationFrequency, p.RotationOscillationHalfLife, dt);
                                break;

                            case ParameterMode.OscillationByDampingRatio:
                                RotationSpring.TrackDampingRatio(RotationTarget, p.RotationOscillationFrequency * MathUtil.TwoPi, p.RotationOscillationDampingRatio, dt);
                                break;
                            }
                        }
                    }

                    if (!useAccumulatedEffectors)
                    {
                        if (!positionSpringNeedsUpdate)
                        {
                            PositionSpring.Reset(PositionTarget);
                        }
                        if (!rotationSpringNeedsUpdate)
                        {
                            RotationSpring.Reset(RotationTarget);
                        }
                    }
                }
Exemple #8
0
        public void OnDrawGizmos()
        {
            if (BoneData == null)
            {
                return;
            }

            bool selected = false;

            foreach (var selectedGo in UnityEditor.Selection.gameObjects)
            {
                if (gameObject == selectedGo)
                {
                    selected = true;
                    break;
                }

                foreach (var collider in BoingColliders)
                {
                    if (collider == null)
                    {
                        continue;
                    }

                    if (collider.gameObject == selectedGo)
                    {
                        selected = true;
                        break;
                    }
                }
                if (selected)
                {
                    break;
                }
            }

            if (!selected)
            {
                return;
            }

            for (int iChain = 0; iChain < BoneData.Length; ++iChain)
            {
                var chain = BoneChains[iChain];
                var aBone = BoneData[iChain];

                if (aBone == null)
                {
                    continue;
                }

                foreach (var bone in aBone)
                {
                    var parentBone =
                        bone.ParentIndex >= 0
              ? aBone[bone.ParentIndex]
              : null;

                    Vector3    boneAnimPos    = Application.isPlaying ? bone.CachedPositionWs : bone.Transform.position;
                    Vector3    boneTargetPos  = bone.Instance.PositionTarget;
                    Vector3    boneSpringPos  = bone.Instance.PositionSpring.Value;
                    Vector3    boneBlendedPos = bone.BlendedPositionWs;
                    Quaternion boneAnimRot    = Application.isPlaying ? bone.CachedRotationWs : bone.Transform.rotation;
                    Quaternion boneTargetRot  = QuaternionUtil.FromVector4(bone.Instance.RotationTarget);
                    Quaternion boneSpringRot  = bone.Instance.RotationSpring.ValueQuat;
                    Quaternion boneBlendedRot = bone.BlendedRotationWs;

                    float boneRadius =
                        (chain.EnableBoingKitCollision || chain.EnableUnityCollision || chain.EnableInterChainCollision)
              ? MinScale * bone.CollisionRadius
              : 0.02f;

                    Gizmos.color = Color.white;
                    if (DebugDrawRawBones)
                    {
                        Gizmos.matrix = Matrix4x4.TRS(boneAnimPos, boneAnimRot, Vector3.one);
                        Gizmos.DrawWireSphere(Vector3.zero, boneRadius);
                        Gizmos.matrix = Matrix4x4.identity;

                        if (parentBone != null)
                        {
                            Vector3 parentAnimPos =
                                Application.isPlaying
                  ? parentBone.CachedPositionWs
                  : parentBone.Transform.position;

                            Gizmos.DrawLine(boneAnimPos, parentAnimPos);
                        }

                        if (DebugDrawBoneNames)
                        {
                            Handles.Label(boneAnimPos, bone.Transform.name);
                        }

                        if (DebugDrawLengthFromRoot)
                        {
                            float tBone = Mathf.Clamp01(bone.LengthFromRoot * MathUtil.InvSafe(chain.MaxLengthFromRoot));
                            Handles.Label(boneAnimPos, bone.LengthFromRoot.ToString("n3") + " (t: " + tBone.ToString("n2") + ")");
                        }
                    }

                    Gizmos.color = Color.yellow;
                    if (DebugDrawBoingBones && Application.isPlaying)
                    {
                        Gizmos.matrix = Matrix4x4.TRS(boneSpringPos, boneSpringRot, Vector3.one);
                        Gizmos.DrawWireSphere(Vector3.zero, boneRadius);
                        Gizmos.matrix = Matrix4x4.identity;

                        if (parentBone != null)
                        {
                            Vector3 parentSpringPos = parentBone.Instance.PositionSpring.Value;

                            Gizmos.DrawLine(boneSpringPos, parentSpringPos);
                        }

                        if (DebugDrawBoneNames)
                        {
                            Handles.Label(boneSpringPos, bone.Transform.name);
                        }
                    }

                    Gizmos.color = Color.red;
                    if (DebugDrawTargetBones && Application.isPlaying)
                    {
                        Gizmos.matrix = Matrix4x4.TRS(boneTargetPos, boneTargetRot, Vector3.one);
                        Gizmos.DrawWireSphere(Vector3.zero, boneRadius);
                        Gizmos.matrix = Matrix4x4.identity;

                        if (parentBone != null)
                        {
                            Vector3 parentTargetPos = parentBone.Instance.PositionTarget;

                            Gizmos.DrawLine(boneTargetPos, parentTargetPos);
                        }

                        if (DebugDrawBoneNames)
                        {
                            Handles.Label(boneTargetPos, bone.Transform.name);
                        }
                    }

                    Gizmos.color = Color.green;
                    if (DebugDrawFinalBones && Application.isPlaying)
                    {
                        Gizmos.matrix = Matrix4x4.TRS(boneBlendedPos, boneBlendedRot, Vector3.one);
                        Gizmos.DrawWireSphere(Vector3.zero, boneRadius);
                        Gizmos.matrix = Matrix4x4.identity;

                        if (parentBone != null)
                        {
                            Vector3 blendedParentBone = Vector3.Lerp(parentBone.Instance.PositionSpring.Value, parentBone.CachedPositionWs, parentBone.AnimationBlend);

                            Gizmos.DrawLine(boneBlendedPos, blendedParentBone);
                        }

                        if (DebugDrawBoneNames)
                        {
                            Handles.Label(boneBlendedPos, bone.Transform.name);
                        }
                    }
                }

                Gizmos.color = Color.cyan;
                if (DebugDrawChainBounds && (chain.EnableBoingKitCollision || chain.EnableUnityCollision))
                {
                    Gizmos.matrix = Matrix4x4.Translate(chain.Bounds.center);
                    Gizmos.DrawWireCube(Vector3.zero, chain.Bounds.size);
                    Gizmos.matrix = Matrix4x4.identity;
                }
            }

            if (DebugDrawColliders)
            {
                foreach (var collider in BoingColliders)
                {
                    if (collider == null)
                    {
                        continue;
                    }

                    collider.DrawGizmos();
                }
            }
        }