From 443243a52c517321bf269b1fae5802f9bf290bdd Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Wed, 18 Oct 2017 19:26:27 -0700 Subject: [PATCH] Only ever create one BufferViewData per file. It is not uncommon for multiple logical textures in an FBX to reference the same filename. Each such filename should yield one buffer view only, and all sharing textures should reference it. --- src/Raw2Gltf.cpp | 54 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index 2ea7465f..3c8e759f 100644 --- a/src/Raw2Gltf.cpp +++ b/src/Raw2Gltf.cpp @@ -93,6 +93,35 @@ struct GLTFData return bufferView; } + std::shared_ptr AddBufferViewForFile(BufferData &buffer, const std::string &filename) + { + // see if we've already created a BufferViewData for this precise file + auto iter = filenameToBufferView.find(filename); + if (iter != filenameToBufferView.end()) { + return iter->second; + } + + std::shared_ptr result; + std::ifstream file(filename, std::ios::binary | std::ios::ate); + if (file) { + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + + std::vector fileBuffer(size); + if (file.read(fileBuffer.data(), size)) { + result = AddRawBufferView(buffer, fileBuffer.data(), size); + } else { + fmt::printf("Warning: Couldn't read %lu bytes from %s, skipping\n", size, filename); + } + } else { + fmt::printf("Warning: Couldn't open texture file %s, skipping\n", filename); + } + // note that we persist here not only success, but also failure, as nullptr + filenameToBufferView[filename] = result; + return result; + } + + template std::shared_ptr AddAccessorWithView( BufferViewData &bufferView, const GLType &type, const std::vector &source) @@ -164,8 +193,13 @@ struct GLTFData } const bool isGlb; + + // cache BufferViewData instances that've already been created from a given filename + std::map> filenameToBufferView; + std::shared_ptr > binary; + Holder buffers; Holder bufferViews; Holder accessors; @@ -332,23 +366,13 @@ ModelData *Raw2Gltf( ImageData *source = nullptr; if (options.outputBinary) { - std::ifstream file(texFilename, std::ios::binary | std::ios::ate); - if (file) { - std::streamsize size = file.tellg(); - file.seekg(0, std::ios::beg); - - std::vector fileBuffer(size); - if (file.read(fileBuffer.data(), size)) { - auto bufferView = gltf->AddRawBufferView(buffer, fileBuffer.data(), size); - source = new ImageData(textureName, *bufferView, "image/png"); - } else { - fmt::printf("Warning: Couldn't read %lu bytes from %s, skipping\n", size, texFilename.c_str()); - } - } else { - fmt::printf("Warning: Couldn't open texture file %s, skipping\n", texFilename.c_str()); + auto bufferView = gltf->AddBufferViewForFile(buffer, texFilename); + if (bufferView) { + source = new ImageData(textureName, *bufferView, "image/png"); } + } else { - // TODO: write to buffer.bin? + // TODO: don't add .ktx here; try to work out a reasonable relative path. source = new ImageData(textureName, textureName + ".ktx"); } if (!source) {