Ejemplo n.º 1
0
 public AdditiveBlend( Clip c , TreeNode b , string blend_control , string add_control )
 {
     children = new TreeNode[2];
     children[0] = c;
     children[1] = b;
     controls = new string[2];
     controls[0] = blend_control;
     controls[1] = add_control;
 }
Ejemplo n.º 2
0
    private RootMotionResult _CalculateRootMotion()
    {
        if (lastRootMotionResult == null)
        {
            RootMotionResult result = new RootMotionResult();

            // ---
            // 1. Reverse Engineer the Unity Weights based on the amount and the layer
            // ---

            // 1a) temporarily accumulate all current AnimationStates and layers
            foreach (AnimationState s in Target.GetComponent <Animation>())
            {
                Mixamo.Clip c = graph.GetClipByAnimName(s.name);
                c.Weight = s.weight;
            }

            SortedList <int, List <AnimationState> > lst = new SortedList <int, List <AnimationState> >(new DescIntComparer());

            foreach (AnimationState aState in Target.GetComponent <Animation>())
            {
                if (aState.layer == 0)
                {
                    if (!lst.ContainsKey(aState.layer))
                    {
                        lst.Add(aState.layer, new List <AnimationState>());
                    }
                    lst[aState.layer].Add(aState);
                }
            }


            // 1b) iterate thru each layer in descending order and calculate the "real" normalized weight of each AnimationState in that layer
            float remainingWeight = 1f;
            List <AnimationState> lastWeightedList = null;
            float lastRemainingWeight = 0f;
            float lastSumWeight       = 0f;
            foreach (KeyValuePair <int, List <AnimationState> > kvp in lst)
            {
                if (remainingWeight > 0f)
                {
                    float sumWeight = 0f;
                    foreach (AnimationState s in kvp.Value)
                    {
                        if (s.enabled)
                        {
                            sumWeight += s.weight;
                        }
                    }

                    if (sumWeight > 0f)
                    {
                        lastWeightedList    = kvp.Value;
                        lastRemainingWeight = remainingWeight;
                        lastSumWeight       = sumWeight;
                    }

                    float normalizeBy = 1f;
                    if (sumWeight > 1f)
                    {
                        normalizeBy = 1f / sumWeight;
                    }

                    float lostWeight = 0f;
                    foreach (AnimationState s in kvp.Value)
                    {
                        Mixamo.Clip c = graph.GetClipByAnimName(s.name);
                        if (s.enabled)
                        {
                            c.NormalizedRootWeight = s.weight * normalizeBy * remainingWeight;
                            lostWeight            += c.NormalizedRootWeight;
                        }
                        else
                        {
                            c.NormalizedRootWeight = 0f;
                        }
                    }

                    remainingWeight -= lostWeight;
                }
                else
                {
                    foreach (AnimationState s in kvp.Value)
                    {
                        Mixamo.Clip c = graph.GetClipByAnimName(s.name);
                        c.NormalizedRootWeight = 0f;
                    }
                }
            }

            if (remainingWeight > 0f && lastWeightedList != null && lastRemainingWeight > 0f && lastSumWeight > 0f)
            {
                foreach (AnimationState s in lastWeightedList)
                {
                    Mixamo.Clip c = graph.GetClipByAnimName(s.name);
                    if (s.enabled)
                    {
                        c.NormalizedRootWeight = (s.weight / lastSumWeight) * lastRemainingWeight;
                        remainingWeight       -= c.NormalizedRootWeight;
                    }
                }
            }


            // ---
            // 2. Calculate Root Motion
            // ---

            // 2a) turn off all animations, so we can look at one by one
            foreach (AnimationState s in Target.GetComponent <Animation>())
            {
                s.weight = 0f;
            }

            result.LocalTranslation    = Vector3.zero;
            result.PelvisLocalPosition = Vector3.zero;
            result.GlobalTranslation   = Vector3.zero;
            result.LocalDeltaRotation  = Vector3.zero;
            result.PelvisLocalRotation = Vector3.zero;
            result.GlobalRotation      = Vector3.zero;

            // 2b) based on the json graph, iterate thru each clip that is set up to have its root motion extracted, sample that clip, and save the root motion change
            foreach (Mixamo.Clip clip in graph.clips)
            {
                if (clip.RootMotion.ExtractionType != Mixamo.RootMotionExtractionType.None || clip.RootMotion.RotExtractionType != Mixamo.RootMotionRotExtractionType.None)
                {
                    // TODO: doesn't need to be computed every time (should optimize this by storing precalculated root motion)

                    // sample animation
                    clip.anim_state.weight = 1f;
                    Target.GetComponent <Animation>().Sample();

                    // compute root motion
                    Vector3 currPos = rmSetup.GetPelvisPosition();
                    Vector3 currRot = rmSetup.GetPelvisRotation();
                    clip.RootMotion.ComputeRootMotion(currPos, currRot, clip.anim_state.normalizedTime, clip.anim_state.wrapMode);

                    clip.anim_state.weight = 0f;

                    if (clip.RootMotion.ExtractionType != Mixamo.RootMotionExtractionType.None)
                    {
                        // calculate root motion translation
                        Vector3 axis = Vector3.one;

                        switch (clip.RootMotion.ExtractionType)
                        {
                        case Mixamo.RootMotionExtractionType.Z:
                            axis = Vector3.forward;
                            break;

                        case Mixamo.RootMotionExtractionType.X:
                            axis = Vector3.right;
                            break;

                        case Mixamo.RootMotionExtractionType.Y:
                            axis = Vector3.up;
                            break;

                        case Mixamo.RootMotionExtractionType.XY:
                            axis = new Vector3(1f, 1f, 0f);
                            break;

                        case Mixamo.RootMotionExtractionType.YZ:
                            axis = new Vector3(0f, 1f, 1f);
                            break;

                        case Mixamo.RootMotionExtractionType.XZ:
                            axis = new Vector3(1f, 0f, 1f);
                            break;

                        case Mixamo.RootMotionExtractionType.XYZ:
                            axis = Vector3.one;
                            break;
                        }

                        Matrix4x4 axis_m = Matrix4x4.Scale(axis);
                        result.LocalTranslation    += axis_m.MultiplyVector(clip.RootMotion.DeltaPosition * clip.NormalizedRootWeight);
                        result.PelvisLocalPosition += axis_m.MultiplyVector((currPos - clip.RootMotion.StartPosition) * clip.NormalizedRootWeight);
                    }

                    if (clip.RootMotion.RotExtractionType != Mixamo.RootMotionRotExtractionType.None)
                    {
                        // calculate root motion rotation
                        Vector3 rotAxis = Vector3.one;
                        if (clip.RootMotion.RotExtractionType == Mixamo.RootMotionRotExtractionType.Y)
                        {
                            rotAxis = Vector3.up;
                        }
                        else if (clip.RootMotion.RotExtractionType == Mixamo.RootMotionRotExtractionType.X)
                        {
                            rotAxis = Vector3.right;
                        }
                        else if (clip.RootMotion.RotExtractionType == Mixamo.RootMotionRotExtractionType.Z)
                        {
                            rotAxis = Vector3.forward;
                        }

                        Matrix4x4 rotAxis_m = Matrix4x4.Scale(rotAxis);
                        result.LocalDeltaRotation  += rotAxis_m.MultiplyVector(clip.RootMotion.DeltaRotation * clip.NormalizedRootWeight);
                        result.PelvisLocalRotation += rotAxis_m.MultiplyVector(currRot * clip.NormalizedRootWeight);
                    }
                }
            }

            // 2c) return to normal position based on animation
            foreach (AnimationState s in Target.GetComponent <Animation>())
            {
                Mixamo.Clip c = graph.GetClipByAnimName(s.name);
                s.weight = c.Weight;
            }
            Target.GetComponent <Animation>().Sample();


            // 2d) remove the calculated root translation from the root node and optionally apply it to the current transform attached to this script

            // save root position to separate node
            RootMotionLocalPosition.localPosition = result.PelvisLocalPosition;
            // remove root position from pelvis
            rmSetup.pelvis.localPosition -= result.PelvisLocalPosition;

            // calculate global root motion translation
            Vector3 startPosition = rmSetup.pelvis.position;
            rmSetup.pelvis.localPosition += result.LocalTranslation;
            Vector3 endPosition = rmSetup.pelvis.position;
            result.GlobalTranslation      = endPosition - startPosition;
            rmSetup.pelvis.localPosition -= result.LocalTranslation;

            // 2e) remove the calculated root rotation and optionally apply it to the current transform
            // TODO: uncomment out this code and make it work. Basically I've calculated the root rotation the same way I've calculated translation, the problem is
            // that this calculation below (removing the rotation and translation from the pelvis node and applying it to the root node) is wrong.
            // I know I need to apply the rotation displaced to the translation or something like that, but I just can't figure it out.

            /*
             * // remove root motion rotation from pelvis
             * RootMotionLocalPosition.localEulerAngles = result.PelvisLocalRotation;
             *
             * rmSetup.pelvis.localEulerAngles -= result.PelvisLocalRotation;
             *
             * // calculate global root motion rotation
             * Vector3 startRot = rmSetup.pelvis.eulerAngles;
             * rmSetup.pelvis.localEulerAngles += result.LocalDeltaRotation;
             * Vector3 endRot = rmSetup.pelvis.eulerAngles;
             * result.GlobalRotation = (endRot - startRot);
             * rmSetup.pelvis.localEulerAngles -= result.LocalDeltaRotation;
             */

            if (RootMotionMode == AnimationStateMachine.RootMotionModeType.Automatic)
            {
                // TODO: uncomment out this code and get it to work, see above step 2e
                //	rmSetup.root.Rotate( result.GlobalRotation , Space.World );
                CharacterController cc = this.GetComponent <CharacterController>();
                if (cc == null)
                {
                    rmSetup.root.Translate(result.GlobalTranslation, Space.World);
                }
                else
                {
                    cc.Move(result.GlobalTranslation);
                }
            }



            lastRootMotionResult = result;
        }

        return(lastRootMotionResult);
    }
Ejemplo n.º 3
0
 public ClipTransition(  Clip c , State source , State dest , float dur_in , float dur_out , string[] guards )
 {
     clip = c;
     clip.anim_state.wrapMode = WrapMode.ClampForever;
     clip.anim_state.enabled = true;
     this.source = source;
     this.start_destination = dest;
     duration_in = dur_in;
     if( duration_in == 0f ) {
         WaitTillEnd = true;
     }
     duration_out = dur_out;
     this.guards = guards;
 }