Texture size reduction on the fly for 3D model using metadata 99/284399/17
authorRichard <r.huang@samsung.com>
Wed, 16 Nov 2022 14:56:40 +0000 (14:56 +0000)
committerRichard Huang <r.huang@samsung.com>
Mon, 5 Dec 2022 12:28:05 +0000 (12:28 +0000)
Change-Id: Id07b93141797569bc99496c8baa9f72e6a4dde15

13 files changed:
automated-tests/resources/AnimatedCube.metadata [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-DliLoader.cpp
automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/loader/gltf2-asset.cpp
dali-scene3d/internal/loader/gltf2-asset.h
dali-scene3d/public-api/file.list
dali-scene3d/public-api/loader/gltf2-loader.cpp
dali-scene3d/public-api/loader/load-result.h
dali-scene3d/public-api/loader/load-scene-metadata.cpp [new file with mode: 0644]
dali-scene3d/public-api/loader/load-scene-metadata.h [new file with mode: 0644]
dali-scene3d/public-api/loader/material-definition.cpp
dali-scene3d/public-api/loader/material-definition.h

diff --git a/automated-tests/resources/AnimatedCube.metadata b/automated-tests/resources/AnimatedCube.metadata
new file mode 100644 (file)
index 0000000..70b5b7f
--- /dev/null
@@ -0,0 +1,17 @@
+ {
+    "images": [
+        {
+            "uri": "AnimatedCube_BaseColor.png",
+            "minWidth": 256,
+            "minHeight": 256,
+            "samplingMode": "BOX_THEN_NEAREST"
+        },
+        {
+            "uri": "AnimatedCube_MetallicRoughness.png",
+            "minWidth": 256,
+            "minHeight": 256,
+            "samplingMode": "NEAREST"
+        }
+    ]
+}
+
index 6a33200..c663327 100644 (file)
 // Enable debug log for test coverage
 #define DEBUG_ENABLED 1
 
+#include <dali-scene3d/internal/loader/json-util.h>
+#include <dali-scene3d/public-api/loader/dli-loader.h>
+#include <dali-scene3d/public-api/loader/load-result.h>
+#include <dali-scene3d/public-api/loader/resource-bundle.h>
+#include <dali-scene3d/public-api/loader/scene-definition.h>
 #include <dali-test-suite-utils.h>
 #include <string_view>
-#include "dali-scene3d/internal/loader/json-util.h"
-#include "dali-scene3d/public-api/loader/dli-loader.h"
-#include "dali-scene3d/public-api/loader/load-result.h"
-#include "dali-scene3d/public-api/loader/resource-bundle.h"
-#include "dali-scene3d/public-api/loader/scene-definition.h"
 
 using namespace Dali;
 using namespace Dali::Scene3D::Loader;
@@ -61,9 +61,12 @@ struct Context
   std::vector<AnimationDefinition>      animations;
   std::vector<AnimationGroupDefinition> animGroups;
 
+  SceneMetadata metaData;
+
   LoadResult output{
     resources,
     scene,
+    metaData,
     animations,
     animGroups,
     cameraParameters,
index d6687c5..eb19c4d 100644 (file)
 // Enable debug log for test coverage
 #define DEBUG_ENABLED 1
 
+#include <dali-scene3d/public-api/loader/gltf2-loader.h>
+#include <dali-scene3d/public-api/loader/load-result.h>
+#include <dali-scene3d/public-api/loader/resource-bundle.h>
+#include <dali-scene3d/public-api/loader/scene-definition.h>
+#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
 #include <dali-test-suite-utils.h>
 #include <string_view>
-#include "dali-scene3d/public-api/loader/gltf2-loader.h"
-#include "dali-scene3d/public-api/loader/load-result.h"
-#include "dali-scene3d/public-api/loader/resource-bundle.h"
-#include "dali-scene3d/public-api/loader/scene-definition.h"
-#include "dali-scene3d/public-api/loader/shader-definition-factory.h"
 
 using namespace Dali;
 using namespace Dali::Scene3D::Loader;
@@ -61,6 +61,7 @@ struct Context
 
   ResourceBundle  resources;
   SceneDefinition scene;
+  SceneMetadata   metaData;
 
   std::vector<AnimationDefinition>      animations;
   std::vector<AnimationGroupDefinition> animationGroups;
@@ -70,6 +71,7 @@ struct Context
   LoadResult loadResult{
     resources,
     scene,
+    metaData,
     animations,
     animationGroups,
     cameras,
@@ -153,6 +155,21 @@ int UtcDaliGltfLoaderSuccess1(void)
 {
   Context ctx;
 
+  LoadSceneMetadata(TEST_RESOURCE_DIR "/AnimatedCube.metadata", ctx.metaData);
+
+  std::unordered_map<std::string, ImageMetadata> imageMetadataGroundTruth;
+  imageMetadataGroundTruth["AnimatedCube_BaseColor.png"]         = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::BOX_THEN_NEAREST};
+  imageMetadataGroundTruth["AnimatedCube_MetallicRoughness.png"] = ImageMetadata{ImageDimensions(256, 256), Dali::SamplingMode::NEAREST};
+
+  auto metaData = ctx.metaData.mImageMetadata.begin();
+  for(auto& groundTruth : imageMetadataGroundTruth)
+  {
+    DALI_TEST_EQUAL(groundTruth.first, metaData->first);
+    DALI_TEST_EQUAL(groundTruth.second.mMinSize, metaData->second.mMinSize);
+    DALI_TEST_EQUAL(groundTruth.second.mSamplingMode, metaData->second.mSamplingMode);
+    ++metaData;
+  }
+
   ShaderDefinitionFactory sdf;
   sdf.SetResources(ctx.resources);
 
@@ -164,6 +181,17 @@ int UtcDaliGltfLoaderSuccess1(void)
   // Default envmap is used
   DALI_TEST_EQUAL(1u, ctx.resources.mEnvironmentMaps.size());
 
+  TestApplication app;
+
+  Customization::Choices choices;
+  for(auto iRoot : ctx.scene.GetRoots())
+  {
+    auto resourceRefs = ctx.resources.CreateRefCounter();
+    ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs);
+    ctx.resources.CountEnvironmentReferences(resourceRefs);
+    ctx.resources.LoadResources(resourceRefs, ctx.pathProvider);
+  }
+
   auto& materials = ctx.resources.mMaterials;
   DALI_TEST_EQUAL(2u, materials.size());
   const MaterialDefinition materialGroundTruth[]{
@@ -188,22 +216,34 @@ int UtcDaliGltfLoaderSuccess1(void)
      {
        {MaterialDefinition::ALBEDO,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::NORMAL,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::OCCLUSION,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::EMISSIVE,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::SPECULAR,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::SPECULAR_COLOR,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
      }},
     {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
        MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
@@ -226,23 +266,34 @@ int UtcDaliGltfLoaderSuccess1(void)
      {
        {MaterialDefinition::ALBEDO,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
         {"AnimatedCube_MetallicRoughness.png",
-         SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT)}},
+         SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::NEAREST}},
        {MaterialDefinition::NORMAL,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::OCCLUSION,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
        {MaterialDefinition::EMISSIVE,
         {"AnimatedCube_BaseColor.png",
-         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+         ImageDimensions(256, 256),
+         SamplingMode::BOX_THEN_NEAREST}},
      }},
   };
 
   auto iMaterial = materials.begin();
+  auto iMetadata = ctx.metaData.mImageMetadata.begin();
   for(auto& m : materialGroundTruth)
   {
     printf("material %ld\n", iMaterial - materials.begin());
@@ -271,9 +322,13 @@ int UtcDaliGltfLoaderSuccess1(void)
       DALI_TEST_EQUAL(iTexture->mSemantic, ts.mSemantic);
       DALI_TEST_EQUAL(iTexture->mTexture.mImageUri, ts.mTexture.mImageUri);
       DALI_TEST_EQUAL(uint32_t(iTexture->mTexture.mSamplerFlags), uint32_t(ts.mTexture.mSamplerFlags)); // don't interpret it as a character
+      DALI_TEST_EQUAL(iTexture->mTexture.mMinImageDimensions, ts.mTexture.mMinImageDimensions);
+      DALI_TEST_EQUAL(iTexture->mTexture.mSamplingMode, ts.mTexture.mSamplingMode);
+
       ++iTexture;
     }
     ++iMaterial;
+    ++iMetadata;
   }
 
   auto& meshes = ctx.resources.mMeshes;
index 86893a7..73f1248 100644 (file)
@@ -425,7 +425,14 @@ void Model::LoadModel()
   std::vector<Dali::Scene3D::Loader::AnimationDefinition> animations;
   animations.clear();
 
-  Dali::Scene3D::Loader::LoadResult output{resources, scene, animations, animGroups, cameraParameters, lights};
+  Dali::Scene3D::Loader::SceneMetadata metaData;
+
+  std::filesystem::path metaDataUrl = modelUrl;
+  metaDataUrl.replace_extension("metadata");
+
+  Dali::Scene3D::Loader::LoadSceneMetadata(metaDataUrl.c_str(), metaData);
+
+  Dali::Scene3D::Loader::LoadResult output{resources, scene, metaData, animations, animGroups, cameraParameters, lights};
 
   if(extension == DLI_EXTENSION)
   {
index 8297045..a747405 100644 (file)
 * limitations under the License.
 *
 */
-#include "dali-scene3d/internal/loader/gltf2-asset.h"
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
 #include <algorithm>
 #include <map>
-#include "dali/public-api/math/matrix.h"
 
-#define ENUM_STRING_MAPPING(t, x) \
-  {                               \
-#x, t::x                      \
-  }
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/loader/gltf2-asset.h>
 
 using namespace Dali;
 
@@ -82,6 +81,12 @@ const std::map<std::string_view, Animation::Channel::Target::Type> ANIMATION_CHA
 
 } // namespace
 
+ENUM_TYPE_FROM_STRING(AccessorType, ACCESSOR_TYPES)
+ENUM_TYPE_FROM_STRING(AlphaMode, ALPHA_MODE_TYPES)
+ENUM_TYPE_FROM_STRING(Attribute, ATTRIBUTE_TYPES)
+ENUM_TYPE_FROM_STRING(Animation::Sampler::Interpolation, ANIMATION_SAMPLER_INTERPOLATION)
+ENUM_TYPE_FROM_STRING(Animation::Channel::Target, ANIMATION_CHANNEL_TARGET_PATH_TYPES)
+
 bool Component::IsUnsigned(Type t)
 {
   return t == UNSIGNED_BYTE || t == UNSIGNED_SHORT || t == UNSIGNED_INT;
@@ -110,64 +115,11 @@ uint32_t AccessorType::ElementCount(Type t)
   return ACCESSOR_TYPE_ELEMENT_COUNT[t];
 }
 
-AccessorType::Type AccessorType::FromString(const char* s, size_t len)
-{
-  auto iFind = ACCESSOR_TYPES.find(std::string_view(s, len));
-  if(iFind != ACCESSOR_TYPES.end())
-  {
-    return iFind->second;
-  }
-  return AccessorType::INVALID;
-}
-
-AlphaMode::Type AlphaMode::FromString(const char* s, size_t len)
-{
-  auto iFind = ALPHA_MODE_TYPES.find(std::string_view(s, len));
-  if(iFind != ALPHA_MODE_TYPES.end())
-  {
-    return iFind->second;
-  }
-  return AlphaMode::INVALID;
-}
-
-Attribute::Type Attribute::FromString(const char* s, size_t len)
-{
-  auto iFind = ATTRIBUTE_TYPES.find(std::string_view(s, len));
-  if(iFind != ATTRIBUTE_TYPES.end())
-  {
-    return iFind->second;
-  }
-  return Attribute::INVALID;
-}
-
-Animation::Sampler::Interpolation::Type Animation::Sampler::Interpolation::FromString(const char* s, size_t len)
-{
-  auto iFind = ANIMATION_SAMPLER_INTERPOLATION.find(std::string_view(s, len));
-  if(iFind != ANIMATION_SAMPLER_INTERPOLATION.end())
-  {
-    return iFind->second;
-  }
-  return Animation::Sampler::Interpolation::Type::INVALID;
-}
-
 uint32_t ComponentTypedBufferViewClient::GetBytesPerComponent() const
 {
   return Component::Size(mComponentType);
 }
 
-Animation::Channel::Target::Type Animation::Channel::Target::FromString(const char* s, size_t len)
-{
-  std::string target(s, len);
-  std::transform(target.begin(), target.end(), target.begin(), ::toupper);
-
-  auto iFind = ANIMATION_CHANNEL_TARGET_PATH_TYPES.find(std::string_view(target.c_str(), len));
-  if(iFind != ANIMATION_CHANNEL_TARGET_PATH_TYPES.end())
-  {
-    return iFind->second;
-  }
-  return Animation::Channel::Target::INVALID;
-};
-
 void Node::SetMatrix(const Matrix& m)
 {
   m.GetTransformComponents(mTranslation, mRotation, mScale);
index 3fa2705..19d56b6 100644 (file)
 #include "dali/public-api/math/quaternion.h"
 #include "dali/public-api/math/vector4.h"
 
+#define ENUM_STRING_MAPPING(t, x) \
+  {                               \
+#x, t::x                      \
+  }
+
+#define ENUM_TYPE_FROM_STRING(structName, table)                             \
+  structName::Type structName::FromString(const char* s, size_t len)         \
+  {                                                                          \
+    std::string target(s, len);                                              \
+    std::transform(target.begin(), target.end(), target.begin(), ::toupper); \
+                                                                             \
+    auto iFind = table.find(std::string_view(target.c_str(), len));          \
+    if(iFind != table.end())                                                 \
+    {                                                                        \
+      return iFind->second;                                                  \
+    }                                                                        \
+    return structName::INVALID;                                              \
+  }
+
 namespace gltf2
 {
 using Index = Dali::Scene3D::Loader::Index;
@@ -365,14 +384,14 @@ struct Material : Named
     //TODO: extras
   };
 
-  Pbr               mPbrMetallicRoughness;
-  TextureInfo       mNormalTexture;
-  TextureInfo       mOcclusionTexture;
-  TextureInfo       mEmissiveTexture;
-  Dali::Vector3     mEmissiveFactor;
-  AlphaMode::Type   mAlphaMode   = AlphaMode::OPAQUE;
-  float             mAlphaCutoff = .5f;
-  bool              mDoubleSided = false;
+  Pbr             mPbrMetallicRoughness;
+  TextureInfo     mNormalTexture;
+  TextureInfo     mOcclusionTexture;
+  TextureInfo     mEmissiveTexture;
+  Dali::Vector3   mEmissiveFactor;
+  AlphaMode::Type mAlphaMode   = AlphaMode::OPAQUE;
+  float           mAlphaCutoff = .5f;
+  bool            mDoubleSided = false;
 
   //extensions
   MaterialExtensions mMaterialExtensions;
index 1ce931f..29a1b33 100644 (file)
@@ -18,6 +18,7 @@ set(scene3d_src_files ${scene3d_src_files}
        ${scene3d_public_api_dir}/loader/facial-animation-loader.cpp
        ${scene3d_public_api_dir}/loader/gltf2-loader.cpp
        ${scene3d_public_api_dir}/loader/ktx-loader.cpp
+       ${scene3d_public_api_dir}/loader/load-scene-metadata.cpp
        ${scene3d_public_api_dir}/loader/material-definition.cpp
        ${scene3d_public_api_dir}/loader/matrix-stack.cpp
        ${scene3d_public_api_dir}/loader/mesh-definition.cpp
index e6d34fc..75d7ad0 100644 (file)
  * limitations under the License.
  *
  */
-#include <fstream>
+
+// FILE HEADER
 #include <dali-scene3d/public-api/loader/gltf2-loader.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/math/quaternion.h>
+#include <fstream>
+
+// INTERNAL INCLUDES
 #include <dali-scene3d/internal/loader/gltf2-asset.h>
 #include <dali-scene3d/public-api/loader/load-result.h>
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
 #include <dali-scene3d/public-api/loader/shader-definition-factory.h>
 #include <dali-scene3d/public-api/loader/utils.h>
-#include <dali/public-api/math/quaternion.h>
-#include <dali/integration-api/debug.h>
-
-#define ENUM_STRING_MAPPING(t, x) \
-  {                               \
-#x, t::x                      \
-  }
 
 namespace gt = gltf2;
 namespace js = json;
@@ -178,7 +180,6 @@ const auto MATERIAL_SPECULAR_READER = std::move(js::Reader<gt::MaterialSpecular>
 const auto MATERIAL_IOR_READER = std::move(js::Reader<gt::MaterialIor>()
                                              .Register(*js::MakeProperty("ior", js::Read::Number<float>, &gt::MaterialIor::mIor)));
 
-
 const auto MATERIAL_EXTENSION_READER = std::move(js::Reader<gt::MaterialExtensions>()
                                                    .Register(*js::MakeProperty("KHR_materials_ior", js::ObjectReader<gt::MaterialIor>::Read, &gt::MaterialExtensions::mMaterialIor))
                                                    .Register(*js::MakeProperty("KHR_materials_specular", js::ObjectReader<gt::MaterialSpecular>::Read, &gt::MaterialExtensions::mMaterialSpecular)));
@@ -437,13 +438,24 @@ SamplerFlags::Type ConvertSampler(const gt::Ref<gt::Sampler>& s)
   }
 }
 
-TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm)
+TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, const ImageMetadata& metaData = ImageMetadata())
 {
-  return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler)};
+  return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode};
 }
 
-void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMaterials)& outMaterials)
+void ConvertMaterial(const gt::Material& material, const std::unordered_map<std::string, ImageMetadata>& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials)
 {
+  auto getTextureMetaData = [](const std::unordered_map<std::string, ImageMetadata>& metaData, const gt::TextureInfo& info) {
+    if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end())
+    {
+      return search->second;
+    }
+    else
+    {
+      return ImageMetadata();
+    }
+  };
+
   MaterialDefinition matDef;
 
   auto& pbr = material.mPbrMetallicRoughness;
@@ -463,7 +475,7 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
   if(pbr.mBaseColorTexture)
   {
     const auto semantic = MaterialDefinition::ALBEDO;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mBaseColorTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mBaseColorTexture, getTextureMetaData(imageMetaData, pbr.mBaseColorTexture))});
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
   }
@@ -479,7 +491,7 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
   {
     const auto semantic = MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
                           MaterialDefinition::GLTF_CHANNELS;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mMetallicRoughnessTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mMetallicRoughnessTexture, getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture))});
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
   }
@@ -492,7 +504,7 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
   if(material.mNormalTexture)
   {
     const auto semantic = MaterialDefinition::NORMAL;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mNormalTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mNormalTexture, getTextureMetaData(imageMetaData, material.mNormalTexture))});
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
   }
@@ -504,7 +516,7 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
   if(material.mOcclusionTexture)
   {
     const auto semantic = MaterialDefinition::OCCLUSION;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mOcclusionTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mOcclusionTexture, getTextureMetaData(imageMetaData, material.mOcclusionTexture))});
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
     matDef.mOcclusionStrength = material.mOcclusionTexture.mStrength;
@@ -513,7 +525,7 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
   if(material.mEmissiveTexture)
   {
     const auto semantic = MaterialDefinition::EMISSIVE;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mEmissiveTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mEmissiveTexture, getTextureMetaData(imageMetaData, material.mEmissiveTexture))});
     // TODO: and there had better be one
     matDef.mFlags |= semantic;
     matDef.mEmissiveFactor = material.mEmissiveFactor;
@@ -521,8 +533,8 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
 
   if(material.mMaterialExtensions.mMaterialIor.mIor < MAXFLOAT)
   {
-    float ior = material.mMaterialExtensions.mMaterialIor.mIor;
-    matDef.mDielectricSpecular = powf((ior-1.0f)/(ior+1.0f), 2.0f);
+    float ior                  = material.mMaterialExtensions.mMaterialIor.mIor;
+    matDef.mDielectricSpecular = powf((ior - 1.0f) / (ior + 1.0f), 2.0f);
   }
   matDef.mSpecularFactor      = material.mMaterialExtensions.mMaterialSpecular.mSpecularFactor;
   matDef.mSpecularColorFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularColorFactor;
@@ -530,14 +542,14 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
   if(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)
   {
     const auto semantic = MaterialDefinition::SPECULAR;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture))});
     matDef.mFlags |= semantic;
   }
 
   if(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)
   {
     const auto semantic = MaterialDefinition::SPECULAR_COLOR;
-    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)});
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture))});
     matDef.mFlags |= semantic;
   }
 
@@ -548,12 +560,14 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
 
 void ConvertMaterials(const gt::Document& doc, ConversionContext& context)
 {
+  auto& imageMetaData = context.mOutput.mSceneMetadata.mImageMetadata;
+
   auto& outMaterials = context.mOutput.mResources.mMaterials;
   outMaterials.reserve(doc.mMaterials.size());
 
   for(auto& m : doc.mMaterials)
   {
-    ConvertMaterial(m, outMaterials);
+    ConvertMaterial(m, imageMetaData, outMaterials);
   }
 }
 
@@ -628,11 +642,11 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& context)
     {
       MeshDefinition meshDefinition;
 
-      auto& attribs          = primitive.mAttributes;
+      auto& attribs                 = primitive.mAttributes;
       meshDefinition.mUri           = attribs.begin()->second->mBufferView->mBuffer->mUri;
       meshDefinition.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[primitive.mMode];
 
-      auto& accPositions = *attribs.find(gt::Attribute::POSITION)->second;
+      auto& accPositions        = *attribs.find(gt::Attribute::POSITION)->second;
       meshDefinition.mPositions = ConvertMeshPrimitiveAccessor(accPositions);
       // glTF2 support vector4 tangent for mesh.
       // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview
@@ -730,10 +744,10 @@ ModelRenderable* MakeModelRenderable(const gt::Mesh::Primitive& prim, Conversion
     // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#default-material
     if(INVALID_INDEX == context.mDefaultMaterial)
     {
-      auto& outMaterials    = context.mOutput.mResources.mMaterials;
+      auto& outMaterials       = context.mOutput.mResources.mMaterials;
       context.mDefaultMaterial = outMaterials.size();
 
-      ConvertMaterial(gt::Material{}, outMaterials);
+      ConvertMaterial(gt::Material{}, context.mOutput.mSceneMetadata.mImageMetadata, outMaterials);
     }
 
     materialIdx = context.mDefaultMaterial;
@@ -814,8 +828,8 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con
     for(uint32_t i = 0; i < primitiveCount; ++i)
     {
       std::unique_ptr<NodeDefinition::Renderable> renderable;
-      auto modelRenderable      = MakeModelRenderable(mesh.mPrimitives[i], context);
-      modelRenderable->mMeshIdx = meshIdx + i;
+      auto                                        modelRenderable = MakeModelRenderable(mesh.mPrimitives[i], context);
+      modelRenderable->mMeshIdx                                   = meshIdx + i;
 
       DALI_ASSERT_DEBUG(resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx == INVALID_INDEX ||
                         resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx == skeletonIdx);
index a9428eb..bd7e486 100644 (file)
  */
 
 // INTERNAL INCLUDES
-#include "dali-scene3d/public-api/api.h"
-#include "dali-scene3d/public-api/loader/animation-definition.h"
-#include "dali-scene3d/public-api/loader/camera-parameters.h"
-#include "dali-scene3d/public-api/loader/light-parameters.h"
+#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/loader/animation-definition.h>
+#include <dali-scene3d/public-api/loader/camera-parameters.h>
+#include <dali-scene3d/public-api/loader/light-parameters.h>
+#include <dali-scene3d/public-api/loader/load-scene-metadata.h>
 
 namespace Dali
 {
@@ -48,6 +49,11 @@ struct DALI_SCENE3D_API LoadResult
   SceneDefinition& mScene;
 
   /**
+   * @brief The metadata of the scene.
+   */
+  SceneMetadata& mSceneMetadata;
+
+  /**
    * @brief The list of animation definitions, in lexicographical order of their names.
    */
   std::vector<AnimationDefinition>& mAnimationDefinitions;
diff --git a/dali-scene3d/public-api/loader/load-scene-metadata.cpp b/dali-scene3d/public-api/loader/load-scene-metadata.cpp
new file mode 100644 (file)
index 0000000..76c1056
--- /dev/null
@@ -0,0 +1,126 @@
+/*\r
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// INTERNAL INCLUDES\r
+#include <dali-scene3d/internal/loader/gltf2-asset.h>\r
+#include <dali-scene3d/internal/loader/json-reader.h>\r
+#include <dali-scene3d/public-api/loader/load-scene-metadata.h>\r
+#include <dali-scene3d/public-api/loader/utils.h>\r
+\r
+namespace js = json;\r
+namespace gt = gltf2;\r
+\r
+namespace Dali::Scene3D::Loader\r
+{\r
+namespace\r
+{\r
+struct ImageData\r
+{\r
+  struct SamplingMode\r
+  {\r
+    enum Type\r
+    {\r
+      INVALID          = -1,\r
+      BOX              = Dali::SamplingMode::BOX,\r
+      NEAREST          = Dali::SamplingMode::NEAREST,\r
+      LINEAR           = Dali::SamplingMode::LINEAR,\r
+      BOX_THEN_NEAREST = Dali::SamplingMode::BOX_THEN_NEAREST,\r
+      BOX_THEN_LINEAR  = Dali::SamplingMode::BOX_THEN_LINEAR,\r
+      NO_FILTER        = Dali::SamplingMode::NO_FILTER,\r
+      DONT_CARE        = Dali::SamplingMode::DONT_CARE\r
+    };\r
+\r
+    static Type FromString(const char* s, size_t len);\r
+  };\r
+\r
+  std::string mImageUri{};  ///< The URI of the image\r
+  uint16_t    mMinWidth{};  ///< The minimum width of the image\r
+  uint16_t    mMinHeight{}; ///< The mimimum height of the image\r
+\r
+  ImageData::SamplingMode::Type mSamplingMode{ImageData::SamplingMode::BOX_THEN_LINEAR}; ///< The sampling mode used to resize the image.\r
+};\r
+\r
+const std::map<std::string_view, ImageData::SamplingMode::Type> SAMPLING_MODE_TYPES{\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX),\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, NEAREST),\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, LINEAR),\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX_THEN_NEAREST),\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX_THEN_LINEAR),\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, NO_FILTER),\r
+  ENUM_STRING_MAPPING(ImageData::SamplingMode, DONT_CARE),\r
+};\r
+\r
+ENUM_TYPE_FROM_STRING(ImageData::SamplingMode, SAMPLING_MODE_TYPES)\r
+\r
+struct MetaData\r
+{\r
+  std::vector<ImageData> mImageData;\r
+};\r
+\r
+const auto IMAGE_METADATA_READER = std::move(js::Reader<ImageData>()\r
+                                               .Register(*js::MakeProperty("uri", js::Read::String, &ImageData::mImageUri))\r
+                                               .Register(*js::MakeProperty("minWidth", js::Read::Number, &ImageData::mMinWidth))\r
+                                               .Register(*js::MakeProperty("minHeight", js::Read::Number, &ImageData::mMinHeight))\r
+                                               .Register(*js::MakeProperty("samplingMode", gt::ReadStringEnum<ImageData::SamplingMode>, &ImageData::mSamplingMode)));\r
+\r
+const auto METADATA_READER = std::move(js::Reader<MetaData>()\r
+                                         .Register(*js::MakeProperty("images", js::Read::Array<ImageData, js::ObjectReader<ImageData>::Read>, &MetaData::mImageData)));\r
+\r
+} // namespace\r
+\r
+void LoadSceneMetadata(const std::string& url, SceneMetadata& sceneMetadata)\r
+{\r
+  bool failed = false;\r
+  auto js     = LoadTextFile(url.c_str(), &failed);\r
+  if(failed)\r
+  {\r
+    return;\r
+  }\r
+\r
+  json::unique_ptr root(json_parse(js.c_str(), js.size()));\r
+  if(!root)\r
+  {\r
+    throw std::runtime_error("Failed to parse " + url);\r
+  }\r
+  auto& rootObj = js::Cast<json_object_s>(*root);\r
+\r
+  static bool setObjectReaders = true;\r
+  if(setObjectReaders)\r
+  {\r
+    js::SetObjectReader(IMAGE_METADATA_READER);\r
+\r
+    setObjectReaders = false;\r
+  }\r
+\r
+  MetaData metaData;\r
+  METADATA_READER.Read(rootObj, metaData);\r
+\r
+  sceneMetadata.mImageMetadata.reserve(metaData.mImageData.size() + metaData.mImageData.size());\r
+  for(auto&& data : metaData.mImageData)\r
+  {\r
+    if(data.mSamplingMode == ImageData::SamplingMode::INVALID)\r
+    {\r
+      throw std::runtime_error("Sampling mode type unsupported.");\r
+    }\r
+    else\r
+    {\r
+      sceneMetadata.mImageMetadata.insert({data.mImageUri, ImageMetadata{ImageDimensions(data.mMinWidth, data.mMinHeight), static_cast<Dali::SamplingMode::Type>(data.mSamplingMode)}});\r
+    }\r
+  }\r
+}\r
+\r
+} // namespace Dali::Scene3D::Loader\r
diff --git a/dali-scene3d/public-api/loader/load-scene-metadata.h b/dali-scene3d/public-api/loader/load-scene-metadata.h
new file mode 100644 (file)
index 0000000..ca7e16f
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef DALI_SCENE3D_LOADER_LOAD_SCENE_METADATA_H_\r
+#define DALI_SCENE3D_LOADER_LOAD_SCENE_METADATA_H_\r
+/*\r
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// EXTERNAL INCLUDES\r
+#include <dali/public-api/images/image-operations.h>\r
+#include <string>\r
+#include <unordered_map>\r
+\r
+// INTERNAL INCLUDES\r
+#include <dali-scene3d/public-api/api.h>\r
+\r
+namespace Dali::Scene3D::Loader\r
+{\r
+/**\r
+ * @brief Defines the matadata for an image.\r
+ */\r
+struct ImageMetadata\r
+{\r
+  ImageDimensions    mMinSize{};                                   ///< The minimum required image size for rendering\r
+  SamplingMode::Type mSamplingMode{SamplingMode::BOX_THEN_LINEAR}; ///< The sampling mode used to resize the image\r
+};\r
+\r
+/**\r
+ * @brief Stores the metadata for a scene.\r
+ *\r
+ * @note The supported format is the following:\r
+ *  {\r
+ *    "images": (optional) [ {\r
+ *      "uri": name of the image file,\r
+ *      "minWidth": minimum width required for rendering,\r
+ *      "minHeight": minimum height required for rendering.\r
+ *      "samplingMode": sampling mode used to resize the image (@see Dali::SamplingMode). (optional)\r
+ *    } ]\r
+ *  }\r
+ */\r
+struct SceneMetadata\r
+{\r
+  std::unordered_map<std::string, ImageMetadata> mImageMetadata{}; ///< The container of image metadata (i.e. the pairs of image URI and image metadata)\r
+};\r
+\r
+/**\r
+ * @brief Attempts to load and process a json file specifying scene metadata\r
+ * for pre-processing the scene resources: e.g. the minimum size required for rendering images, etc.\r
+ * @note Will fail quietly if the file is not present.\r
+ */\r
+DALI_SCENE3D_API void LoadSceneMetadata(const std::string& url, SceneMetadata& sceneMetadata);\r
+\r
+} // namespace Dali::Scene3D::Loader\r
+\r
+#endif // DALI_SCENE3D_LOADER_LOAD_SCENE_METADATA_H_\r
index 7f86add..7245652 100644 (file)
@@ -100,9 +100,11 @@ Sampler SamplerFlags::MakeSampler(Type flags)
   return sampler;
 }
 
-TextureDefinition::TextureDefinition(const std::string& imageUri, SamplerFlags::Type samplerFlags)
+TextureDefinition::TextureDefinition(const std::string& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode)
 : mImageUri(imageUri),
-  mSamplerFlags(samplerFlags)
+  mSamplerFlags(samplerFlags),
+  mMinImageDimensions(minImageDimensions),
+  mSamplingMode(samplingMode)
 {
 }
 
@@ -130,12 +132,12 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
   // Check for compulsory textures: Albedo, Metallic, Roughness, Normal
   if(checkStage(ALBEDO | METALLIC))
   {
-    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
     ++iTexture;
 
     if(checkStage(NORMAL | ROUGHNESS))
     {
-      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
       ++iTexture;
     }
     else // single value normal-roughness
@@ -149,7 +151,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
   {
     if(checkStage(ALBEDO))
     {
-      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
       ++iTexture;
     }
     else if(mNeedAlbedoTexture) // single value albedo, albedo-alpha or albedo-metallic
@@ -183,7 +185,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
     const bool createMetallicRoughnessAndNormal = hasTransparency || std::distance(mTextureStages.begin(), iTexture) > 0;
     if(checkStage(METALLIC | ROUGHNESS))
     {
-      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
       ++iTexture;
     }
     else if(createMetallicRoughnessAndNormal && mNeedMetallicRoughnessTexture)
@@ -197,7 +199,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
 
     if(checkStage(NORMAL))
     {
-      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+      raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
       ++iTexture;
     }
     else if(mNeedNormalTexture)
@@ -220,31 +222,31 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
   // Extra textures.
   if(checkStage(SUBSURFACE))
   {
-    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
     ++iTexture;
   }
 
   if(checkStage(OCCLUSION))
   {
-    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
     ++iTexture;
   }
 
   if(checkStage(EMISSIVE))
   {
-    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
     ++iTexture;
   }
 
   if(checkStage(SPECULAR))
   {
-    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
     ++iTexture;
   }
 
   if(checkStage(SPECULAR_COLOR))
   {
-    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri, iTexture->mTexture.mMinImageDimensions, FittingMode::DEFAULT, iTexture->mTexture.mSamplingMode, true), iTexture->mTexture.mSamplerFlags});
     ++iTexture;
   }
 
index 119f7c4..08b59c6 100644 (file)
@@ -24,6 +24,7 @@
 #include "dali-scene3d/public-api/loader/utils.h"
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/images/image-operations.h>
 #include <cmath>
 #include "dali/public-api/common/vector-wrapper.h"
 #include "dali/public-api/math/vector4.h"
@@ -115,8 +116,10 @@ struct DALI_SCENE3D_API TextureDefinition
 {
   std::string        mImageUri;
   SamplerFlags::Type mSamplerFlags;
+  ImageDimensions    mMinImageDimensions;
+  SamplingMode::Type mSamplingMode;
 
-  TextureDefinition(const std::string& imageUri = "", SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT);
+  TextureDefinition(const std::string& imageUri = "", SamplerFlags::Type samplerFlags = SamplerFlags::DEFAULT, ImageDimensions minImageDimensions = ImageDimensions(), SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR);
 };
 
 /**