AnimationSampleComponent.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Globalization;
  5. using Microsoft.Xna.Framework;
  6. using Microsoft.Xna.Framework.Audio;
  7. using Microsoft.Xna.Framework.Content;
  8. using Microsoft.Xna.Framework.Graphics;
  9. using Microsoft.Xna.Framework.Input;
  10. using nkast.Aether.Animation;
  11. using nkast.Aether.Shaders.Components;
  12. namespace Samples.Animation
  13. {
  14. internal class AnimationSampleComponent : DrawableGameComponent
  15. {
  16. enum DrawMode : int
  17. {
  18. GPU,
  19. CPU,
  20. }
  21. ContentManager Content;
  22. SpriteBatch spriteBatch;
  23. SpriteFont font;
  24. InfiniteGridComponent grid;
  25. Model _model_CPU;
  26. Model _model_GPU;
  27. Animations _animations;
  28. DrawMode drawMode = DrawMode.GPU;
  29. KeyboardState prevKeyboardState;
  30. public AnimationSampleComponent(Game game) : base(game)
  31. {
  32. }
  33. /// <summary>Initializes the component. Used to load non-graphical resources.</summary>
  34. public override void Initialize()
  35. {
  36. Content = new ContentManager(Game.Services, "Content");
  37. base.Initialize();
  38. }
  39. /// <summary>Load graphical resources needed by this component.</summary>
  40. protected override void LoadContent()
  41. {
  42. spriteBatch = new SpriteBatch(GraphicsDevice);
  43. font = Content.Load<SpriteFont>("font");
  44. grid = new InfiniteGridComponent(GraphicsDevice, Content);
  45. grid.Initialize();
  46. _model_CPU = Content.Load<Model>("Dude/dude");
  47. _model_GPU = Content.Load<Model>("Dude/dude_GPU");
  48. _animations = _model_CPU.GetAnimations(); // Animation Data are the same between the two models
  49. var clip = _animations.Clips["Take 001"];
  50. _animations.SetClip(clip);
  51. }
  52. /// <summary>Unload graphical resources needed by this component.</summary>
  53. protected override void UnloadContent()
  54. {
  55. Content.Unload();
  56. }
  57. /// <summary>Update the component.</summary>
  58. /// <param name="gameTime">GameTime of the Game.</param>
  59. public override void Update(GameTime gameTime)
  60. {
  61. var keyboardState = Keyboard.GetState();
  62. var gamePadState = GamePad.GetState(PlayerIndex.One);
  63. if ((keyboardState.IsKeyDown(Keys.Space) && prevKeyboardState.IsKeyUp(Keys.Space)) || gamePadState.Buttons.A == ButtonState.Pressed)
  64. {
  65. int drawModesCount = Enum.GetValues(drawMode.GetType()).Length;
  66. drawMode = (DrawMode)(((int)drawMode + 1) % drawModesCount);
  67. }
  68. prevKeyboardState = keyboardState;
  69. _animations.Update(gameTime.ElapsedGameTime, true, Matrix.Identity);
  70. }
  71. private Vector3 Position = Vector3.Zero;
  72. private float Zoom = 100f;
  73. private float RotationY = 0.0f;
  74. private float RotationX = 0.0f;
  75. private Matrix gameWorldRotation = Matrix.Identity;
  76. Stopwatch sw = new Stopwatch();
  77. double msecMin = double.MaxValue;
  78. double msecMax = 0;
  79. double avg = 0;
  80. double acc = 0;
  81. int c;
  82. /// <summary>Draw this component.</summary>
  83. /// <param name="gameTime">The time elapsed since the last call to Draw.</param>
  84. public override void Draw(GameTime gameTime)
  85. {
  86. float aspectRatio = GraphicsDevice.Viewport.AspectRatio;
  87. Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 0.01f, 500.0f);
  88. Matrix view = Matrix.CreateLookAt(
  89. new Vector3(0.0f, 35.0f, -Zoom),
  90. new Vector3(0.0f, 35.0f, 0),
  91. Vector3.Up);
  92. // Draw Grid
  93. grid.Projection = projection;
  94. grid.View = view;
  95. //grid.EditMatrix = Matrix.Identity; // XY plane
  96. grid.EditMatrix = Matrix.CreateFromAxisAngle(Vector3.UnitX, MathHelper.ToRadians(-90)); // XZ plane
  97. grid.Draw(gameTime);
  98. GraphicsDevice.BlendState = BlendState.Opaque;
  99. GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  100. GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  101. GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
  102. Model m = _model_CPU;
  103. if (drawMode == DrawMode.CPU)
  104. m = _model_CPU;
  105. else if (drawMode == DrawMode.GPU)
  106. m = _model_GPU;
  107. Matrix[] transforms = new Matrix[m.Bones.Count];
  108. m.CopyAbsoluteBoneTransformsTo(transforms);
  109. sw.Reset();
  110. sw.Start();
  111. foreach (ModelMesh mesh in m.Meshes)
  112. {
  113. foreach (var part in mesh.MeshParts)
  114. {
  115. if (drawMode == DrawMode.CPU)
  116. ((BasicEffect)part.Effect).SpecularColor = Vector3.Zero;
  117. else if (drawMode == DrawMode.GPU)
  118. ((SkinnedEffect)part.Effect).SpecularColor = Vector3.Zero;
  119. ConfigureEffectMatrices((IEffectMatrices)part.Effect, Matrix.Identity, view, projection);
  120. ConfigureEffectLighting((IEffectLights)part.Effect);
  121. if (drawMode == DrawMode.CPU)
  122. part.UpdateVertices(_animations.AnimationTransforms); // animate vertices on CPU
  123. else if (drawMode == DrawMode.GPU)
  124. ((SkinnedEffect)part.Effect).SetBoneTransforms(_animations.AnimationTransforms);// animate vertices on GPU
  125. }
  126. mesh.Draw();
  127. }
  128. sw.Stop();
  129. double msec = sw.Elapsed.TotalMilliseconds;
  130. msecMin = Math.Min(msecMin, msec);
  131. if (avg != 0)
  132. msecMax = Math.Max(msecMax, msec);
  133. acc += msec; c++;
  134. if (c > 60 * 2)
  135. {
  136. avg = acc / c;
  137. acc = c = 0;
  138. }
  139. spriteBatch.Begin();
  140. spriteBatch.DrawString(font, "Draw Mode: " + drawMode, new Vector2(32, 32), Color.White);
  141. spriteBatch.DrawString(font, msec.ToString("#0.000", CultureInfo.InvariantCulture) + "ms", new Vector2(32, GraphicsDevice.Viewport.Height - 130), Color.White);
  142. spriteBatch.DrawString(font, avg.ToString("#0.000", CultureInfo.InvariantCulture) + "ms (avg)", new Vector2(32, GraphicsDevice.Viewport.Height - 100), Color.White);
  143. spriteBatch.DrawString(font, msecMin.ToString("#0.000", CultureInfo.InvariantCulture) + "ms (min)", new Vector2(32, GraphicsDevice.Viewport.Height - 70), Color.White);
  144. spriteBatch.DrawString(font, msecMax.ToString("#0.000", CultureInfo.InvariantCulture) + "ms (max)", new Vector2(32, GraphicsDevice.Viewport.Height - 40), Color.White);
  145. spriteBatch.End();
  146. }
  147. private void ConfigureEffectMatrices(IEffectMatrices effect, Matrix world, Matrix view, Matrix projection)
  148. {
  149. effect.World = world;
  150. effect.View = view;
  151. effect.Projection = projection;
  152. }
  153. private void ConfigureEffectLighting(IEffectLights effect)
  154. {
  155. effect.EnableDefaultLighting();
  156. effect.DirectionalLight0.Direction = Vector3.Backward;
  157. effect.DirectionalLight0.Enabled = true;
  158. effect.DirectionalLight1.Enabled = false;
  159. effect.DirectionalLight2.Enabled = false;
  160. }
  161. }
  162. }