예제 #1
0
        private static uint LoadBufferView(AttributeAccessor attributeAccessor, out byte[] bufferViewCache)
        {
            BufferView bufferView  = attributeAccessor.AccessorId.Value.BufferView.Value;
            uint       totalOffset = bufferView.ByteOffset + attributeAccessor.Offset;

#if !NETFX_CORE
            if (attributeAccessor.Stream is System.IO.MemoryStream)
            {
                MemoryStream memoryStream = (MemoryStream)attributeAccessor.Stream;
#if NETFX_CORE || NETSTANDARD1_3
                if (memoryStream.TryGetBuffer(out System.ArraySegment <byte> arraySegment))
                {
                    bufferViewCache = arraySegment.Array;
                    return(totalOffset);
                }
#else
                bufferViewCache = memoryStream.GetBuffer();
                return(totalOffset);
#endif
            }
#endif
            attributeAccessor.Stream.Position = totalOffset;
            bufferViewCache = new byte[bufferView.ByteLength];

            // stream.Read only accepts int for length
            uint remainingSize = bufferView.ByteLength;
            while (remainingSize != 0)
            {
                int sizeToLoad = (int)System.Math.Min(remainingSize, int.MaxValue);
                attributeAccessor.Stream.Read(bufferViewCache, (int)(bufferView.ByteLength - remainingSize), sizeToLoad);
                remainingSize -= (uint)sizeToLoad;
            }
            return(0);
        }
예제 #2
0
        private static long LoadBufferView(AttributeAccessor attributeAccessor, out byte[] bufferViewCache)
        {
            BufferView bufferView  = attributeAccessor.AccessorId.Value.BufferView.Value;
            long       totalOffset = bufferView.ByteOffset + attributeAccessor.Offset;

            if (attributeAccessor.Stream is System.IO.MemoryStream)
            {
                using (var memoryStream = attributeAccessor.Stream as System.IO.MemoryStream)
                {
#if NETFX_CORE || NETSTANDARD1_3
                    if (memoryStream.TryGetBuffer(out System.ArraySegment <byte> arraySegment))
                    {
                        bufferViewCache = arraySegment.Array;
                        return(totalOffset);
                    }
#else
                    bufferViewCache = memoryStream.GetBuffer();
                    return(totalOffset);
#endif
                }
            }
            attributeAccessor.Stream.Position = totalOffset;
            bufferViewCache = new byte[bufferView.ByteLength];
            attributeAccessor.Stream.Read(bufferViewCache, 0, bufferView.ByteLength);
            return(0);
        }
예제 #3
0
        private BufferViewId ExportBufferView(int byteOffset, int byteLength)
        {
            var bufferView = new BufferView {
                Buffer     = _bufferId,
                ByteOffset = byteOffset,
                ByteLength = byteLength,
            };

            var id = new BufferViewId {
                Id   = _root.BufferViews.Count,
                Root = _root
            };

            _root.BufferViews.Add(bufferView);

            return(id);
        }
예제 #4
0
        private static long LoadBufferView(AttributeAccessor attributeAccessor, out byte[] bufferViewCache)
        {
            BufferView bufferView  = attributeAccessor.AccessorId.Value.BufferView.Value;
            long       totalOffset = bufferView.ByteOffset + attributeAccessor.Offset;

#if !NETFX_CORE
            if (attributeAccessor.Stream is System.IO.MemoryStream)
            {
                using (var memoryStream = attributeAccessor.Stream as System.IO.MemoryStream)
                {
                    bufferViewCache = memoryStream.GetBuffer();
                    return(totalOffset);
                }
            }
#endif
            attributeAccessor.Stream.Position = totalOffset;
            bufferViewCache = new byte[bufferView.ByteLength];
            attributeAccessor.Stream.Read(bufferViewCache, 0, bufferView.ByteLength);
            return(0);
        }
예제 #5
0
        public static BufferView Deserialize(GLTFRoot root, JsonReader reader)
        {
            var bufferView = new BufferView();

            while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
            {
                var curProp = reader.Value.ToString();

                switch (curProp)
                {
                case "buffer":
                    bufferView.Buffer = BufferId.Deserialize(root, reader);
                    break;

                case "byteOffset":
                    bufferView.ByteOffset = reader.ReadAsInt32().Value;
                    break;

                case "byteLength":
                    bufferView.ByteLength = reader.ReadAsInt32().Value;
                    break;

                case "byteStride":
                    bufferView.ByteStride = reader.ReadAsInt32().Value;
                    break;

                case "target":
                    bufferView.Target = (BufferViewTarget)reader.ReadAsInt32().Value;
                    break;

                default:
                    bufferView.DefaultPropertyDeserializer(root, reader);
                    break;
                }
            }

            return(bufferView);
        }
예제 #6
0
        /// <summary>
        /// Removes a blob from the GLB at the given BufferView
        /// Updates accessors and images to have correct new bufferview index
        /// This function can invalidate BufferViewId's returned by previous function
        /// </summary>
        /// <param name="glb">The glb to remove from</param>
        /// <param name="bufferViewId">The buffer to remove</param>
        public static void RemoveBinaryData(GLBObject glb, BufferViewId bufferViewId)
        {
            if (glb == null)
            {
                throw new ArgumentNullException(nameof(glb));
            }
            if (bufferViewId == null)
            {
                throw new ArgumentNullException(nameof(bufferViewId));
            }

            BufferView bufferViewToRemove = bufferViewId.Value;
            int        id = bufferViewId.Id;

            if (bufferViewToRemove.ByteOffset + bufferViewToRemove.ByteLength == glb.BinaryChunkInfo.Length)
            {
                uint bufferViewLengthAsUint = bufferViewToRemove.ByteLength;
                glb.SetFileLength(glb.Header.FileLength - bufferViewLengthAsUint);
                glb.SetBinaryChunkLength(glb.BinaryChunkInfo.Length - bufferViewLengthAsUint);
                if (glb.BinaryChunkInfo.Length == 0)
                {
                    glb.Root.Buffers.RemoveAt(0);
                    foreach (BufferView bufferView in glb.Root.BufferViews)                     // other buffers may still exist, and their index has now changed
                    {
                        --bufferView.Buffer.Id;
                    }

                    glb.SetFileLength(glb.Header.FileLength - GLTFParser.CHUNK_HEADER_SIZE);
                }
                else
                {
                    glb.Root.Buffers[0].ByteLength = glb.BinaryChunkInfo.Length;

                    // write binary chunk header
                    WriteChunkHeader(glb.Stream, glb.BinaryChunkInfo);
                }

                // trim the end
                glb.Stream.SetLength(glb.Header.FileLength);

                // write glb header
                WriteHeader(glb.Stream, glb.Header, glb.StreamStartPosition);
            }

            glb.Root.BufferViews.RemoveAt(id);
            if (glb.Root.Accessors != null)
            {
                foreach (Accessor accessor in glb.Root.Accessors)                 // shift over all accessors
                {
                    if (accessor.BufferView != null && accessor.BufferView.Id >= id)
                    {
                        --accessor.BufferView.Id;
                    }

                    if (accessor.Sparse != null)
                    {
                        if (accessor.Sparse.Indices?.BufferView.Id >= id)
                        {
                            --accessor.Sparse.Indices.BufferView.Id;
                        }

                        if (accessor.Sparse.Values?.BufferView.Id >= id)
                        {
                            --accessor.Sparse.Values.BufferView.Id;
                        }
                    }
                }
            }

            if (glb.Root.Images != null)
            {
                foreach (GLTFImage image in glb.Root.Images)
                {
                    if (image.BufferView != null && image.BufferView.Id >= id)
                    {
                        --image.BufferView.Id;
                    }
                }
            }
        }
예제 #7
0
        private static BufferViewId _AddBinaryData(GLBObject glb, Stream binaryData, bool createBufferView, long streamStartPosition, string bufferViewName = null)
        {
            binaryData.Position = streamStartPosition;

            // Append new binary chunk to end
            uint blobLengthAsUInt    = CalculateAlignment((uint)(binaryData.Length - streamStartPosition), 4);
            uint newBinaryBufferSize = glb.BinaryChunkInfo.Length + blobLengthAsUInt;
            uint newGLBSize          = glb.Header.FileLength + blobLengthAsUInt;
            uint blobWritePosition   = glb.Header.FileLength;

            // there was an existing file that had no binary chunk info previously
            if (glb.BinaryChunkInfo.Length == 0)
            {
                newGLBSize        += GLTFParser.CHUNK_HEADER_SIZE;
                blobWritePosition += GLTFParser.CHUNK_HEADER_SIZE;
                glb.SetBinaryChunkStartPosition(glb.Header.FileLength);                  // if 0, then appends chunk info at the end
            }

            glb.Stream.SetLength(glb.Header.FileLength + blobLengthAsUInt);
            glb.Stream.Position = blobWritePosition;                // assuming the end of the file is the end of the binary chunk
            binaryData.CopyTo(glb.Stream);                          // make sure this doesn't supersize it

            glb.SetFileLength(newGLBSize);
            glb.SetBinaryChunkLength(newBinaryBufferSize);

            // write glb header past magic number
            WriteHeader(glb.Stream, glb.Header, glb.StreamStartPosition);

            WriteChunkHeader(glb.Stream, glb.BinaryChunkInfo);

            if (createBufferView)
            {
                // Add a new BufferView to the GLTFRoot
                BufferView bufferView = new BufferView
                {
                    Buffer = new BufferId
                    {
                        Id   = 0,
                        Root = glb.Root
                    },
                    ByteLength = blobLengthAsUInt,                     // figure out whether glb size is wrong or if documentation is unclear
                    ByteOffset = glb.BinaryChunkInfo.Length - blobLengthAsUInt,
                    Name       = bufferViewName
                };

                if (glb.Root.BufferViews == null)
                {
                    glb.Root.BufferViews = new List <BufferView>();
                }

                glb.Root.BufferViews.Add(bufferView);

                return(new BufferViewId
                {
                    Id = glb.Root.BufferViews.Count - 1,
                    Root = glb.Root
                });
            }

            return(null);
        }
예제 #8
0
파일: GLTFRoot.cs 프로젝트: meenuh/LearnAR
        public static GLTFRoot Deserialize(JsonReader reader)
        {
            var root = new GLTFRoot();

            if (reader.Read() && reader.TokenType != JsonToken.StartObject)
            {
                throw new Exception("glTF JSON must be an object");
            }

            while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
            {
                var curProp = reader.Value.ToString();

                switch (curProp)
                {
                case "extensionsUsed":
                    root.ExtensionsUsed = reader.ReadStringList();
                    break;

                case "extensionsRequired":
                    root.ExtensionsRequired = reader.ReadStringList();
                    break;

                case "accessors":
                    root.Accessors = reader.ReadList(() => Accessor.Deserialize(root, reader));
                    break;

                case "animations":
                    root.Animations = reader.ReadList(() => GLTFAnimation.Deserialize(root, reader));
                    break;

                case "asset":
                    root.Asset = Asset.Deserialize(root, reader);
                    break;

                case "buffers":
                    root.Buffers = reader.ReadList(() => Buffer.Deserialize(root, reader));
                    break;

                case "bufferViews":
                    root.BufferViews = reader.ReadList(() => BufferView.Deserialize(root, reader));
                    break;

                case "cameras":
                    root.Cameras = reader.ReadList(() => GLTFCamera.Deserialize(root, reader));
                    break;

                case "images":
                    root.Images = reader.ReadList(() => Image.Deserialize(root, reader));
                    break;

                case "materials":
                    root.Materials = reader.ReadList(() => Material.Deserialize(root, reader));
                    break;

                case "meshes":
                    root.Meshes = reader.ReadList(() => Mesh.Deserialize(root, reader));
                    break;

                case "nodes":
                    root.Nodes = reader.ReadList(() => Node.Deserialize(root, reader));
                    break;

                case "samplers":
                    root.Samplers = reader.ReadList(() => Sampler.Deserialize(root, reader));
                    break;

                case "scene":
                    root.Scene = SceneId.Deserialize(root, reader);
                    break;

                case "scenes":
                    root.Scenes = reader.ReadList(() => GLTF.Scene.Deserialize(root, reader));
                    break;

                case "skins":
                    root.Skins = reader.ReadList(() => Skin.Deserialize(root, reader));
                    break;

                case "textures":
                    root.Textures = reader.ReadList(() => Texture.Deserialize(root, reader));
                    break;

                default:
                    root.DefaultPropertyDeserializer(root, reader);
                    break;
                }
            }

            return(root);
        }