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); }
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)); } }