mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-03-21 18:05:03 -05:00
Merge branch 'master' into v0.131.0-pw
This commit is contained in:
commit
9220d85d57
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using Unity.Profiling;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
|
|
@ -20,6 +21,9 @@ namespace UniGLTF
|
|||
private readonly IReadOnlyDictionary<SubAssetKey, Texture> m_subAssets;
|
||||
UnityPath m_textureDirectory;
|
||||
|
||||
private static ProfilerMarker s_MarkerStartExtractTextures = new ProfilerMarker("Start Extract Textures");
|
||||
private static ProfilerMarker s_MarkerDelayedExtractTextures = new ProfilerMarker("Delayed Extract Textures");
|
||||
|
||||
public TextureExtractor(GltfData data, UnityPath textureDirectory, IReadOnlyDictionary<SubAssetKey, Texture> subAssets)
|
||||
{
|
||||
m_data = data;
|
||||
|
|
@ -77,14 +81,33 @@ namespace UniGLTF
|
|||
Action<SubAssetKey, Texture2D> addRemap,
|
||||
Action<IEnumerable<UnityPath>> onCompleted = null)
|
||||
{
|
||||
s_MarkerStartExtractTextures.Begin();
|
||||
|
||||
var extractor = new TextureExtractor(data, textureDirectory, subAssets);
|
||||
foreach (var param in textureDescriptorGenerator.Get().GetEnumerable())
|
||||
try
|
||||
{
|
||||
extractor.Extract(param.SubAssetKey, param);
|
||||
AssetDatabase.StartAssetEditing();
|
||||
|
||||
foreach (var param in textureDescriptorGenerator.Get().GetEnumerable())
|
||||
{
|
||||
extractor.Extract(param.SubAssetKey, param);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AssetDatabase.StopAssetEditing();
|
||||
}
|
||||
|
||||
s_MarkerStartExtractTextures.End();
|
||||
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
s_MarkerDelayedExtractTextures.Begin();
|
||||
|
||||
// Wait for the texture assets to be imported
|
||||
|
||||
foreach (var (key, targetPath) in extractor.Textures)
|
||||
|
|
@ -97,6 +120,8 @@ namespace UniGLTF
|
|||
}
|
||||
}
|
||||
|
||||
s_MarkerDelayedExtractTextures.End();
|
||||
|
||||
if (onCompleted != null)
|
||||
{
|
||||
onCompleted(extractor.Textures.Values);
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ namespace UniGLTF.MeshUtility
|
|||
|
||||
if (copyBlendShape)
|
||||
{
|
||||
var vertices = src.vertices;
|
||||
var normals = src.normals;
|
||||
var deltaVertices = new Vector3[src.vertexCount];
|
||||
var deltaNormals = new Vector3[src.vertexCount];
|
||||
Vector3[] tangents = null;
|
||||
if (Symbols.VRM_NORMALIZE_BLENDSHAPE_TANGENT)
|
||||
{
|
||||
|
|
@ -62,14 +62,18 @@ namespace UniGLTF.MeshUtility
|
|||
|
||||
for (int i = 0; i < src.blendShapeCount; ++i)
|
||||
{
|
||||
src.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents);
|
||||
dst.AddBlendShapeFrame(
|
||||
src.GetBlendShapeName(i),
|
||||
src.GetBlendShapeFrameWeight(i, 0),
|
||||
vertices,
|
||||
normals,
|
||||
tangents
|
||||
);
|
||||
var frameCount = src.GetBlendShapeFrameCount(i);
|
||||
for (int f = 0; f < frameCount; ++f)
|
||||
{
|
||||
src.GetBlendShapeFrameVertices(i, f, deltaVertices, deltaNormals, tangents);
|
||||
dst.AddBlendShapeFrame(
|
||||
src.GetBlendShapeName(i),
|
||||
src.GetBlendShapeFrameWeight(i, f),
|
||||
deltaVertices,
|
||||
deltaNormals,
|
||||
tangents
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ namespace UniGLTF.SpringBoneJobs
|
|||
in quaternion parentRotation)
|
||||
{
|
||||
// Y+方向からjointのheadからtailに向かうベクトルへの最小回転
|
||||
var axisRotation = fromToQuaternion(new float3(0, 1, 0), logic.boneAxis);
|
||||
var axisRotation = getAxisRotation(logic.boneAxis);
|
||||
|
||||
// limitのローカル空間をワールド空間に写像する回転
|
||||
return
|
||||
|
|
@ -63,29 +63,28 @@ namespace UniGLTF.SpringBoneJobs
|
|||
;
|
||||
}
|
||||
|
||||
// https://discussions.unity.com/t/unity-mathematics-equivalent-to-quaternion-fromtorotation/237459
|
||||
public static quaternion fromToQuaternion(in float3 from, in float3 to)
|
||||
/// <summary>
|
||||
/// Y軸正方向から `to` への回転を表すクォータニオンを計算して返す。
|
||||
/// `to` は正規化されていると仮定する。
|
||||
///
|
||||
/// See: https://github.com/0b5vr/vrm-specification/blob/75fbd48a7cb1d7250fa955838af6140e9c84844c/specification/VRMC_springBone_limit-1.0/README.ja.md#rotation-1
|
||||
///
|
||||
/// TODO: Replace with the appropriate link to the specification later
|
||||
/// </summary>
|
||||
public static quaternion getAxisRotation(in float3 to)
|
||||
{
|
||||
var fromNorm = math.normalize(from);
|
||||
var toNorm = math.normalize(to);
|
||||
var dot = math.dot(fromNorm, toNorm);
|
||||
// dot(from, to) + 1
|
||||
var dot1 = to.y + 1f;
|
||||
|
||||
// Handle the case where from and to are parallel but opposite
|
||||
if (math.abs(dot + 1f) < 1e-6f) // dot is approximately -1
|
||||
// Handle the case where from and to are parallel and opposite
|
||||
if (dot1 < 1e-8f) // dot is approximately -1
|
||||
{
|
||||
// Find a perpendicular axis
|
||||
var perpAxis = math.abs(fromNorm.x) > math.abs(fromNorm.z)
|
||||
? new float3(-fromNorm.y, fromNorm.x, 0f)
|
||||
: new float3(0f, -fromNorm.z, fromNorm.y);
|
||||
return quaternion.AxisAngle(math.normalize(perpAxis), math.PI);
|
||||
return new quaternion(1f, 0f, 0f, 0f);
|
||||
}
|
||||
|
||||
// General case
|
||||
return quaternion.AxisAngle(
|
||||
angle: math.acos(math.clamp(dot, -1f, 1f)),
|
||||
axis: math.normalize(math.cross(fromNorm, toNorm))
|
||||
);
|
||||
// quaternion(cross(from, to); dot(from, to) + 1).normalized
|
||||
return math.normalize(new quaternion(to.z, 0f, -to.x, dot1));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -283,6 +283,138 @@ namespace UniGLTF
|
|||
}
|
||||
}
|
||||
|
||||
private static NativeArray<Vector3> GetMorphTargetVec3(GltfData data, int accessorIndex, string attribute)
|
||||
{
|
||||
if (accessorIndex < 0) return data.NativeArrayManager.CreateNativeArray<Vector3>(0);
|
||||
|
||||
var accessor = data.GLTF.accessors[accessorIndex];
|
||||
if (accessor.type != "VEC3")
|
||||
{
|
||||
throw new ArgumentException($"unknown {attribute} type: {accessor.componentType}:{accessor.type}");
|
||||
}
|
||||
|
||||
static float NormalizeSByte(sbyte v)
|
||||
{
|
||||
// glTF normalized signed integer maps min to -1.0 exactly.
|
||||
return Mathf.Max(v / 127.0f, -1.0f);
|
||||
}
|
||||
|
||||
static float NormalizeShort(short v)
|
||||
{
|
||||
// glTF normalized signed integer maps min to -1.0 exactly.
|
||||
return Mathf.Max(v / 32767.0f, -1.0f);
|
||||
}
|
||||
|
||||
switch (accessor.componentType)
|
||||
{
|
||||
case glComponentType.FLOAT:
|
||||
return data.GetArrayFromAccessor<Vector3>(accessorIndex);
|
||||
|
||||
case glComponentType.BYTE:
|
||||
{
|
||||
var src = data.GetArrayFromAccessor<SByte3>(accessorIndex);
|
||||
var dst = data.NativeArrayManager.CreateNativeArray<Vector3>(src.Length);
|
||||
if (accessor.normalized)
|
||||
{
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(
|
||||
NormalizeSByte(v.x),
|
||||
NormalizeSByte(v.y),
|
||||
NormalizeSByte(v.z));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
case glComponentType.UNSIGNED_BYTE:
|
||||
{
|
||||
var src = data.GetArrayFromAccessor<Byte3>(accessorIndex);
|
||||
var dst = data.NativeArrayManager.CreateNativeArray<Vector3>(src.Length);
|
||||
if (accessor.normalized)
|
||||
{
|
||||
const float factor = 1.0f / 255.0f;
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(v.x * factor, v.y * factor, v.z * factor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
case glComponentType.SHORT:
|
||||
{
|
||||
var src = data.GetArrayFromAccessor<Short3>(accessorIndex);
|
||||
var dst = data.NativeArrayManager.CreateNativeArray<Vector3>(src.Length);
|
||||
if (accessor.normalized)
|
||||
{
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(
|
||||
NormalizeShort(v.x),
|
||||
NormalizeShort(v.y),
|
||||
NormalizeShort(v.z));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
case glComponentType.UNSIGNED_SHORT:
|
||||
{
|
||||
var src = data.GetArrayFromAccessor<UShort3>(accessorIndex);
|
||||
var dst = data.NativeArrayManager.CreateNativeArray<Vector3>(src.Length);
|
||||
if (accessor.normalized)
|
||||
{
|
||||
const float factor = 1.0f / 65535.0f;
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(v.x * factor, v.y * factor, v.z * factor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
var v = src[i];
|
||||
dst[i] = new Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"unknown {attribute} type: {accessor.componentType}:{accessor.type}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 各 primitive の attribute の要素が同じでない。=> uv が有るものと無いものが混在するなど
|
||||
/// glTF 的にはありうる。
|
||||
|
|
@ -438,7 +570,7 @@ namespace UniGLTF
|
|||
var blendShape = GetOrCreateBlendShape(i);
|
||||
if (primTarget.POSITION != -1)
|
||||
{
|
||||
var array = data.GetArrayFromAccessor<Vector3>(primTarget.POSITION);
|
||||
var array = GetMorphTargetVec3(data, primTarget.POSITION, "POSITION");
|
||||
if (array.Length != positions.Length)
|
||||
{
|
||||
throw new Exception("different length");
|
||||
|
|
@ -449,7 +581,7 @@ namespace UniGLTF
|
|||
|
||||
if (primTarget.NORMAL != -1)
|
||||
{
|
||||
var array = data.GetArrayFromAccessor<Vector3>(primTarget.NORMAL);
|
||||
var array = GetMorphTargetVec3(data, primTarget.NORMAL, "NORMAL");
|
||||
if (array.Length != positions.Length)
|
||||
{
|
||||
throw new Exception("different length");
|
||||
|
|
@ -460,7 +592,7 @@ namespace UniGLTF
|
|||
|
||||
if (primTarget.TANGENT != -1)
|
||||
{
|
||||
var array = data.GetArrayFromAccessor<Vector3>(primTarget.TANGENT);
|
||||
var array = GetMorphTargetVec3(data, primTarget.TANGENT, "TANGENT");
|
||||
if (array.Length != positions.Length)
|
||||
{
|
||||
throw new Exception("different length");
|
||||
|
|
@ -579,7 +711,7 @@ namespace UniGLTF
|
|||
|
||||
if (hasPosition)
|
||||
{
|
||||
var morphPositions = data.GetArrayFromAccessor<Vector3>(primTarget.POSITION);
|
||||
var morphPositions = GetMorphTargetVec3(data, primTarget.POSITION, "POSITION");
|
||||
blendShape.Positions.Capacity = morphPositions.Length;
|
||||
for (var j = 0; j < positions.Length; ++j)
|
||||
{
|
||||
|
|
@ -589,7 +721,7 @@ namespace UniGLTF
|
|||
|
||||
if (hasNormal)
|
||||
{
|
||||
var morphNormals = data.GetArrayFromAccessor<Vector3>(primTarget.NORMAL);
|
||||
var morphNormals = GetMorphTargetVec3(data, primTarget.NORMAL, "NORMAL");
|
||||
blendShape.Normals.Capacity = morphNormals.Length;
|
||||
for (var j = 0; j < positions.Length; ++j)
|
||||
{
|
||||
|
|
@ -600,7 +732,7 @@ namespace UniGLTF
|
|||
|
||||
if (hasTangent)
|
||||
{
|
||||
var morphTangents = data.GetArrayFromAccessor<Vector3>(primTarget.TANGENT);
|
||||
var morphTangents = GetMorphTargetVec3(data, primTarget.TANGENT, "TANGENT");
|
||||
blendShape.Tangents.Capacity = morphTangents.Length;
|
||||
for (var j = 0; j < positions.Length; ++j)
|
||||
{
|
||||
|
|
@ -639,4 +771,4 @@ namespace UniGLTF
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
|
@ -41,28 +40,33 @@ namespace UniGLTF
|
|||
}
|
||||
}
|
||||
|
||||
private static async Task BuildBlendShapeAsync(IAwaitCaller awaitCaller, Mesh mesh, BlendShape blendShape,
|
||||
private static async Task BuildBlendShapeAsync(
|
||||
IAwaitCaller awaitCaller,
|
||||
Mesh mesh,
|
||||
BlendShape blendShape,
|
||||
Vector3[] emptyVertices)
|
||||
{
|
||||
Vector3[] positions = null;
|
||||
Vector3[] normals = null;
|
||||
await awaitCaller.Run(() =>
|
||||
{
|
||||
positions = blendShape.Positions.ToArray();
|
||||
if (blendShape.Normals != null)
|
||||
{
|
||||
normals = blendShape.Normals.ToArray();
|
||||
}
|
||||
positions = blendShape.Positions != null ? blendShape.Positions.ToArray() : Array.Empty<Vector3>();
|
||||
normals = blendShape.Normals != null ? blendShape.Normals.ToArray() : Array.Empty<Vector3>();
|
||||
});
|
||||
|
||||
Profiler.BeginSample("MeshUploader.BuildBlendShapeAsync");
|
||||
var hasPositions = positions.Length == mesh.vertexCount;
|
||||
var hasNormals = normals.Length == mesh.vertexCount;
|
||||
|
||||
if (positions.Length > 0)
|
||||
{
|
||||
if (positions.Length == mesh.vertexCount)
|
||||
if (hasPositions)
|
||||
{
|
||||
var deltaNormals = hasNormals ? normals : null;
|
||||
|
||||
mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight,
|
||||
positions,
|
||||
normals.Length == mesh.vertexCount && normals.Length == positions.Length ? normals : null,
|
||||
deltaNormals,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
|
@ -76,7 +80,7 @@ namespace UniGLTF
|
|||
// add empty blend shape for keep blend shape index
|
||||
mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight,
|
||||
emptyVertices,
|
||||
null,
|
||||
normals.Length == mesh.vertexCount ? normals : null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
|
@ -132,7 +136,11 @@ namespace UniGLTF
|
|||
var emptyVertices = new Vector3[mesh.vertexCount];
|
||||
foreach (var blendShape in data.BlendShapes)
|
||||
{
|
||||
await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices);
|
||||
await BuildBlendShapeAsync(
|
||||
awaitCaller,
|
||||
mesh,
|
||||
blendShape,
|
||||
emptyVertices);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
25
Packages/UniGLTF/Runtime/UniGLTF/IO/SByte3.cs
Normal file
25
Packages/UniGLTF/Runtime/UniGLTF/IO/SByte3.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct SByte3 : IEquatable<SByte3>
|
||||
{
|
||||
public readonly sbyte x;
|
||||
public readonly sbyte y;
|
||||
public readonly sbyte z;
|
||||
|
||||
public SByte3(sbyte _x, sbyte _y, sbyte _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
public bool Equals(SByte3 other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Packages/UniGLTF/Runtime/UniGLTF/IO/SByte3.cs.meta
Normal file
2
Packages/UniGLTF/Runtime/UniGLTF/IO/SByte3.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 93c772ed657e23c448e9b036d9c9071c
|
||||
25
Packages/UniGLTF/Runtime/UniGLTF/IO/Short3.cs
Normal file
25
Packages/UniGLTF/Runtime/UniGLTF/IO/Short3.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public readonly struct Short3 : IEquatable<Short3>
|
||||
{
|
||||
public readonly short x;
|
||||
public readonly short y;
|
||||
public readonly short z;
|
||||
|
||||
public Short3(short _x, short _y, short _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
public bool Equals(Short3 other)
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Packages/UniGLTF/Runtime/UniGLTF/IO/Short3.cs.meta
Normal file
2
Packages/UniGLTF/Runtime/UniGLTF/IO/Short3.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f74b316e688844c428c7b45dcb38ee54
|
||||
|
|
@ -55,7 +55,10 @@ namespace UniHumanoid
|
|||
/// HumanBone のマッピングを流用して、新たな Avatar を作り直す。
|
||||
/// 古い Avatar は破棄する。
|
||||
/// </summary>
|
||||
public static void RebuildHumanAvatar(Animator animator)
|
||||
/// <remarks>
|
||||
/// This method runs asynchronously only in play mode.
|
||||
/// </remarks>
|
||||
public static async Awaitable RebuildHumanAvatar(Animator animator)
|
||||
{
|
||||
if (animator == null)
|
||||
{
|
||||
|
|
@ -77,6 +80,9 @@ namespace UniHumanoid
|
|||
if (Application.isPlaying)
|
||||
{
|
||||
GameObject.Destroy(animator);
|
||||
|
||||
// Else, the following AddComponent call will fail.
|
||||
await Awaitable.NextFrameAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
using Unity.Profiling;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
|
@ -12,6 +13,8 @@ namespace VRM
|
|||
UnityPath m_prefabPath;
|
||||
List<UnityPath> m_paths = new List<UnityPath>();
|
||||
|
||||
private static ProfilerMarker s_MarkerConvertAndExtractImages = new ProfilerMarker("Convert and Extract Images");
|
||||
|
||||
public ITextureDescriptorGenerator TextureDescriptorGenerator => m_context.TextureDescriptorGenerator;
|
||||
|
||||
public VRMEditorImporterContext(VRMImporterContext context, UnityPath prefabPath)
|
||||
|
|
@ -76,22 +79,27 @@ namespace VRM
|
|||
/// </summary>
|
||||
public void ConvertAndExtractImages(Action<IEnumerable<UnityPath>> onTextureReloaded)
|
||||
{
|
||||
s_MarkerConvertAndExtractImages.Begin();
|
||||
|
||||
//
|
||||
// convert images(metallic roughness, occlusion map)
|
||||
//
|
||||
var task = m_context.LoadMaterialsAsync(new ImmediateCaller());
|
||||
if (!task.IsCompleted)
|
||||
{
|
||||
s_MarkerConvertAndExtractImages.End();
|
||||
throw new Exception();
|
||||
}
|
||||
if (task.IsFaulted)
|
||||
{
|
||||
if (task.Exception is AggregateException ae && ae.InnerExceptions.Count == 1)
|
||||
{
|
||||
s_MarkerConvertAndExtractImages.End();
|
||||
throw ae.InnerException;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_MarkerConvertAndExtractImages.End();
|
||||
throw task.Exception;
|
||||
}
|
||||
}
|
||||
|
|
@ -100,6 +108,7 @@ namespace VRM
|
|||
var task2 = m_context.ReadMetaAsync(new ImmediateCaller());
|
||||
if (!task2.IsCompleted || task2.IsCanceled || task2.IsFaulted)
|
||||
{
|
||||
s_MarkerConvertAndExtractImages.End();
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +119,8 @@ namespace VRM
|
|||
var vrmTextures = new BuiltInVrmMaterialDescriptorGenerator(m_context.VRM);
|
||||
var dirName = $"{m_prefabPath.FileNameWithoutExtension}.Textures";
|
||||
TextureExtractor.ExtractTextures(m_context.Data, m_prefabPath.Parent.Child(dirName), m_context.TextureDescriptorGenerator, subAssets, (_x, _y) => { }, onTextureReloaded);
|
||||
|
||||
s_MarkerConvertAndExtractImages.End();
|
||||
}
|
||||
|
||||
void SaveAsAsset(SubAssetKey _, UnityEngine.Object o)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using UniGLTF;
|
||||
using Unity.Profiling;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
|
@ -10,6 +11,8 @@ namespace VRM
|
|||
{
|
||||
public class vrmAssetPostprocessor : AssetPostprocessor
|
||||
{
|
||||
private static ProfilerMarker s_MarkerCreatePrefab = new ProfilerMarker("Create Prefab");
|
||||
|
||||
#if !VRM_STOP_ASSETPOSTPROCESSOR
|
||||
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
{
|
||||
|
|
@ -63,6 +66,9 @@ namespace VRM
|
|||
return;
|
||||
}
|
||||
|
||||
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
/// <summary>
|
||||
/// これは EditorApplication.delayCall により呼び出される。
|
||||
///
|
||||
|
|
@ -73,24 +79,46 @@ namespace VRM
|
|||
/// <value></value>
|
||||
Action<IEnumerable<UnityPath>> onCompleted = texturePaths =>
|
||||
{
|
||||
s_MarkerCreatePrefab.Begin();
|
||||
|
||||
var map = texturePaths
|
||||
.Select(x => x.LoadAsset<Texture>())
|
||||
.ToDictionary(x => new SubAssetKey(x), x => x as UnityEngine.Object);
|
||||
var settings = new ImporterContextSettings();
|
||||
|
||||
// 確実に Dispose するために敢えて再パースしている
|
||||
using (var data = new GlbFileParser(vrmPath).Parse())
|
||||
using (var context = new VRMImporterContext(new VRMData(data), externalObjectMap: map, settings: settings))
|
||||
try
|
||||
{
|
||||
var editor = new VRMEditorImporterContext(context, prefabPath);
|
||||
foreach (var textureInfo in context.TextureDescriptorGenerator.Get().GetEnumerable())
|
||||
AssetDatabase.StartAssetEditing();
|
||||
|
||||
var settings = new ImporterContextSettings();
|
||||
|
||||
// 確実に Dispose するために敢えて再パースしている
|
||||
using (var data = new GlbFileParser(vrmPath).Parse())
|
||||
using (var context = new VRMImporterContext(new VRMData(data), externalObjectMap: map, settings: settings))
|
||||
{
|
||||
TextureImporterConfigurator.Configure(textureInfo, context.TextureFactory.ExternalTextures);
|
||||
var editor = new VRMEditorImporterContext(context, prefabPath);
|
||||
foreach (var textureInfo in context.TextureDescriptorGenerator.Get().GetEnumerable())
|
||||
{
|
||||
TextureImporterConfigurator.Configure(textureInfo, context.TextureFactory.ExternalTextures);
|
||||
}
|
||||
var loaded = context.Load();
|
||||
editor.SaveAsAsset(loaded);
|
||||
}
|
||||
var loaded = context.Load();
|
||||
editor.SaveAsAsset(loaded);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AssetDatabase.StopAssetEditing();
|
||||
}
|
||||
|
||||
s_MarkerCreatePrefab.End();
|
||||
|
||||
sw.Stop();
|
||||
|
||||
Debug.Log($"Import complete [importMs={sw.ElapsedMilliseconds}]");
|
||||
};
|
||||
|
||||
using (var data = new GlbFileParser(vrmPath).Parse())
|
||||
|
|
|
|||
|
|
@ -53,7 +53,10 @@ namespace VRM
|
|||
/// <param name="go">対象モデルのルート</param>
|
||||
/// <param name="forceTPose">強制的にT-Pose化するか</param>
|
||||
/// <param name="useCurrentBlendShapeWeight">BlendShape の現状をbakeするか</param>
|
||||
public static void Execute(GameObject go, bool forceTPose, bool useCurrentBlendShapeWeight)
|
||||
/// <remarks>
|
||||
/// This method runs asynchronously only in play mode.
|
||||
/// </remarks>
|
||||
public static async Awaitable Execute(GameObject go, bool forceTPose, bool useCurrentBlendShapeWeight)
|
||||
{
|
||||
if (forceTPose)
|
||||
{
|
||||
|
|
@ -83,7 +86,7 @@ namespace VRM
|
|||
// 回転とスケールが除去された新しいヒエラルキーからAvatarを作る
|
||||
if (go.TryGetComponent<Animator>(out var animator))
|
||||
{
|
||||
HumanoidLoader.RebuildHumanAvatar(animator);
|
||||
await HumanoidLoader.RebuildHumanAvatar(animator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,15 @@ namespace UniVRM10
|
|||
var binding = default(UniVRM10.MaterialUVBinding?);
|
||||
if (material != null)
|
||||
{
|
||||
var (scale, offset) = UniGLTF.TextureTransform.VerticalFlipScaleOffset(new Vector2(bind.Scale[0], bind.Scale[1]), new Vector2(bind.Offset[0], bind.Offset[1]));
|
||||
// Default values: scale [1, 1], offset [0, 0]
|
||||
Vector2 scaleVec = bind.Scale != null && bind.Scale.Length >= 2
|
||||
? new Vector2(bind.Scale[0], bind.Scale[1])
|
||||
: new Vector2(1.0f, 1.0f);
|
||||
Vector2 offsetVec = bind.Offset != null && bind.Offset.Length >= 2
|
||||
? new Vector2(bind.Offset[0], bind.Offset[1])
|
||||
: new Vector2(0.0f, 0.0f);
|
||||
|
||||
var (scale, offset) = UniGLTF.TextureTransform.VerticalFlipScaleOffset(scaleVec, offsetVec);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user