Merge pull request #1280 from ousttrue/fix10/migrate_not_normalized

[1.0] ヒエラルキーに回転・スケールが含まれているモデルのマイグレーション
This commit is contained in:
ousttrue
2021-10-11 14:37:22 +09:00
committed by GitHub
13 changed files with 304 additions and 131 deletions

View File

@@ -65,7 +65,7 @@ namespace UniGLTF
{ typeof(Color), new ComponentVec(glComponentType.FLOAT, 4) },
};
static glComponentType GetComponentType<T>()
public static glComponentType GetComponentType<T>()
{
var cv = default(ComponentVec);
if (ComponentTypeMap.TryGetValue(typeof(T), out cv))
@@ -86,7 +86,7 @@ namespace UniGLTF
}
}
static string GetAccessorType<T>()
public static string GetAccessorType<T>()
{
var cv = default(ComponentVec);
if (ComponentTypeMap.TryGetValue(typeof(T), out cv))

View File

@@ -4,7 +4,7 @@ namespace UniGLTF
{
public interface IStorage
{
ArraySegment<Byte> Get(string url);
ArraySegment<Byte> Get(string url = default);
/// <summary>
/// Get original filepath if exists

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
@@ -24,7 +25,7 @@ namespace UniGLTF
m_bytes = bytes;
}
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target) where T : struct
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target = default) where T : struct
{
using (var pin = Pin.Create(array))
{

View File

@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UniGLTF
{
@@ -16,20 +12,32 @@ namespace UniGLTF
public string TargetPath { get; }
/// <summary>
/// JSON source
/// Chunk Data.
/// Maybe empty if source file was not glb format.
/// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#chunks
/// [0] must JSON
/// [1] must BIN
/// [2...] may exists.
/// </summary>
public IReadOnlyList<GlbChunk> Chunks { get; }
/// <summary>
/// JSON chunk ToString
/// > This chunk MUST be the very first chunk of Binary glTF asset
/// </summary>
public string Json { get; }
/// <summary>
/// GLTF parsed from JSON
/// GLTF parsed from JSON chunk
/// </summary>
public glTF GLTF { get; }
/// <summary>
/// Chunk Data.
/// Maybe empty if source file was not glb format.
/// BIN chunk
/// > This chunk MUST be the second chunk of the Binary glTF asset
/// </summary>
public IReadOnlyList<GlbChunk> Chunks { get; }
/// <returns></returns>
public ArraySegment<byte> Bin => Chunks[1].Bytes;
/// <summary>
/// URI access

View File

@@ -6,7 +6,7 @@ namespace UniGLTF
{
private readonly byte[] _data;
private readonly string _name;
public GlbBinaryParser(byte[] data, string uniqueName)
{
_data = data;

View File

@@ -9,19 +9,20 @@ namespace UniVRM10
/// </summary>
public static class ModelReader
{
static Model Load(Vrm10Storage storage, string rootName)
static Model Load(Vrm10Storage storage, string rootName, Coordinates coords)
{
if (storage == null)
{
return null;
}
var model = new Model(Coordinates.Vrm1)
var model = new Model(coords)
{
AssetVersion = storage.AssetVersion,
AssetGenerator = storage.AssetGenerator,
AssetCopyright = storage.AssetCopyright,
AssetMinVersion = storage.AssetMinVersion,
Coordinates = coords,
};
// node
@@ -74,10 +75,10 @@ namespace UniVRM10
return model;
}
public static Model Read(UniGLTF.GltfData data)
public static Model Read(UniGLTF.GltfData data, Coordinates? coords = default)
{
var storage = new Vrm10Storage(data);
var model = Load(storage, Path.GetFileName(data.TargetPath));
var model = Load(storage, Path.GetFileName(data.TargetPath), coords.GetValueOrDefault(Coordinates.Vrm1));
model.ConvertCoordinate(Coordinates.Unity);
return model;
}

View File

@@ -68,8 +68,6 @@ namespace UniVRM10
try
{
var json = data.Json.ParseAsJson();
var bin = data.Chunks.First(x => x.ChunkType == GlbChunkType.BIN);
try
{
if (!json.TryGet("extensions", out JsonNode extensions))
@@ -95,7 +93,7 @@ namespace UniVRM10
return false;
}
migrated = MigrationVrm.Migrate(json, bin.Bytes);
migrated = MigrationVrm.Migrate(data);
if (migrated == null)
{
result = new Vrm10Data(default, default, Vrm10FileType.Vrm0, "vrm0: cannot migrate");

View File

@@ -49,54 +49,45 @@ namespace UniVRM10
m_textureExporter.Dispose();
}
public void ExportAsset(Model model)
public static glTFAssets ExportAsset(Model model)
{
Storage.Gltf.asset = new glTFAssets
{
};
if (!string.IsNullOrEmpty(model.AssetVersion)) Storage.Gltf.asset.version = model.AssetVersion;
if (!string.IsNullOrEmpty(model.AssetMinVersion)) Storage.Gltf.asset.minVersion = model.AssetMinVersion;
if (!string.IsNullOrEmpty(model.AssetGenerator)) Storage.Gltf.asset.generator = model.AssetGenerator;
if (!string.IsNullOrEmpty(model.AssetCopyright)) Storage.Gltf.asset.copyright = model.AssetCopyright;
var asset = new glTFAssets();
if (!string.IsNullOrEmpty(model.AssetVersion)) asset.version = model.AssetVersion;
if (!string.IsNullOrEmpty(model.AssetMinVersion)) asset.minVersion = model.AssetMinVersion;
if (!string.IsNullOrEmpty(model.AssetGenerator)) asset.generator = model.AssetGenerator;
if (!string.IsNullOrEmpty(model.AssetCopyright)) asset.copyright = model.AssetCopyright;
return asset;
}
public void Reserve(int bytesLength)
{
Storage.Reserve(bytesLength);
}
public void ExportMeshes(List<MeshGroup> groups, List<object> materials, ExportArgs option)
public static IEnumerable<glTFMesh> ExportMeshes(List<MeshGroup> groups, List<object> materials, Vrm10Storage storage, ExportArgs option)
{
foreach (var group in groups)
{
var mesh = group.ExportMeshGroup(materials, Storage, option);
Storage.Gltf.meshes.Add(mesh);
yield return group.ExportMeshGroup(materials, storage, option);
}
}
public void ExportNodes(Node root, List<Node> nodes, List<MeshGroup> groups, ExportArgs option)
public static IEnumerable<(glTFNode, glTFSkin)> ExportNodes(List<Node> nodes, List<MeshGroup> groups, Vrm10Storage storage, ExportArgs option)
{
foreach (var x in nodes)
foreach (var node in nodes)
{
var node = new glTFNode
var gltfNode = new glTFNode
{
name = x.Name,
name = node.Name,
};
glTFSkin gltfSkin = default;
node.translation = x.LocalTranslation.ToFloat3();
node.rotation = x.LocalRotation.ToFloat4();
node.scale = x.LocalScaling.ToFloat3();
gltfNode.translation = node.LocalTranslation.ToFloat3();
gltfNode.rotation = node.LocalRotation.ToFloat4();
gltfNode.scale = node.LocalScaling.ToFloat3();
if (x.MeshGroup != null)
if (node.MeshGroup != null)
{
node.mesh = groups.IndexOfThrow(x.MeshGroup);
var skin = x.MeshGroup.Skin;
gltfNode.mesh = groups.IndexOfThrow(node.MeshGroup);
var skin = node.MeshGroup.Skin;
if (skin != null)
{
var skinIndex = Storage.Gltf.skins.Count;
var gltfSkin = new glTFSkin()
gltfSkin = new glTFSkin()
{
joints = skin.Joints.Select(joint => nodes.IndexOfThrow(joint)).ToArray()
};
@@ -106,26 +97,19 @@ namespace UniVRM10
}
if (skin.InverseMatrices != null)
{
gltfSkin.inverseBindMatrices = skin.InverseMatrices.AddAccessorTo(Storage, 0, option.sparse);
gltfSkin.inverseBindMatrices = skin.InverseMatrices.AddAccessorTo(storage, 0, option.sparse);
}
if (skin.Root != null)
{
gltfSkin.skeleton = nodes.IndexOf(skin.Root);
}
Storage.Gltf.skins.Add(gltfSkin);
node.skin = skinIndex;
}
}
node.children = x.Children.Select(child => nodes.IndexOfThrow(child)).ToArray();
gltfNode.children = node.Children.Select(child => nodes.IndexOfThrow(child)).ToArray();
Storage.Gltf.nodes.Add(node);
yield return (gltfNode, gltfSkin);
}
Storage.Gltf.scenes.Add(new gltfScene()
{
nodes = root.Children.Select(child => nodes.IndexOfThrow(child)).ToArray()
});
}
/// <summary>
@@ -138,55 +122,77 @@ namespace UniVRM10
return new float[] { -v.x, v.y, v.z };
}
public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, VRM10ObjectMeta vrmMeta = null)
///
/// 必要な容量を計算
/// (sparseは考慮してないので大きめ)
static int CalcReserveBytes(Model model)
{
ExportAsset(model);
///
/// 必要な容量を先に確保
/// (sparseは考慮してないので大きめ)
///
int reserveBytes = 0;
// mesh
foreach (var g in model.MeshGroups)
{
var reserveBytes = 0;
// mesh
foreach (var g in model.MeshGroups)
foreach (var mesh in g.Meshes)
{
foreach (var mesh in g.Meshes)
// 頂点バッファ
reserveBytes += mesh.IndexBuffer.ByteLength;
foreach (var kv in mesh.VertexBuffer)
{
// 頂点バッファ
reserveBytes += mesh.IndexBuffer.ByteLength;
foreach (var kv in mesh.VertexBuffer)
reserveBytes += kv.Value.ByteLength;
}
// morph
foreach (var morph in mesh.MorphTargets)
{
foreach (var kv in morph.VertexBuffer)
{
reserveBytes += kv.Value.ByteLength;
}
// morph
foreach (var morph in mesh.MorphTargets)
{
foreach (var kv in morph.VertexBuffer)
{
reserveBytes += kv.Value.ByteLength;
}
}
}
}
Reserve(reserveBytes);
}
return reserveBytes;
}
// material
static IEnumerable<glTFMaterial> ExportMaterials(Model model, ITextureExporter textureExporter, GltfExportSettings settings)
{
var materialExporter = new Vrm10MaterialExporter();
foreach (Material material in model.Materials)
{
var glTFMaterial = materialExporter.ExportMaterial(material, m_textureExporter, m_settings);
Storage.Gltf.materials.Add(glTFMaterial);
yield return materialExporter.ExportMaterial(material, textureExporter, settings);
}
}
public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, VRM10ObjectMeta vrmMeta = null)
{
Storage.Gltf.asset = ExportAsset(model);
Storage.Reserve(CalcReserveBytes(model));
foreach (var material in ExportMaterials(model, m_textureExporter, m_settings))
{
Storage.Gltf.materials.Add(material);
}
// mesh
ExportMeshes(model.MeshGroups, model.Materials, option);
foreach (var mesh in ExportMeshes(model.MeshGroups, model.Materials, Storage, option))
{
Storage.Gltf.meshes.Add(mesh);
}
// node
ExportNodes(model.Root, model.Nodes, model.MeshGroups, option);
foreach (var (node, skin) in ExportNodes(model.Nodes, model.MeshGroups, Storage, option))
{
Storage.Gltf.nodes.Add(node);
if (skin != null)
{
var skinIndex = Storage.Gltf.skins.Count;
Storage.Gltf.skins.Add(skin);
node.skin = skinIndex;
}
}
Storage.Gltf.scenes.Add(new gltfScene()
{
nodes = model.Root.Children.Select(child => model.Nodes.IndexOfThrow(child)).ToArray()
});
var (vrm, vrmSpringBone, thumbnailTextureIndex) = ExportVrm(root, model, converter, vrmMeta);
var (vrm, vrmSpringBone, thumbnailTextureIndex) = ExportVrm(root, model, converter, vrmMeta, Storage.Gltf.nodes, m_textureExporter);
// Extension で Texture が増える場合があるので最後に呼ぶ
var exportedTextures = m_textureExporter.Export();
@@ -225,7 +231,8 @@ 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, ModelExporter converter, VRM10ObjectMeta vrmMeta)
int? thumbnailIndex) ExportVrm(GameObject root, Model model, ModelExporter converter,
VRM10ObjectMeta vrmMeta, List<glTFNode> nodes, ITextureExporter textureExporter)
{
var vrmController = root?.GetComponent<Vrm10Instance>();
@@ -259,7 +266,7 @@ namespace UniVRM10
// required
//
ExportHumanoid(vrm, model);
var thumbnailTextureIndex = ExportMeta(vrm, vrmMeta);
var thumbnailTextureIndex = ExportMeta(vrm, vrmMeta, textureExporter);
//
// optional
@@ -272,13 +279,13 @@ namespace UniVRM10
ExportFirstPerson(vrm, vrmController, model, converter);
vrmSpringBone = ExportSpringBone(vrmController, model, converter);
ExportConstraints(vrmController, model, converter);
ExportConstraints(vrmController, model, converter, nodes);
}
return (vrm, vrmSpringBone, thumbnailTextureIndex);
}
UniGLTF.Extensions.VRMC_springBone.ColliderShape ExportShape(VRM10SpringBoneCollider z)
static UniGLTF.Extensions.VRMC_springBone.ColliderShape ExportShape(VRM10SpringBoneCollider z)
{
var shape = new UniGLTF.Extensions.VRMC_springBone.ColliderShape();
switch (z.ColliderType)
@@ -307,7 +314,7 @@ namespace UniVRM10
return shape;
}
UniGLTF.Extensions.VRMC_springBone.SpringBoneJoint ExportJoint(VRM10SpringBoneJoint y, Func<Transform, int> getIndexFromTransform)
static UniGLTF.Extensions.VRMC_springBone.SpringBoneJoint ExportJoint(VRM10SpringBoneJoint y, Func<Transform, int> getIndexFromTransform)
{
var joint = new UniGLTF.Extensions.VRMC_springBone.SpringBoneJoint
{
@@ -321,7 +328,7 @@ namespace UniVRM10
return joint;
}
UniGLTF.Extensions.VRMC_springBone.VRMC_springBone ExportSpringBone(Vrm10Instance controller, Model model, ModelExporter converter)
static UniGLTF.Extensions.VRMC_springBone.VRMC_springBone ExportSpringBone(Vrm10Instance controller, Model model, ModelExporter converter)
{
var springBone = new UniGLTF.Extensions.VRMC_springBone.VRMC_springBone
{
@@ -371,7 +378,7 @@ namespace UniVRM10
return springBone;
}
void ExportConstraints(Vrm10Instance vrmController, Model model, ModelExporter converter)
static void ExportConstraints(Vrm10Instance vrmController, Model model, ModelExporter converter, List<glTFNode> nodes)
{
var constraints = vrmController.GetComponentsInChildren<VRM10Constraint>();
foreach (var constraint in constraints)
@@ -398,7 +405,7 @@ namespace UniVRM10
// serialize to gltfNode
var node = converter.Nodes[constraint.gameObject];
var nodeIndex = model.Nodes.IndexOf(node);
var gltfNode = Storage.Gltf.nodes[nodeIndex];
var gltfNode = nodes[nodeIndex];
UniGLTF.Extensions.VRMC_node_constraint.GltfSerializer.SerializeTo(ref gltfNode.extensions, vrmConstraint);
}
}
@@ -497,7 +504,7 @@ namespace UniVRM10
}
}
UniGLTF.Extensions.VRMC_vrm.LookAtRangeMap ExportLookAtRangeMap(CurveMapper mapper)
static UniGLTF.Extensions.VRMC_vrm.LookAtRangeMap ExportLookAtRangeMap(CurveMapper mapper)
{
return new UniGLTF.Extensions.VRMC_vrm.LookAtRangeMap
{
@@ -506,7 +513,7 @@ namespace UniVRM10
};
}
void ExportLookAt(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, Vrm10Instance vrmController)
static void ExportLookAt(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, Vrm10Instance vrmController)
{
if (!(vrmController?.Vrm?.LookAt is VRM10ObjectLookAt lookAt))
{
@@ -528,7 +535,7 @@ namespace UniVRM10
};
}
UniGLTF.Extensions.VRMC_vrm.MorphTargetBind ExportMorphTargetBinding(MorphTargetBinding binding, Func<string, int> getIndex)
static UniGLTF.Extensions.VRMC_vrm.MorphTargetBind ExportMorphTargetBinding(MorphTargetBinding binding, Func<string, int> getIndex)
{
return new UniGLTF.Extensions.VRMC_vrm.MorphTargetBind
{
@@ -538,7 +545,7 @@ namespace UniVRM10
};
}
UniGLTF.Extensions.VRMC_vrm.MaterialColorBind ExportMaterialColorBinding(MaterialColorBinding binding, Func<string, int> getIndex)
static UniGLTF.Extensions.VRMC_vrm.MaterialColorBind ExportMaterialColorBinding(MaterialColorBinding binding, Func<string, int> getIndex)
{
return new UniGLTF.Extensions.VRMC_vrm.MaterialColorBind
{
@@ -548,7 +555,7 @@ namespace UniVRM10
};
}
UniGLTF.Extensions.VRMC_vrm.TextureTransformBind ExportTextureTransformBinding(MaterialUVBinding binding, Func<string, int> getIndex)
static UniGLTF.Extensions.VRMC_vrm.TextureTransformBind ExportTextureTransformBinding(MaterialUVBinding binding, Func<string, int> getIndex)
{
var (scale, offset) = TextureTransform.VerticalFlipScaleOffset(binding.Scaling, binding.Offset);
return new UniGLTF.Extensions.VRMC_vrm.TextureTransformBind
@@ -559,7 +566,7 @@ namespace UniVRM10
};
}
UniGLTF.Extensions.VRMC_vrm.Expression ExportExpression(VRM10Expression e, Vrm10Instance vrmController, Model model, ModelExporter converter)
static UniGLTF.Extensions.VRMC_vrm.Expression ExportExpression(VRM10Expression e, Vrm10Instance vrmController, Model model, ModelExporter converter)
{
if (e == null)
{
@@ -634,7 +641,7 @@ namespace UniVRM10
return vrmExpression;
}
void ExportExpression(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, Vrm10Instance vrmController, Model model, ModelExporter converter)
static void ExportExpression(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, Vrm10Instance vrmController, Model model, ModelExporter converter)
{
if (vrmController?.Vrm?.Expression?.Clips == null)
{
@@ -667,7 +674,7 @@ namespace UniVRM10
};
}
int? ExportMeta(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10ObjectMeta meta)
static int? ExportMeta(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10ObjectMeta meta, ITextureExporter textureExporter)
{
vrm.Meta.Name = meta.Name;
vrm.Meta.Version = meta.Version;
@@ -689,12 +696,12 @@ namespace UniVRM10
int? thumbnailTextureIndex = default;
if (meta.Thumbnail != null)
{
thumbnailTextureIndex = m_textureExporter.RegisterExportingAsSRgb(meta.Thumbnail, needsAlpha: true);
thumbnailTextureIndex = textureExporter.RegisterExportingAsSRgb(meta.Thumbnail, needsAlpha: true);
}
return thumbnailTextureIndex;
}
void ExportHumanoid(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, Model model)
static void ExportHumanoid(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, Model model)
{
// humanoid
for (int i = 0; i < model.Nodes.Count; ++i)

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UnityEngine;
namespace UniVRM10
{
/// <summary>
/// 座標系を変換した Model により、Mesh, Node, BindMatrices を更新する。
/// buffer, bufferAccessor の更新もある。
/// </summary>
class MeshUpdater
{
GltfData _data;
ArrayByteBuffer _buffer;
List<glTFBufferView> _bufferViews = new List<glTFBufferView>();
List<glTFAccessor> _accessors = new List<glTFAccessor>();
public MeshUpdater(GltfData data)
{
_data = data;
_buffer = new ArrayByteBuffer(new byte[data.Bin.Count]);
}
int AddBuffer(ArraySegment<byte> bytes)
{
var bufferView = _buffer.Extend(bytes);
var index = _bufferViews.Count;
_bufferViews.Add(bufferView);
return index;
}
int AddAccessor<T>(SpanLike<T> span) where T : struct
{
var bufferViewIndex = AddBuffer(span.Bytes);
var accessor = new glTFAccessor
{
bufferView = bufferViewIndex,
count = span.Length,
byteOffset = 0,
componentType = glTFExtensions.GetComponentType<T>(),
type = glTFExtensions.GetAccessorType<T>(),
};
var index = _accessors.Count;
_accessors.Add(accessor);
return index;
}
int? AddAccessor<T>(VrmLib.BufferAccessor buffer) where T : struct
{
if (buffer == null)
{
return default;
}
return AddAccessor(buffer.GetSpan<T>());
}
struct MorphAccessor
{
public int? Position;
public int? Normal;
};
public (glTF, ArraySegment<byte>) Update(VrmLib.Model model)
{
var gltf = _data.GLTF;
// copy images
foreach (var image in gltf.images)
{
var bytes = gltf.GetViewBytes(image.bufferView);
image.bufferView = AddBuffer(bytes);
}
// update Mesh
foreach (var (gltfMesh, mesh) in Enumerable.Zip(gltf.meshes, model.MeshGroups, (l, r) => (l, r.Meshes[0])))
{
var indices = mesh.IndexBuffer.GetSpan<uint>();
var position = AddAccessor<Vector3>(mesh.VertexBuffer.Positions);
var normal = AddAccessor<Vector3>(mesh.VertexBuffer.Normals);
var uv = AddAccessor<Vector2>(mesh.VertexBuffer.TexCoords);
var weights = AddAccessor<Vector4>(mesh.VertexBuffer.Weights);
var joints = AddAccessor<UShort4>(mesh.VertexBuffer.Joints);
var morphTargets = new MorphAccessor[] { };
if (mesh.MorphTargets != null)
{
morphTargets = mesh.MorphTargets.Select(x => new MorphAccessor
{
Position = AddAccessor<Vector3>(x.VertexBuffer.Positions),
Normal = AddAccessor<Vector3>(x.VertexBuffer.Normals),
}).ToArray();
}
foreach (var (gltfPrim, submesh) in Enumerable.Zip(gltfMesh.primitives, mesh.Submeshes, (l, r) => (l, r)))
{
var subIndices = indices.Slice(submesh.Offset, submesh.DrawCount);
gltfPrim.indices = AddAccessor(subIndices);
gltfPrim.attributes.POSITION = position.Value;
gltfPrim.attributes.NORMAL = normal.Value;
gltfPrim.attributes.TEXCOORD_0 = uv.Value;
gltfPrim.attributes.WEIGHTS_0 = weights.GetValueOrDefault(-1);
gltfPrim.attributes.JOINTS_0 = joints.GetValueOrDefault(-1);
foreach (var (gltfMorph, morph) in Enumerable.Zip(gltfPrim.targets, morphTargets, (l, r) => (l, r)))
{
gltfMorph.POSITION = morph.Position.GetValueOrDefault(-1);
gltfMorph.NORMAL = morph.Normal.GetValueOrDefault(-1);
}
}
}
// update nodes
foreach (var (gltfNode, node) in Enumerable.Zip(gltf.nodes, model.Nodes, (l, r) => (l, r)))
{
gltfNode.translation = node.LocalTranslation.ToFloat3();
gltfNode.rotation = node.LocalRotation.ToFloat4();
gltfNode.scale = node.LocalScaling.ToFloat3();
if (gltfNode.skin >= 0)
{
var gltfSkin = gltf.skins[gltfNode.skin];
gltfSkin.inverseBindMatrices = AddAccessor(node.MeshGroup.Skin.InverseMatrices.GetSpan<Matrix4x4>());
}
}
// replace
gltf.bufferViews = _bufferViews;
gltf.accessors = _accessors;
return (gltf, _buffer.Bytes);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c49ea19813d8f214dbe789fd79f78b28
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -268,13 +268,13 @@ namespace UniVRM10
}
}
public static void Migrate(glTF gltf, JsonNode json)
public static void Migrate(glTF gltf, JsonNode vrm0)
{
// Create MToonDefinition(0.x) from JSON(0.x)
var sourceMaterials = new (Vrm0XMToonValue, glTFMaterial)[gltf.materials.Count];
for (int i = 0; i < gltf.materials.Count; ++i)
{
var vrmMaterial = json["extensions"]["VRM"]["materialProperties"][i];
var vrmMaterial = vrm0["materialProperties"][i];
if (vrmMaterial["shader"].GetString() != "VRM/MToon")
{
continue;

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniJSON;
namespace UniVRM10
@@ -12,27 +12,36 @@ namespace UniVRM10
{
public static byte[] Migrate(byte[] src)
{
var glb = UniGLTF.Glb.Parse(src);
var json = glb.Json.Bytes.ParseAsJson();
return Migrate(json, glb.Binary.Bytes);
var data = new GlbBinaryParser(src, "migration").Parse();
return Migrate(data);
}
public static byte[] Migrate(JsonNode json, ArraySegment<byte> bin)
static (int, int) GetVertexRange(SpanLike<int> indices)
{
var gltf = UniGLTF.GltfDeserializer.Deserialize(json);
// attach glb bin to buffer
foreach (var buffer in gltf.buffers)
var min = int.MaxValue; ;
var max = 0;
foreach (var i in indices)
{
buffer.OpenStorage(new UniGLTF.SimpleStorage(bin));
if (i < min) min = i;
if (i > max) max = i;
}
return (min, max);
}
// https://github.com/vrm-c/vrm-specification/issues/205
RotateY180.Rotate(gltf);
public static byte[] Migrate(GltfData data)
{
// VRM0 -> Unity
var model = ModelReader.Read(data, VrmLib.Coordinates.Vrm0);
// Unity -> VRM1
VrmLib.ModelExtensionsForCoordinates.ConvertCoordinate(model, VrmLib.Coordinates.Vrm1);
var vrm0 = json["extensions"]["VRM"];
var (gltf, bin) = new MeshUpdater(data).Update(model);
gltf.extensions = null;
return MigrateVrm(gltf, bin, data.Json.ParseAsJson()["extensions"]["VRM"]);
}
static byte[] MigrateVrm(glTF gltf, ArraySegment<byte> bin, JsonNode vrm0)
{
{
// vrm
var vrm1 = new UniGLTF.Extensions.VRMC_vrm.VRMC_vrm();
@@ -96,18 +105,18 @@ namespace UniVRM10
// MToon
{
MigrationMToon.Migrate(gltf, json);
MigrationMToon.Migrate(gltf, vrm0);
}
// Serialize whole glTF
ArraySegment<byte> vrm1Json = default;
{
var f = new JsonFormatter();
UniGLTF.GltfSerializer.Serialize(f, gltf);
GltfSerializer.Serialize(f, gltf);
vrm1Json = f.GetStoreBytes();
}
// JSON 部分だけが改変されて、BIN はそのまま
return UniGLTF.Glb.Create(vrm1Json, bin).ToBytes();
return Glb.Create(vrm1Json, bin).ToBytes();
}
public static void Check(JsonNode vrm0, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm1)
@@ -116,9 +125,10 @@ namespace UniVRM10
MigrationVrmHumanoid.Check(vrm0["humanoid"], vrm1.Humanoid);
}
public static void Check(JsonNode vrm0, UniGLTF.Extensions.VRMC_springBone.VRMC_springBone vrm1, List<UniGLTF.glTFNode> nodes)
public static void Check(JsonNode vrm0, UniGLTF.Extensions.VRMC_springBone.VRMC_springBone vrm1, List<glTFNode> nodes)
{
// Migration.CheckSpringBone(vrm0["secondaryAnimation"], vrm1.sp)
}
}
}
}

View File

@@ -98,21 +98,25 @@ namespace VrmLib
{
model.ReverseAxisAndFlipTriangle(ZReverser, ignoreVrm);
model.UVVerticalFlip();
model.Coordinates = coordinates;
}
else if (model.Coordinates.IsUnity && coordinates.IsVrm0)
{
model.ReverseAxisAndFlipTriangle(ZReverser, ignoreVrm);
model.UVVerticalFlip();
model.Coordinates = coordinates;
}
else if (model.Coordinates.IsVrm1 && coordinates.IsUnity)
{
model.ReverseAxisAndFlipTriangle(XReverser, ignoreVrm);
model.UVVerticalFlip();
model.Coordinates = coordinates;
}
else if (model.Coordinates.IsUnity && coordinates.IsVrm1)
{
model.ReverseAxisAndFlipTriangle(XReverser, ignoreVrm);
model.UVVerticalFlip();
model.Coordinates = coordinates;
}
else
{