Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gltf Importer #1030

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
bf458c9
Re added gltf importer
ykafia Mar 6, 2021
0a94004
Merge pull request #1 from stride3d/master
ykafia Mar 13, 2021
bd99662
Merge pull request #2 from stride3d/master
ykafia Mar 17, 2021
0ed55b5
file corrections
ykafia Mar 25, 2021
97c4899
bump SharpGltf version
ykafia Mar 25, 2021
f8ddb09
Merge pull request #3 from ykafia/master
ykafia Mar 25, 2021
01fa0d9
first MVP import gltf model + skeleton
ykafia Mar 25, 2021
468c5b3
Finished importing all types of materials
ykafia Mar 28, 2021
d46164d
Mesh + Animation constraints
ykafia Mar 28, 2021
9fe612c
Some changes
ykafia Mar 29, 2021
5c9cc9d
Little Hack to import multiple animations
ykafia Mar 29, 2021
67aa25b
Correct animation naming
ykafia Mar 29, 2021
edb18be
Merge pull request #4 from stride3d/master
ykafia Mar 30, 2021
7a6069b
Animation asset name changes
ykafia Mar 30, 2021
d0825a0
Fixed glb texture import issue
ykafia Mar 30, 2021
81f9fef
Corrected bone null name + animation name
ykafia Apr 1, 2021
02df563
removed unused line of code
ykafia Apr 1, 2021
e0d98f8
Corrected name of mesh for animations
ykafia Apr 1, 2021
e7342f0
Doc comments
ykafia Apr 2, 2021
bf7c38c
static classes
ykafia Apr 6, 2021
42ffc24
Correct naming of texture
ykafia Apr 20, 2021
f1f6843
Merge branch 'stride3d:master' into master
ykafia May 12, 2021
516d12e
Corrected breaking change on FBX animation importer
ykafia Jun 20, 2021
c0a91fe
bump versions + simpler vertex buff creation + minor corrections
ykafia Jun 21, 2021
b9c587a
Corrections + cubic animation import
ykafia Jun 26, 2021
6317fe6
Merge pull request #6 from stride3d/master
ykafia Jun 30, 2021
b2b75cd
Merge pull request #7 from stride3d/master
ykafia Jul 21, 2021
1dd0212
Merge pull request #8 from ykafia/master
ykafia Jul 21, 2021
6dcfc29
Added 8byte vertex color
ykafia Jul 24, 2021
f8a1b26
Merge branch 'gltfimport' of https://github.com/ykafia/stride into gl…
ykafia Jul 24, 2021
fc64315
Merge all meshes
ykafia Aug 7, 2021
7f54126
Fusing animations and meshes
ykafia Aug 21, 2021
005d765
ignore configs
ykafia Nov 12, 2021
7fe1a50
Merge branch 'stride3d:master' into gltfimport
ykafia Nov 26, 2021
f0d9a22
Correction root animation import
ykafia Nov 26, 2021
6770a72
Removed EntityInfoExtended
ykafia Nov 26, 2021
8ee77d4
Merge branch 'stride3d:master' into master
ykafia Nov 28, 2021
7d722e9
Merge pull request #11 from ykafia/master
ykafia Nov 28, 2021
6e6db93
Removed project from sln
ykafia Nov 28, 2021
ddbc547
update reference GLTF
ykafia Nov 28, 2021
6a3482f
Minor changes
ykafia Dec 26, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,5 @@ fastlane/report.xml
fastlane/screenshots
*.user
project.lock.json
/hooks
/lfs/objects
15 changes: 15 additions & 0 deletions build/Stride.sln
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.VisualStudio.Command
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Engine.NoAssets.Tests.Windows", "..\sources\engine\Stride.Engine.NoAssets.Tests\Stride.Engine.NoAssets.Tests.Windows.csproj", "{1C94168A-3C0D-4C6B-883B-91627D2EF3A1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Importer.Gltf", "..\sources\tools\Stride.Importer.Gltf\Stride.Importer.Gltf.csproj", "{69CA1F59-5735-403C-8009-2CE282C72DE6}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\sources\shared\Stride.NuGetResolver\Stride.NuGetResolver.projitems*{00b72ed7-00e9-47f7-868d-8162027cd068}*SharedItemsImports = 13
Expand Down Expand Up @@ -1527,6 +1529,18 @@ Global
{1C94168A-3C0D-4C6B-883B-91627D2EF3A1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1C94168A-3C0D-4C6B-883B-91627D2EF3A1}.Release|Win32.ActiveCfg = Release|Any CPU
{1C94168A-3C0D-4C6B-883B-91627D2EF3A1}.Release|Win32.Build.0 = Release|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Debug|Win32.ActiveCfg = Debug|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Debug|Win32.Build.0 = Debug|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Release|Any CPU.Build.0 = Release|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Release|Win32.ActiveCfg = Release|Any CPU
{69CA1F59-5735-403C-8009-2CE282C72DE6}.Release|Win32.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1654,6 +1668,7 @@ Global
{7FA381C8-8EBE-4515-969D-01369CC47D0E} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185}
{83E4E436-659A-4D82-90DD-0DC67BE38D17} = {E4508D15-6503-4A29-ADC4-27B3A5E99545}
{1C94168A-3C0D-4C6B-883B-91627D2EF3A1} = {A7ED9F01-7D78-4381-90A6-D50E51C17250}
{69CA1F59-5735-403C-8009-2CE282C72DE6} = {6F473FA6-4F8B-4FBA-AE33-EE5AF997D50C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FF877973-604D-4EA7-B5F5-A129961F9EF2}
Expand Down
2 changes: 1 addition & 1 deletion sources/engine/Stride.Assets.Models/AssimpAssetImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ static AssimpAssetImporter()
}

// Supported file extensions for this importer
internal const string FileExtensions = ".dae;.3ds;.gltf;.glb;.obj;.blend;.x;.md2;.md3;.dxf;.ply;.stl;.stp";
internal const string FileExtensions = ".dae;.3ds;.obj;.blend;.x;.md2;.md3;.dxf;.ply;.stl;.stp";

private static readonly Guid Uid = new Guid("30243FC0-CEC7-4433-977E-95DCA29D846E");

Expand Down
47 changes: 47 additions & 0 deletions sources/engine/Stride.Assets.Models/GltfAssetImporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Stride contributors (https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using Stride.Core.Assets;
using Stride.Core;
using Stride.Core.Diagnostics;
using Stride.Core.IO;
using Stride.Animations;
using Stride.Assets.Textures;
using Stride.Importer.Common;
using Stride.Importer.Gltf;
using System.Linq;

namespace Stride.Assets.Models
{
public class GltfAssetImporter : ModelAssetImporter
{

// Supported file extensions for this importer
internal const string FileExtensions = ".gltf;.glb;";

private static readonly Guid Uid = new Guid("A5A08530-4856-4EB7-91F8-B0A148B3A627");

public override Guid Id => Uid;

public override string Description => "Gltf importer used for creating entities, 3D Models or animations assets";

public override string SupportedFileExtensions => FileExtensions;

/// <inheritdoc/>
public override EntityInfo GetEntityInfo(UFile localPath, Logger logger, AssetImporterParameters importParameters)
{

return GltfMeshParser.ExtractEntityInfo(SharpGLTF.Schema2.ModelRoot.Load(localPath.FullPath), localPath);
}

/// <inheritdoc/>
public override void GetAnimationDuration(UFile localPath, Logger logger, AssetImporterParameters importParameters, out TimeSpan startTime, out TimeSpan endTime)
{
var gltfFile = SharpGLTF.Schema2.ModelRoot.Load(localPath);
endTime = GltfMeshParser.GetAnimationDuration(gltfFile);
startTime = CompressedTimeSpan.Zero;
}

}
}
66 changes: 66 additions & 0 deletions sources/engine/Stride.Assets.Models/ImportGltfCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Stride contributors (https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using Stride.Core.BuildEngine;
using Stride.Core.Serialization.Contents;
using Stride.Animations;
using Stride.Rendering;
using Stride.Importer.Gltf;

namespace Stride.Assets.Models
{
[Description("Import GLTF")]
public class ImportGltfCommand : ImportModelCommand
{
private static string[] supportedExtensions = GltfAssetImporter.FileExtensions.Split(';');

/// <inheritdoc/>
public override string Title { get { string title = "Import GLTF "; try { title += Path.GetFileName(SourcePath) ?? "[File]"; } catch { title += "[INVALID PATH]"; } return title; } }

public static bool IsSupportingExtensions(string ext)
{
if (string.IsNullOrEmpty(ext))
return false;

var extToLower = ext.ToLowerInvariant();

return supportedExtensions.Any(supExt => supExt.Equals(extToLower));
}

protected override Model LoadModel(ICommandContext commandContext, ContentManager contentManager)
{
var model = GltfMeshParser.LoadGltf(SourcePath);
var sceneData = GltfMeshParser.LoadFirstModel(model);
return sceneData;
}

protected override Dictionary<string, AnimationClip> LoadAnimation(ICommandContext commandContext, ContentManager contentManager, out TimeSpan duration)
{
var file = SharpGLTF.Schema2.ModelRoot.Load(SourcePath);
var sceneData = GltfMeshParser.ConvertAnimations(file,SourcePath.GetFileNameWithoutExtension());
duration = GltfMeshParser.GetAnimationDuration(file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duration isn't used anywhere...

return sceneData;
}

protected override Skeleton LoadSkeleton(ICommandContext commandContext, ContentManager contentManager)
{
var file = SharpGLTF.Schema2.ModelRoot.Load(SourcePath);
var sceneData = GltfAnimationParser.ConvertSkeleton(file);
return sceneData;
}

public override bool ShouldSpawnNewProcess()
{
return true;
}

public override string ToString()
{
return "Import GLTF " + base.ToString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ public partial class ImportModelCommand

private unsafe object ExportAnimation(ICommandContext commandContext, ContentManager contentManager, bool failOnEmptyAnimation)
{
// Gltf case
if (commandContext.CurrentCommand.Title.ToLower().Contains("gltf"))
{
var ts = TimeSpan.FromSeconds(1);
return LoadAnimation(commandContext, contentManager, out ts);
}

// Read from model file
var modelSkeleton = LoadSkeleton(commandContext, contentManager); // we get model skeleton to compare it to real skeleton we need to map to
AdjustSkeleton(modelSkeleton);
Expand All @@ -42,7 +49,7 @@ private unsafe object ExportAnimation(ICommandContext commandContext, ContentMan
{
foreach (var animationCurve in clip.Value.Curves)
{
animationCurve.ShiftKeys(startTime);
animationCurve?.ShiftKeys(startTime);
}
}

Expand Down Expand Up @@ -76,6 +83,10 @@ private unsafe object ExportAnimation(ICommandContext commandContext, ContentMan
{
animationClip.AddCurve($"[TransformComponent.Key]." + channelName.Replace("Transform.", string.Empty), curve);
}
else if(channelName.StartsWith("[TransformComponent.Key]"))
{
animationClip.AddCurve(channelName, curve);
}

// Also apply Camera curves
// TODO: Add some other curves?
Expand Down Expand Up @@ -140,13 +151,13 @@ private unsafe object ExportAnimation(ICommandContext commandContext, ContentMan
foreach (var node in nodesToMerge)
{
if (node.Item3 != null)
foreach (var curve in node.Item3.Clip.Curves)
{
foreach (CompressedTimeSpan time in curve.Keys)
foreach (var curve in node.Item3.Clip.Curves)
{
animationKeysSet.Add(time);
foreach (CompressedTimeSpan time in curve.Keys)
{
animationKeysSet.Add(time);
}
}
}
}

// Sort key times
Expand All @@ -170,7 +181,7 @@ private unsafe object ExportAnimation(ICommandContext commandContext, ContentMan
foreach (var node in nodesToMerge)
{
// Needs to be an array in order for it to be modified by the UpdateEngine, otherwise it would get passed by value
var modelNodeDefinitions = new ModelNodeDefinition[1] {node.Item1};
var modelNodeDefinitions = new ModelNodeDefinition[1] { node.Item1 };

if (node.Item2 != null && node.Item3 != null)
{
Expand Down
17 changes: 14 additions & 3 deletions sources/engine/Stride.Assets.Models/ImportModelCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public abstract partial class ImportModelCommand : SingleFileImportCommand

public static ImportModelCommand Create(string extension)
{
if (ImportGltfCommand.IsSupportingExtensions(extension))
return new ImportGltfCommand();
if (ImportFbxCommand.IsSupportingExtensions(extension))
return new ImportFbxCommand();
if (ImportAssimpCommand.IsSupportingExtensions(extension))
Expand Down Expand Up @@ -90,8 +92,17 @@ protected override async Task<ResultStatus> DoCommandOverride(ICommandContext co
commandContext.Logger.Error($"Failed to import file {ContextAsString}.");
return ResultStatus.Failed;
}
if (exportedObject is Dictionary<string, AnimationClip>)
{
var exportedObjects = exportedObject as Dictionary<string, AnimationClip>;
foreach (var obj in exportedObjects)
assetManager.Save(obj.Key, obj.Value);
}
else
{
assetManager.Save(Location, exportedObject);
}

assetManager.Save(Location, exportedObject);

commandContext.Logger.Verbose($"The {ContextAsString} has been successfully imported.");

Expand Down Expand Up @@ -130,7 +141,7 @@ private Matrix CombineMatricesFromNodeIndices(ModelNodeTransformation[] nodes, i

return result;
}

protected abstract Model LoadModel(ICommandContext commandContext, ContentManager contentManager);

protected abstract Dictionary<string, AnimationClip> LoadAnimation(ICommandContext commandContext, ContentManager contentManager, out TimeSpan duration);
Expand Down Expand Up @@ -172,7 +183,7 @@ private static bool CompareParameters(Model model, Mesh baseMesh, Mesh newMesh)
return false;
return IsSubsetOf(localParams, newMesh.Parameters) && IsSubsetOf(newMesh.Parameters, localParams);
}

/// <summary>
/// Compares the shadow options between the two meshes.
/// </summary>
Expand Down
46 changes: 35 additions & 11 deletions sources/engine/Stride.Assets.Models/ModelAssetImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ public override IEnumerable<AssetItem> Import(UFile localPath, AssetImporterPara
{
TimeSpan startTime, endTime;
GetAnimationDuration(localPath, importParameters.Logger, importParameters, out startTime, out endTime);

ImportAnimation(rawAssetReferences, localPath, entityInfo.AnimationNodes, isImportingModel, skeletonAsset, startTime, endTime);
bool isGltfAsset = localPath.GetFileExtension().ToLower().Contains("glb") || localPath.GetFileExtension().ToLower().Contains("gltf");
ImportAnimation(rawAssetReferences, localPath, isGltfAsset ? entityInfo.AnimationNames : entityInfo.AnimationNodes, isImportingModel, isGltfAsset, skeletonAsset, startTime, endTime);
}

// 4. Materials
Expand Down Expand Up @@ -141,20 +141,44 @@ private static AssetItem ImportSkeleton(List<AssetItem> assetReferences, UFile a
return assetItem;
}

private static void ImportAnimation(List<AssetItem> assetReferences, UFile localPath, List<string> animationNodes, bool shouldPostFixName, AssetItem skeletonAsset, TimeSpan animationStartTime, TimeSpan animationEndTime)
private static void ImportAnimation(List<AssetItem> assetReferences, UFile localPath, List<string> animationNodes, bool shouldPostFixName, bool isGltfAsset, AssetItem skeletonAsset, TimeSpan animationStartTime, TimeSpan animationEndTime)
{
if (animationNodes != null && animationNodes.Count > 0)
{
var assetSource = localPath;
if (isGltfAsset)
{
// Animation nodes in GLTF correspond to animations inside the gltf files, not the bone names in fbx files.
foreach (var anim in animationNodes)
{
var assetSource = localPath;

var asset = new AnimationAsset { Source = assetSource, AnimationTimeMaximum = animationEndTime, AnimationTimeMinimum = animationStartTime };
string animUrl = anim + "_Animation";

if (skeletonAsset != null)
asset.Skeleton = AttachedReferenceManager.CreateProxyObject<Skeleton>(skeletonAsset.Id, skeletonAsset.Location);

var asset = new AnimationAsset { Source = assetSource, AnimationTimeMaximum = animationEndTime, AnimationTimeMinimum = animationStartTime };
var animUrl = localPath.GetFileNameWithoutExtension() + (shouldPostFixName ? " Animation" : "");
assetReferences.Add(new AssetItem(animUrl, asset));
}

}
else
{

if (skeletonAsset != null)
asset.Skeleton = AttachedReferenceManager.CreateProxyObject<Skeleton>(skeletonAsset.Id, skeletonAsset.Location);
var assetSource = localPath;

assetReferences.Add(new AssetItem(animUrl, asset));
var asset = new AnimationAsset { Source = assetSource, AnimationTimeMaximum = animationEndTime, AnimationTimeMinimum = animationStartTime };
var animUrl = localPath.GetFileNameWithoutExtension() + (shouldPostFixName ? " Animation" : "");

if (skeletonAsset != null)
asset.Skeleton = AttachedReferenceManager.CreateProxyObject<Skeleton>(skeletonAsset.Id, skeletonAsset.Location);

assetReferences.Add(new AssetItem(animUrl, asset));

}
}


}

private static void ImportModel(List<AssetItem> assetReferences, UFile assetSource, UFile localPath, EntityInfo entityInfo, bool shouldPostFixName, AssetItem skeletonAsset)
Expand Down Expand Up @@ -190,7 +214,7 @@ private static void ImportModel(List<AssetItem> assetReferences, UFile assetSour
if (skeletonAsset != null)
asset.Skeleton = AttachedReferenceManager.CreateProxyObject<Skeleton>(skeletonAsset.Id, skeletonAsset.Location);

var modelUrl = new UFile(localPath.GetFileNameWithoutExtension() + (shouldPostFixName?" Model": ""));
var modelUrl = new UFile(localPath.GetFileNameWithoutExtension() + (shouldPostFixName ? " Model" : ""));
var assetItem = new AssetItem(modelUrl, asset);
assetReferences.Add(assetItem);
}
Expand Down Expand Up @@ -269,7 +293,7 @@ private static void AdjustForTransparency(MaterialAsset material)
// var isTransparent = false;
// if (material.Parameters.ContainsKey(MaterialParameters.HasTransparency))
// isTransparent = (bool)material.Parameters[MaterialParameters.HasTransparency];

// if (!isTransparent)
// {
// // remove the diffuse node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<ProjectReference Include="..\..\tools\Stride.Importer.Assimp\Stride.Importer.Assimp.vcxproj" PrivateAssets="All" />
<ProjectReference Include="..\..\tools\Stride.Importer.Common\Stride.Importer.Common.vcxproj" PrivateAssets="All" />
<ProjectReference Include="..\..\tools\Stride.Importer.FBX\Stride.Importer.FBX.vcxproj" PrivateAssets="All" />
<ProjectReference Include="..\..\tools\Stride.Importer.Gltf\Stride.Importer.Gltf.csproj" />
<ProjectReference Include="..\Stride.Assets\Stride.Assets.csproj" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public ref class EntityInfo
List<String^>^ AnimationNodes;
List<MeshParameters^>^ Models;
List<NodeInfo^>^ Nodes;
List<String^>^ AnimationNames;
};

public ref class MeshMaterials
Expand Down
Loading