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

Support animation #27

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
93 changes: 93 additions & 0 deletions Assets/VGltfExamples/VRMExample/Scripts/VRMLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using UnityEngine.UI;
using VGltf;
using VGltf.Unity;
using System.Linq;

namespace VGltfExamples.VRMExample
{
Expand Down Expand Up @@ -39,6 +40,21 @@ public void Dispose()

readonly List<VRMResource> _vrmResources = new List<VRMResource>();

[Serializable]
sealed class ClipResource : IDisposable
{
public IImporterContext Context;
[SerializeField] public AnimationClip[] ClipRefs;

public void Dispose()
{
Context?.Dispose();
}
}

// デバッグ用
[SerializeField] List<ClipResource> _clipResources = new List<ClipResource>();

void Start()
{
loadButton.onClick.AddListener(UIOnLoadButtonClick);
Expand All @@ -58,6 +74,11 @@ void OnDestroy()
{
disposable.Dispose();
}

foreach(var disposable in _clipResources)
{
disposable.Dispose();
}
}

async UniTask<VRMResource> LoadVRM()
Expand Down Expand Up @@ -120,6 +141,11 @@ void UIOnLoadButtonClick()

async UniTaskVoid UIOnLoadButtonClickAsync()
{
#if false
var clipRes = await ImportClip("anim.glb");
_clipResources.Insert(0, clipRes);
#endif

var p0 = Common.MemoryProfile.Now;
DebugLogProfile(p0);

Expand Down Expand Up @@ -168,6 +194,10 @@ async UniTaskVoid UIOnExportButtonClickedAsync()
var head = _vrmResources[0];

var anim = head.Go.GetComponentInChildren<Animator>();

var info = anim.GetCurrentAnimatorClipInfo(0);
var clip = info[0].clip;

var animCtrl = anim.runtimeAnimatorController;
anim.runtimeAnimatorController = null; // Make the model to the rest pose

Expand Down Expand Up @@ -211,6 +241,69 @@ await Task.Run(() =>

Debug.Log("exported");
});

#if false
await ExportClip(clip, "anim.glb");
#endif
}

async Task<ClipResource> ImportClip(string path)
{
// Read the glTF container (unity-independent)
var gltfContainer = await Task.Run(() =>
{
using (var fs = new FileStream(path, FileMode.Open))
{
return GltfContainer.FromGlb(fs);
}
});

var clipRefs = new List<AnimationClip>();

var timeSlicer = new Common.TimeSlicer();
using (var gltfImporter = new Importer(gltfContainer, timeSlicer))
{
gltfImporter.AddHook(new VGltf.Unity.Ext.Helper.AnimationClipImporter(
hooks: new VGltf.Unity.Ext.Helper.AnimationClipImporterHook[] {
new VGltf.Unity.Ext.Helper.HumanoidAnimationImporter(),
},
clipRefs: clipRefs
));

var context = await gltfImporter.ImportEmpty(System.Threading.CancellationToken.None);
return new ClipResource
{
Context = context,
ClipRefs = clipRefs.ToArray(),
};
}
}

async Task ExportClip(AnimationClip clip, string path)
{
GltfContainer gltfContainer = null;
using (var gltfExporter = new Exporter())
{
gltfExporter.AddHook(new VGltf.Unity.Ext.Helper.AnimationClipExporter(
clips: new AnimationClip[] { clip },
hooks: new VGltf.Unity.Ext.Helper.AnimationClipExporterHook[] {
new VGltf.Unity.Ext.Helper.HumanoidAnimationExporter(),
}
));

gltfExporter.ExportEmpty();
gltfContainer = gltfExporter.IntoGlbContainer();
}

await Task.Run(() =>
{
using (var fs = new FileStream(path, FileMode.Create))
{
GltfContainer.ToGlb(fs, gltfContainer);
}

Debug.Log("clip exported");
});
}

void DebugLogProfile(Common.MemoryProfile now, Common.MemoryProfile prev = null)
Expand Down
8 changes: 8 additions & 0 deletions Packages/net.yutopp.vgltf.unity/Runtime/Exporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ public void ExportGameObjectAsScene(GameObject go)
}
}

public void ExportEmpty()
{
foreach (var hook in Hooks)
{
hook.PostHook(this, null);
}
}

void ExportGameObjectAsSceneWithoutNormalize(GameObject go)
{
Func<IndexedResource<GameObject>[]> generator = () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public sealed class ExporterRuntimeResources : IDisposable
public IndexedResourceDict<Material, Material> Materials = new IndexedResourceDict<Material, Material>();
public IndexedResourceDict<(Mesh, Material[]), Mesh> Meshes = new IndexedResourceDict<(Mesh, Material[]), Mesh>(new MeshEqualityComparer());
public IndexedResourceDict<Mesh, Skin> Skins = new IndexedResourceDict<Mesh, Skin>();
public IndexedResourceDict<AnimationClip, AnimationClip> Animations = new IndexedResourceDict<AnimationClip, AnimationClip>();

public void Dispose()
{
Expand Down
8 changes: 8 additions & 0 deletions Packages/net.yutopp.vgltf.unity/Runtime/Extra/Helper.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright (c) 2022- yutopp ([email protected])
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using VGltf.Types.Extensions;

namespace VGltf.Unity.Ext.Helper
{
public abstract class AnimationClipExporterHook
{
public abstract IndexedResource<AnimationClip> Export(IExporterContext context, AnimationClip clip);
}

public sealed class AnimationClipExporter : ExporterHookBase
{
readonly AnimationClip[] _clips;
readonly AnimationClipExporterHook[] _hooks;

public AnimationClipExporter(AnimationClip clip, AnimationClipExporterHook[] hooks)
: this(new AnimationClip[] { clip }, hooks)
{
}

public AnimationClipExporter(AnimationClip[] clips, AnimationClipExporterHook[] hooks)
{
_clips = clips;
_hooks = hooks;
}

public override void PostHook(Exporter exporter, GameObject go)
{
foreach (var clip in _clips)
{
foreach (var hook in _hooks)
{
var r = hook.Export(exporter.Context, clip);
if (r != null)
{
// If the clip was processed, ignore hooks subsequently (per clips).
break;
}
}
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright (c) 2022- yutopp ([email protected])
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace VGltf.Unity.Ext.Helper
{
public abstract class AnimationClipImporterHook
{
public abstract Task<IndexedResource<AnimationClip>> Import(IImporterContext context, int animIndex, CancellationToken ct);
}

public sealed class AnimationClipImporter : ImporterHookBase
{
readonly AnimationClipImporterHook[] _hooks;
readonly List<AnimationClip> _clipRefs;

public AnimationClipImporter(AnimationClipImporterHook[] hooks, List<AnimationClip> clipRefs)
{
_hooks = hooks;
_clipRefs = clipRefs;
}

public override async Task PostHook(IImporterContext context, CancellationToken ct)
{
var gltf = context.Container.Gltf;

for(var i=0; i<gltf.Animations.Count; ++i)
{
foreach(var hook in _hooks)
{
var r = await hook.Import(context, i, ct);
if (r != null)
{
// If the clip was processed, ignore hooks subsequently (per clips).
_clipRefs.Add(r.Value); // mutate the container

await context.TimeSlicer.Slice(ct);

break;
}
}
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading