Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region File Description
- //-----------------------------------------------------------------------------
- // Author: JCBDigger
- // URL: http://Games.DiscoverThat.co.uk
- //-----------------------------------------------------------------------------
- // Central store for animation clips used by all models
- //-----------------------------------------------------------------------------
- // Read the separate document describing what each animation does.
- // See the enums for the list of animations used.
- // .clip animations move the body and legs
- // .head animations only move the head and neck for looking round
- // .arms animations only move the arms to hold weapons
- //-----------------------------------------------------------------------------
- #endregion
- #region Using Statements
- using System;
- using System.IO;
- using System.Collections.Generic;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Content;
- using AssetData;
- #endregion
- namespace Engine
- {
- /// <summary>
- /// Central store for animation clips
- /// </summary>
- public class AnimationManager
- {
- // The rig type is for human or droid or whatever bone layout is used by the model
- // It is multiplied by a number so it can be added to the Clip and part type numbers
- // to create a unique number to represent the clip or the part.
- private const int rigTypeMultiplier = 100;
- private enum RigType
- {
- Alien,
- Human,
- LocalHuman
- }
- // Every rig type must have all of the following animation clips (.clip) and parts
- public enum ClipType
- {
- Alert,
- Charge,
- Crouch,
- Patrol,
- Shuffle,
- Spin,
- Walk
- }
- // Arms (.arms):
- // HoldRifle, AimRifle, HoldPistol, AimPistol
- // ReloadRifle, ReloadPistol, MeleeRifle, MeleePistol
- // Head (.head):
- // Look, Aim
- public enum PartType
- {
- HoldRifle,
- AimRifle,
- Look,
- Aim
- }
- // To avoid garbage collection the strings are converted to unique numbers
- private Dictionary<string, int> rigNumbers = new Dictionary<string, int>();
- private Dictionary<string, int> clipNumbers = new Dictionary<string, int>();
- private Dictionary<string, int> partNumbers = new Dictionary<string, int>();
- // Animation clips used by all the models
- private Dictionary<int, AnimationClip> animationClips = new Dictionary<int, AnimationClip>();
- // Animation parts that can be used to blend some bones in to other animations
- private Dictionary<int, AnimationPart> animationParts = new Dictionary<int, AnimationPart>();
- private ContentManager Content;
- public volatile bool Ready = false;
- public AnimationManager(ContentManager content)
- {
- Content = content;
- //LoadAnimations();
- }
- // Load animationClips and animationParts from the storage manager thread
- public void LoadAnimations()
- {
- Ready = false;
- ClearClips();
- ClearParts();
- FillLookupTables();
- // Convert lookups back to text for use as filenames
- string[] rigNames = new string[rigNumbers.Keys.Count];
- rigNumbers.Keys.CopyTo(rigNames, 0);
- string[] clipNames = new string[clipNumbers.Keys.Count];
- clipNumbers.Keys.CopyTo(clipNames, 0);
- string[] partNames = new string[partNumbers.Keys.Count];
- partNumbers.Keys.CopyTo(partNames, 0);
- // Load Clips
- foreach (string rig in rigNames)
- {
- foreach (string name in clipNames)
- {
- string filename = rig + "-" + name;
- string path = Path.Combine(GameSettings.pathAnimationFolder, filename);
- int unique = rigNumbers[rig] + clipNumbers[name];
- AddClip(unique, Content.Load<AnimationClip>(path));
- }
- }
- // Load Parts
- foreach (string rig in rigNames)
- {
- foreach (string name in partNames)
- {
- string filename = rig + "-" + name;
- string path = Path.Combine(GameSettings.pathAnimationFolder, filename);
- int unique = rigNumbers[rig] + partNumbers[name];
- AddPart(unique, Content.Load<AnimationPart>(path));
- }
- }
- Ready = true;
- }
- // Convert string to unique numbers to avoid garbage collection when joining the
- // rig to the clip or part to get the desired animation to play.
- private void FillLookupTables()
- {
- // The rig is the type of bone structure used by the model
- rigNumbers.Clear();
- // Create numbers to add to the clip and part numbers to give unique results
- rigNumbers.Add("alien", (int)RigType.Alien * rigTypeMultiplier);
- rigNumbers.Add("human", (int)RigType.Human * rigTypeMultiplier);
- // The local player is the 3rd person view. It uses different animations
- rigNumbers.Add(GameSettings.localPlayerAnimationPrefix + "human", (int)RigType.LocalHuman * rigTypeMultiplier);
- // Clips move the whole body
- clipNumbers.Clear();
- clipNumbers.Add("Alert", (int)ClipType.Alert);
- clipNumbers.Add("Charge", (int)ClipType.Charge);
- clipNumbers.Add("Crouch", (int)ClipType.Crouch);
- clipNumbers.Add("Patrol", (int)ClipType.Patrol);
- clipNumbers.Add("Shuffle", (int)ClipType.Shuffle);
- clipNumbers.Add("Spin", (int)ClipType.Spin);
- clipNumbers.Add("Walk", (int)ClipType.Walk);
- // Parts move separate bones such as the arms for aiming the weapon
- partNumbers.Clear();
- partNumbers.Add("HoldRifle", (int)PartType.HoldRifle);
- partNumbers.Add("AimRifle", (int)PartType.AimRifle);
- partNumbers.Add("Look", (int)PartType.Look);
- partNumbers.Add("Aim", (int)PartType.Aim);
- }
- #region Use
- // checkBoneCount is the number of bones in the character model
- public AnimationClip GetAnimationClip(int take, int checkBoneCount)
- {
- if (IsClipBoneCountOK(take, checkBoneCount))
- {
- return GetClip(take);
- }
- else
- {
- return null;
- }
- }
- // checkBoneCount is the number of bones in the character model
- public AnimationPart GetAnimationPart(int partNum, int checkBoneCount)
- {
- if (IsPartBoneCountOK(partNum, checkBoneCount))
- {
- return GetPart(partNum);
- }
- else
- {
- return null;
- }
- }
- /// <summary>
- /// Return true if the number of bones in the model is the same as the number
- /// required to use the clip. Animations are unlikely to work unless the rigs
- /// are identical. The clip must also exist.
- /// </summary>
- /// <param name="clipName">The name of the animation clip, e.g. "Walk" or "Run" etc.</param>
- /// <param name="modelBoneCount">The number of bones in the calling model</param>
- public bool IsClipBoneCountOK(int clipNum, int modelBoneCount)
- {
- if (ClipExists(clipNum) && animationClips[clipNum].BoneCount == modelBoneCount)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- public bool ClipExists(int clipNum)
- {
- if (animationClips.ContainsKey(clipNum))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- public AnimationClip GetClip(int clipNum)
- {
- if (ClipExists(clipNum))
- {
- return animationClips[clipNum];
- }
- else
- {
- return null;
- }
- }
- /// <summary>
- /// Return true if the number of bones in the model is the same as the number
- /// required to use the part clip. Animations are unlikely to work unless the rigs
- /// are identical. The part must also exist.
- /// </summary>
- public bool IsPartBoneCountOK(int partNum, int modelBoneCount)
- {
- if (PartExists(partNum) && animationParts[partNum].BoneCount == modelBoneCount)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- public bool PartExists(int partNum)
- {
- if (animationParts.ContainsKey(partNum))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- public AnimationPart GetPart(int partNum)
- {
- if (PartExists(partNum))
- {
- return animationParts[partNum];
- }
- else
- {
- return null;
- }
- }
- /// <summary>
- /// Calculate a bone transform part way between two other transforms.
- /// </summary>
- /// <param name="blendFactor">Fraction from 0.0f closest to blendFrom
- /// up to 1.0f closest to blendTo</param>
- public static Matrix Blend(Matrix blendFrom, Matrix blendTo, float blendFactor)
- {
- // From the AvatarAnimationBlending sample
- // Variables to hold the rotations and translations for the
- // current, target, and blended transforms
- Quaternion currentRotation, targetRotation, finalRotation;
- Vector3 currentTranslation, targetTranslation, finalTranslation;
- // Find the rotation of the current and target bone transforms
- currentRotation =
- Quaternion.CreateFromRotationMatrix(blendFrom);
- targetRotation =
- Quaternion.CreateFromRotationMatrix(blendTo);
- // Calculate the blended rotation from the current to the target
- Quaternion.Slerp(ref currentRotation, ref targetRotation,
- blendFactor, out finalRotation);
- // Find the translation of the current and target bone transforms
- currentTranslation = blendFrom.Translation;
- targetTranslation = blendTo.Translation;
- // Calculate the blended translation from the current to the target
- Vector3.Lerp(ref currentTranslation, ref targetTranslation,
- blendFactor, out finalTranslation);
- // Build the final bone transform
- return Matrix.CreateFromQuaternion(finalRotation) *
- Matrix.CreateTranslation(finalTranslation);
- }
- #endregion
- #region Load and Save
- public void ClearClips()
- {
- animationClips.Clear();
- }
- public void AddClip(int takeNum, AnimationClip clip)
- {
- if (clip != null && takeNum > -1)
- {
- animationClips.Add(takeNum, clip);
- }
- }
- public void ClearParts()
- {
- animationParts.Clear();
- }
- public void AddPart(int partNum, AnimationPart part)
- {
- if (part != null && partNum > -1)
- {
- animationParts.Add(partNum, part);
- }
- }
- // The character calls this when loading to get the rig type numbers for that character
- public int GetRigTypeNumber(string rigTypeName)
- {
- if (rigNumbers.ContainsKey(rigTypeName))
- {
- return rigNumbers[rigTypeName];
- }
- // No matching number so return anything negative
- return -1 * rigTypeMultiplier;
- }
- public int GetClipNumber(int rigNum, string clipName)
- {
- if (clipNumbers.ContainsKey(clipName) && rigNum > -1)
- {
- return rigNum + clipNumbers[clipName];
- }
- else
- {
- return -1;
- }
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement