ModelViewerControl.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // ModelViewerControl.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Diagnostics;
  12. using System.Windows.Forms;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Graphics;
  15. #endregion
  16. namespace WinFormsContentLoading
  17. {
  18. /// <summary>
  19. /// Example control inherits from GraphicsDeviceControl, and displays
  20. /// a spinning 3D model. The main form class is responsible for loading
  21. /// the model: this control just displays it.
  22. /// </summary>
  23. class ModelViewerControl : GraphicsDeviceControl
  24. {
  25. /// <summary>
  26. /// Gets or sets the current model.
  27. /// </summary>
  28. public Model Model
  29. {
  30. get { return model; }
  31. set
  32. {
  33. model = value;
  34. if (model != null)
  35. {
  36. MeasureModel();
  37. }
  38. }
  39. }
  40. Model model;
  41. // Cache information about the model size and position.
  42. Matrix[] boneTransforms;
  43. Vector3 modelCenter;
  44. float modelRadius;
  45. // Timer controls the rotation speed.
  46. Stopwatch timer;
  47. /// <summary>
  48. /// Initializes the control.
  49. /// </summary>
  50. protected override void Initialize()
  51. {
  52. // Start the animation timer.
  53. timer = Stopwatch.StartNew();
  54. // Hook the idle event to constantly redraw our animation.
  55. Application.Idle += delegate { Invalidate(); };
  56. }
  57. /// <summary>
  58. /// Draws the control.
  59. /// </summary>
  60. protected override void Draw()
  61. {
  62. // Clear to the default control background color.
  63. Color backColor = new Color(BackColor.R, BackColor.G, BackColor.B);
  64. GraphicsDevice.Clear(backColor);
  65. if (model != null)
  66. {
  67. // Compute camera matrices.
  68. float rotation = (float)timer.Elapsed.TotalSeconds;
  69. Vector3 eyePosition = modelCenter;
  70. eyePosition.Z += modelRadius * 2;
  71. eyePosition.Y += modelRadius;
  72. float aspectRatio = GraphicsDevice.Viewport.AspectRatio;
  73. float nearClip = modelRadius / 100;
  74. float farClip = modelRadius * 100;
  75. Matrix world = Matrix.CreateRotationY(rotation);
  76. Matrix view = Matrix.CreateLookAt(eyePosition, modelCenter, Vector3.Up);
  77. Matrix projection = Matrix.CreatePerspectiveFieldOfView(1, aspectRatio,
  78. nearClip, farClip);
  79. // Draw the model.
  80. foreach (ModelMesh mesh in model.Meshes)
  81. {
  82. foreach (BasicEffect effect in mesh.Effects)
  83. {
  84. effect.World = boneTransforms[mesh.ParentBone.Index] * world;
  85. effect.View = view;
  86. effect.Projection = projection;
  87. effect.EnableDefaultLighting();
  88. effect.PreferPerPixelLighting = true;
  89. effect.SpecularPower = 16;
  90. }
  91. mesh.Draw();
  92. }
  93. }
  94. }
  95. /// <summary>
  96. /// Whenever a new model is selected, we examine it to see how big
  97. /// it is and where it is centered. This lets us automatically zoom
  98. /// the display, so we can correctly handle models of any scale.
  99. /// </summary>
  100. void MeasureModel()
  101. {
  102. // Look up the absolute bone transforms for this model.
  103. boneTransforms = new Matrix[model.Bones.Count];
  104. model.CopyAbsoluteBoneTransformsTo(boneTransforms);
  105. // Compute an (approximate) model center position by
  106. // averaging the center of each mesh bounding sphere.
  107. modelCenter = Vector3.Zero;
  108. foreach (ModelMesh mesh in model.Meshes)
  109. {
  110. BoundingSphere meshBounds = mesh.BoundingSphere;
  111. Matrix transform = boneTransforms[mesh.ParentBone.Index];
  112. Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform);
  113. modelCenter += meshCenter;
  114. }
  115. modelCenter /= model.Meshes.Count;
  116. // Now we know the center point, we can compute the model radius
  117. // by examining the radius of each mesh bounding sphere.
  118. modelRadius = 0;
  119. foreach (ModelMesh mesh in model.Meshes)
  120. {
  121. BoundingSphere meshBounds = mesh.BoundingSphere;
  122. Matrix transform = boneTransforms[mesh.ParentBone.Index];
  123. Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform);
  124. float transformScale = transform.Forward.Length();
  125. float meshRadius = (meshCenter - modelCenter).Length() +
  126. (meshBounds.Radius * transformScale);
  127. modelRadius = Math.Max(modelRadius, meshRadius);
  128. }
  129. }
  130. }
  131. }