Merge pull request #1504 from Santarh/fixHlapi

Refactor High-level VRM-1.0 Loading API.
This commit is contained in:
ousttrue
2022-02-04 19:52:58 +09:00
committed by GitHub
9 changed files with 223 additions and 103 deletions

View File

@@ -0,0 +1,200 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using UniGLTF;
using UnityEngine;
using VRMShaders;
namespace UniVRM10
{
/// <summary>
/// High-level VRM-1.0 loading API.
/// </summary>
public static class Vrm10
{
/// <summary>
/// You can receive the thumbnail texture and the meta information.
/// `vrm10Meta` will be available if the model was vrm-1.0.
/// `vrm0Meta` will be available if the model was vrm-0.x.
/// </summary>
public delegate void VrmMetaInformationCallback(Texture2D thumbnail, UniGLTF.Extensions.VRMC_vrm.Meta vrm10Meta, Migration.Vrm0Meta vrm0Meta);
/// <summary>
/// Load the VRM file from the path.
/// </summary>
/// <param name="path">vrm file path</param>
/// <param name="canLoadVrm0X">if true, this loader can load the vrm-0.x model as vrm-1.0 model with migration.</param>
/// <param name="normalizeTransform">if true, vrm-1.0 models' transforms are normalized. (e.g. rotation, scaling)</param>
/// <param name="showMeshes">if true, show meshes when loaded.</param>
/// <param name="awaitCaller">this loader use specified await strategy.</param>
/// <param name="materialGenerator">this loader use specified material generation strategy.</param>
/// <param name="vrmMetaInformationCallback">return callback that notify meta information before loading.</param>
/// <param name="ct">CancellationToken</param>
/// <returns>vrm-1.0 instance</returns>
public static async Task<Vrm10Instance> LoadPathAsync(
string path,
bool canLoadVrm0X = true,
bool normalizeTransform = true,
bool showMeshes = true,
IAwaitCaller awaitCaller = null,
IMaterialDescriptorGenerator materialGenerator = null,
VrmMetaInformationCallback vrmMetaInformationCallback = null,
CancellationToken ct = default)
{
return await LoadAsync(
path,
System.IO.File.ReadAllBytes(path),
canLoadVrm0X,
normalizeTransform,
showMeshes,
awaitCaller,
materialGenerator,
vrmMetaInformationCallback,
ct);
}
/// <summary>
/// Load the VRM file from the binary.
/// </summary>
/// <param name="bytes">vrm file data</param>
/// <param name="canLoadVrm0X">if true, this loader can load the vrm-0.x model as vrm-1.0 model with migration.</param>
/// <param name="normalizeTransform">if true, vrm-1.0 models' transforms are normalized. (e.g. rotation, scaling)</param>
/// <param name="showMeshes">if true, show meshes when loaded.</param>
/// <param name="awaitCaller">this loader use specified await strategy.</param>
/// <param name="materialGenerator">this loader use specified material generation strategy.</param>
/// <param name="vrmMetaInformationCallback">return callback that notify meta information before loading.</param>
/// <param name="ct">CancellationToken</param>
/// <returns>vrm-1.0 instance</returns>
public static async Task<Vrm10Instance> LoadBytesAsync(
byte[] bytes,
bool canLoadVrm0X = true,
bool normalizeTransform = true,
bool showMeshes = true,
IAwaitCaller awaitCaller = null,
IMaterialDescriptorGenerator materialGenerator = null,
VrmMetaInformationCallback vrmMetaInformationCallback = null,
CancellationToken ct = default)
{
return await LoadAsync(
string.Empty,
bytes,
canLoadVrm0X,
normalizeTransform,
showMeshes,
awaitCaller,
materialGenerator,
vrmMetaInformationCallback,
ct);
}
private static async Task<Vrm10Instance> LoadAsync(
string name,
byte[] bytes,
bool canLoadVrm0X,
bool normalizeTransform,
bool showMeshes,
IAwaitCaller awaitCaller,
IMaterialDescriptorGenerator materialGenerator,
VrmMetaInformationCallback vrmMetaInformationCallback,
CancellationToken ct)
{
using (var data = new GlbLowLevelParser(name, bytes).Parse())
{
// 1. Try loading as vrm-1.0
var vrm10Data = Vrm10Data.Parse(data);
var vrm10Instance = await LoadVrm10DataAsync(
vrm10Data,
null,
normalizeTransform,
showMeshes,
awaitCaller,
materialGenerator,
vrmMetaInformationCallback,
ct);
if (vrm10Instance != null) return vrm10Instance;
if (!canLoadVrm0X)
{
return default;
}
// 2. Try migration from vrm-0.x into vrm-1.0
MigrationData migrationData;
using (var migrated = Vrm10Data.Migrate(data, out vrm10Data, out migrationData))
{
var instance = await LoadVrm10DataAsync(
vrm10Data,
migrationData,
normalizeTransform,
showMeshes,
awaitCaller,
materialGenerator,
vrmMetaInformationCallback,
ct);
if (instance != null) return instance;
}
// 3. failed
if (migrationData != null)
{
Debug.LogWarning(migrationData.Message);
}
return default;
}
}
private static async Task<Vrm10Instance> LoadVrm10DataAsync(
Vrm10Data vrm10Data,
MigrationData migrationData,
bool normalizeTransform,
bool showMeshes,
IAwaitCaller awaitCaller,
IMaterialDescriptorGenerator materialGenerator,
VrmMetaInformationCallback vrmMetaInformationCallback,
CancellationToken ct)
{
if (vrm10Data == null)
{
return default;
}
using (var loader = new Vrm10Importer(vrm10Data, materialGenerator: materialGenerator, doNormalize: normalizeTransform))
{
// 1. Load meta information if callback was available.
if (vrmMetaInformationCallback != null)
{
var thumbnail = await loader.LoadVrmThumbnailAsync();
if (migrationData != null)
{
vrmMetaInformationCallback(thumbnail, default, migrationData.OriginalMetaBeforeMigration);
}
else
{
vrmMetaInformationCallback(thumbnail, vrm10Data.VrmExtension.Meta, default);
}
}
// 2. Load
var gltfInstance = await loader.LoadAsync(awaitCaller);
if (ct.IsCancellationRequested)
{
gltfInstance.Dispose();
return default;
}
var vrm10Instance = gltfInstance.GetComponent<Vrm10Instance>();
if (vrm10Instance == null)
{
gltfInstance.Dispose();
return default;
}
if (showMeshes)
{
gltfInstance.ShowMeshes();
}
return vrm10Instance;
}
}
}
}

View File

@@ -1,83 +0,0 @@
using System.Threading.Tasks;
using UniGLTF;
using UnityEngine;
using VRMShaders;
namespace UniVRM10
{
public static class Vrm10Utility
{
public delegate void MetaCallback(Texture2D thumbnail, UniGLTF.Extensions.VRMC_vrm.Meta meta1, Migration.Vrm0Meta meta0);
public static async Task<RuntimeGltfInstance> LoadPathAsync(string path,
bool doMigrate,
bool doNormalize,
IAwaitCaller awaitCaller = null,
IMaterialDescriptorGenerator materialGenerator = null,
MetaCallback metaCallback = null
)
{
return await LoadBytesAsync(path, System.IO.File.ReadAllBytes(path), doMigrate, doNormalize, awaitCaller, materialGenerator, metaCallback);
}
public static async Task<RuntimeGltfInstance> LoadBytesAsync(string path, byte[] bytes,
bool doMigrate,
bool doNormalize,
IAwaitCaller awaitCaller = null,
IMaterialDescriptorGenerator materialGenerator = null,
MetaCallback metaCallback = null
)
{
// 1st parse as vrm1
using (var data = new GlbLowLevelParser(path, bytes).Parse())
{
var vrm1Data = Vrm10Data.Parse(data);
if (vrm1Data != null)
{
// successfully parsed vrm-1.0
using (var loader = new Vrm10Importer(vrm1Data, materialGenerator: materialGenerator, doNormalize: doNormalize))
{
if (metaCallback != null)
{
var thumbnail = await loader.LoadVrmThumbnailAsync();
metaCallback(thumbnail, vrm1Data.VrmExtension.Meta, null);
}
var instance = await loader.LoadAsync(awaitCaller);
return instance;
}
}
if (!doMigrate)
{
return default;
}
// try migration...
MigrationData migration;
using (var migrated = Vrm10Data.Migrate(data, out vrm1Data, out migration))
{
if (vrm1Data != null)
{
// successfully migrated from vrm-0.x
using (var loader = new Vrm10Importer(vrm1Data, materialGenerator: materialGenerator, doNormalize: doNormalize))
{
if (metaCallback != null)
{
var thumbnail = await loader.LoadVrmThumbnailAsync();
metaCallback(thumbnail, vrm1Data.VrmExtension.Meta, null);
}
var instance = await loader.LoadAsync(awaitCaller);
return instance;
}
}
}
// fail to migrate...
if (migration != null)
{
Debug.LogWarning(migration.Message);
}
return default;
}
}
}
}

View File

@@ -22,12 +22,12 @@ namespace UniVRM10.Sample
async void Run()
{
var src = new FileInfo(m_vrmPath);
var instance = await Vrm10Utility.LoadPathAsync(m_vrmPath, true, true);
var instance = await Vrm10.LoadPathAsync(m_vrmPath, true, true);
var exportedBytes = Vrm10Exporter.Export(instance.gameObject);
// Import 1.0
var vrm10 = await Vrm10Utility.LoadBytesAsync("tmp.vrm", exportedBytes, false, true);
var vrm10 = await Vrm10.LoadBytesAsync(exportedBytes, false, true);
var pos = vrm10.transform.position;
pos.x += 1.5f;
vrm10.transform.position = pos;

View File

@@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 705507994}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@@ -325,8 +325,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d2dd74f31dd71684da8aa80eaa66390e, type: 3}
m_Name:
m_EditorClassIdentifier:
m_vrmPath: ../UniVRM_1_0/Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm
m_rightHandToLeftHand: 1
m_vrmPath: Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm
--- !u!4 &1706915413
Transform:
m_ObjectHideFlags: 0

View File

@@ -198,7 +198,7 @@ namespace UniVRM10
{
try
{
Vrm10Utility.LoadPathAsync(gltf.FullName, true, false).Wait();
Vrm10.LoadPathAsync(gltf.FullName, true, false).Wait();
}
catch (UnNormalizedException)
{

View File

@@ -16,7 +16,7 @@ namespace UniVRM10
public static Vrm10Instance LoadAlicia()
{
var task = Vrm10Utility.LoadPathAsync(AliciaPath, true, true);
var task = Vrm10.LoadPathAsync(AliciaPath, true, true);
task.Wait();
var instance = task.Result;

View File

@@ -82,17 +82,14 @@ namespace UniVRM10.FirstPersonSample
}
m_target = humanPoseTransfer;
SetupTarget(m_target);
instance.ShowMeshes();
}
async Task<RuntimeGltfInstance> LoadAsync(string path)
async Task<Vrm10Instance> LoadAsync(string path)
{
var instance = await Vrm10Utility.LoadPathAsync(path, true, true);
var instance = await Vrm10.LoadPathAsync(path);
// VR用 FirstPerson 設定
var controller = instance.GetComponent<Vrm10Instance>();
await controller.Vrm.FirstPerson.SetupAsync(controller.gameObject);
await instance.Vrm.FirstPerson.SetupAsync(instance.gameObject);
return instance;
}

View File

@@ -415,16 +415,23 @@ namespace UniVRM10.VRM10Viewer
}
Debug.LogFormat("{0}", path);
var instance = await Vrm10Utility.LoadPathAsync(path, true, m_useNormalization.isOn,
awaitCaller: new RuntimeOnlyAwaitCaller(),
materialGenerator: GetVrmMaterialDescriptorGenerator(m_useUrpMaterial.isOn),
metaCallback: m_texts.UpdateMeta);
if (instance == null)
var vrm10Instance = await Vrm10.LoadPathAsync(path,
canLoadVrm0X: true,
normalizeTransform: m_useNormalization.isOn,
showMeshes: false,
awaitCaller: new RuntimeOnlyAwaitCaller(),
materialGenerator: GetVrmMaterialDescriptorGenerator(m_useUrpMaterial.isOn),
vrmMetaInformationCallback: m_texts.UpdateMeta);
if (vrm10Instance != null)
{
SetModel(vrm10Instance.GetComponent<RuntimeGltfInstance>());
}
else
{
// fallback to gltf
instance = await GltfUtility.LoadAsync(path, awaitCaller: new RuntimeOnlyAwaitCaller());
var instance = await GltfUtility.LoadAsync(path, awaitCaller: new RuntimeOnlyAwaitCaller());
SetModel(instance);
}
SetModel(instance);
}
void SetModel(RuntimeGltfInstance instance)