mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-27 21:34:38 -05:00
Merge pull request #911 from ousttrue/feature10/rename_importer_exporter
Feature10/rename importer exporter
This commit is contained in:
@@ -311,7 +311,7 @@ namespace UniVRM10.Samples
|
||||
var parser = new UniGLTF.GltfParser();
|
||||
parser.ParsePath(path);
|
||||
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
using (var loader = new Vrm10Importer(parser))
|
||||
{
|
||||
loader.Load();
|
||||
loader.ShowMeshes();
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace UniVRM10
|
||||
m_parser = null;
|
||||
return;
|
||||
}
|
||||
m_model = VrmLoader.CreateVrmModel(m_parser);
|
||||
m_model = ModelReader.Read(m_parser);
|
||||
}
|
||||
|
||||
enum Tabs
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace UniVRM10
|
||||
//
|
||||
var externalObjectMap = scriptedImporter.GetExternalObjectMap().ToDictionary(kv => new SubAssetKey(kv.Key.type, kv.Key.name), kv => kv.Value);
|
||||
|
||||
using (var loader = new RuntimeUnityBuilder(parser, externalObjectMap))
|
||||
using (var loader = new Vrm10Importer(parser, externalObjectMap))
|
||||
{
|
||||
// settings TextureImporters
|
||||
foreach (var (key, textureInfo) in Vrm10MaterialImporter.EnumerateAllTexturesDistinct(parser))
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace UniVRM10
|
||||
|
||||
try
|
||||
{
|
||||
var converter = new UniVRM10.RuntimeVrmConverter();
|
||||
var converter = new UniVRM10.ModelExporter();
|
||||
var model = converter.ToModelFrom10(root);
|
||||
|
||||
if (HumanoidValidator.HasRotationOrScale(root))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class ComponentBuilder
|
||||
{
|
||||
#region Util
|
||||
static (Transform, Mesh) GetTransformAndMesh(Transform t)
|
||||
{
|
||||
var skinnedMeshRenderer = t.GetComponent<SkinnedMeshRenderer>();
|
||||
if (skinnedMeshRenderer != null)
|
||||
{
|
||||
return (t, skinnedMeshRenderer.sharedMesh);
|
||||
}
|
||||
|
||||
var filter = t.GetComponent<MeshFilter>();
|
||||
if (filter != null)
|
||||
{
|
||||
return (t, filter.sharedMesh);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class DictionaryExtensions
|
||||
{
|
||||
public static U GetOrDefault<T, U>(this Dictionary<T, U> d, T key)
|
||||
{
|
||||
if(key == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if(d.TryGetValue(key, out U value))
|
||||
{
|
||||
return value;;
|
||||
}
|
||||
else{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace UniVRM10
|
||||
{
|
||||
public static class ExpressionExtensions
|
||||
{
|
||||
public static UniVRM10.MorphTargetBinding Build10(this MorphTargetBind bind, GameObject root, RuntimeUnityBuilder.ModelMap loader, VrmLib.Model model)
|
||||
public static UniVRM10.MorphTargetBinding Build10(this MorphTargetBind bind, GameObject root, Vrm10Importer.ModelMap loader, VrmLib.Model model)
|
||||
{
|
||||
var libNode = model.Nodes[bind.Node.Value];
|
||||
var node = loader.Nodes[libNode].transform;
|
||||
|
||||
@@ -1,401 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using UniGLTF;
|
||||
using VrmLib;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class MeshAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// VertexBufferはひとつでIndexBufferの参照が異なる
|
||||
///
|
||||
/// VertexBuffer
|
||||
/// +----------------------------------+
|
||||
/// | |
|
||||
/// +----------------------------------+
|
||||
/// A A A
|
||||
/// | | |
|
||||
/// +---------+--------+--------+
|
||||
/// | submesh0|submesh1|submesh2|
|
||||
/// +---------+--------+--------+
|
||||
/// IndexBuffer
|
||||
/// </summary>
|
||||
public static Mesh SharedBufferFromGltf(this glTFMesh x, Vrm10Storage storage)
|
||||
{
|
||||
// 先頭を使う
|
||||
return FromGltf(storage, x, x.primitives[0], true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IndexBuffer毎に異なるVertexBufferを参照する
|
||||
///
|
||||
/// VertexBuffer
|
||||
/// +--------+ +--------+ +--------+
|
||||
/// |0 | |1 | |2 |
|
||||
/// +--------+ +--------+ +--------+
|
||||
/// A A A
|
||||
/// | | |
|
||||
/// +---------+--------+--------+
|
||||
/// | submesh0|submesh1|submesh2|
|
||||
/// +---------+--------+--------+
|
||||
/// IndexBuffer
|
||||
/// </summary>
|
||||
public static Mesh FromGltf(this glTFPrimitives primitive, Vrm10Storage storage, glTFMesh x)
|
||||
{
|
||||
return FromGltf(storage, x, primitive, false);
|
||||
}
|
||||
|
||||
static Mesh FromGltf(Vrm10Storage storage, glTFMesh x, glTFPrimitives primitive, bool isShared)
|
||||
{
|
||||
var mesh = new Mesh((TopologyType)primitive.mode)
|
||||
{
|
||||
VertexBuffer = primitive.attributes.FromGltf(storage)
|
||||
};
|
||||
|
||||
if (isShared)
|
||||
{
|
||||
// create joined index buffer
|
||||
mesh.IndexBuffer = storage.CreateAccessor(x.primitives.Select(y => y.indices).ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh.IndexBuffer = storage.CreateAccessor(primitive.indices);
|
||||
}
|
||||
|
||||
{
|
||||
gltf_mesh_extras_targetNames.TryGet(x, out List<string> targetNames);
|
||||
|
||||
for (int i = 0; i < primitive.targets.Count; ++i)
|
||||
{
|
||||
var gltfTarget = primitive.targets[i];
|
||||
|
||||
string targetName = null;
|
||||
{
|
||||
targetName = targetNames[i];
|
||||
}
|
||||
var target = new MorphTarget(targetName)
|
||||
{
|
||||
VertexBuffer = gltfTarget.FromGltf(storage)
|
||||
};
|
||||
|
||||
// validate count
|
||||
foreach (var kv in target.VertexBuffer)
|
||||
{
|
||||
if (kv.Value.Count != mesh.VertexBuffer.Count)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
mesh.MorphTargets.Add(target);
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public static VertexBuffer FromGltf(this glTFAttributes attributes,
|
||||
Vrm10Storage storage)
|
||||
{
|
||||
var b = new VertexBuffer();
|
||||
|
||||
if (storage.TryCreateAccessor(attributes.POSITION, out BufferAccessor position))
|
||||
{
|
||||
b.Add(VertexBuffer.PositionKey, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
// position required
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
if (storage.TryCreateAccessor(attributes.NORMAL, out BufferAccessor normal)) b.Add(VertexBuffer.NormalKey, normal);
|
||||
if (storage.TryCreateAccessor(attributes.COLOR_0, out BufferAccessor color)) b.Add(VertexBuffer.ColorKey, color);
|
||||
if (storage.TryCreateAccessor(attributes.TEXCOORD_0, out BufferAccessor tex0)) b.Add(VertexBuffer.TexCoordKey, tex0);
|
||||
if (storage.TryCreateAccessor(attributes.TEXCOORD_1, out BufferAccessor tex1)) b.Add(VertexBuffer.TexCoordKey2, tex1);
|
||||
// if(storage.TryCreateAccessor(attributes.TANGENT, out BufferAccessor tangent))b.Add(VertexBuffer.TangentKey, tangent);
|
||||
if (storage.TryCreateAccessor(attributes.WEIGHTS_0, out BufferAccessor weights)) b.Add(VertexBuffer.WeightKey, weights);
|
||||
if (storage.TryCreateAccessor(attributes.JOINTS_0, out BufferAccessor joints)) b.Add(VertexBuffer.JointKey, joints);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
public static VertexBuffer FromGltf(this gltfMorphTarget target, Vrm10Storage storage)
|
||||
{
|
||||
var b = new VertexBuffer();
|
||||
storage.CreateBufferAccessorAndAdd(target.POSITION, b, VertexBuffer.PositionKey);
|
||||
storage.CreateBufferAccessorAndAdd(target.NORMAL, b, VertexBuffer.NormalKey);
|
||||
storage.CreateBufferAccessorAndAdd(target.TANGENT, b, VertexBuffer.TangentKey);
|
||||
return b;
|
||||
}
|
||||
|
||||
public static bool HasSameVertexBuffer(this glTFPrimitives lhs, glTFPrimitives rhs)
|
||||
{
|
||||
if (lhs.attributes.POSITION != rhs.attributes.POSITION) return false;
|
||||
if (lhs.attributes.NORMAL != rhs.attributes.NORMAL) return false;
|
||||
if (lhs.attributes.TEXCOORD_0 != rhs.attributes.TEXCOORD_0) return false;
|
||||
if (lhs.attributes.TEXCOORD_1 != rhs.attributes.TEXCOORD_1) return false;
|
||||
if (lhs.attributes.COLOR_0 != rhs.attributes.COLOR_0) return false;
|
||||
if (lhs.attributes.WEIGHTS_0 != rhs.attributes.WEIGHTS_0) return false;
|
||||
if (lhs.attributes.JOINTS_0 != rhs.attributes.JOINTS_0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool AllPrimitivesHasSameVertexBuffer(this glTFMesh m)
|
||||
{
|
||||
if (m.primitives.Count <= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var first = m.primitives[0];
|
||||
for (int i = 1; i < m.primitives.Count; ++i)
|
||||
{
|
||||
if (!first.HasSameVertexBuffer(m.primitives[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static MeshGroup FromGltf(this glTFMesh x, Vrm10Storage storage)
|
||||
{
|
||||
var group = new MeshGroup(x.name);
|
||||
|
||||
if (x.primitives.Count == 1)
|
||||
{
|
||||
var primitive = x.primitives[0];
|
||||
var mesh = primitive.FromGltf(storage, x);
|
||||
var materialIndex = primitive.material;
|
||||
|
||||
mesh.Submeshes.Add(
|
||||
new Submesh(0, mesh.IndexBuffer.Count, materialIndex));
|
||||
|
||||
group.Meshes.Add(mesh);
|
||||
}
|
||||
else if (!x.AllPrimitivesHasSameVertexBuffer())
|
||||
{
|
||||
int offset = 0;
|
||||
foreach (var primitive in x.primitives)
|
||||
{
|
||||
var mesh = primitive.FromGltf(storage, x);
|
||||
var materialIndex = primitive.material;
|
||||
|
||||
mesh.Submeshes.Add(
|
||||
new Submesh(offset, mesh.IndexBuffer.Count, materialIndex));
|
||||
offset += mesh.IndexBuffer.Count;
|
||||
|
||||
group.Meshes.Add(mesh);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// for VRM
|
||||
|
||||
var mesh = x.SharedBufferFromGltf(storage);
|
||||
int offset = 0;
|
||||
foreach (var primitive in x.primitives)
|
||||
{
|
||||
var materialIndex = primitive.material;
|
||||
var count = storage.Gltf.accessors[primitive.indices].count;
|
||||
mesh.Submeshes.Add(
|
||||
new Submesh(offset, count, materialIndex));
|
||||
offset += count;
|
||||
}
|
||||
|
||||
group.Meshes.Add(mesh);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void Vec3MinMax(ArraySegment<byte> bytes, glTFAccessor accessor)
|
||||
{
|
||||
var positions = SpanLike.Wrap<Vector3>(bytes);
|
||||
var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
||||
var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
|
||||
foreach (var p in positions)
|
||||
{
|
||||
min = Vector3.Min(min, p);
|
||||
max = Vector3.Max(max, p);
|
||||
}
|
||||
accessor.min = min.ToFloat3();
|
||||
accessor.max = max.ToFloat3();
|
||||
}
|
||||
|
||||
static int ExportIndices(Vrm10Storage storage, BufferAccessor x, int offset, int count, ExportArgs option)
|
||||
{
|
||||
if (x.Count <= ushort.MaxValue)
|
||||
{
|
||||
if (x.ComponentType == AccessorValueType.UNSIGNED_INT)
|
||||
{
|
||||
// ensure ushort
|
||||
var src = x.GetSpan<UInt32>().Slice(offset, count);
|
||||
var bytes = new byte[src.Length * 2];
|
||||
var dst = SpanLike.Wrap<UInt16>(new ArraySegment<byte>(bytes));
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
dst[i] = (ushort)src[i];
|
||||
}
|
||||
var accessor = new BufferAccessor(new ArraySegment<byte>(bytes), AccessorValueType.UNSIGNED_SHORT, AccessorVectorType.SCALAR, count);
|
||||
return accessor.AddAccessorTo(storage, 0, option.sparse, null, 0, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return x.AddAccessorTo(storage, 0, option.sparse, null, offset, count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return x.AddAccessorTo(storage, 0, option.sparse, null, offset, count);
|
||||
}
|
||||
}
|
||||
|
||||
static void ExportMesh(this Mesh mesh, List<object> materials, Vrm10Storage storage, glTFMesh gltfMesh, ExportArgs option)
|
||||
{
|
||||
//
|
||||
// primitive share vertex buffer
|
||||
//
|
||||
var attributeAccessorIndexMap = mesh.VertexBuffer
|
||||
.ToDictionary(
|
||||
kv => kv.Key,
|
||||
kv => kv.Value.AddAccessorTo(
|
||||
storage, 0, option.sparse,
|
||||
kv.Key == VertexBuffer.PositionKey ? (Action<ArraySegment<byte>, glTFAccessor>)Vec3MinMax : null
|
||||
)
|
||||
);
|
||||
|
||||
List<Dictionary<string, int>> morphTargetAccessorIndexMapList = null;
|
||||
if (mesh.MorphTargets.Any())
|
||||
{
|
||||
morphTargetAccessorIndexMapList = new List<Dictionary<string, int>>();
|
||||
foreach (var morphTarget in mesh.MorphTargets)
|
||||
{
|
||||
var dict = new Dictionary<string, int>();
|
||||
|
||||
foreach (var kv in morphTarget.VertexBuffer)
|
||||
{
|
||||
if (option.removeTangent && kv.Key == VertexBuffer.TangentKey)
|
||||
{
|
||||
// remove tangent
|
||||
continue;
|
||||
}
|
||||
if (option.removeMorphNormal && kv.Key == VertexBuffer.NormalKey)
|
||||
{
|
||||
// normal normal
|
||||
continue;
|
||||
}
|
||||
if (kv.Value.Count != mesh.VertexBuffer.Count)
|
||||
{
|
||||
throw new Exception("inavlid data");
|
||||
}
|
||||
var accessorIndex = kv.Value.AddAccessorTo(storage, 0,
|
||||
option.sparse,
|
||||
kv.Key == VertexBuffer.PositionKey ? (Action<ArraySegment<byte>, glTFAccessor>)Vec3MinMax : null);
|
||||
dict.Add(kv.Key, accessorIndex);
|
||||
}
|
||||
|
||||
morphTargetAccessorIndexMapList.Add(dict);
|
||||
}
|
||||
}
|
||||
|
||||
var drawCountOffset = 0;
|
||||
foreach (var y in mesh.Submeshes)
|
||||
{
|
||||
// index
|
||||
// slide index buffer accessor
|
||||
var indicesAccessorIndex = ExportIndices(storage, mesh.IndexBuffer, drawCountOffset, y.DrawCount, option);
|
||||
drawCountOffset += y.DrawCount;
|
||||
|
||||
var prim = new glTFPrimitives
|
||||
{
|
||||
mode = (int)mesh.Topology,
|
||||
material = y.Material,
|
||||
indices = indicesAccessorIndex,
|
||||
attributes = new glTFAttributes(),
|
||||
};
|
||||
gltfMesh.primitives.Add(prim);
|
||||
|
||||
// attribute
|
||||
foreach (var kv in mesh.VertexBuffer)
|
||||
{
|
||||
var attributeAccessorIndex = attributeAccessorIndexMap[kv.Key];
|
||||
|
||||
switch (kv.Key)
|
||||
{
|
||||
case VertexBuffer.PositionKey: prim.attributes.POSITION = attributeAccessorIndex; break;
|
||||
case VertexBuffer.NormalKey: prim.attributes.NORMAL = attributeAccessorIndex; break;
|
||||
case VertexBuffer.ColorKey: prim.attributes.COLOR_0 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.TexCoordKey: prim.attributes.TEXCOORD_0 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.TexCoordKey2: prim.attributes.TEXCOORD_1 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.JointKey: prim.attributes.JOINTS_0 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.WeightKey: prim.attributes.WEIGHTS_0 = attributeAccessorIndex; break;
|
||||
}
|
||||
}
|
||||
|
||||
// morph target
|
||||
if (mesh.MorphTargets.Any())
|
||||
{
|
||||
foreach (var (t, accessorIndexMap) in
|
||||
Enumerable.Zip(mesh.MorphTargets, morphTargetAccessorIndexMapList, (t, v) => (t, v)))
|
||||
{
|
||||
var target = new gltfMorphTarget();
|
||||
prim.targets.Add(target);
|
||||
|
||||
foreach (var kv in t.VertexBuffer)
|
||||
{
|
||||
if (!accessorIndexMap.TryGetValue(kv.Key, out int targetAccessorIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (kv.Key)
|
||||
{
|
||||
case VertexBuffer.PositionKey:
|
||||
target.POSITION = targetAccessorIndex;
|
||||
break;
|
||||
case VertexBuffer.NormalKey:
|
||||
target.NORMAL = targetAccessorIndex;
|
||||
break;
|
||||
case VertexBuffer.TangentKey:
|
||||
target.TANGENT = targetAccessorIndex;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// target name
|
||||
if (mesh.MorphTargets.Any())
|
||||
{
|
||||
gltf_mesh_extras_targetNames.Serialize(gltfMesh, mesh.MorphTargets.Select(z => z.Name));
|
||||
}
|
||||
}
|
||||
|
||||
public static glTFMesh ExportMeshGroup(this MeshGroup src, List<object> materials, Vrm10Storage storage, ExportArgs option)
|
||||
{
|
||||
var mesh = new glTFMesh
|
||||
{
|
||||
name = src.Name
|
||||
};
|
||||
|
||||
foreach (var x in src.Meshes)
|
||||
{
|
||||
// MeshとSubmeshがGltfのPrimitiveに相当する?
|
||||
x.ExportMesh(materials, storage, mesh, option);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Assets/VRM10/Runtime/IO/Model.meta
Normal file
8
Assets/VRM10/Runtime/IO/Model.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18a0f7c989f911547aa4b75abb583b4c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,12 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class MeshLoader
|
||||
public static class MeshImporter
|
||||
{
|
||||
public static void LoadMesh(this Mesh mesh, VrmLib.Mesh src, VrmLib.Skin skin = null)
|
||||
/// <summary>
|
||||
/// VrmLib.Mesh => UnityEngine.Mesh
|
||||
/// </summary>
|
||||
/// <param name="mesh"></param>
|
||||
/// <param name="src"></param>
|
||||
/// <param name="skin"></param>
|
||||
public static void LoadSharedMesh(UnityEngine.Mesh mesh, VrmLib.Mesh src, VrmLib.Skin skin = null)
|
||||
{
|
||||
mesh.vertices = src.VertexBuffer.Positions.GetSpan<Vector3>().ToArray();
|
||||
mesh.normals = src.VertexBuffer.Normals?.GetSpan<Vector3>().ToArray();
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 573f68f30d3f14a4cb8181b07981c6e0
|
||||
guid: 98874f743a5ae754eb8382f3991a5646
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
222
Assets/VRM10/Runtime/IO/Model/MeshReader.cs
Normal file
222
Assets/VRM10/Runtime/IO/Model/MeshReader.cs
Normal file
@@ -0,0 +1,222 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UniGLTF;
|
||||
using VrmLib;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
/// <summary>
|
||||
/// GLTF -> VrmLib.MeshGroup
|
||||
/// </summary>
|
||||
public static class MeshReader
|
||||
{
|
||||
/// <summary>
|
||||
/// VertexBufferはひとつでIndexBufferの参照が異なる
|
||||
///
|
||||
/// VertexBuffer
|
||||
/// +----------------------------------+
|
||||
/// | |
|
||||
/// +----------------------------------+
|
||||
/// A A A
|
||||
/// | | |
|
||||
/// +---------+--------+--------+
|
||||
/// | submesh0|submesh1|submesh2|
|
||||
/// +---------+--------+--------+
|
||||
/// IndexBuffer
|
||||
/// </summary>
|
||||
static Mesh SharedBufferFromGltf(this glTFMesh x, Vrm10Storage storage)
|
||||
{
|
||||
// 先頭を使う
|
||||
return FromGltf(storage, x, x.primitives[0], true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IndexBuffer毎に異なるVertexBufferを参照する
|
||||
///
|
||||
/// VertexBuffer
|
||||
/// +--------+ +--------+ +--------+
|
||||
/// |0 | |1 | |2 |
|
||||
/// +--------+ +--------+ +--------+
|
||||
/// A A A
|
||||
/// | | |
|
||||
/// +---------+--------+--------+
|
||||
/// | submesh0|submesh1|submesh2|
|
||||
/// +---------+--------+--------+
|
||||
/// IndexBuffer
|
||||
/// </summary>
|
||||
static Mesh FromGltf(this glTFPrimitives primitive, Vrm10Storage storage, glTFMesh x)
|
||||
{
|
||||
return FromGltf(storage, x, primitive, false);
|
||||
}
|
||||
|
||||
static Mesh FromGltf(Vrm10Storage storage, glTFMesh x, glTFPrimitives primitive, bool isShared)
|
||||
{
|
||||
var mesh = new Mesh((TopologyType)primitive.mode)
|
||||
{
|
||||
VertexBuffer = primitive.attributes.FromGltf(storage)
|
||||
};
|
||||
|
||||
if (isShared)
|
||||
{
|
||||
// create joined index buffer
|
||||
mesh.IndexBuffer = storage.CreateAccessor(x.primitives.Select(y => y.indices).ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh.IndexBuffer = storage.CreateAccessor(primitive.indices);
|
||||
}
|
||||
|
||||
{
|
||||
gltf_mesh_extras_targetNames.TryGet(x, out List<string> targetNames);
|
||||
|
||||
for (int i = 0; i < primitive.targets.Count; ++i)
|
||||
{
|
||||
var gltfTarget = primitive.targets[i];
|
||||
|
||||
string targetName = null;
|
||||
{
|
||||
targetName = targetNames[i];
|
||||
}
|
||||
var target = new MorphTarget(targetName)
|
||||
{
|
||||
VertexBuffer = gltfTarget.FromGltf(storage)
|
||||
};
|
||||
|
||||
// validate count
|
||||
foreach (var kv in target.VertexBuffer)
|
||||
{
|
||||
if (kv.Value.Count != mesh.VertexBuffer.Count)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
mesh.MorphTargets.Add(target);
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static VertexBuffer FromGltf(this glTFAttributes attributes,
|
||||
Vrm10Storage storage)
|
||||
{
|
||||
var b = new VertexBuffer();
|
||||
|
||||
if (storage.TryCreateAccessor(attributes.POSITION, out BufferAccessor position))
|
||||
{
|
||||
b.Add(VertexBuffer.PositionKey, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
// position required
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
if (storage.TryCreateAccessor(attributes.NORMAL, out BufferAccessor normal)) b.Add(VertexBuffer.NormalKey, normal);
|
||||
if (storage.TryCreateAccessor(attributes.COLOR_0, out BufferAccessor color)) b.Add(VertexBuffer.ColorKey, color);
|
||||
if (storage.TryCreateAccessor(attributes.TEXCOORD_0, out BufferAccessor tex0)) b.Add(VertexBuffer.TexCoordKey, tex0);
|
||||
if (storage.TryCreateAccessor(attributes.TEXCOORD_1, out BufferAccessor tex1)) b.Add(VertexBuffer.TexCoordKey2, tex1);
|
||||
// if(storage.TryCreateAccessor(attributes.TANGENT, out BufferAccessor tangent))b.Add(VertexBuffer.TangentKey, tangent);
|
||||
if (storage.TryCreateAccessor(attributes.WEIGHTS_0, out BufferAccessor weights)) b.Add(VertexBuffer.WeightKey, weights);
|
||||
if (storage.TryCreateAccessor(attributes.JOINTS_0, out BufferAccessor joints)) b.Add(VertexBuffer.JointKey, joints);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static VertexBuffer FromGltf(this gltfMorphTarget target, Vrm10Storage storage)
|
||||
{
|
||||
var b = new VertexBuffer();
|
||||
storage.CreateBufferAccessorAndAdd(target.POSITION, b, VertexBuffer.PositionKey);
|
||||
storage.CreateBufferAccessorAndAdd(target.NORMAL, b, VertexBuffer.NormalKey);
|
||||
storage.CreateBufferAccessorAndAdd(target.TANGENT, b, VertexBuffer.TangentKey);
|
||||
return b;
|
||||
}
|
||||
|
||||
static bool HasSameVertexBuffer(this glTFPrimitives lhs, glTFPrimitives rhs)
|
||||
{
|
||||
if (lhs.attributes.POSITION != rhs.attributes.POSITION) return false;
|
||||
if (lhs.attributes.NORMAL != rhs.attributes.NORMAL) return false;
|
||||
if (lhs.attributes.TEXCOORD_0 != rhs.attributes.TEXCOORD_0) return false;
|
||||
if (lhs.attributes.TEXCOORD_1 != rhs.attributes.TEXCOORD_1) return false;
|
||||
if (lhs.attributes.COLOR_0 != rhs.attributes.COLOR_0) return false;
|
||||
if (lhs.attributes.WEIGHTS_0 != rhs.attributes.WEIGHTS_0) return false;
|
||||
if (lhs.attributes.JOINTS_0 != rhs.attributes.JOINTS_0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AllPrimitivesHasSameVertexBuffer(this glTFMesh m)
|
||||
{
|
||||
if (m.primitives.Count <= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var first = m.primitives[0];
|
||||
for (int i = 1; i < m.primitives.Count; ++i)
|
||||
{
|
||||
if (!first.HasSameVertexBuffer(m.primitives[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static MeshGroup FromGltf(this glTFMesh x, Vrm10Storage storage)
|
||||
{
|
||||
var group = new MeshGroup(x.name);
|
||||
|
||||
if (x.primitives.Count == 1)
|
||||
{
|
||||
var primitive = x.primitives[0];
|
||||
var mesh = primitive.FromGltf(storage, x);
|
||||
var materialIndex = primitive.material;
|
||||
|
||||
mesh.Submeshes.Add(
|
||||
new Submesh(0, mesh.IndexBuffer.Count, materialIndex));
|
||||
|
||||
group.Meshes.Add(mesh);
|
||||
}
|
||||
else if (!x.AllPrimitivesHasSameVertexBuffer())
|
||||
{
|
||||
int offset = 0;
|
||||
foreach (var primitive in x.primitives)
|
||||
{
|
||||
var mesh = primitive.FromGltf(storage, x);
|
||||
var materialIndex = primitive.material;
|
||||
|
||||
mesh.Submeshes.Add(
|
||||
new Submesh(offset, mesh.IndexBuffer.Count, materialIndex));
|
||||
offset += mesh.IndexBuffer.Count;
|
||||
|
||||
group.Meshes.Add(mesh);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// obsolete
|
||||
//
|
||||
// for VRM
|
||||
|
||||
var mesh = x.SharedBufferFromGltf(storage);
|
||||
int offset = 0;
|
||||
foreach (var primitive in x.primitives)
|
||||
{
|
||||
var materialIndex = primitive.material;
|
||||
var count = storage.Gltf.accessors[primitive.indices].count;
|
||||
mesh.Submeshes.Add(
|
||||
new Submesh(offset, count, materialIndex));
|
||||
offset += count;
|
||||
}
|
||||
|
||||
group.Meshes.Add(mesh);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6cc4e6978a4fdf40999cc13aaa472fe
|
||||
guid: 2f4647a633dfc844eb1b8e7563addba2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
198
Assets/VRM10/Runtime/IO/Model/MeshWriter.cs
Normal file
198
Assets/VRM10/Runtime/IO/Model/MeshWriter.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using UniGLTF;
|
||||
using VrmLib;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
/// <summary>
|
||||
/// VrmLib.MeshGroup => GLTF
|
||||
/// </summary>
|
||||
public static class MeshWriter
|
||||
{
|
||||
static void Vec3MinMax(ArraySegment<byte> bytes, glTFAccessor accessor)
|
||||
{
|
||||
var positions = SpanLike.Wrap<Vector3>(bytes);
|
||||
var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
||||
var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
|
||||
foreach (var p in positions)
|
||||
{
|
||||
min = Vector3.Min(min, p);
|
||||
max = Vector3.Max(max, p);
|
||||
}
|
||||
accessor.min = min.ToFloat3();
|
||||
accessor.max = max.ToFloat3();
|
||||
}
|
||||
|
||||
static int ExportIndices(Vrm10Storage storage, BufferAccessor x, int offset, int count, ExportArgs option)
|
||||
{
|
||||
if (x.Count <= ushort.MaxValue)
|
||||
{
|
||||
if (x.ComponentType == AccessorValueType.UNSIGNED_INT)
|
||||
{
|
||||
// ensure ushort
|
||||
var src = x.GetSpan<UInt32>().Slice(offset, count);
|
||||
var bytes = new byte[src.Length * 2];
|
||||
var dst = SpanLike.Wrap<UInt16>(new ArraySegment<byte>(bytes));
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
dst[i] = (ushort)src[i];
|
||||
}
|
||||
var accessor = new BufferAccessor(new ArraySegment<byte>(bytes), AccessorValueType.UNSIGNED_SHORT, AccessorVectorType.SCALAR, count);
|
||||
return accessor.AddAccessorTo(storage, 0, option.sparse, null, 0, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return x.AddAccessorTo(storage, 0, option.sparse, null, offset, count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return x.AddAccessorTo(storage, 0, option.sparse, null, offset, count);
|
||||
}
|
||||
}
|
||||
|
||||
static void ExportMesh(this VrmLib.Mesh mesh, List<object> materials, Vrm10Storage storage, glTFMesh gltfMesh, ExportArgs option)
|
||||
{
|
||||
//
|
||||
// primitive share vertex buffer
|
||||
//
|
||||
var attributeAccessorIndexMap = mesh.VertexBuffer
|
||||
.ToDictionary(
|
||||
kv => kv.Key,
|
||||
kv => kv.Value.AddAccessorTo(
|
||||
storage, 0, option.sparse,
|
||||
kv.Key == VertexBuffer.PositionKey ? (Action<ArraySegment<byte>, glTFAccessor>)Vec3MinMax : null
|
||||
)
|
||||
);
|
||||
|
||||
List<Dictionary<string, int>> morphTargetAccessorIndexMapList = null;
|
||||
if (mesh.MorphTargets.Any())
|
||||
{
|
||||
morphTargetAccessorIndexMapList = new List<Dictionary<string, int>>();
|
||||
foreach (var morphTarget in mesh.MorphTargets)
|
||||
{
|
||||
var dict = new Dictionary<string, int>();
|
||||
|
||||
foreach (var kv in morphTarget.VertexBuffer)
|
||||
{
|
||||
if (option.removeTangent && kv.Key == VertexBuffer.TangentKey)
|
||||
{
|
||||
// remove tangent
|
||||
continue;
|
||||
}
|
||||
if (option.removeMorphNormal && kv.Key == VertexBuffer.NormalKey)
|
||||
{
|
||||
// normal normal
|
||||
continue;
|
||||
}
|
||||
if (kv.Value.Count != mesh.VertexBuffer.Count)
|
||||
{
|
||||
throw new Exception("inavlid data");
|
||||
}
|
||||
var accessorIndex = kv.Value.AddAccessorTo(storage, 0,
|
||||
option.sparse,
|
||||
kv.Key == VertexBuffer.PositionKey ? (Action<ArraySegment<byte>, glTFAccessor>)Vec3MinMax : null);
|
||||
dict.Add(kv.Key, accessorIndex);
|
||||
}
|
||||
|
||||
morphTargetAccessorIndexMapList.Add(dict);
|
||||
}
|
||||
}
|
||||
|
||||
var drawCountOffset = 0;
|
||||
foreach (var y in mesh.Submeshes)
|
||||
{
|
||||
// index
|
||||
// slide index buffer accessor
|
||||
var indicesAccessorIndex = ExportIndices(storage, mesh.IndexBuffer, drawCountOffset, y.DrawCount, option);
|
||||
drawCountOffset += y.DrawCount;
|
||||
|
||||
var prim = new glTFPrimitives
|
||||
{
|
||||
mode = (int)mesh.Topology,
|
||||
material = y.Material,
|
||||
indices = indicesAccessorIndex,
|
||||
attributes = new glTFAttributes(),
|
||||
};
|
||||
gltfMesh.primitives.Add(prim);
|
||||
|
||||
// attribute
|
||||
foreach (var kv in mesh.VertexBuffer)
|
||||
{
|
||||
var attributeAccessorIndex = attributeAccessorIndexMap[kv.Key];
|
||||
|
||||
switch (kv.Key)
|
||||
{
|
||||
case VertexBuffer.PositionKey: prim.attributes.POSITION = attributeAccessorIndex; break;
|
||||
case VertexBuffer.NormalKey: prim.attributes.NORMAL = attributeAccessorIndex; break;
|
||||
case VertexBuffer.ColorKey: prim.attributes.COLOR_0 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.TexCoordKey: prim.attributes.TEXCOORD_0 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.TexCoordKey2: prim.attributes.TEXCOORD_1 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.JointKey: prim.attributes.JOINTS_0 = attributeAccessorIndex; break;
|
||||
case VertexBuffer.WeightKey: prim.attributes.WEIGHTS_0 = attributeAccessorIndex; break;
|
||||
}
|
||||
}
|
||||
|
||||
// morph target
|
||||
if (mesh.MorphTargets.Any())
|
||||
{
|
||||
foreach (var (t, accessorIndexMap) in
|
||||
Enumerable.Zip(mesh.MorphTargets, morphTargetAccessorIndexMapList, (t, v) => (t, v)))
|
||||
{
|
||||
var target = new gltfMorphTarget();
|
||||
prim.targets.Add(target);
|
||||
|
||||
foreach (var kv in t.VertexBuffer)
|
||||
{
|
||||
if (!accessorIndexMap.TryGetValue(kv.Key, out int targetAccessorIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (kv.Key)
|
||||
{
|
||||
case VertexBuffer.PositionKey:
|
||||
target.POSITION = targetAccessorIndex;
|
||||
break;
|
||||
case VertexBuffer.NormalKey:
|
||||
target.NORMAL = targetAccessorIndex;
|
||||
break;
|
||||
case VertexBuffer.TangentKey:
|
||||
target.TANGENT = targetAccessorIndex;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// target name
|
||||
if (mesh.MorphTargets.Any())
|
||||
{
|
||||
gltf_mesh_extras_targetNames.Serialize(gltfMesh, mesh.MorphTargets.Select(z => z.Name));
|
||||
}
|
||||
}
|
||||
|
||||
public static glTFMesh ExportMeshGroup(this MeshGroup src, List<object> materials, Vrm10Storage storage, ExportArgs option)
|
||||
{
|
||||
var mesh = new glTFMesh
|
||||
{
|
||||
name = src.Name
|
||||
};
|
||||
|
||||
foreach (var x in src.Meshes)
|
||||
{
|
||||
// MeshとSubmeshがGltfのPrimitiveに相当する?
|
||||
x.ExportMesh(materials, storage, mesh, option);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d80d88b180871234ea03afcc24e118da
|
||||
guid: f71759cba771a95449d96df3fa37b115
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -8,7 +8,10 @@ using VrmLib;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public class RuntimeVrmConverter
|
||||
/// <summary>
|
||||
/// UnityEngine.GameObject hierarchy => GLTF.Nodes, GLTF.Meshes, GLTF.Skins
|
||||
/// </summary>
|
||||
public class ModelExporter
|
||||
{
|
||||
public VrmLib.Model Model;
|
||||
|
||||
@@ -16,15 +19,16 @@ namespace UniVRM10
|
||||
public List<UnityEngine.Material> Materials = new List<UnityEngine.Material>();
|
||||
public Dictionary<UnityEngine.Mesh, VrmLib.MeshGroup> Meshes = new Dictionary<UnityEngine.Mesh, VrmLib.MeshGroup>();
|
||||
|
||||
#region Export 1.0
|
||||
/// <summary>
|
||||
/// metaObject が null のときは、root から取得する
|
||||
/// GameObject to VrmLib.Model
|
||||
/// </summary>
|
||||
/// <param name="root"></param>
|
||||
/// <returns></returns>
|
||||
public VrmLib.Model ToModelFrom10(GameObject root)
|
||||
{
|
||||
Model = new VrmLib.Model(VrmLib.Coordinates.Unity);
|
||||
|
||||
ToGlbModel(root);
|
||||
Export(root);
|
||||
|
||||
// humanoid
|
||||
{
|
||||
@@ -48,7 +52,7 @@ namespace UniVRM10
|
||||
return Model;
|
||||
}
|
||||
|
||||
public VrmLib.Model ToGlbModel(GameObject root)
|
||||
VrmLib.Model Export(GameObject root)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
@@ -123,9 +127,6 @@ namespace UniVRM10
|
||||
|
||||
return Model;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
private static void CreateNodes(
|
||||
Transform parentTransform,
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 936824d3022642f40a65a003e0ee3b83
|
||||
guid: 096d30ddf9b2aee4f96746f05610d75f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using VrmLib;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class ModelLoader
|
||||
/// <summary>
|
||||
/// GLTF => VrmLib.Model
|
||||
/// </summary>
|
||||
public static class ModelReader
|
||||
{
|
||||
public static Model Load(Vrm10Storage storage, string rootName)
|
||||
static Model Load(Vrm10Storage storage, string rootName)
|
||||
{
|
||||
if (storage == null)
|
||||
{
|
||||
@@ -70,5 +73,13 @@ namespace UniVRM10
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
public static Model Read(UniGLTF.GltfParser parser)
|
||||
{
|
||||
var storage = new Vrm10Storage(parser);
|
||||
var model = Load(storage, Path.GetFileName(parser.TargetPath));
|
||||
model.ConvertCoordinate(Coordinates.Unity);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRM10/Runtime/IO/Model/ModelReader.cs.meta
Normal file
11
Assets/VRM10/Runtime/IO/Model/ModelReader.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb219f8797f990649a7531dbb96d3305
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42576b7471f4a4e4fb25c1815a92f44b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 962f584a4519d62419f01b8151f99169
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b619b24f8ac1494290458193ebca6aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -128,7 +128,7 @@ namespace UniVRM10
|
||||
return new float[] { -v.x, v.y, v.z };
|
||||
}
|
||||
|
||||
public void Export(GameObject root, Model model, RuntimeVrmConverter converter, ExportArgs option, Func<Texture2D, (byte[], string)> getTextureBytes, VRM10MetaObject metaObject = null)
|
||||
public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, Func<Texture2D, (byte[], string)> getTextureBytes, VRM10MetaObject metaObject = null)
|
||||
{
|
||||
ExportAsset(model);
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace UniVRM10
|
||||
/// <returns></returns>
|
||||
(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm,
|
||||
UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone,
|
||||
int? thumbnailIndex) ExportVrm(GameObject root, Model model, RuntimeVrmConverter converter, VRM10MetaObject meta)
|
||||
int? thumbnailIndex) ExportVrm(GameObject root, Model model, ModelExporter converter, VRM10MetaObject meta)
|
||||
{
|
||||
var vrmController = root?.GetComponent<VRM10Controller>();
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace UniVRM10
|
||||
return joint;
|
||||
}
|
||||
|
||||
UniGLTF.Extensions.VRMC_springBone.VRMC_springBone ExportSpringBone(VRM10Controller vrmController, Model model, RuntimeVrmConverter converter)
|
||||
UniGLTF.Extensions.VRMC_springBone.VRMC_springBone ExportSpringBone(VRM10Controller vrmController, Model model, ModelExporter converter)
|
||||
{
|
||||
var springBone = new UniGLTF.Extensions.VRMC_springBone.VRMC_springBone
|
||||
{
|
||||
@@ -353,7 +353,7 @@ namespace UniVRM10
|
||||
return springBone;
|
||||
}
|
||||
|
||||
void ExportConstraints(VRM10Controller vrmController, Model model, RuntimeVrmConverter converter)
|
||||
void ExportConstraints(VRM10Controller vrmController, Model model, ModelExporter converter)
|
||||
{
|
||||
var constraints = vrmController.GetComponentsInChildren<VRM10Constraint>();
|
||||
foreach (var constraint in constraints)
|
||||
@@ -395,7 +395,7 @@ namespace UniVRM10
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportPostionConstraint(VRM10PositionConstraint c, Model model, RuntimeVrmConverter converter)
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportPostionConstraint(VRM10PositionConstraint c, Model model, ModelExporter converter)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
|
||||
{
|
||||
@@ -413,7 +413,7 @@ namespace UniVRM10
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportRotationConstraint(VRM10RotationConstraint c, Model model, RuntimeVrmConverter converter)
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportRotationConstraint(VRM10RotationConstraint c, Model model, ModelExporter converter)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
|
||||
{
|
||||
@@ -431,7 +431,7 @@ namespace UniVRM10
|
||||
};
|
||||
}
|
||||
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportAimConstraint(VRM10AimConstraint c, Model model, RuntimeVrmConverter converter)
|
||||
static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportAimConstraint(VRM10AimConstraint c, Model model, ModelExporter converter)
|
||||
{
|
||||
return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint
|
||||
{
|
||||
@@ -457,7 +457,7 @@ namespace UniVRM10
|
||||
};
|
||||
}
|
||||
|
||||
void ExportFirstPerson(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10Controller vrmController, Model model, RuntimeVrmConverter converter)
|
||||
void ExportFirstPerson(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10Controller vrmController, Model model, ModelExporter converter)
|
||||
{
|
||||
if (vrmController?.FirstPerson == null)
|
||||
{
|
||||
@@ -540,7 +540,7 @@ namespace UniVRM10
|
||||
};
|
||||
}
|
||||
|
||||
void ExportExpression(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10Controller vrmController, Model model, RuntimeVrmConverter converter)
|
||||
void ExportExpression(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10Controller vrmController, Model model, ModelExporter converter)
|
||||
{
|
||||
if (vrmController?.Expression?.ExpressionAvatar?.Clips == null)
|
||||
{
|
||||
@@ -779,7 +779,7 @@ namespace UniVRM10
|
||||
}
|
||||
|
||||
// ヒエラルキーからジオメトリーを収集
|
||||
var converter = new UniVRM10.RuntimeVrmConverter();
|
||||
var converter = new UniVRM10.ModelExporter();
|
||||
var model = converter.ToModelFrom10(go);
|
||||
|
||||
// 右手系に変換
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UniGLTF;
|
||||
@@ -12,7 +13,7 @@ namespace UniVRM10
|
||||
/// <summary>
|
||||
/// VrmLib.Model から UnityPrefab を構築する
|
||||
/// </summary>
|
||||
public class RuntimeUnityBuilder : UniGLTF.ImporterContext
|
||||
public class Vrm10Importer : UniGLTF.ImporterContext
|
||||
{
|
||||
readonly Model m_model;
|
||||
|
||||
@@ -20,11 +21,15 @@ namespace UniVRM10
|
||||
|
||||
IDictionary<SubAssetKey, UnityEngine.Object> m_externalMap;
|
||||
|
||||
public RuntimeUnityBuilder(UniGLTF.GltfParser parser, IDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null)
|
||||
: base(parser, externalObjectMap.Select(kv => (kv.Key.Name, kv.Value)))
|
||||
public Vrm10Importer(UniGLTF.GltfParser parser, IDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null)
|
||||
: base(parser, externalObjectMap?.Select(kv => (kv.Key.Name, kv.Value)))
|
||||
{
|
||||
m_externalMap = externalObjectMap;
|
||||
m_model = VrmLoader.CreateVrmModel(parser);
|
||||
if (m_externalMap == null)
|
||||
{
|
||||
m_externalMap = new Dictionary<SubAssetKey, UnityEngine.Object>();
|
||||
}
|
||||
m_model = ModelReader.Read(parser);
|
||||
|
||||
// for `VRMC_materials_mtoon`
|
||||
this.GltfMaterialImporter.GltfMaterialParamProcessors.Insert(0, Vrm10MaterialImporter.TryCreateParam);
|
||||
@@ -140,7 +145,7 @@ namespace UniVRM10
|
||||
// submesh 方式
|
||||
var mesh = new UnityEngine.Mesh();
|
||||
mesh.name = src.Name;
|
||||
mesh.LoadMesh(src.Meshes[0], src.Skin);
|
||||
MeshImporter.LoadSharedMesh(mesh, src.Meshes[0], src.Skin);
|
||||
m_map.Meshes.Add(src, mesh);
|
||||
Meshes.Add(new MeshWithMaterials
|
||||
{
|
||||
11
Assets/VRM10/Runtime/IO/Vrm10Importer.cs.meta
Normal file
11
Assets/VRM10/Runtime/IO/Vrm10Importer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae61d167cf541b44c8645b3c864390f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,20 +0,0 @@
|
||||
using System.IO;
|
||||
using VrmLib;
|
||||
using UniGLTF;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
/// <summary>
|
||||
/// utility for load VrmLib Model from byte[]
|
||||
/// </summary>
|
||||
public static class VrmLoader
|
||||
{
|
||||
public static Model CreateVrmModel(GltfParser parser)
|
||||
{
|
||||
var storage = new Vrm10Storage(parser);
|
||||
var model = ModelLoader.Load(storage, Path.GetFileName(parser.TargetPath));
|
||||
model.ConvertCoordinate(Coordinates.Unity);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef069ccddc286cc4e930ba33447b0094
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -16,7 +16,7 @@ public class Sample : MonoBehaviour
|
||||
var parser = new GltfParser();
|
||||
parser.Parse(path.FullName, bytes);
|
||||
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
using (var loader = new Vrm10Importer(parser))
|
||||
{
|
||||
loader.Load();
|
||||
loader.ShowMeshes();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace UniVRM10.Test
|
||||
private (GameObject, IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo>) ToUnity(GltfParser parser)
|
||||
{
|
||||
// Model => Unity
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
using (var loader = new Vrm10Importer(parser))
|
||||
{
|
||||
loader.Load();
|
||||
loader.DisposeOnGameObjectDestroyed();
|
||||
@@ -49,7 +49,7 @@ namespace UniVRM10.Test
|
||||
|
||||
private Model ToVrmModel(GameObject root)
|
||||
{
|
||||
var exporter = new UniVRM10.RuntimeVrmConverter();
|
||||
var exporter = new UniVRM10.ModelExporter();
|
||||
var model = exporter.ToModelFrom10(root);
|
||||
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using VRMShaders;
|
||||
|
||||
namespace UniVRM10.Test
|
||||
@@ -17,13 +15,13 @@ namespace UniVRM10.Test
|
||||
var parser = new GltfParser();
|
||||
parser.Parse("migrated", bytes);
|
||||
|
||||
var model = UniVRM10.VrmLoader.CreateVrmModel(parser);
|
||||
var model = ModelReader.Read(parser);
|
||||
return model;
|
||||
}
|
||||
|
||||
GameObject BuildGameObject(GltfParser parser, bool showMesh)
|
||||
{
|
||||
using (var loader = new RuntimeUnityBuilder(parser))
|
||||
using (var loader = new Vrm10Importer(parser))
|
||||
{
|
||||
loader.Load();
|
||||
if (showMesh)
|
||||
|
||||
Reference in New Issue
Block a user