Пример #1
0
        public H3DAnimation ToH3DSkeletalAnimation(H3DDict <H3DBone> Skeleton)
        {
            H3DAnimation Output = new H3DAnimation()
            {
                Name          = "GFMotion",
                FramesCount   = FramesCount,
                AnimationType = H3DAnimationType.Skeletal
            };

            foreach (GF1MotBoneTransform Bone in Bones)
            {
                H3DAnimTransform Transform = new H3DAnimTransform();

                SetKeyFrameGroup(Bone.TranslationX, Transform.TranslationX, 0);
                SetKeyFrameGroup(Bone.TranslationY, Transform.TranslationY, 1);
                SetKeyFrameGroup(Bone.TranslationZ, Transform.TranslationZ, 2);

                SetKeyFrameGroup(Bone.RotationX, Transform.RotationX, 3);
                SetKeyFrameGroup(Bone.RotationY, Transform.RotationY, 4);
                SetKeyFrameGroup(Bone.RotationZ, Transform.RotationZ, 5);

                SetKeyFrameGroup(Bone.ScaleX, Transform.ScaleX, 6);
                SetKeyFrameGroup(Bone.ScaleY, Transform.ScaleY, 7);
                SetKeyFrameGroup(Bone.ScaleZ, Transform.ScaleZ, 8);

                Output.Elements.Add(new H3DAnimationElement()
                {
                    Name          = Bone.Name,
                    Content       = Transform,
                    TargetType    = H3DTargetType.Bone,
                    PrimitiveType = H3DPrimitiveType.Transform
                });
            }

            //If we don't have a Skeleton then can't convert anything, just return with
            //what we have.
            if (Skeleton == null)
            {
                return(Output);
            }

            /*
             * Transform World Space bones to Local Space.
             * Not all animations have those.
             * This can be improved, for example, by supporting Scales aswell,
             * and checking for the special case where the World Space bone have no parent.
             * Those cases doesn't actually happen in any of the observed animations,
             * but it's always good pratice to check all fail paths.
             */
            int AnimIdx = 0;

            foreach (GF1MotBoneTransform Bone in Bones)
            {
                if (Bone.IsWorldSpace)
                {
                    if (!Skeleton.Contains(Bone.Name))
                    {
                        break;
                    }

                    H3DBone PoseBone = Skeleton[Bone.Name];

                    Vector3[] LocalTrans = new Vector3[FramesCount + 1];
                    Vector3[] ParentRot  = new Vector3[FramesCount + 1];

                    int    BoneIndex   = Skeleton.Find(Bone.Name);
                    int    ParentIndex = Skeleton[BoneIndex].ParentIndex;
                    string ParentName  = Skeleton[ParentIndex].Name;

                    for (int Frame = 0; Frame < FramesCount + 1; Frame++)
                    {
                        Matrix4x4 Transform = Matrix4x4.Identity;

                        int b = BoneIndex;

                        while ((b = Skeleton[b].ParentIndex) != -1)
                        {
                            GetBoneRT(
                                Output,
                                Skeleton,
                                Skeleton[b].Name,
                                Frame,
                                out Vector3 R,
                                out Vector3 T);

                            Transform *= Matrix4x4.CreateRotationX(R.X);
                            Transform *= Matrix4x4.CreateRotationY(R.Y);
                            Transform *= Matrix4x4.CreateRotationZ(R.Z);
                            Transform *= Matrix4x4.CreateTranslation(T);
                        }

                        GetBoneRT(
                            Output,
                            Skeleton,
                            ParentName,
                            Frame,
                            out Vector3 PR,
                            out Vector3 PT);

                        GetBoneRT(
                            Output,
                            Skeleton,
                            Bone.Name,
                            Frame,
                            out Vector3 BR,
                            out Vector3 BT);

                        Matrix4x4.Invert(Transform, out Matrix4x4 ITransform);

                        BT = Vector3.Transform(BT, ITransform);

                        Quaternion Rotation = VectorExtensions.CreateRotationBetweenVectors(PT, BT);

                        LocalTrans[Frame] = Vector3.Transform(BT, Quaternion.Inverse(Rotation));

                        ParentRot[Frame] = Rotation.ToEuler();
                    }

                    H3DAnimationElement B_Anim = Output.Elements[AnimIdx];
                    H3DAnimationElement P_Anim = Output.Elements.Find(x => x.Name == ParentName);

                    if (P_Anim == null)
                    {
                        P_Anim = new H3DAnimationElement()
                        {
                            Name          = ParentName,
                            Content       = new H3DAnimTransform(),
                            TargetType    = H3DTargetType.Bone,
                            PrimitiveType = H3DPrimitiveType.Transform
                        };

                        Output.Elements.Add(P_Anim);
                    }

                    H3DAnimTransform B_AT = (H3DAnimTransform)B_Anim.Content;
                    H3DAnimTransform P_AT = (H3DAnimTransform)P_Anim.Content;

                    AddVectors(LocalTrans, B_AT.TranslationX, B_AT.TranslationY, B_AT.TranslationZ);

                    if (!P_AT.RotationExists)
                    {
                        AddVectors(ParentRot, P_AT.RotationX, P_AT.RotationY, P_AT.RotationZ);
                    }
                }

                AnimIdx++;
            }

            return(Output);
        }