示例#1
0
        /**
         * @brief Stores the current clip into a Unity .anim file
         * Important: If you use your own character with blend shapes, you have to make sure it is
         * set to 'legacy' animation type. You can do this by the following steps in Unity3D:
         * 1. In the 'project' window in the Assets hierarchy, click on your fbx model
         * 2. In the Inspector, you should see now the Import Settings of your model.
         * 3. Select in these Import Settings in the 'Rig' tab for the 'Animation Type' the value 'Legacy'
         */
        public void SaveClipAsAnim(string path)
        {
            bool have_t_pose = false;

            if (m_tpose != null && m_tpose.m_joints != null)
            {
                if (m_tpose.m_joints.Count != targetTransformations.Count)
                {
                    Debug.LogError("tpose and model do not have the same number of transformations (" + m_tpose.m_joints.Count + "!="
                                   + targetTransformations.Count + ")");
                    return;
                }
                have_t_pose = true;
            }
            else
            {
                Debug.LogWarning("tpose missing");
            }


            AnimationClip animation_clip = new AnimationClip();

            // Not all of them might actually be used, since not all of them might be a target
            AnimationCurve [] translation_x_curves = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] translation_y_curves = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] translation_z_curves = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] rotation_x_curves    = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] rotation_y_curves    = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] rotation_z_curves    = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] rotation_w_curves    = new AnimationCurve[targetTransformations.Count];
            AnimationCurve [] bs_curves            = new AnimationCurve[targetBlendShapeInfos.Count];

            Debug.Log("nr of clip states: " + m_clip.num_states());
            for (int frame_nr = 0; frame_nr < m_clip.num_states(); frame_nr++)
            {
                // get frame time
                float time = (float)(m_clip[frame_nr].timestamp() - m_clip[0].timestamp()) * 0.001f;                 // time is in ms

                // evaluate transformation
                TransformationValue [] transformation_values = null;
                if (have_t_pose)
                {
                    transformation_values = Utils.evaluate_target_transformations(m_retargeting, m_fs_Rig, m_clip[frame_nr], m_tpose.m_joints);
                }
                else
                {
                    transformation_values = Utils.evaluate_target_transformations(m_retargeting, m_fs_Rig, m_clip[frame_nr], targetTransformations);
                }

                if (transformation_values.Length == targetTransformations.Count)
                {
                    for (int index = 0; index < transformation_values.Length; index++)
                    {
                        // Apply the value for this target
                        if (transformation_values[index] != null)
                        {
                            // Apply the translation value for this target
                            if (translation_x_curves[index] == null)
                            {
                                translation_x_curves[index] = new AnimationCurve();
                                translation_y_curves[index] = new AnimationCurve();
                                translation_z_curves[index] = new AnimationCurve();
                            }
                            translation_x_curves[index].AddKey(time, transformation_values[index].m_translation.x);
                            translation_y_curves[index].AddKey(time, transformation_values[index].m_translation.y);
                            translation_z_curves[index].AddKey(time, transformation_values[index].m_translation.z);

                            if (rotation_x_curves[index] == null)
                            {
                                rotation_x_curves[index] = new AnimationCurve();
                                rotation_y_curves[index] = new AnimationCurve();
                                rotation_z_curves[index] = new AnimationCurve();
                                rotation_w_curves[index] = new AnimationCurve();
                            }
                            // Add to curve for the animation
                            rotation_x_curves[index].AddKey(time, transformation_values[index].m_rotation.x);
                            rotation_y_curves[index].AddKey(time, transformation_values[index].m_rotation.y);
                            rotation_z_curves[index].AddKey(time, transformation_values[index].m_rotation.z);
                            rotation_w_curves[index].AddKey(time, transformation_values[index].m_rotation.w);
                        }
                    }
                }
                else
                {
                    Debug.LogError("Cannot create transformation as evaluated shape size is incorrect");
                }


                // evaluate blendshapes
                BlendshapeValue [] blendshape_values = Utils.evaluate_target_blendshapes(m_retargeting, m_clip.rig(), m_clip[frame_nr], targetBlendShapeInfos);
                if (blendshape_values.Length == targetBlendShapeInfos.Count)
                {
                    for (int index = 0; index < targetBlendShapeInfos.Count; index++)
                    {
                        // Apply the value for this target
                        if (blendshape_values[index] != null)
                        {
                            if (bs_curves[index] == null)
                            {
                                bs_curves[index] = new AnimationCurve();
                            }
                            bs_curves[index].AddKey(time, (float)blendshape_values[index].m_value);
                        }
                    }
                }
                else
                {
                    Debug.LogError("Cannot create blendshapes as evaluated shape size is incorrect");
                }
            }

            // Set all transformation curves for all transformation that are animated
            for (int target_nr = 0; target_nr < targetTransformations.Count; target_nr++)
            {
                // Extract path:
                string path_to_transformation = ((TransformationInformation)targetTransformations[target_nr]).transformPath;
                // Apply translation curve, if there is one
                if (translation_x_curves[target_nr] != null)
                {
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localPosition.x", translation_x_curves[target_nr]);
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localPosition.y", translation_y_curves[target_nr]);
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localPosition.z", translation_z_curves[target_nr]);
                }
                // Apply rotation curve, if there is one
                if (rotation_x_curves[target_nr] != null)
                {
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localRotation.x", rotation_x_curves[target_nr]);
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localRotation.y", rotation_y_curves[target_nr]);
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localRotation.z", rotation_z_curves[target_nr]);
                    animation_clip.SetCurve(path_to_transformation, typeof(Transform), "localRotation.w", rotation_w_curves[target_nr]);
                }
            }

            // Without this, there are some weird jumps (rotation) in the animation:
            animation_clip.EnsureQuaternionContinuity();

            // Set all blendshape curves for all blendshapes that are animated
            for (int i = 0; i < targetBlendShapeInfos.Count; i++)
            {
                if (bs_curves[i] != null)
                {
                    BlendshapeInfo bs_info = (BlendshapeInfo)(targetBlendShapeInfos[i]);
                    // Debug.Log("bs_curves[" + i + "].length=" + bs_curves[i].length);
                    string bs_path = bs_info.m_path;
                    string bs_name = bs_info.m_name;
                    animation_clip.SetCurve(bs_path, typeof(SkinnedMeshRenderer), "blendShape." + bs_name, bs_curves[i]);
                }
            }

            // animation clip asset
            string animation_name = Path.GetFileNameWithoutExtension(path);

            animation_clip.name = animation_name;
                        #if UNITY_EDITOR
            AssetDatabase.CreateAsset(animation_clip, path);
                        #endif

            // Add the clip to the animations of the attached game object
            Animation my_animation = gameObject.animation;
            if (!my_animation)
            {
                gameObject.AddComponent(typeof(Animation));
                my_animation = gameObject.animation;
            }
            if (my_animation)
            {
                my_animation.AddClip(animation_clip, animation_name);
                my_animation.clip = animation_clip;
                my_animation[animation_name].blendMode = AnimationBlendMode.Blend;
            }
            else
            {
                print("Error: could not get animation object");
            }
            Debug.Log("Wrote animation with length " + (1000.0 * animation_clip.length) + " milliseconds");
        }