Exemple #1
0
        /// <summary>
        /// submeshのindexが連続した領域に格納されているかを確認する
        /// </summary>
        static bool AccessorsIsContinuous(GltfSerialization.GltfStorage storage, int[] accessorIndices)
        {
            var gltf          = storage.Gltf;
            var firstAccessor = gltf.accessors[accessorIndices[0]];
            var firstView     = gltf.bufferViews[firstAccessor.bufferView];
            var start         = firstView.byteOffset + firstAccessor.byteOffset;
            var pos           = start;

            foreach (var i in accessorIndices)
            {
                var current = gltf.accessors[i];
                if (current.type != GltfAccessorType.SCALAR)
                {
                    throw new ArgumentException($"accessor.type: {current.type}");
                }
                if (firstAccessor.componentType != current.componentType)
                {
                    return(false);
                }

                var view = gltf.bufferViews[current.bufferView];
                if (pos != view.byteOffset + current.byteOffset)
                {
                    return(false);
                }

                var begin      = view.byteOffset + current.byteOffset;
                var byteLength = current.componentType.ByteSize() * current.type.TypeCount() * current.count;

                pos += byteLength;
            }

            return(true);
        }
Exemple #2
0
        public static Image FromGltf(this GltfImage x, GltfSerialization.GltfStorage storage)
        {
            var view   = storage.Gltf.bufferViews[x.bufferView];
            var buffer = storage.Gltf.buffers[view.buffer];
            var memory = storage.GetBufferBytes(buffer);

            // テクスチャの用途を調べる
            var usage = default(ImageUsage);

            foreach (var material in storage.Gltf.materials)
            {
                var colorImage = GetColorImage(storage, material);
                if (colorImage == x)
                {
                    usage |= ImageUsage.Color;
                }

                var normalImage = GetNormalImage(storage, material);
                if (normalImage == x)
                {
                    usage |= ImageUsage.Normal;
                }
            }

            return(new Image(x.name,
                             x.mimeType,
                             usage,
                             memory.Slice(view.byteOffset, view.byteLength)));
        }
 public static CurveSampler FromGltf(GltfSerialization.GltfStorage storage, int inIndex, int outIndex)
 {
     return(new CurveSampler
     {
         In = storage.AccessorFromGltf(inIndex),
         Out = storage.AccessorFromGltf(outIndex),
     });
 }
Exemple #4
0
 static GltfImage GetNormalImage(GltfSerialization.GltfStorage storage, GltfMaterial m)
 {
     if (m.normalTexture == null)
     {
         return(null);
     }
     return(GetTexture(storage, m.normalTexture.index));
 }
        public static void AddCurve(this Animation self, GltfSerialization.GltfStorage storage, Node node, AnimationPathType path, GltfAnimationSampler sampler)
        {
            var nodeAnimation = self.GetOrCreateNodeAnimation(node);

            nodeAnimation.Curves[path] = FromGltf(storage, sampler.input, sampler.output);

            self.UpdateChannelsAndLastTime();
        }
Exemple #6
0
        public static VertexBuffer FromGltf(this GltfMorphTarget target, GltfSerialization.GltfStorage storage)
        {
            var b = new VertexBuffer();

            CreateBufferAccessorAndAdd(storage, target.POSITION, b, VertexBuffer.PositionKey);
            CreateBufferAccessorAndAdd(storage, target.NORMAL, b, VertexBuffer.NormalKey);
            CreateBufferAccessorAndAdd(storage, target.TANGENT, b, VertexBuffer.TangentKey);
            return(b);
        }
        static void CreateBufferAccessorAndAdd(GltfSerialization.GltfStorage storage, int accessorIndex,
                                               VertexBuffer b, string key)
        {
            var a = storage.AccessorFromGltf(accessorIndex);

            if (a != null)
            {
                b.Add(key, a);
            }
        }
Exemple #8
0
 static GltfImage GetColorImage(GltfSerialization.GltfStorage storage, GltfMaterial m)
 {
     if (m.pbrMetallicRoughness == null)
     {
         return(null);
     }
     if (m.pbrMetallicRoughness.baseColorTexture == null)
     {
         return(null);
     }
     return(GetTexture(storage, m.pbrMetallicRoughness.baseColorTexture.index));
 }
Exemple #9
0
        public static BufferAccessor AccessorFromGltf(this GltfSerialization.GltfStorage storage, int accessorIndex)
        {
            if (accessorIndex < 0)
            {
                return(null);
            }
            var gltf     = storage.Gltf;
            var accessor = gltf.accessors[accessorIndex];
            var bytes    = storage.GetAccessorBytes(accessorIndex);

            return(new BufferAccessor(bytes,
                                      (AccessorValueType)accessor.componentType, (AccessorVectorType)accessor.type, accessor.count));
        }
Exemple #10
0
        public static VertexBuffer FromGltf(this GltfAttributes attributes, GltfSerialization.GltfStorage storage)
        {
            var b = new VertexBuffer();

            b.Add(VertexBuffer.PositionKey, storage.AccessorFromGltf(attributes.POSITION));
            CreateBufferAccessorAndAdd(storage, attributes.NORMAL, b, VertexBuffer.NormalKey);
            CreateBufferAccessorAndAdd(storage, attributes.TEXCOORD_0, b, VertexBuffer.TexCoordKey);
            CreateBufferAccessorAndAdd(storage, attributes.TANGENT, b, VertexBuffer.TangentKey);
            CreateBufferAccessorAndAdd(storage, attributes.COLOR_0, b, VertexBuffer.ColorKey);
            CreateBufferAccessorAndAdd(storage, attributes.JOINTS_0, b, VertexBuffer.JointKey);
            CreateBufferAccessorAndAdd(storage, attributes.WEIGHTS_0, b, VertexBuffer.WeightKey);
            return(b);
        }
Exemple #11
0
        static Mesh FromGltf(GltfSerialization.GltfStorage storage, GltfMesh x, GltfPrimitive primitive, bool isShared)
        {
            var mesh = new Mesh((TopologyType)primitive.mode)
            {
                VertexBuffer = primitive.attributes.FromGltf(storage)
            };

            if (isShared)
            {
                // create joined index buffer
                mesh.IndexBuffer = storage.IndexBufferFromGltf(x.primitives.Select(y => y.indices).ToArray());
            }
            else
            {
                mesh.IndexBuffer = storage.AccessorFromGltf(primitive.indices);
            }

            if (primitive.targets != null)
            {
                for (int i = 0; i < primitive.targets.Count; ++i)
                {
                    var    gltfTarget = primitive.targets[i];
                    string targetName = null;
                    if (primitive.extras != null &&
                        primitive.extras.targetNames != null &&
                        i < primitive.extras.targetNames.Count
                        )
                    {
                        targetName = primitive.extras.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);
        }
Exemple #12
0
        static GltfImage GetTexture(GltfSerialization.GltfStorage storage, int index)
        {
            if (index < 0 || index >= storage.Gltf.textures.Count)
            {
                return(null);
            }
            var texture = storage.Gltf.textures[index];

            if (texture.source < 0 || texture.source >= storage.Gltf.images.Count)
            {
                return(null);
            }
            return(storage.Gltf.images[texture.source]);
        }
Exemple #13
0
        public static Animation FromGltf(this GltfAnimation src,
                                         GltfSerialization.GltfStorage storage, List <Node> nodes)
        {
            var animation = new Animation(src.name);

            foreach (var ch in src.channels)
            {
                var sampler = src.samplers[ch.sampler];
                var target  = ch.target;
                var node    = nodes[target.node];
                animation.AddCurve(storage, node, (AnimationPathType)target.path, sampler);
            }

            return(animation);
        }
Exemple #14
0
        public static MeshGroup FromGltf(this GltfMesh x,
                                         GltfSerialization.GltfStorage storage, List <Material> materials)
        {
            var group = new MeshGroup(x.name);

            if (x.primitives.Count == 1)
            {
                var primitive = x.primitives[0];
                var mesh      = primitive.FromGltf(storage, x);

                mesh.Submeshes.Add(
                    new Submesh(0, mesh.IndexBuffer.Count, materials[primitive.material]));

                group.Meshes.Add(mesh);
            }
            else if (!x.AllPrimitivesHasSameVertexBuffer())
            {
                int offset = 0;
                foreach (var primitive in x.primitives)
                {
                    var mesh = primitive.FromGltf(storage, x);

                    mesh.Submeshes.Add(
                        new Submesh(offset, mesh.IndexBuffer.Count, materials[primitive.material]));
                    offset += mesh.IndexBuffer.Count;

                    group.Meshes.Add(mesh);
                }
            }
            else
            {
                // for VRM

                var mesh   = x.SharedBufferFromGltf(storage);
                int offset = 0;
                foreach (var primitive in x.primitives)
                {
                    var count = storage.Gltf.accessors[primitive.indices].count;
                    mesh.Submeshes.Add(
                        new Submesh(offset, count, materials[primitive.material]));
                    offset += count;
                }

                group.Meshes.Add(mesh);
            }

            return(group);
        }
Exemple #15
0
        public static Model CreateVrmModel(byte[] bytes, FileInfo path)
        {
            if (!Glb.TryParse(bytes, out Glb glb, out Exception ex))
            {
                throw ex;
            }

            var flag = VRMVersionCheck.GetVRMExtensionFlag(glb.Json.Bytes);

            if (flag.HasFlag(VRMExtensionFlags.Vrm10))
            {
                var storage = new Vrm10.Vrm10Storage(glb.Json.Bytes, glb.Binary.Bytes);
                var model   = ModelLoader.Load(storage, path.Name);
                model.ConvertCoordinate(Coordinates.Unity);
                return(model);
            }

            if (flag.HasFlag(VRMExtensionFlags.Vrm0X))
            {
                var storage = new GltfSerialization.GltfStorage(path, glb.Json.Bytes, glb.Binary.Bytes);
                var model   = ModelLoader.Load(storage, path.Name);

                // convert meta frm 0x to 10
                var meta0x = model.Vrm.Meta.AvatarPermission;
                model.Vrm.Meta.AvatarPermission = new AvatarPermission
                {
                    AvatarUsage        = meta0x.AvatarUsage,
                    CommercialUsage    = meta0x.CommercialUsage,
                    IsAllowedGameUsage = meta0x.IsAllowedGameUsage,
                    IsAllowedPoliticalOrReligiousUsage = meta0x.IsAllowedPoliticalOrReligiousUsage,
                    IsAllowedSexualUsage  = meta0x.IsAllowedSexualUsage,
                    IsAllowedViolentUsage = meta0x.IsAllowedViolentUsage,
                    OtherPermissionUrl    = meta0x.OtherPermissionUrl,
                };
                model.Vrm.Meta.RedistributionLicense = new RedistributionLicense
                {
                    OtherLicenseUrl = VRM0X_LICENSE_URL,
                };
                UnityEngine.Debug.LogWarning($"convert {model.Vrm.ExporterVersion} to 1.0. please update meta information");

                model.ConvertCoordinate(Coordinates.Unity, ignoreVrm: true);
                return(model);
            }

            throw new NotImplementedException();
        }
Exemple #16
0
 /// <summary>
 /// IndexBuffer毎に異なるVertexBufferを参照する
 ///
 ///  VertexBuffer
 ///  +--------+ +--------+ +--------+
 ///  |0       | |1       | |2       |
 ///  +--------+ +--------+ +--------+
 ///       A         A        A
 ///       |         |        |
 ///  +---------+--------+--------+
 ///  | submesh0|submesh1|submesh2|
 ///  +---------+--------+--------+
 ///  IndexBuffer
 /// </summary>
 public static Mesh FromGltf(this GltfPrimitive primitive, GltfSerialization.GltfStorage storage, GltfMesh x)
 {
     return(FromGltf(storage, x, primitive, false));
 }
Exemple #17
0
 /// <summary>
 /// VertexBufferはひとつでIndexBufferの参照が異なる
 ///
 ///  VertexBuffer
 ///  +----------------------------------+
 ///  |                                  |
 ///  +----------------------------------+
 ///       A         A        A
 ///       |         |        |
 ///  +---------+--------+--------+
 ///  | submesh0|submesh1|submesh2|
 ///  +---------+--------+--------+
 ///  IndexBuffer
 /// </summary>
 public static Mesh SharedBufferFromGltf(this GltfMesh x, GltfSerialization.GltfStorage storage)
 {
     // 先頭を使う
     return(FromGltf(storage, x, x.primitives[0], true));
 }
Exemple #18
0
        /// <summary>
        /// Gltfの Primitive[] の indices をひとまとめにした
        /// IndexBuffer を返す。
        /// </summary>
        public static BufferAccessor IndexBufferFromGltf(this GltfSerialization.GltfStorage storage, int[] accessorIndices)
        {
            var gltf       = storage.Gltf;
            var totalCount = accessorIndices.Sum(x => gltf.accessors[x].count);

            if (AccessorsIsContinuous(storage, accessorIndices))
            {
                // IndexBufferが連続して格納されている => Slice でいける
                var firstAccessor = gltf.accessors[accessorIndices[0]];
                var firstView     = gltf.bufferViews[firstAccessor.bufferView];
                var start         = firstView.byteOffset + firstAccessor.byteOffset;
                var buffer        = gltf.buffers[firstView.buffer];
                var bin           = storage.GetBufferBytes(buffer);
                var bytes         = bin.Slice(start, totalCount * firstAccessor.GetStride());
                return(new BufferAccessor(bytes,
                                          (AccessorValueType)firstAccessor.componentType, (AccessorVectorType)firstAccessor.type, totalCount));
            }
            else
            {
                // IndexBufferが連続して格納されていない => Int[] を作り直す
                var indices = new byte[totalCount * Marshal.SizeOf(typeof(int))];
                var span    = MemoryMarshal.Cast <byte, int>(indices.AsSpan());
                var offset  = 0;
                foreach (var accessorIndex in accessorIndices)
                {
                    var accessor = gltf.accessors[accessorIndex];
                    if (accessor.type != GltfAccessorType.SCALAR)
                    {
                        throw new ArgumentException($"accessor.type: {accessor.type}");
                    }
                    var view   = gltf.bufferViews[accessor.bufferView];
                    var buffer = gltf.buffers[view.buffer];
                    var bin    = storage.GetBufferBytes(buffer);
                    var start  = view.byteOffset + accessor.byteOffset;
                    var bytes  = bin.Slice(start, accessor.count * accessor.GetStride());
                    var dst    = MemoryMarshal.Cast <byte, int>(indices.AsSpan()).Slice(offset, accessor.count);
                    offset += accessor.count;
                    switch (accessor.componentType)
                    {
                    case GltfComponentType.UNSIGNED_BYTE:
                    {
                        var src = bytes.Span;
                        for (int i = 0; i < src.Length; ++i)
                        {
                            // byte to int
                            dst[i] = src[i];
                        }
                    }
                    break;

                    case GltfComponentType.UNSIGNED_SHORT:
                    {
                        var src = MemoryMarshal.Cast <byte, ushort>(bytes.Span);
                        for (int i = 0; i < src.Length; ++i)
                        {
                            // ushort to int
                            dst[i] = src[i];
                        }
                    }
                    break;

                    case GltfComponentType.UNSIGNED_INT:
                    {
                        var src = MemoryMarshal.Cast <byte, int>(bytes.Span);
                        // int to int
                        src.CopyTo(dst);
                    }
                    break;

                    default:
                        throw new NotImplementedException($"accessor.componentType: {accessor.componentType}");
                    }
                }
                return(new BufferAccessor(indices, AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, totalCount));
            }
        }