|
|
@@ -22,85 +22,116 @@ namespace SharpGLTF.Runtime
|
|
|
{
|
|
|
srcModel.FixTextureSampler();
|
|
|
|
|
|
- var template = Runtime.SceneTemplate.Create(srcModel.DefaultScene, true);
|
|
|
-
|
|
|
+ var templates = srcModel.LogicalScenes
|
|
|
+ .Select(item => SceneTemplate.Create(item, true))
|
|
|
+ .ToArray();
|
|
|
+
|
|
|
var context = new LoaderContext(device);
|
|
|
|
|
|
- var meshes = template
|
|
|
- .LogicalMeshIds
|
|
|
- .ToDictionary(k => k, k => context.CreateMesh(srcModel.LogicalMeshes[k]));
|
|
|
-
|
|
|
+ var meshes = templates
|
|
|
+ .SelectMany(item => item.LogicalMeshIds)
|
|
|
+ .ToDictionary(k => k, k => context.CreateMesh(srcModel.LogicalMeshes[k]));
|
|
|
|
|
|
- var mdl = new MonoGameModelTemplate(template, meshes);
|
|
|
+ var mdl = new MonoGameModelTemplate(templates,srcModel.DefaultScene.LogicalIndex, meshes);
|
|
|
|
|
|
return new MonoGameDeviceContent<MonoGameModelTemplate>(mdl, context.Disposables.ToArray());
|
|
|
}
|
|
|
-
|
|
|
- internal MonoGameModelTemplate(Runtime.SceneTemplate scene, IReadOnlyDictionary<int, ModelMesh> meshes)
|
|
|
+
|
|
|
+ internal MonoGameModelTemplate(SceneTemplate[] scenes, int defaultSceneIndex, IReadOnlyDictionary<int, ModelMesh> meshes)
|
|
|
{
|
|
|
- _Template = scene;
|
|
|
_Meshes = meshes;
|
|
|
-
|
|
|
_Effects = _Meshes.Values
|
|
|
.SelectMany(item => item.Effects)
|
|
|
.Distinct()
|
|
|
.ToArray();
|
|
|
|
|
|
- var instance = _Template.CreateInstance();
|
|
|
- instance.SetPoseTransforms();
|
|
|
-
|
|
|
- _Bounds = default(BoundingSphere);
|
|
|
-
|
|
|
- foreach (var d in instance.DrawableReferences)
|
|
|
- {
|
|
|
- var b = meshes[d.Item1].BoundingSphere;
|
|
|
-
|
|
|
- if (d.Item2 is Transforms.StaticTransform statXform) b = b.Transform(statXform.WorldMatrix.ToXna());
|
|
|
-
|
|
|
- if (d.Item2 is Transforms.SkinTransform skinXform)
|
|
|
- {
|
|
|
- // this is a bit agressive and probably over-reaching, but with skins you never know the actual bounds
|
|
|
- // unless you calculate the bounds frame by frame.
|
|
|
-
|
|
|
- var bb = b;
|
|
|
-
|
|
|
- foreach(var xb in skinXform.SkinMatrices.Select(item => bb.Transform(item.ToXna())))
|
|
|
- {
|
|
|
- b = BoundingSphere.CreateMerged(b, xb);
|
|
|
- }
|
|
|
- }
|
|
|
+ _Scenes = scenes;
|
|
|
+ _Bounds = scenes
|
|
|
+ .Select(item => CalculateBounds(item))
|
|
|
+ .ToArray();
|
|
|
|
|
|
- _Bounds = _Bounds.Radius == 0 ? b : BoundingSphere.CreateMerged(_Bounds, b);
|
|
|
- }
|
|
|
+ _DefaultSceneIndex = defaultSceneIndex;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region data
|
|
|
-
|
|
|
- private readonly Runtime.SceneTemplate _Template;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Meshes shared by all the scenes.
|
|
|
+ /// </summary>
|
|
|
internal readonly IReadOnlyDictionary<int, ModelMesh> _Meshes;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Effects shared by all the meshes.
|
|
|
+ /// </summary>
|
|
|
private readonly Effect[] _Effects;
|
|
|
- private readonly BoundingSphere _Bounds;
|
|
|
+
|
|
|
+
|
|
|
+ private readonly SceneTemplate[] _Scenes;
|
|
|
+ private readonly BoundingSphere[] _Bounds;
|
|
|
+
|
|
|
+ private readonly int _DefaultSceneIndex;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region properties
|
|
|
|
|
|
+ public int SceneCount => _Scenes.Length;
|
|
|
+
|
|
|
public IReadOnlyList<Effect> Effects => _Effects;
|
|
|
|
|
|
- public BoundingSphere Bounds => _Bounds;
|
|
|
+ public BoundingSphere Bounds => GetBounds(_DefaultSceneIndex);
|
|
|
|
|
|
- public IEnumerable<string> AnimationTracks => _Template.AnimationTracks;
|
|
|
+ public IEnumerable<string> AnimationTracks => GetAnimationTracks(_DefaultSceneIndex);
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region API
|
|
|
|
|
|
- public MonoGameModelInstance CreateInstance()
|
|
|
+ public int IndexOfScene(string sceneName) => Array.FindIndex(_Scenes, item => item.Name == sceneName);
|
|
|
+
|
|
|
+ public BoundingSphere GetBounds(int sceneIndex) => _Bounds[sceneIndex];
|
|
|
+
|
|
|
+ public IEnumerable<string> GetAnimationTracks(int sceneIndex) => _Scenes[sceneIndex].AnimationTracks;
|
|
|
+
|
|
|
+ public MonoGameModelInstance CreateInstance() => CreateInstance(_DefaultSceneIndex);
|
|
|
+
|
|
|
+ public MonoGameModelInstance CreateInstance(int sceneIndex)
|
|
|
{
|
|
|
- return new MonoGameModelInstance(this, _Template.CreateInstance());
|
|
|
+ return new MonoGameModelInstance(this, _Scenes[sceneIndex].CreateInstance());
|
|
|
+ }
|
|
|
+
|
|
|
+ private BoundingSphere CalculateBounds(SceneTemplate scene)
|
|
|
+ {
|
|
|
+ var instance = scene.CreateInstance();
|
|
|
+ instance.SetPoseTransforms();
|
|
|
+
|
|
|
+ var bounds = default(BoundingSphere);
|
|
|
+
|
|
|
+ foreach (var d in instance.DrawableReferences)
|
|
|
+ {
|
|
|
+ var b = _Meshes[d.Item1].BoundingSphere;
|
|
|
+
|
|
|
+ if (d.Item2 is Transforms.StaticTransform statXform) b = b.Transform(statXform.WorldMatrix.ToXna());
|
|
|
+
|
|
|
+ if (d.Item2 is Transforms.SkinTransform skinXform)
|
|
|
+ {
|
|
|
+ // this is a bit agressive and probably over-reaching, but with skins you never know the actual bounds
|
|
|
+ // unless you calculate the bounds frame by frame.
|
|
|
+
|
|
|
+ var bb = b;
|
|
|
+
|
|
|
+ foreach (var xb in skinXform.SkinMatrices.Select(item => bb.Transform(item.ToXna())))
|
|
|
+ {
|
|
|
+ b = BoundingSphere.CreateMerged(b, xb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bounds = bounds.Radius == 0 ? b : BoundingSphere.CreateMerged(bounds, b);
|
|
|
+ }
|
|
|
+
|
|
|
+ return bounds;
|
|
|
}
|
|
|
|
|
|
#endregion
|