#region File Description //----------------------------------------------------------------------------- // ModelViewerControl.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using System.Diagnostics; using System.Windows.Forms; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; #endregion namespace WinFormsContentLoading { /// /// Example control inherits from GraphicsDeviceControl, and displays /// a spinning 3D model. The main form class is responsible for loading /// the model: this control just displays it. /// class ModelViewerControl : GraphicsDeviceControl { /// /// Gets or sets the current model. /// public Model Model { get { return model; } set { model = value; if (model != null) { MeasureModel(); } } } Model model; // Cache information about the model size and position. Matrix[] boneTransforms; Vector3 modelCenter; float modelRadius; // Timer controls the rotation speed. Stopwatch timer; /// /// Initializes the control. /// protected override void Initialize() { // Start the animation timer. timer = Stopwatch.StartNew(); // Hook the idle event to constantly redraw our animation. Application.Idle += delegate { Invalidate(); }; } /// /// Draws the control. /// protected override void Draw() { // Clear to the default control background color. Color backColor = new Color(BackColor.R, BackColor.G, BackColor.B); GraphicsDevice.Clear(backColor); if (model != null) { // Compute camera matrices. float rotation = (float)timer.Elapsed.TotalSeconds; Vector3 eyePosition = modelCenter; eyePosition.Z += modelRadius * 2; eyePosition.Y += modelRadius; float aspectRatio = GraphicsDevice.Viewport.AspectRatio; float nearClip = modelRadius / 100; float farClip = modelRadius * 100; Matrix world = Matrix.CreateRotationY(rotation); Matrix view = Matrix.CreateLookAt(eyePosition, modelCenter, Vector3.Up); Matrix projection = Matrix.CreatePerspectiveFieldOfView(1, aspectRatio, nearClip, farClip); // Draw the model. foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.World = boneTransforms[mesh.ParentBone.Index] * world; effect.View = view; effect.Projection = projection; effect.EnableDefaultLighting(); effect.PreferPerPixelLighting = true; effect.SpecularPower = 16; } mesh.Draw(); } } } /// /// Whenever a new model is selected, we examine it to see how big /// it is and where it is centered. This lets us automatically zoom /// the display, so we can correctly handle models of any scale. /// void MeasureModel() { // Look up the absolute bone transforms for this model. boneTransforms = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(boneTransforms); // Compute an (approximate) model center position by // averaging the center of each mesh bounding sphere. modelCenter = Vector3.Zero; foreach (ModelMesh mesh in model.Meshes) { BoundingSphere meshBounds = mesh.BoundingSphere; Matrix transform = boneTransforms[mesh.ParentBone.Index]; Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform); modelCenter += meshCenter; } modelCenter /= model.Meshes.Count; // Now we know the center point, we can compute the model radius // by examining the radius of each mesh bounding sphere. modelRadius = 0; foreach (ModelMesh mesh in model.Meshes) { BoundingSphere meshBounds = mesh.BoundingSphere; Matrix transform = boneTransforms[mesh.ParentBone.Index]; Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform); float transformScale = transform.Forward.Length(); float meshRadius = (meshCenter - modelCenter).Length() + (meshBounds.Radius * transformScale); modelRadius = Math.Max(modelRadius, meshRadius); } } } }