From cb1187e9e6a39bd7e31f2b46382d3b878ae5b348 Mon Sep 17 00:00:00 2001 From: LeeRiva <76054616+LeeRiva@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:28:59 +0200 Subject: [PATCH 1/4] The vsgXchange::assimp ReaderWriter now offers the option of not embedding texture files into the generated vsg native file. This is done by setting the external_textures option to true. Note that this does not work for textures already embedded within the source model! In addition, by suppling the external_texture_format command line option, it is possible to specify whether the stand-alone texture files should be saved in the vsg-native format (either vsgt or vsga). By dong this there is no need for the integrating application to link against vsgXchange for texture conversion. --- include/vsgXchange/models.h | 2 + src/assimp/assimp.cpp | 88 ++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/include/vsgXchange/models.h b/include/vsgXchange/models.h index 5c0d032..f777769 100644 --- a/include/vsgXchange/models.h +++ b/include/vsgXchange/models.h @@ -54,6 +54,8 @@ namespace vsgXchange static constexpr const char* crease_angle = "crease_angle"; /// float static constexpr const char* two_sided = "two_sided"; /// bool static constexpr const char* discard_empty_nodes = "discard_empty_nodes"; /// bool + static constexpr const char* external_textures = "external_textures"; /// bool + static constexpr const char* external_texture_format = "external_texture_format"; // TextureFormat bool readOptions(vsg::Options& options, vsg::CommandLine& arguments) const override; diff --git a/src/assimp/assimp.cpp b/src/assimp/assimp.cpp index 25887af..b140887 100644 --- a/src/assimp/assimp.cpp +++ b/src/assimp/assimp.cpp @@ -16,6 +16,31 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include +enum class TextureFormat +{ + native, + vsgt, + vsgb +}; + +// this needs to be defined before 'vsg/commandline.h' has been included +std::istream& operator>> (std::istream& is, TextureFormat& textureFormat) +{ + std::string value; + is >> value; + + if (value == "native") + textureFormat = TextureFormat::native; + else if (value == "vsgb") + textureFormat = TextureFormat::vsgb; + else if ((value == "vsgt")||(value == "vsga")) + textureFormat = TextureFormat::vsgt; + else + textureFormat = TextureFormat::native; + + return is; +} + #include #include @@ -117,6 +142,8 @@ bool assimp::getFeatures(Features& features) const features.optionNameTypeMap[assimp::crease_angle] = vsg::type_name(); features.optionNameTypeMap[assimp::two_sided] = vsg::type_name(); features.optionNameTypeMap[assimp::discard_empty_nodes] = vsg::type_name(); + features.optionNameTypeMap[assimp::external_textures] = vsg::type_name(); + features.optionNameTypeMap[assimp::external_texture_format] = vsg::type_name(); return true; } @@ -128,6 +155,9 @@ bool assimp::readOptions(vsg::Options& options, vsg::CommandLine& arguments) con result = arguments.readAndAssign(assimp::crease_angle, &options) || result; result = arguments.readAndAssign(assimp::two_sided, &options) || result; result = arguments.readAndAssign(assimp::discard_empty_nodes, &options) || result; + result = arguments.readAndAssign(assimp::external_textures, &options) || result; + result = arguments.readAndAssign(assimp::external_texture_format, &options) || result; + return result; } @@ -149,11 +179,14 @@ struct SceneConverter bool useViewDependentState = true; bool discardEmptyNodes = true; + bool externalTextures = false; + TextureFormat externalTextureFormat = TextureFormat::native; // TODO flatShadedShaderSet? vsg::ref_ptr pbrShaderSet; vsg::ref_ptr phongShaderSet; vsg::ref_ptr sharedObjects; + vsg::ref_ptr externalObjects; std::vector> convertedMaterials; std::vector> convertedMeshes; @@ -250,6 +283,7 @@ SamplerData SceneConverter::convertTexture(const aiMaterial& material, aiTexture if (material.GetTexture(type, 0, &texPath, nullptr, nullptr, nullptr, nullptr, wrapMode) == AI_SUCCESS) { SamplerData samplerImage; + vsg::Path externalTextureFilename; if (auto texture = scene->GetEmbeddedTexture(texPath.C_Str())) { @@ -288,10 +322,10 @@ SamplerData SceneConverter::convertTexture(const aiMaterial& material, aiTexture } else { - auto textureFilename = vsg::findFile(texPath.C_Str(), options); - if (samplerImage.data = vsg::read_cast(textureFilename, options); !samplerImage.data.valid()) + externalTextureFilename = vsg::findFile(texPath.C_Str(), options); + if (samplerImage.data = vsg::read_cast(externalTextureFilename, options); !samplerImage.data.valid()) { - vsg::warn("Failed to load texture: ", textureFilename, " texPath = ", texPath.C_Str()); + vsg::warn("Failed to load texture: ", externalTextureFilename, " texPath = ", texPath.C_Str()); return {}; } } @@ -317,6 +351,40 @@ SamplerData SceneConverter::convertTexture(const aiMaterial& material, aiTexture sharedObjects->share(samplerImage.sampler); } + if (externalTextures && externalObjects) + { + // calculate the texture filename + switch (externalTextureFormat) + { + case TextureFormat::native: + break; /// nothing to do + case TextureFormat::vsgt: + externalTextureFilename = vsg::removeExtension(externalTextureFilename).concat(".vsgt"); + break; + case TextureFormat::vsgb: + externalTextureFilename = vsg::removeExtension(externalTextureFilename).concat(".vsgb"); + break; + } + + // actually write out the texture.. this need only be done once per texture! + if (externalObjects->entries.count(externalTextureFilename) == 0) + { + switch (externalTextureFormat) + { + case TextureFormat::native: + break; /// nothing to do + case TextureFormat::vsgt: + vsg::write(samplerImage.data, externalTextureFilename, options); + break; + case TextureFormat::vsgb: + vsg::write(samplerImage.data, externalTextureFilename, options); + break; + } + + externalObjects->add(externalTextureFilename, samplerImage.data); + } + } + return samplerImage; } else @@ -717,11 +785,14 @@ vsg::ref_ptr SceneConverter::visit(const aiScene* in_scene, vsg::ref_ scene = in_scene; options = in_options; discardEmptyNodes = vsg::value(true, assimp::discard_empty_nodes, options); + externalTextures = vsg::value(false, assimp::external_textures, options); + externalTextureFormat = vsg::value(TextureFormat::native, assimp::external_texture_format, options); std::string name = scene->mName.C_Str(); if (options) sharedObjects = options->sharedObjects; if (!sharedObjects) sharedObjects = vsg::SharedObjects::create(); + if (!externalObjects) externalObjects = vsg::External::create(); processCameras(); processLights(); @@ -1023,7 +1094,14 @@ vsg::ref_ptr assimp::Implementation::read(const vsg::Path& filename SceneConverter converter; converter.filename = filename; - return converter.visit(scene, opt, ext); + + if (auto root = converter.visit(scene, opt, ext)) + { + if (converter.externalTextures && converter.externalObjects && !converter.externalObjects->entries.empty()) + root->setObject("external", converter.externalObjects); + + return root; + } } else { @@ -1038,7 +1116,7 @@ vsg::ref_ptr assimp::Implementation::read(const vsg::Path& filename opt->paths.push_back(vsg::filePath(filename)); opt->extensionHint = vsg::lowerCaseFileExtension(filename); - return read(file, opt); + return vsg::read(file, opt); #endif return {}; From 39d0cf8f433e6ce34a0f163db12feec2ff7c0894 Mon Sep 17 00:00:00 2001 From: LeeRiva <76054616+LeeRiva@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:58:46 +0200 Subject: [PATCH 2/4] Fixed documentation --- include/vsgXchange/models.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/vsgXchange/models.h b/include/vsgXchange/models.h index f777769..1a060ad 100644 --- a/include/vsgXchange/models.h +++ b/include/vsgXchange/models.h @@ -55,7 +55,7 @@ namespace vsgXchange static constexpr const char* two_sided = "two_sided"; /// bool static constexpr const char* discard_empty_nodes = "discard_empty_nodes"; /// bool static constexpr const char* external_textures = "external_textures"; /// bool - static constexpr const char* external_texture_format = "external_texture_format"; // TextureFormat + static constexpr const char* external_texture_format = "external_texture_format"; /// TextureFormat enum bool readOptions(vsg::Options& options, vsg::CommandLine& arguments) const override; From e1cafc890154ad8d6fc6c897dc8f43131bf84fde Mon Sep 17 00:00:00 2001 From: LeeRiva <76054616+LeeRiva@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:20:26 +0200 Subject: [PATCH 3/4] Updated comments --- src/assimp/assimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assimp/assimp.cpp b/src/assimp/assimp.cpp index b140887..512e8a0 100644 --- a/src/assimp/assimp.cpp +++ b/src/assimp/assimp.cpp @@ -357,7 +357,7 @@ SamplerData SceneConverter::convertTexture(const aiMaterial& material, aiTexture switch (externalTextureFormat) { case TextureFormat::native: - break; /// nothing to do + break; // nothing to do case TextureFormat::vsgt: externalTextureFilename = vsg::removeExtension(externalTextureFilename).concat(".vsgt"); break; @@ -372,7 +372,7 @@ SamplerData SceneConverter::convertTexture(const aiMaterial& material, aiTexture switch (externalTextureFormat) { case TextureFormat::native: - break; /// nothing to do + break; // nothing to do case TextureFormat::vsgt: vsg::write(samplerImage.data, externalTextureFilename, options); break; From 5e5a1e0696e8aa12f5747b8c09fc1109991f7923 Mon Sep 17 00:00:00 2001 From: LeeRiva <76054616+LeeRiva@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:23:49 +0200 Subject: [PATCH 4/4] Integrated PR review suggestions --- src/assimp/assimp.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/assimp/assimp.cpp b/src/assimp/assimp.cpp index 512e8a0..0ab7163 100644 --- a/src/assimp/assimp.cpp +++ b/src/assimp/assimp.cpp @@ -792,7 +792,7 @@ vsg::ref_ptr SceneConverter::visit(const aiScene* in_scene, vsg::ref_ if (options) sharedObjects = options->sharedObjects; if (!sharedObjects) sharedObjects = vsg::SharedObjects::create(); - if (!externalObjects) externalObjects = vsg::External::create(); + if (externalTextures && !externalObjects) externalObjects = vsg::External::create(); processCameras(); processLights(); @@ -1095,13 +1095,14 @@ vsg::ref_ptr assimp::Implementation::read(const vsg::Path& filename SceneConverter converter; converter.filename = filename; - if (auto root = converter.visit(scene, opt, ext)) + auto root = converter.visit(scene, opt, ext); + if (root) { if (converter.externalTextures && converter.externalObjects && !converter.externalObjects->entries.empty()) root->setObject("external", converter.externalObjects); - - return root; } + + return root; } else {