Skip to content

Commit

Permalink
Model tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dellis1972 committed Apr 8, 2024
1 parent c6e47a1 commit 7fffb47
Show file tree
Hide file tree
Showing 27 changed files with 412 additions and 240 deletions.
61 changes: 60 additions & 1 deletion MonoGame.Framework.Content.Pipeline/Graphics/MeshHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Microsoft.Xna.Framework.Graphics;

namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics
{
Expand Down Expand Up @@ -361,10 +366,64 @@ public static BoneContent FindSkeleton(NodeContent node)
return root;
}

// We didn't find any bones!
// We didn't find any bones!
return null;
}

/// <summary>
/// Builds a set of BoneContent nodes and injects them into a Model which
/// contains Mesh based Animations but has Zero BoneContent nodes.
/// </summary>
/// <param name="node">The base note on which to build the new BoneContent</param>
/// <returns>The root Skeleton Node.</returns>
internal static BoneContent BuildSkeleton (NodeContent node)
{
var nodes = node.AsEnumerable().SelectDeep(n => n.Children).ToList ();
var meshes = nodes.FindAll(n => n is MeshContent).Cast<MeshContent>().ToList();
BoneContent root = null;
foreach (var mesh in meshes) {
var parent = mesh.Parent;
parent.Children.Remove (mesh);
var bone = new BoneContent () {
Name = "bone_" + mesh.Name,
Transform = mesh.Transform,
};
if (root == null)
root = bone;
bone.Parent = null;
mesh.Parent = null;
mesh.Transform = Matrix.Identity;
parent.Children.Add (bone);
bone.Children.Add (mesh);
// foreach (var animation in mesh.Animations) {
// if (!node.Animations.TryGetValue (animation.Key, out AnimationContent ac)) {
// ac = new AnimationContent ();
// node.Animations.Add (animation.Key, ac);
// ac.Duration = animation.Value.Duration;
// ac.Identity = animation.Value.Identity;
// }

// // foreach (var c in animation.Value.Channels) {
// // var key = "bone_" + c.Key;
// // if (!ac.Channels.TryGetValue (key, out AnimationChannel chan)) {
// // ac.Channels.Add(key, c.Value);
// // }
// // chan.Add (c.Value.)
// // }
// }
foreach (var geometry in mesh.Geometry) {
var weightsName = VertexChannelNames.Weights ();
var xnaWeights = new List<BoneWeightCollection>();
var weights = new BoneWeightCollection();
weights.Add(new BoneWeight("bone_" + mesh.Name, 1.0f));
for (int i=0; i <= geometry.Vertices.VertexCount-1; i++)
xnaWeights.Add (weights);
geometry.Vertices.Channels.Add (weightsName, xnaWeights );
}
}
return root;
}

/// <summary>
/// Traverses a skeleton depth-first and builds a list of its bones.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@


<ItemGroup>
<PackageReference Include="AssimpNet" Version="4.1.0" />
<PackageReference Include="AssimpNet" Version="5.0.0-beta1" />
<PackageReference Include="Microsoft.NETCore.App" Version="2.1.30" />
<PackageReference Include="SharpDX" Version="4.0.1" />
<PackageReference Include="SharpDX.D3DCompiler" Version="4.0.1" />
Expand Down Expand Up @@ -170,6 +170,11 @@
<PackagePath>runtimes\osx\native\libfreetype6.dylib</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\Dependencies\assimp\libassimp.dylib" Visible="false">
<Link>libassimp.dylib</Link>
<PackagePath>runtimes\osx\native\libassimp.dylib</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\ThirdParty\Dependencies\SharpFont\x64\libpng16.16.dylib" Visible="false">
<PackagePath>runtimes\osx\native</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,19 @@ public override ModelContent Process(NodeContent input, ContentProcessorContext
var scale = Matrix.CreateScale(Scale);
MeshHelper.TransformScene(input, rotZ * rotX * rotY * scale);
}

// Gather all the nodes in tree traversal order.
var nodes = input.AsEnumerable().SelectDeep(n => n.Children).ToList();

var meshes = nodes.FindAll(n => n is MeshContent).Cast<MeshContent>().ToList();
var geometries = meshes.SelectMany(m => m.Geometry).ToList();
var distinctMaterials = geometries.Select(g => g.Material).Distinct().ToList();

// var hasBones = MeshHelper.FindSkeleton (input) != null;
// var hasRootAnimations = input.Animations.Any ();
// var hasMeshAnimations = meshes.Any (x => x.Animations.Count > 0);
// if (!hasBones && (hasRootAnimations || hasMeshAnimations))
// MeshHelper.BuildSkeleton (input);

// Loop through all distinct materials, passing them through the conversion method
// only once, and then processing all geometries using that material.
foreach (var inputMaterial in distinctMaterials)
Expand Down Expand Up @@ -238,6 +243,7 @@ protected virtual void ProcessGeometryUsingMaterial(MaterialContent material,
else if (material is SkinnedMaterialContent)
{
textureChannels = 1;
// if we don't have bones but have animations we need to add "fake" weights.
vertexWeights = true;
}
else if (material is EnvironmentMapMaterialContent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ protected internal override void Write(ContentWriter output, ModelContent value)

WriteBoneReference(output, value.Root, value.Bones);
output.WriteObject(value.Tag);
// Add serialization of Animation data here.
}

private void WriteBones(ContentWriter output, ModelBoneContentCollection bones)
Expand Down
33 changes: 33 additions & 0 deletions MonoGame.Framework.DesktopGL.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Framework.DesktopG
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Tests.DesktopGL", "Tests\MonoGame.Tests.DesktopGL.csproj", "{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Framework.Content.Pipeline", "MonoGame.Framework.Content.Pipeline\MonoGame.Framework.Content.Pipeline.csproj", "{50610F72-EE08-475E-84E4-88B86E05ED77}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{8792B021-CB1C-420C-8A1E-AB9CB3B7751F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Tools.Tests", "Tools\MonoGame.Tools.Tests\MonoGame.Tools.Tests.csproj", "{44A60138-0D95-4673-A597-36E528571D53}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -41,11 +47,38 @@ Global
{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}.Release|x64.Build.0 = Release|Any CPU
{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}.Release|x86.ActiveCfg = Release|Any CPU
{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}.Release|x86.Build.0 = Release|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x64.ActiveCfg = Debug|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x64.Build.0 = Debug|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x86.ActiveCfg = Debug|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x86.Build.0 = Debug|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Release|Any CPU.Build.0 = Release|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x64.ActiveCfg = Release|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x64.Build.0 = Release|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x86.ActiveCfg = Release|Any CPU
{50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x86.Build.0 = Release|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Debug|x64.ActiveCfg = Debug|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Debug|x64.Build.0 = Debug|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Debug|x86.ActiveCfg = Debug|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Debug|x86.Build.0 = Debug|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Release|Any CPU.Build.0 = Release|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Release|x64.ActiveCfg = Release|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Release|x64.Build.0 = Release|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Release|x86.ActiveCfg = Release|Any CPU
{44A60138-0D95-4673-A597-36E528571D53}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {847BFB97-3FE9-4E70-B4D0-0B0C8F6921A8}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{44A60138-0D95-4673-A597-36E528571D53} = {8792B021-CB1C-420C-8A1E-AB9CB3B7751F}
EndGlobalSection
EndGlobal
13 changes: 11 additions & 2 deletions MonoGame.Framework/Content/ContentExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
using System;
using System.Reflection;
using System.Linq;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.Xna.Framework.Content
{
internal static class ContentExtensions
{
public static ConstructorInfo GetDefaultConstructor(this Type type)
public static ConstructorInfo GetDefaultConstructor(
#if NET5_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
#endif
this Type type)
{
#if NET45
var typeInfo = type.GetTypeInfo();
Expand All @@ -18,7 +23,11 @@ public static ConstructorInfo GetDefaultConstructor(this Type type)
#endif
}

public static PropertyInfo[] GetAllProperties(this Type type)
public static PropertyInfo[] GetAllProperties(
#if NET5_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
#endif
this Type type)
{

// Sometimes, overridden properties of abstract classes can show up even with
Expand Down
4 changes: 4 additions & 0 deletions MonoGame.Framework/Content/ContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ private static void RemoveContentManager(ContentManager contentManager)
}
}

#if __ANDROID__
internal static void ReloadGraphicsContent()
{
lock (ContentManagerLock)
Expand All @@ -134,6 +135,7 @@ internal static void ReloadGraphicsContent()
}
}
}
#endif

// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
Expand Down Expand Up @@ -406,6 +408,7 @@ protected virtual Dictionary<string, object> LoadedAssets
get { return loadedAssets; }
}

#if __ANDROID__
protected virtual void ReloadGraphicsAssets()
{
foreach (var asset in LoadedAssets)
Expand All @@ -420,6 +423,7 @@ protected virtual void ReloadGraphicsAssets()
genericMethod.Invoke(this, new object[] { asset.Key, Convert.ChangeType(asset.Value, asset.Value.GetType()) });
}
}
#endif

protected virtual void ReloadAsset<T>(string originalAssetName, T currentAsset)
{
Expand Down
9 changes: 8 additions & 1 deletion MonoGame.Framework/Content/ContentReaders/ModelReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,11 @@ protected internal override Model Read(ContentReader reader, Model existingInsta
if (existingInstance != null)
part = existingInstance.Meshes[i].MeshParts[(int)j];
else
#pragma warning disable CS0618 // Type or member is obsolete
part = new ModelMeshPart();
#pragma warning restore CS0618 // Type or member is obsolete

part.VertexOffset = reader.ReadInt32();
part.VertexOffset = reader.ReadInt32();
part.NumVertices = reader.ReadInt32();
part.StartIndex = reader.ReadInt32();
part.PrimitiveCount = reader.ReadInt32();
Expand Down Expand Up @@ -191,6 +193,11 @@ protected internal override Model Read(ContentReader reader, Model existingInsta

// Tag?
model.Tag = reader.ReadObject<object>();

if (reader.PeekChar () == -1)
return model;

// We have additional data to read :D Ooooo animations

return model;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using MonoGame.Framework.Utilities;

namespace Microsoft.Xna.Framework.Content
{
internal class ReflectiveReader<T> : ContentTypeReader
internal class ReflectiveReader<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields | DynamicallyAccessedMemberTypes.NonPublicProperties)] T> : ContentTypeReader
{
delegate void ReadElement(ContentReader input, object parent);

Expand Down
9 changes: 8 additions & 1 deletion MonoGame.Framework/Content/ContentTypeReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@
// file 'LICENSE.txt', which is part of this source code package.

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;

namespace Microsoft.Xna.Framework.Content
{
public abstract class ContentTypeReader
{
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
private Type _targetType;

public virtual bool CanDeserializeIntoExistingObject
{
get { return false; }
}

[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
public Type TargetType
{
get { return _targetType; }
Expand All @@ -26,7 +29,11 @@ public virtual int TypeVersion
get { return 0; } // The default version (unless overridden) is zero
}

protected ContentTypeReader(Type targetType)
protected ContentTypeReader(
#if NET5_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
#endif
Type targetType)
{
_targetType = targetType;
}
Expand Down
7 changes: 6 additions & 1 deletion MonoGame.Framework/Design/VectorConversion.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.Xna.Framework.Graphics.PackedVector;

Expand All @@ -23,7 +24,11 @@ public static bool CanConvertTo(ITypeDescriptorContext context, Type destination
return false;
}

public static object ConvertToFromVector4(ITypeDescriptorContext context, CultureInfo culture, Vector4 value, Type destinationType)
public static object ConvertToFromVector4(ITypeDescriptorContext context, CultureInfo culture, Vector4 value,
#if NET5_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
#endif
Type destinationType)
{
if (destinationType == typeof(float))
return value.X;
Expand Down
Loading

0 comments on commit 7fffb47

Please sign in to comment.