mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-09 04:19:42 -05:00
Merge pull request #1280 from ousttrue/fix10/migrate_not_normalized
[1.0] ヒエラルキーに回転・スケールが含まれているモデルのマイグレーション
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace UniGLTF
|
||||
{
|
||||
private readonly byte[] _data;
|
||||
private readonly string _name;
|
||||
|
||||
|
||||
public GlbBinaryParser(byte[] data, string uniqueName)
|
||||
{
|
||||
_data = data;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
133
Assets/VRM10/Runtime/Migration/MeshUpdater.cs
Normal file
133
Assets/VRM10/Runtime/Migration/MeshUpdater.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRM10/Runtime/Migration/MeshUpdater.cs.meta
Normal file
11
Assets/VRM10/Runtime/Migration/MeshUpdater.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c49ea19813d8f214dbe789fd79f78b28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user