/// <summary>
        /// Prepara una nueva animacion para ser ejecutada
        /// </summary>
        protected void initAnimationSettings(string animationName, bool playLoop, float userFrameRate)
        {
            isAnimating      = true;
            currentAnimation = animations[animationName];
            this.playLoop    = playLoop;
            currentTime      = 0;
            currentFrame     = 0;

            //Cambiar BoundingBox
            boundingBox = currentAnimation.BoundingBox;
            updateBoundingBox();

            //Si el usuario no especifico un FrameRate, tomar el default de la animacion
            if (userFrameRate == -1f)
            {
                frameRate = (float)currentAnimation.FrameRate;
            }
            else
            {
                frameRate = userFrameRate;
            }

            //La duracion de la animacion.
            animationTimeLenght = ((float)currentAnimation.FramesCount - 1) / frameRate;


            //Configurar postura inicial de los huesos
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                if (!currentAnimation.hasFrames(i))
                {
                    throw new Exception("El hueso " + bone.Name + " no posee KeyFrames");
                }

                //Determinar matriz local inicial
                TgcSkeletalAnimationFrame firstFrame = currentAnimation.BoneFrames[i][0];
                bone.MatLocal = Matrix.RotationQuaternion(firstFrame.Rotation) * Matrix.Translation(firstFrame.Position);

                //Multiplicar por matriz del padre, si tiene
                if (bone.ParentBone != null)
                {
                    bone.MatFinal = bone.MatLocal * bone.ParentBone.MatFinal;
                }
                else
                {
                    bone.MatFinal = bone.MatLocal;
                }
            }


            //Ajustar vertices a posicion inicial del esqueleto
            updateMeshVertices();
        }
        /// <summary>
        /// Actualiza la posicion de cada hueso del esqueleto segun sus KeyFrames de la animacion
        /// </summary>
        protected void updateSkeleton()
        {
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                //Tomar el frame actual para este hueso
                List <TgcSkeletalAnimationFrame> boneFrames = currentAnimation.BoneFrames[i];

                //Solo hay un frame, no hacer nada, ya se hizo en el init de la animacion
                if (boneFrames.Count == 1)
                {
                    continue;
                }

                //Obtener cuadro actual segun el tiempo transcurrido
                float currentFrameF = currentTime * frameRate;
                //Ve a que KeyFrame le corresponde
                int keyFrameIdx = getCurrentFrameBone(boneFrames, currentFrameF);
                this.currentFrame = keyFrameIdx;

                //Armar un intervalo entre el proximo KeyFrame y el anterior
                TgcSkeletalAnimationFrame frame1 = boneFrames[keyFrameIdx - 1];
                TgcSkeletalAnimationFrame frame2 = boneFrames[keyFrameIdx];

                //Calcular la cantidad que hay interpolar en base al la diferencia entre cuadros
                float framesDiff         = frame2.Frame - frame1.Frame;
                float interpolationValue = (currentFrameF - frame1.Frame) / framesDiff;

                //Interpolar traslacion
                Vector3 frameTranslation = (frame2.Position - frame1.Position) * interpolationValue + frame1.Position;

                //Interpolar rotacion con SLERP
                Quaternion quatFrameRotation = Quaternion.Slerp(frame1.Rotation, frame2.Rotation, interpolationValue);

                //Unir ambas transformaciones de este frame
                Matrix frameMatrix = Matrix.RotationQuaternion(quatFrameRotation) * Matrix.Translation(frameTranslation);

                //Multiplicar por la matriz del padre, si tiene
                if (bone.ParentBone != null)
                {
                    bone.MatFinal = frameMatrix * bone.ParentBone.MatFinal;
                }
                else
                {
                    bone.MatFinal = frameMatrix;
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Cargar estructura de animacion
        /// </summary>
        private TgcSkeletalAnimation loadAnimation(TgcSkeletalMesh mesh, TgcSkeletalAnimationData animationData)
        {
            //Crear array para todos los huesos, tengan o no keyFrames
            List <TgcSkeletalAnimationFrame>[] boneFrames = new List <TgcSkeletalAnimationFrame> [mesh.Bones.Length];

            //Cargar los frames para los huesos que si tienen
            for (int i = 0; i < animationData.bonesFrames.Length; i++)
            {
                TgcSkeletalAnimationBoneData boneData = animationData.bonesFrames[i];

                //Crear frames
                for (int j = 0; j < boneData.keyFrames.Length; j++)
                {
                    TgcSkeletalAnimationBoneFrameData frameData = boneData.keyFrames[j];

                    TgcSkeletalAnimationFrame frame = new TgcSkeletalAnimationFrame(
                        frameData.frame,
                        new Vector3(frameData.position[0], frameData.position[1], frameData.position[2]),
                        new Quaternion(frameData.rotation[0], frameData.rotation[1], frameData.rotation[2], frameData.rotation[3])
                        );

                    //Agregar a lista de frames del hueso
                    if (boneFrames[boneData.id] == null)
                    {
                        boneFrames[boneData.id] = new List <TgcSkeletalAnimationFrame>();
                    }
                    boneFrames[boneData.id].Add(frame);
                }
            }

            //BoundingBox de la animación, aprovechar lo que viene en el XML o utilizar el de la malla estática
            TgcBoundingBox boundingBox = null;

            if (animationData.pMin != null && animationData.pMax != null)
            {
                boundingBox = new TgcBoundingBox(
                    TgcParserUtils.float3ArrayToVector3(animationData.pMin),
                    TgcParserUtils.float3ArrayToVector3(animationData.pMax));
            }
            else
            {
                boundingBox = mesh.BoundingBox;
            }

            //Crear animacion
            TgcSkeletalAnimation animation = new TgcSkeletalAnimation(animationData.name, animationData.frameRate, animationData.framesCount, boneFrames, boundingBox);

            return(animation);
        }
        /// <summary>
        /// Cargar estructura de animacion
        /// </summary>
        private TgcSkeletalAnimation loadAnimation(TgcSkeletalMesh mesh, TgcSkeletalAnimationData animationData)
        {
            //Crear array para todos los huesos, tengan o no keyFrames
            List<TgcSkeletalAnimationFrame>[] boneFrames = new List<TgcSkeletalAnimationFrame>[mesh.Bones.Length];
  
            //Cargar los frames para los huesos que si tienen
            for (int i = 0; i < animationData.bonesFrames.Length; i++)
			{
			    TgcSkeletalAnimationBoneData boneData = animationData.bonesFrames[i];
                
                //Crear frames
                for (int j = 0; j < boneData.keyFrames.Length; j++)
			    {
    			    TgcSkeletalAnimationBoneFrameData frameData = boneData.keyFrames[j];

                    TgcSkeletalAnimationFrame frame = new TgcSkeletalAnimationFrame(
                        frameData.frame,
                        new Vector3(frameData.position[0], frameData.position[1], frameData.position[2]),
                        new Quaternion(frameData.rotation[0], frameData.rotation[1], frameData.rotation[2], frameData.rotation[3])
                        );

                    //Agregar a lista de frames del hueso
                    if (boneFrames[boneData.id] == null)
                    {
                        boneFrames[boneData.id] = new List<TgcSkeletalAnimationFrame>();
                    }
                    boneFrames[boneData.id].Add(frame);
			    }
			}

            //BoundingBox de la animación, aprovechar lo que viene en el XML o utilizar el de la malla estática
            TgcBoundingBox boundingBox = null;
            if (animationData.pMin != null && animationData.pMax != null)
            {
                boundingBox = new TgcBoundingBox(
                    TgcParserUtils.float3ArrayToVector3(animationData.pMin),
                    TgcParserUtils.float3ArrayToVector3(animationData.pMax));
            }
            else
            {
                boundingBox = mesh.BoundingBox;
            }
                
            //Crear animacion
            TgcSkeletalAnimation animation = new TgcSkeletalAnimation(animationData.name, animationData.frameRate, animationData.framesCount, boneFrames, boundingBox);
            return animation;
        }