public static Model Read(UniGLTF.GltfData data, Coordinates?coords = default) { var storage = new Vrm10ImportData(data); var model = Load(storage, Path.GetFileName(data.TargetPath), coords.GetValueOrDefault(Coordinates.Vrm1)); model.ConvertCoordinate(Coordinates.Unity); return(model); }
static VertexBuffer FromGltf(this gltfMorphTarget target, Vrm10ImportData 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 Mesh FromGltf(Vrm10ImportData 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); } if (mesh.IndexBuffer == null) { var indices = Enumerable.Range(0, mesh.VertexBuffer.Count).ToArray(); var na = storage.Data.NativeArrayManager.CreateNativeArray(indices); mesh.IndexBuffer = new BufferAccessor(storage.Data.NativeArrayManager, na.Reinterpret <byte>(4), AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, na.Length); } { 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 MeshGroup FromGltf(this glTFMesh x, Vrm10ImportData 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); }
static VertexBuffer FromGltf(this glTFAttributes attributes, Vrm10ImportData 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 Model Load(Vrm10ImportData storage, string rootName, Coordinates coords) { if (storage == null) { return(null); } var model = new Model(coords) { AssetVersion = storage.AssetVersion, AssetGenerator = storage.AssetGenerator, AssetCopyright = storage.AssetCopyright, AssetMinVersion = storage.AssetMinVersion, Coordinates = coords, }; // node model.Root.Name = rootName; for (var i = 0; i < storage.NodeCount; ++i) { var node = storage.CreateNode(i); model.Nodes.Add(node); } for (var i = 0; i < model.Nodes.Count; ++i) { var parent = model.Nodes[i]; foreach (var j in storage.GetChildNodeIndices(i)) { var child = model.Nodes[j]; parent.Add(child); } } foreach (var x in model.Nodes) { if (x.Parent == null) { model.Root.Add(x); } } // skin model.Skins.AddRange(Enumerable.Range(0, storage.SkinCount).Select(x => storage.CreateSkin(x, model.Nodes))); // mesh model.MeshGroups.AddRange(Enumerable.Range(0, storage.MeshCount).Select(x => storage.CreateMesh(x))); // skin for (int i = 0; i < storage.NodeCount; ++i) { var(meshIndex, skinIndex) = storage.GetNodeMeshSkin(i); if (meshIndex >= 0 && meshIndex < model.MeshGroups.Count) { var node = model.Nodes[i]; var mesh = model.MeshGroups[meshIndex]; node.MeshGroup = mesh; if (skinIndex >= 0 && skinIndex < model.Skins.Count) { var skin = model.Skins[skinIndex]; mesh.Skin = skin; } } } // boneWeight の付与 foreach (var meshGroup in model.MeshGroups) { if (meshGroup.Skin == null && meshGroup.Meshes.Any(mesh => mesh.MorphTargets.Count > 0)) { // Skinning が無くて MorphTarget が有る場合に実施する var nodes = model.Nodes.Where(node => node.MeshGroup == meshGroup).ToArray(); if (nodes.Length != 1) { // throw new NotImplementedException(); // このメッシュが複数のノードから共有されている場合は、 // 個別に Skin を作成する必要があり、 // 異なる bindPoses が必要になるため mesh の複製が必要になる! // 稀にあるかもしれない。 continue; } var node = nodes[0]; // add bone weight foreach (var mesh in meshGroup.Meshes) { // all (1, 0, 0, 0) var weights = storage.Data.NativeArrayManager.CreateNativeArray <UnityEngine.Vector4>(mesh.VertexBuffer.Count); for (int i = 0; i < weights.Length; ++i) { weights[i] = new UnityEngine.Vector4(1, 0, 0, 0); } mesh.VertexBuffer.Add(VertexBuffer.WeightKey, new UniGLTF.BufferAccessor(storage.Data.NativeArrayManager, weights.Reinterpret <byte>(16), UniGLTF.AccessorValueType.FLOAT, UniGLTF.AccessorVectorType.VEC4, weights.Length)); // all zero var joints = storage.Data.NativeArrayManager.CreateNativeArray <UniGLTF.UShort4>(mesh.VertexBuffer.Count); mesh.VertexBuffer.Add(VertexBuffer.JointKey, new UniGLTF.BufferAccessor(storage.Data.NativeArrayManager, joints.Reinterpret <byte>(8), UniGLTF.AccessorValueType.UNSIGNED_SHORT, UniGLTF.AccessorVectorType.VEC4, joints.Length)); } // bind matrix var bindMatrices = storage.Data.NativeArrayManager.CreateNativeArray <UnityEngine.Matrix4x4>(1); bindMatrices[0] = node.Matrix.inverse; // skinning meshGroup.Skin = new Skin { GltfIndex = -1, Joints = new System.Collections.Generic.List <Node> { node }, Root = node, InverseMatrices = new UniGLTF.BufferAccessor(storage.Data.NativeArrayManager, bindMatrices.Reinterpret <byte>(64), UniGLTF.AccessorValueType.FLOAT, UniGLTF.AccessorVectorType.MAT4, bindMatrices.Length), }; } } return(model); }
/// <summary> /// IndexBuffer毎に異なるVertexBufferを参照する /// /// VertexBuffer /// +--------+ +--------+ +--------+ /// |0 | |1 | |2 | /// +--------+ +--------+ +--------+ /// A A A /// | | | /// +---------+--------+--------+ /// | submesh0|submesh1|submesh2| /// +---------+--------+--------+ /// IndexBuffer /// </summary> static Mesh FromGltf(this glTFPrimitives primitive, Vrm10ImportData storage, glTFMesh x) { return(FromGltf(storage, x, primitive, false)); }
/// <summary> /// VertexBufferはひとつでIndexBufferの参照が異なる /// /// VertexBuffer /// +----------------------------------+ /// | | /// +----------------------------------+ /// A A A /// | | | /// +---------+--------+--------+ /// | submesh0|submesh1|submesh2| /// +---------+--------+--------+ /// IndexBuffer /// </summary> static Mesh SharedBufferFromGltf(this glTFMesh x, Vrm10ImportData storage) { // 先頭を使う return(FromGltf(storage, x, x.primitives[0], true)); }