From 0b6e8f366cf88af6cfa401817a9f4b8e0995470f 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 2ea7465..4c9a87a 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 + const 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) {