|
@@ -512,6 +512,7 @@ inline void BufferView::Read(Value& obj, Asset& r)
|
|
|
|
|
|
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
|
|
|
byteLength = MemberOrDefault(obj, "byteLength", 0u);
|
|
|
+ byteStride = MemberOrDefault(obj, "byteStride", 0u);
|
|
|
}
|
|
|
|
|
|
//
|
|
@@ -526,7 +527,6 @@ inline void Accessor::Read(Value& obj, Asset& r)
|
|
|
}
|
|
|
|
|
|
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
|
|
|
- byteStride = MemberOrDefault(obj, "byteStride", 0u);
|
|
|
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
|
|
|
count = MemberOrDefault(obj, "count", 0u);
|
|
|
|
|
@@ -601,7 +601,7 @@ bool Accessor::ExtractData(T*& outData)
|
|
|
const size_t elemSize = GetElementSize();
|
|
|
const size_t totalSize = elemSize * count;
|
|
|
|
|
|
- const size_t stride = byteStride ? byteStride : elemSize;
|
|
|
+ const size_t stride = bufferView && bufferView->byteStride ? bufferView->byteStride : elemSize;
|
|
|
|
|
|
const size_t targetElemSize = sizeof(T);
|
|
|
ai_assert(elemSize <= targetElemSize);
|
|
@@ -641,7 +641,7 @@ inline Accessor::Indexer::Indexer(Accessor& acc)
|
|
|
: accessor(acc)
|
|
|
, data(acc.GetPointer())
|
|
|
, elemSize(acc.GetElementSize())
|
|
|
- , stride(acc.byteStride ? acc.byteStride : elemSize)
|
|
|
+ , stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize)
|
|
|
{
|
|
|
|
|
|
}
|
|
@@ -1037,7 +1037,72 @@ inline void AssetMetadata::Read(Document& doc)
|
|
|
// Asset methods implementation
|
|
|
//
|
|
|
|
|
|
-inline void Asset::Load(const std::string& pFile)
|
|
|
+inline void Asset::ReadBinaryHeader(IOStream& stream, std::vector<char>& sceneData)
|
|
|
+{
|
|
|
+ GLB_Header header;
|
|
|
+ if (stream.Read(&header, sizeof(header), 1) != 1) {
|
|
|
+ throw DeadlyImportError("GLTF: Unable to read the file header");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
|
|
|
+ throw DeadlyImportError("GLTF: Invalid binary glTF file");
|
|
|
+ }
|
|
|
+
|
|
|
+ AI_SWAP4(header.version);
|
|
|
+ asset.version = to_string(header.version);
|
|
|
+ if (header.version != 2) {
|
|
|
+ throw DeadlyImportError("GLTF: Unsupported binary glTF version");
|
|
|
+ }
|
|
|
+
|
|
|
+ GLB_Chunk chunk;
|
|
|
+ if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
|
|
|
+ throw DeadlyImportError("GLTF: Unable to read JSON chunk");
|
|
|
+ }
|
|
|
+
|
|
|
+ AI_SWAP4(chunk.chunkLength);
|
|
|
+ AI_SWAP4(chunk.chunkType);
|
|
|
+
|
|
|
+ if (chunk.chunkType != ChunkType_JSON) {
|
|
|
+ throw DeadlyImportError("GLTF: JSON chunk missing");
|
|
|
+ }
|
|
|
+
|
|
|
+ // read the scene data
|
|
|
+
|
|
|
+ mSceneLength = chunk.chunkLength;
|
|
|
+ sceneData.resize(mSceneLength + 1);
|
|
|
+ sceneData[mSceneLength] = '\0';
|
|
|
+
|
|
|
+ if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
|
|
|
+ throw DeadlyImportError("GLTF: Could not read the file contents");
|
|
|
+ }
|
|
|
+
|
|
|
+ uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength;
|
|
|
+ if (padding > 0) {
|
|
|
+ stream.Seek(padding, aiOrigin_CUR);
|
|
|
+ }
|
|
|
+
|
|
|
+ AI_SWAP4(header.length);
|
|
|
+ mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8;
|
|
|
+ if (header.length >= mBodyOffset) {
|
|
|
+ if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
|
|
|
+ throw DeadlyImportError("GLTF: Unable to read BIN chunk");
|
|
|
+ }
|
|
|
+
|
|
|
+ AI_SWAP4(chunk.chunkLength);
|
|
|
+ AI_SWAP4(chunk.chunkType);
|
|
|
+
|
|
|
+ if (chunk.chunkType != ChunkType_BIN) {
|
|
|
+ throw DeadlyImportError("GLTF: BIN chunk missing");
|
|
|
+ }
|
|
|
+
|
|
|
+ mBodyLength = chunk.chunkLength;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ mBodyOffset = mBodyLength = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+inline void Asset::Load(const std::string& pFile, bool isBinary)
|
|
|
{
|
|
|
mCurrentAssetDir.clear();
|
|
|
int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
|
|
@@ -1048,16 +1113,25 @@ inline void Asset::Load(const std::string& pFile)
|
|
|
throw DeadlyImportError("GLTF: Could not open file for reading");
|
|
|
}
|
|
|
|
|
|
- mSceneLength = stream->FileSize();
|
|
|
- mBodyLength = 0;
|
|
|
+ // is binary? then read the header
|
|
|
+ std::vector<char> sceneData;
|
|
|
+ if (isBinary) {
|
|
|
+ SetAsBinary(); // also creates the body buffer
|
|
|
+ ReadBinaryHeader(*stream, sceneData);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ mSceneLength = stream->FileSize();
|
|
|
+ mBodyLength = 0;
|
|
|
+
|
|
|
|
|
|
- // read the scene data
|
|
|
+ // read the scene data
|
|
|
|
|
|
- std::vector<char> sceneData(mSceneLength + 1);
|
|
|
- sceneData[mSceneLength] = '\0';
|
|
|
+ sceneData.resize(mSceneLength + 1);
|
|
|
+ sceneData[mSceneLength] = '\0';
|
|
|
|
|
|
- if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
|
|
|
- throw DeadlyImportError("GLTF: Could not read the file contents");
|
|
|
+ if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
|
|
|
+ throw DeadlyImportError("GLTF: Could not read the file contents");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1110,6 +1184,15 @@ inline void Asset::Load(const std::string& pFile)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+inline void Asset::SetAsBinary()
|
|
|
+{
|
|
|
+ if (!mBodyBuffer) {
|
|
|
+ mBodyBuffer = buffers.Create("binary_glTF");
|
|
|
+ mBodyBuffer->MarkAsSpecial();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
inline void Asset::ReadExtensionsUsed(Document& doc)
|
|
|
{
|
|
|
Value* extsUsed = FindArray(doc, "extensionsUsed");
|