예제 #1
0
        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);
        }
예제 #2
0
파일: MeshReader.cs 프로젝트: vrm-c/UniVRM
        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);
        }
예제 #3
0
파일: MeshReader.cs 프로젝트: vrm-c/UniVRM
        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);
        }
예제 #4
0
파일: MeshReader.cs 프로젝트: vrm-c/UniVRM
        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);
        }
예제 #5
0
파일: MeshReader.cs 프로젝트: vrm-c/UniVRM
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
파일: MeshReader.cs 프로젝트: vrm-c/UniVRM
 /// <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));
 }
예제 #8
0
파일: MeshReader.cs 프로젝트: vrm-c/UniVRM
 /// <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));
 }