Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/Model.cs
236 lines | 6.0 KiB | text/x-csharp | CSharpLexer
236 lines | 6.0 KiB | text/x-csharp | CSharpLexer
r0 | #region License | |||
/* FNA - XNA4 Reimplementation for Desktop Platforms | ||||
* Copyright 2009-2020 Ethan Lee and the MonoGame Team | ||||
* | ||||
* Released under the Microsoft Public License. | ||||
* See LICENSE for details. | ||||
*/ | ||||
#endregion | ||||
#region Using Statements | ||||
using System; | ||||
using System.Collections.Generic; | ||||
#endregion | ||||
namespace Microsoft.Xna.Framework.Graphics | ||||
{ | ||||
/// <summary> | ||||
/// A basic 3D model with per mesh parent bones. | ||||
/// </summary> | ||||
public class Model | ||||
{ | ||||
#region Public Properties | ||||
/// <summary> | ||||
/// A collection of <see cref="ModelBone"/> objects which describe how each mesh in the | ||||
/// mesh collection for this model relates to its parent mesh. | ||||
/// </summary> | ||||
public ModelBoneCollection Bones | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
/// <summary> | ||||
/// A collection of <see cref="ModelMesh"/> objects which compose the model. Each <see cref="ModelMesh"/> | ||||
/// in a model may be moved independently and may be composed of multiple materials | ||||
/// identified as <see cref="ModelMeshPart"/> objects. | ||||
/// </summary> | ||||
public ModelMeshCollection Meshes | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
/// <summary> | ||||
/// Root bone for this model. | ||||
/// </summary> | ||||
public ModelBone Root | ||||
{ | ||||
get; | ||||
internal set; | ||||
} | ||||
/// <summary> | ||||
/// Custom attached object. | ||||
/// <remarks> | ||||
/// Skinning data is example of attached object for model. | ||||
/// </remarks> | ||||
/// </summary> | ||||
public object Tag | ||||
{ | ||||
get; | ||||
set; | ||||
} | ||||
#endregion | ||||
#region Private Static Variables | ||||
private static Matrix[] sharedDrawBoneMatrices; | ||||
#endregion | ||||
#region Internal Constructor | ||||
/// <summary> | ||||
/// Constructs a model. | ||||
/// </summary> | ||||
/// <param name="graphicsDevice">A valid reference to <see cref="GraphicsDevice"/>.</param> | ||||
/// <param name="bones">The collection of bones.</param> | ||||
/// <param name="meshes">The collection of meshes.</param> | ||||
internal Model(GraphicsDevice graphicsDevice, List<ModelBone> bones, List<ModelMesh> meshes) | ||||
{ | ||||
Bones = new ModelBoneCollection(bones); | ||||
Meshes = new ModelMeshCollection(meshes); | ||||
} | ||||
#endregion | ||||
#region Public Methods | ||||
/// <summary> | ||||
/// Draws the model meshes. | ||||
/// </summary> | ||||
/// <param name="world">The world transform.</param> | ||||
/// <param name="view">The view transform.</param> | ||||
/// <param name="projection">The projection transform.</param> | ||||
public void Draw(Matrix world, Matrix view, Matrix projection) | ||||
{ | ||||
int boneCount = Bones.Count; | ||||
if (sharedDrawBoneMatrices == null || | ||||
sharedDrawBoneMatrices.Length < boneCount) | ||||
{ | ||||
sharedDrawBoneMatrices = new Matrix[boneCount]; | ||||
} | ||||
// Look up combined bone matrices for the entire model. | ||||
CopyAbsoluteBoneTransformsTo(sharedDrawBoneMatrices); | ||||
// Draw the model. | ||||
foreach (ModelMesh mesh in Meshes) | ||||
{ | ||||
foreach (Effect effect in mesh.Effects) | ||||
{ | ||||
IEffectMatrices effectMatricies = effect as IEffectMatrices; | ||||
if (effectMatricies == null) | ||||
{ | ||||
throw new InvalidOperationException(); | ||||
} | ||||
effectMatricies.World = sharedDrawBoneMatrices[mesh.ParentBone.Index] * world; | ||||
effectMatricies.View = view; | ||||
effectMatricies.Projection = projection; | ||||
} | ||||
mesh.Draw(); | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// Copies bone transforms relative to all parent bones of the each bone from this model to a given array. | ||||
/// </summary> | ||||
/// <param name="destinationBoneTransforms">The array receiving the transformed bones.</param> | ||||
public void CopyAbsoluteBoneTransformsTo(Matrix[] destinationBoneTransforms) | ||||
{ | ||||
if (destinationBoneTransforms == null) | ||||
{ | ||||
throw new ArgumentNullException("destinationBoneTransforms"); | ||||
} | ||||
if (destinationBoneTransforms.Length < Bones.Count) | ||||
{ | ||||
throw new ArgumentOutOfRangeException("destinationBoneTransforms"); | ||||
} | ||||
int count = Bones.Count; | ||||
for (int index1 = 0; index1 < count; index1 += 1) | ||||
{ | ||||
ModelBone modelBone = Bones[index1]; | ||||
if (modelBone.Parent == null) | ||||
{ | ||||
destinationBoneTransforms[index1] = modelBone.Transform; | ||||
} | ||||
else | ||||
{ | ||||
int index2 = modelBone.Parent.Index; | ||||
Matrix modelBoneTransform = modelBone.Transform; | ||||
Matrix.Multiply( | ||||
ref modelBoneTransform, | ||||
ref destinationBoneTransforms[index2], | ||||
out destinationBoneTransforms[index1] | ||||
); | ||||
} | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// Copies bone transforms relative to <see cref="Model.Root"/> bone from a given array to this model. | ||||
/// </summary> | ||||
/// <param name="sourceBoneTransforms">The array of prepared bone transform data.</param> | ||||
public void CopyBoneTransformsFrom(Matrix[] sourceBoneTransforms) | ||||
{ | ||||
if (sourceBoneTransforms == null) | ||||
{ | ||||
throw new ArgumentNullException("sourceBoneTransforms"); | ||||
} | ||||
if (sourceBoneTransforms.Length < Bones.Count) | ||||
{ | ||||
throw new ArgumentOutOfRangeException("sourceBoneTransforms"); | ||||
} | ||||
for (int i = 0; i < sourceBoneTransforms.Length; i += 1) | ||||
{ | ||||
Bones[i].Transform = sourceBoneTransforms[i]; | ||||
} | ||||
} | ||||
/// <summary> | ||||
/// Copies bone transforms relative to <see cref="Model.Root"/> bone from this model to a given array. | ||||
/// </summary> | ||||
/// <param name="destinationBoneTransforms">The array receiving the transformed bones.</param> | ||||
public void CopyBoneTransformsTo(Matrix[] destinationBoneTransforms) | ||||
{ | ||||
if (destinationBoneTransforms == null) | ||||
{ | ||||
throw new ArgumentNullException("destinationBoneTransforms"); | ||||
} | ||||
if (destinationBoneTransforms.Length < Bones.Count) | ||||
{ | ||||
throw new ArgumentOutOfRangeException("destinationBoneTransforms"); | ||||
} | ||||
for (int i = 0; i < destinationBoneTransforms.Length; i += 1) | ||||
{ | ||||
destinationBoneTransforms[i] = Bones[i].Transform; | ||||
} | ||||
} | ||||
#endregion | ||||
#region Internal Methods | ||||
internal void BuildHierarchy() | ||||
{ | ||||
Matrix globalScale = Matrix.CreateScale(0.01f); | ||||
foreach (ModelBone node in Root.Children) | ||||
{ | ||||
BuildHierarchy(node, Root.Transform * globalScale, 0); | ||||
} | ||||
} | ||||
#endregion | ||||
#region Private Methods | ||||
private void BuildHierarchy(ModelBone node, Matrix parentTransform, int level) | ||||
{ | ||||
node.ModelTransform = node.Transform * parentTransform; | ||||
foreach (ModelBone child in node.Children) | ||||
{ | ||||
BuildHierarchy(child, node.ModelTransform, level + 1); | ||||
} | ||||
} | ||||
#endregion | ||||
} | ||||
} | ||||