Пример #1
0
        // todo: this needs reimplemented. There is no such thing as a binary chunk index, and the chunk may not be in 0, 1, 2 order
        // Moves stream position to binary chunk location
        public static ChunkInfo SeekToBinaryChunk(Stream stream, int binaryChunkIndex, long startPosition = 0)
        {
            stream.Position = startPosition + 4; // start after magic number chunk
            GLBHeader header      = ParseGLBHeader(stream);
            uint      chunkOffset = 12;          // sizeof(GLBHeader) + magic number
            uint      chunkLength = 0;

            for (int i = 0; i < binaryChunkIndex + 2; ++i)
            {
                chunkOffset    += chunkLength;
                stream.Position = chunkOffset;
                chunkLength     = GetUInt32(stream);
                chunkOffset    += 8;                // to account for chunk length (4 bytes) and type (4 bytes)
            }

            // Load Binary Chunk
            if (chunkOffset + chunkLength <= header.FileLength)
            {
                ChunkFormat chunkType = (ChunkFormat)GetUInt32(stream);
                if (chunkType != ChunkFormat.BIN)
                {
                    throw new GLTFHeaderInvalidException("Second chunk must be of type BIN if present");
                }

                return(new ChunkInfo
                {
                    StartPosition = stream.Position - CHUNK_HEADER_SIZE,
                    Length = chunkLength,
                    Type = chunkType
                });
            }

            throw new GLTFHeaderInvalidException("File length does not match chunk header.");
        }
Пример #2
0
        // Moves stream position to binary chunk location
        public static void SeekToBinaryChunk(Stream stream, int binaryChunkIndex, long startPosition = 0)
        {
            stream.Position = startPosition + 4; // start after magic number chunk
            GLBHeader header      = ParseGLBHeader(stream);
            uint      chunkOffset = 12;          // sizeof(GLBHeader) + magic number
            uint      chunkLength = 0;

            for (int i = 0; i < binaryChunkIndex + 2; ++i)
            {
                chunkOffset += chunkLength;
                //vona 5/25/21
                //stream.Position = chunkOffset;
                stream.Position = startPosition + chunkOffset;
                chunkLength     = GetUInt32(stream);
                chunkOffset    += 8;                // to account for chunk length (4 bytes) and type (4 bytes)
            }

            // Load Binary Chunk
            if (chunkOffset + chunkLength <= header.FileLength)
            {
                uint chunkType = GetUInt32(stream);
                if (chunkType != (uint)ChunkFormat.BIN)
                {
                    throw new GLTFHeaderInvalidException("Second chunk must be of type BIN if present");
                }
            }
            else
            {
                throw new GLTFHeaderInvalidException("File length does not match chunk header.");
            }
        }
Пример #3
0
        // todo optimize: this can have a caching system where GLTFRoot stores data about JSON offset of a GLB
        public static void ExtractBinaryChunk(byte[] gltfBinary, int binaryChunkIndex, out byte[] glbBuffer)
        {
            GLBHeader header      = ParseGLBHeader(gltfBinary);
            int       chunkOffset = 12;         // sizeof(GLBHeader) + magic number
            int       chunkLength = 0;

            for (int i = 0; i < binaryChunkIndex + 2; ++i)
            {
                chunkOffset += chunkLength;
                chunkLength  = (int)GetChunkLength(gltfBinary, chunkOffset);
                chunkOffset += 8;                   // to account for chunk length (4 bytes) and type (4 bytes)
            }

            // Load Binary Chunk
            if (chunkOffset + chunkLength <= header.FileLength)
            {
                uint chunkType = BitConverter.ToUInt32(gltfBinary, chunkOffset - 4);
                if (chunkType != (uint)ChunkFormat.BIN)
                {
                    throw new GLTFHeaderInvalidException("Second chunk must be of type BIN if present");
                }

                glbBuffer = new byte[chunkLength];
                System.Buffer.BlockCopy(gltfBinary, chunkOffset, glbBuffer, 0, chunkLength);
            }
            else
            {
                throw new GLTFHeaderInvalidException("File length does not match chunk header.");
            }
        }
Пример #4
0
        private static string ParseJsonChunk(byte[] gltfBinary)
        {
            GLBHeader header = ParseGLBHeader(gltfBinary);

            if (header.Version != 2)
            {
                throw new GLTFHeaderInvalidException("Unsupported glTF version");
            }
            ;

            if (header.FileLength != gltfBinary.Length)
            {
                throw new GLTFHeaderInvalidException("File length does not match header.");
            }

            uint chunkLength = GetChunkLength(gltfBinary, 12);
            var  chunkType   = BitConverter.ToUInt32(gltfBinary, 16);

            if (chunkType != (uint)ChunkFormat.JSON)
            {
                throw new GLTFHeaderInvalidException("First chunk must be of type JSON");
            }

            // Load JSON chunk
            return(System.Text.Encoding.UTF8.GetString(gltfBinary, 20, (int)chunkLength));
        }
Пример #5
0
        /// <summary>
        /// Turns the GLB data contained in a stream into a GLBObject. Will copy to the outStream if specified
        /// </summary>
        /// <param name="root">The glTF root to turn into a GLBObject</param>
        /// <param name="inputGLBStream">The stream the glb came in</param>
        /// <param name="outStream">If outstream is specified, the glb gets copied to it</param>
        /// <param name="inputGLBStreamStartPosition">Offset into the buffer that the GLB starts</param>
        /// <returns>A constructed GLBObject</returns>
        public static GLBObject ConstructFromGLB(GLTFRoot root, Stream inputGLBStream, Stream outStream = null,
                                                 long inputGLBStreamStartPosition = 0)
        {
            if (outStream != null)
            {
                inputGLBStream.Position = inputGLBStreamStartPosition;
                inputGLBStream.CopyTo(outStream);
            }
            else
            {
                outStream = inputGLBStream;
            }

            // header information is 4 bytes in, past the magic number
            inputGLBStream.Position = 4 + inputGLBStreamStartPosition;
            GLBHeader header = GLTFParser.ParseGLBHeader(inputGLBStream);

            inputGLBStream.Position = GLTFParser.HEADER_SIZE + inputGLBStreamStartPosition;
            List <ChunkInfo> allChunks     = GLTFParser.FindChunks(inputGLBStream);
            ChunkInfo        jsonChunkInfo = new ChunkInfo
            {
                Type = ChunkFormat.JSON
            };
            ChunkInfo binaryChunkInfo = new ChunkInfo
            {
                Type = ChunkFormat.BIN
            };

            foreach (ChunkInfo chunkInfo in allChunks)
            {
                switch (chunkInfo.Type)
                {
                case ChunkFormat.JSON:
                    jsonChunkInfo = chunkInfo;
                    break;

                case ChunkFormat.BIN:
                    binaryChunkInfo = chunkInfo;
                    break;
                }
            }

            if (jsonChunkInfo.Length == 0)
            {
                throw new ArgumentException("JSON chunk must exists for valid GLB", nameof(inputGLBStream));
            }

            // todo: compute the initial bufferview list
            return(new GLBObject
            {
                Root = root,
                Stream = outStream,
                StreamStartPosition = inputGLBStreamStartPosition,
                Header = header,
                JsonChunkInfo = jsonChunkInfo,
                BinaryChunkInfo = binaryChunkInfo
            });
        }
Пример #6
0
        private static void WriteHeader(Stream stream, GLBHeader header, long streamStartPosition)
        {
            stream.Position = streamStartPosition;
            byte[] magicNumber = BitConverter.GetBytes(GLTFParser.MAGIC_NUMBER);
            byte[] version     = BitConverter.GetBytes(header.Version);
            byte[] length      = BitConverter.GetBytes(header.FileLength);

            stream.Write(magicNumber, 0, magicNumber.Length);
            stream.Write(version, 0, version.Length);
            stream.Write(length, 0, length.Length);
        }
Пример #7
0
        private static void ParseJsonChunk(Stream stream, long startPosition)
        {
            GLBHeader header = ParseGLBHeader(stream);              // 4, 8

            if (header.Version != 2)
            {
                throw new GLTFHeaderInvalidException("Unsupported glTF version");
            }
            ;

            if (header.FileLength != (stream.Length - startPosition))
            {
                throw new GLTFHeaderInvalidException("File length does not match header.");
            }

            ChunkInfo chunkInfo = ParseChunkInfo(stream);

            if (chunkInfo.Type != ChunkFormat.JSON)
            {
                throw new GLTFHeaderInvalidException("First chunk must be of type JSON");
            }
        }
Пример #8
0
        private static void ParseJsonChunk(Stream stream, long startPosition)
        {
            GLBHeader header = ParseGLBHeader(stream);              // 4, 8

            if (header.Version != 2)
            {
                throw new GLTFHeaderInvalidException("Unsupported glTF version");
            }
            ;

            if (header.FileLength != (stream.Length - startPosition))
            {
                throw new GLTFHeaderInvalidException("File length does not match header.");
            }

            int chunkLength = (int)GetUInt32(stream);               // 12
            var chunkType   = GetUInt32(stream);                    // 16

            if (chunkType != (uint)ChunkFormat.JSON)
            {
                throw new GLTFHeaderInvalidException("First chunk must be of type JSON");
            }
        }