--- /dev/null
+ {
+ "images": [
+ {
+ "uri": "AnimatedCube_BaseColor.png",
+ "minWidth": 256,
+ "minHeight": 256,
+ "samplingMode": "BOX_THEN_NEAREST"
+ },
+ {
+ "uri": "AnimatedCube_MetallicRoughness.png",
+ "minWidth": 256,
+ "minHeight": 256,
+ "samplingMode": "NEAREST"
+ }
+ ]
+}
+
// 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;
std::vector<AnimationDefinition> animations;
std::vector<AnimationGroupDefinition> animGroups;
+ SceneMetadata metaData;
+
LoadResult output{
resources,
scene,
+ metaData,
animations,
animGroups,
cameraParameters,
// 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;
ResourceBundle resources;
SceneDefinition scene;
+ SceneMetadata metaData;
std::vector<AnimationDefinition> animations;
std::vector<AnimationGroupDefinition> animationGroups;
LoadResult loadResult{
resources,
scene,
+ metaData,
animations,
animationGroups,
cameras,
{
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);
// 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[]{
{
{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 |
{
{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());
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;
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)
{
* 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;
} // 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;
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);
#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;
//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;
${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
* 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;
const auto MATERIAL_IOR_READER = std::move(js::Reader<gt::MaterialIor>()
.Register(*js::MakeProperty("ior", js::Read::Number<float>, >::MaterialIor::mIor)));
-
const auto MATERIAL_EXTENSION_READER = std::move(js::Reader<gt::MaterialExtensions>()
.Register(*js::MakeProperty("KHR_materials_ior", js::ObjectReader<gt::MaterialIor>::Read, >::MaterialExtensions::mMaterialIor))
.Register(*js::MakeProperty("KHR_materials_specular", js::ObjectReader<gt::MaterialSpecular>::Read, >::MaterialExtensions::mMaterialSpecular)));
}
}
-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;
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;
}
{
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;
}
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;
}
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;
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;
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;
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;
}
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);
}
}
{
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
// 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;
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);
*/
// 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
{
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;
--- /dev/null
+/*\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
--- /dev/null
+#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
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)
{
}
// 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
{
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
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)
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)
// 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;
}
#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"
{
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);
};
/**