示例#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));
        }
示例#2
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;
                    }
                }
示例#3
0
        // master sterp function
        public static Quaternion Sterp
        (
            Quaternion a,
            Quaternion b,
            Vector3 twistAxis,
            float tSwing,
            float tTwist,
            out Quaternion swing,
            out Quaternion twist,
            SterpMode mode
        )
        {
            Quaternion q = b * Quaternion.Inverse(a);
            Quaternion swingFull;
            Quaternion twistFull;

            QuaternionUtil.DecomposeSwingTwist(q, twistAxis, out swingFull, out twistFull);

            switch (mode)
            {
            default:
            case SterpMode.Nlerp:
                swing = Quaternion.Lerp(Quaternion.identity, swingFull, tSwing);
                twist = Quaternion.Lerp(Quaternion.identity, twistFull, tTwist);
                break;

            case SterpMode.Slerp:
                swing = Quaternion.Slerp(Quaternion.identity, swingFull, tSwing);
                twist = Quaternion.Slerp(Quaternion.identity, twistFull, tTwist);
                break;
            }

            return(twist * swing);
        }
示例#4
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));
        }
示例#5
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));
        }
示例#6
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));
        }
示例#7
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;
        }
示例#9
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;
                    }
                }
示例#10
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;
                }
示例#11
0
        public static Vector3 ClampBend(Vector3 vector, Vector3 reference, float maxBendAngle)
        {
            float vLenSqr = vector.sqrMagnitude;

            if (vLenSqr < MathUtil.Epsilon)
            {
                return(vector);
            }

            float rLenSqr = reference.sqrMagnitude;

            if (rLenSqr < MathUtil.Epsilon)
            {
                return(vector);
            }

            Vector3 vUnit = vector / Mathf.Sqrt(vLenSqr);
            Vector3 rUnit = reference / Mathf.Sqrt(rLenSqr);

            Vector3 cross = Vector3.Cross(rUnit, vUnit);
            float   dot   = Vector3.Dot(rUnit, vUnit);
            Vector3 axis  =
                cross.sqrMagnitude > MathUtil.Epsilon
          ? cross.normalized
          : FindOrthogonal(rUnit);
            float angle = Mathf.Acos(Mathf.Clamp01(dot));

            if (angle <= maxBendAngle)
            {
                return(vector);
            }

            Quaternion clampedBendRot = QuaternionUtil.AxisAngle(axis, maxBendAngle);
            Vector3    result         = clampedBendRot * reference;

            result *= Mathf.Sqrt(vLenSqr) / Mathf.Sqrt(rLenSqr);

            return(result);
        }
示例#12
0
        public void Restore()
        {
            if (Application.isEditor)
            {
                // transforms can be manually modified in editor between post-update and pre-update
                // we respect that by skipping restoration of cached transforms

                if ((transform.position - RenderPosition).sqrMagnitude < MathUtil.Epsilon)
                {
                    transform.position = CachedPosition;
                }

                if (QuaternionUtil.GetAngle(transform.rotation * Quaternion.Inverse(RenderRotation)) < MathUtil.Epsilon)
                {
                    transform.rotation = CachedRotation;
                }
            }
            else
            {
                transform.position = CachedPosition;
                transform.rotation = CachedRotation;
            }
        }
示例#13
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;
                }
示例#14
0
 public void Reset()
 {
     ValueVec    = QuaternionUtil.ToVector4(Quaternion.identity);
     VelocityVec = Vector4.zero;
 }
示例#15
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();
                }
            }
        }
示例#16
0
 public void Reset(Quaternion initValue)
 {
     ValueVec    = QuaternionUtil.ToVector4(initValue);
     VelocityVec = Vector4.zero;
 }
示例#17
0
 public Quaternion TrackDampingRatio(Quaternion targetValue, float angularFrequency, float dampingRatio, float deltaTime)
 {
     return(TrackDampingRatio(QuaternionUtil.ToVector4(targetValue), angularFrequency, dampingRatio, deltaTime));
 }
示例#18
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);
                        }
                    }
                }
示例#19
0
        void FixedUpdate()
        {
            float dt = Time.fixedDeltaTime;

            Vector3 linearInputVec = Vector3.zero;

            if (Input.GetKey(KeyCode.W))
            {
                linearInputVec += Vector3.forward;
            }
            if (Input.GetKey(KeyCode.S))
            {
                linearInputVec += Vector3.back;
            }
            if (Input.GetKey(KeyCode.A))
            {
                linearInputVec += Vector3.left;
            }
            if (Input.GetKey(KeyCode.D))
            {
                linearInputVec += Vector3.right;
            }
            if (Input.GetKey(KeyCode.R))
            {
                linearInputVec += Vector3.up;
            }
            if (Input.GetKey(KeyCode.F))
            {
                linearInputVec += Vector3.down;
            }

            bool linearThrustOn = linearInputVec.sqrMagnitude > MathUtil.Epsilon;

            if (linearThrustOn)
            {
                linearInputVec    = linearInputVec.normalized * LinearThrust;
                m_linearVelocity += linearInputVec * dt;
                m_linearVelocity  = VectorUtil.ClampLength(m_linearVelocity, 0.0f, MaxLinearSpeed);
            }
            else
            {
                m_linearVelocity = VectorUtil.ClampLength(m_linearVelocity, 0.0f, Mathf.Max(0.0f, m_linearVelocity.magnitude - LinearDrag * dt));
            }

            float speed  = m_linearVelocity.magnitude;
            float tSpeed = speed * MathUtil.InvSafe(MaxLinearSpeed);

            Quaternion tiltRot          = Quaternion.identity;
            float      tHorizontal      = 1.0f;
            float      tHorizontalSpeed = 0.0f;

            if (speed > MathUtil.Epsilon)
            {
                Vector3 flatVel = m_linearVelocity;
                flatVel.y   = 0.0f;
                tHorizontal =
                    m_linearVelocity.magnitude > 0.01f
            ? 1.0f - Mathf.Clamp01(Mathf.Abs(m_linearVelocity.y) / m_linearVelocity.magnitude)
            : 0.0f;
                tHorizontalSpeed = Mathf.Min(1.0f, speed / Mathf.Max(MathUtil.Epsilon, MaxLinearSpeed)) * tHorizontal;
                Vector3 tiltAxis  = Vector3.Cross(Vector3.up, flatVel).normalized;
                float   tiltAngle = Tilt * MathUtil.Deg2Rad * tHorizontalSpeed;
                tiltRot = QuaternionUtil.AxisAngle(tiltAxis, tiltAngle);
            }

            float angularInput = 0.0f;

            if (Input.GetKey(KeyCode.Q))
            {
                angularInput -= 1.0f;
            }
            if (Input.GetKey(KeyCode.E))
            {
                angularInput += 1.0f;
            }

            bool largerMaxAngularSpeed = Input.GetKey(KeyCode.LeftControl);

            bool angularThurstOn = Mathf.Abs(angularInput) > MathUtil.Epsilon;

            if (angularThurstOn)
            {
                float maxAngularSpeed = MaxAngularSpeed * (largerMaxAngularSpeed ? 2.5f : 1.0f);
                angularInput      *= AngularThrust * MathUtil.Deg2Rad;
                m_angularVelocity += angularInput * dt;
                m_angularVelocity  = Mathf.Clamp(m_angularVelocity, -maxAngularSpeed * MathUtil.Deg2Rad, maxAngularSpeed * MathUtil.Deg2Rad);
            }
            else
            {
                m_angularVelocity -= Mathf.Sign(m_angularVelocity) * Mathf.Min(Mathf.Abs(m_angularVelocity), AngularDrag * MathUtil.Deg2Rad * dt);
            }
            m_yawAngle += m_angularVelocity * dt;
            Quaternion yawRot = QuaternionUtil.AxisAngle(Vector3.up, m_yawAngle);

            m_hoverCenter += m_linearVelocity * dt;
            m_hoverPhase  += Time.deltaTime;

            Vector3 hoverVec =
                0.05f * Mathf.Sin(1.37f * m_hoverPhase) * Vector3.right
                + 0.05f * Mathf.Sin(1.93f * m_hoverPhase + 1.234f) * Vector3.forward
                + 0.04f * Mathf.Sin(0.97f * m_hoverPhase + 4.321f) * Vector3.up;

            hoverVec *= Hover;

            Quaternion hoverQuat = Quaternion.FromToRotation(Vector3.up, hoverVec + Vector3.up);

            transform.position = m_hoverCenter + hoverVec;
            transform.rotation = tiltRot * yawRot * hoverQuat;

            if (Motor != null)
            {
                float motorAngularSpeedDeg = Mathf.Lerp(MotorBaseAngularSpeed, MotorMaxAngularSpeed, tHorizontalSpeed);
                m_motorAngle       += motorAngularSpeedDeg * MathUtil.Deg2Rad * dt;
                Motor.localRotation = QuaternionUtil.AxisAngle(Vector3.up, m_motorAngle - m_yawAngle);
            }

            if (BubbleEmitter != null)
            {
                var emission = BubbleEmitter.emission;
                emission.rateOverTime = Mathf.Lerp(BubbleBaseEmissionRate, BubbleMaxEmissionRate, tSpeed);
            }

            if (Eyes != null)
            {
                m_blinkTimer -= dt;
                if (m_blinkTimer <= 0.0f)
                {
                    bool doubleBlink = !m_lastBlinkWasDouble && Random.Range(0.0f, 1.0f) > 0.75f;
                    m_blinkTimer =
                        doubleBlink
                ? 0.2f
                : BlinkInterval + Random.Range(1.0f, 2.0f);
                    m_lastBlinkWasDouble = doubleBlink;

                    m_eyeScaleSpring.Value.y       = 0.0f;
                    m_eyePositionLsSpring.Value.y -= 0.025f;
                }

                Eyes.localScale    = m_eyeScaleSpring.TrackDampingRatio(m_eyeInitScale, 30.0f, 0.8f, dt);
                Eyes.localPosition = m_eyePositionLsSpring.TrackDampingRatio(m_eyeInitPositionLs, 30.0f, 0.8f, dt);
            }
        }
示例#20
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;
                        }
                    }
                }
示例#21
0
 public void Reset(Quaternion initValue, Quaternion initVelocity)
 {
     ValueVec    = QuaternionUtil.ToVector4(initValue);
     VelocityVec = QuaternionUtil.ToVector4(initVelocity);
 }