diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d01197982..90be0328dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,7 +173,7 @@ option(NBL_BUILD_DPL "Enable DPL (Dynamic Parallelism Library)" OFF) option(NBL_PCH "Enable pre-compiled header" ON) option(NBL_FAST_MATH "Enable fast low-precision math" OFF) # the reason OFF is by default now is the var controling it at build time was set AFTER BuildConfigOptions was generated - resulting in the feature being always OFF regardless the value xD - so just for sanity, keeping the same behaviour by default option(NBL_BUILD_EXAMPLES "Enable building examples" ON) -option(NBL_BUILD_MITSUBA_LOADER "Enable nbl::ext::MitsubaLoader?" OFF) # TODO: once it compies turn this ON by default! +option(NBL_BUILD_MITSUBA_LOADER "Enable nbl::ext::MitsubaLoader?" ON) option(NBL_BUILD_IMGUI "Enable nbl::ext::ImGui?" ON) option(NBL_BUILD_OPTIX "Enable nbl::ext::OptiX?" OFF) diff --git a/CMakePresets.json b/CMakePresets.json index e91c46d8e9..3117e607ac 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -15,7 +15,7 @@ "NBL_UPDATE_GIT_SUBMODULE": "OFF", "NBL_COMPILE_WITH_CUDA": "OFF", "NBL_BUILD_OPTIX": "OFF", - "NBL_BUILD_MITSUBA_LOADER": "OFF", + "NBL_BUILD_MITSUBA_LOADER": "ON", "NBL_BUILD_RADEON_RAYS": "OFF", "_NBL_COMPILE_WITH_OPEN_EXR_": "ON", "NBL_EXPLICIT_MODULE_LOAD_LOG": "ON", diff --git a/examples_tests b/examples_tests index fd8ebfeaca..bfcff8a686 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit fd8ebfeacaf42f3cf63b1545cccce03809f9c8d6 +Subproject commit bfcff8a686409dd7c0d55607bb8cb6bcc0e0b80a diff --git a/include/nbl/asset/IAsset.h b/include/nbl/asset/IAsset.h index a691fa6af6..7c6a33193d 100644 --- a/include/nbl/asset/IAsset.h +++ b/include/nbl/asset/IAsset.h @@ -156,24 +156,24 @@ class IAsset : virtual public core::IReferenceCounted //! inline bool isMutable() const {return m_mutable;} - inline void visitDependents(std::function visit) const - { - visitDependents_impl([&visit](const IAsset* dep)->bool - { - if (dep) - return visit(dep); - return true; - }); - } - - inline void visitDependents(std::function visit) - { - assert(isMutable()); - visitDependents([&](const IAsset* dependent) -> bool - { - return visit(const_cast(dependent)); - }); - } + inline void visitDependents(std::function visit) const + { + visitDependents_impl([&visit](const IAsset* dep)->bool + { + if (dep) + return visit(dep); + return true; + }); + } + + inline void visitDependents(std::function visit) + { + assert(isMutable()); + visitDependents([&](const IAsset* dependent) -> bool + { + return visit(const_cast(dependent)); + }); + } virtual bool valid() const = 0; diff --git a/include/nbl/asset/ICPUMorphTargets.h b/include/nbl/asset/ICPUMorphTargets.h index 545d2cd8a9..29924f9727 100644 --- a/include/nbl/asset/ICPUMorphTargets.h +++ b/include/nbl/asset/ICPUMorphTargets.h @@ -23,7 +23,7 @@ class NBL_API2 ICPUMorphTargets : public IAsset, public IMorphTargetsvalid()) @@ -55,7 +55,7 @@ class NBL_API2 ICPUMorphTargets : public IAsset, public IMorphTargets visit) const //override + inline void visitDependents_impl(std::function visit) const override { auto nonNullOnly = [&visit](const IAsset* dep)->bool { diff --git a/include/nbl/asset/ICPUScene.h b/include/nbl/asset/ICPUScene.h new file mode 100644 index 0000000000..4ea7a485b4 --- /dev/null +++ b/include/nbl/asset/ICPUScene.h @@ -0,0 +1,54 @@ +// Copyright (C) 2025-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_ASSET_I_CPU_SCENE_H_INCLUDED_ +#define _NBL_ASSET_I_CPU_SCENE_H_INCLUDED_ + + +#include "nbl/asset/IScene.h" +// TODO: change to true IR later +#include "nbl/asset/material_compiler3/CFrontendIR.h" + + +namespace nbl::asset +{ +// +class NBL_API2 ICPUScene : public IAsset, public IScene +{ + using base_t = IScene; + + public: + inline ICPUScene() = default; + + constexpr static inline auto AssetType = ET_SCENE; + inline E_TYPE getAssetType() const override { return AssetType; } + + inline bool valid() const override + { + return true; + } + + inline core::smart_refctd_ptr clone(uint32_t _depth=~0u) const + { + const auto nextDepth = _depth ? (_depth-1):0; + auto retval = core::smart_refctd_ptr(); + return retval; + } + + protected: + // + inline void visitDependents_impl(std::function visit) const override + { + } + + + // suggested contents: + // - morph target list + // - material table + // - instance list (morph target, keyframed transforms, material table indexings, FUTURE: reference skeleton) + // - area light list (OBB decompositions, material table indexings) + // - envlight data +}; +} + +#endif \ No newline at end of file diff --git a/include/nbl/asset/IScene.h b/include/nbl/asset/IScene.h new file mode 100644 index 0000000000..69bf00ab3a --- /dev/null +++ b/include/nbl/asset/IScene.h @@ -0,0 +1,23 @@ +// Copyright (C) 2025-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_ASSET_I_SCENE_H_INCLUDED_ +#define _NBL_ASSET_I_SCENE_H_INCLUDED_ + + +#include "nbl/asset/IMorphTargets.h" + + +namespace nbl::asset +{ +// This is incredibly temporary, lots of things are going to change +class NBL_API2 IScene : public virtual core::IReferenceCounted +{ + public: + + protected: + virtual ~IScene() = default; +}; +} + +#endif \ No newline at end of file diff --git a/include/nbl/asset/asset.h b/include/nbl/asset/asset.h index fe70e81646..71f689c6fc 100644 --- a/include/nbl/asset/asset.h +++ b/include/nbl/asset/asset.h @@ -61,6 +61,7 @@ #include "nbl/asset/interchange/IAssetLoader.h" #include "nbl/asset/interchange/IImageLoader.h" #include "nbl/asset/interchange/IGeometryLoader.h" +#include "nbl/asset/interchange/ISceneLoader.h" #include "nbl/asset/interchange/IAssetWriter.h" #include "nbl/asset/interchange/IImageWriter.h" #include "nbl/asset/metadata/COpenEXRMetadata.h" diff --git a/include/nbl/asset/interchange/IAssetLoader.h b/include/nbl/asset/interchange/IAssetLoader.h index 64ed4a7fd3..3658f67026 100644 --- a/include/nbl/asset/interchange/IAssetLoader.h +++ b/include/nbl/asset/interchange/IAssetLoader.h @@ -4,6 +4,7 @@ #ifndef _NBL_ASSET_I_ASSET_LOADER_H_INCLUDED_ #define _NBL_ASSET_I_ASSET_LOADER_H_INCLUDED_ + #include "nbl/system/declarations.h" #include "nbl/system/ISystem.h" @@ -11,6 +12,7 @@ #include "nbl/asset/interchange/SAssetBundle.h" + namespace nbl::asset { @@ -86,8 +88,8 @@ class NBL_API2 IAssetLoader : public virtual core::IReferenceCounted enum E_LOADER_PARAMETER_FLAGS : uint64_t { ELPF_NONE = 0, //!< default value, it doesn't do anything - ELPF_RIGHT_HANDED_MESHES = 0x1, //!< specifies that a mesh will be flipped in such a way that it'll look correctly in right-handed camera system - ELPF_DONT_COMPILE_GLSL = 0x2, //!< it states that GLSL won't be compiled to SPIR-V if it is loaded or generated + /*deprecated*/ELPF_RIGHT_HANDED_MESHES = 0x1, //!< specifies that a mesh will be flipped in such a way that it'll look correctly in right-handed camera system + /*deprecated*/ELPF_DONT_COMPILE_GLSL = 0x2, //!< it states that GLSL won't be compiled to SPIR-V if it is loaded or generated ELPF_LOAD_METADATA_ONLY = 0x4 //!< it forces the loader to not load the entire scene for performance in special cases to fetch metadata. }; diff --git a/include/nbl/asset/interchange/IImageLoader.h b/include/nbl/asset/interchange/IImageLoader.h index c7b6119ede..a1177e7d00 100644 --- a/include/nbl/asset/interchange/IImageLoader.h +++ b/include/nbl/asset/interchange/IImageLoader.h @@ -1,9 +1,8 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - -#ifndef __NBL_ASSET_I_IMAGE_LOADER_H_INCLUDED__ -#define __NBL_ASSET_I_IMAGE_LOADER_H_INCLUDED__ +#ifndef _NBL_ASSET_I_IMAGE_LOADER_H_INCLUDED_ +#define _NBL_ASSET_I_IMAGE_LOADER_H_INCLUDED_ #include "nbl/core/declarations.h" diff --git a/include/nbl/asset/interchange/ISceneLoader.h b/include/nbl/asset/interchange/ISceneLoader.h new file mode 100644 index 0000000000..f61a2d3cea --- /dev/null +++ b/include/nbl/asset/interchange/ISceneLoader.h @@ -0,0 +1,30 @@ +// Copyright (C) 2025-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_ASSET_I_SCENE_LOADER_H_INCLUDED_ +#define _NBL_ASSET_I_SCENE_LOADER_H_INCLUDED_ + + +#include "nbl/core/declarations.h" + +#include "nbl/asset/ICPUScene.h" +#include "nbl/asset/interchange/IAssetLoader.h" + + +namespace nbl::asset +{ + +class ISceneLoader : public IAssetLoader +{ + public: + virtual inline uint64_t getSupportedAssetTypesBitfield() const override {return IAsset::ET_SCENE;} + + protected: + inline ISceneLoader() {} + + private: +}; + +} + +#endif diff --git a/include/nbl/core/algorithm/utility.h b/include/nbl/core/algorithm/utility.h index 136f1047cc..2ad3920839 100644 --- a/include/nbl/core/algorithm/utility.h +++ b/include/nbl/core/algorithm/utility.h @@ -18,6 +18,30 @@ struct type_list_size> : std::integral_constant inline constexpr size_t type_list_size_v = type_list_size::value; +template class, typename TypeList> +struct filter; +template class Pred, typename... T> +struct filter> +{ + using type = type_list<>; +}; + +template class Pred, typename T, typename... Ts> +struct filter> +{ + template + struct Cons; + template + struct Cons> + { + using type = type_list; + }; + + using type = std::conditional_t::value,typename Cons>::type>::type,typename filter>::type>; +}; +template class Pred, typename TypeList> +using filter_t = filter::type; + template class ListLikeOutT, template class X, typename ListLike> struct list_transform { diff --git a/include/nbl/core/hash/blake.h b/include/nbl/core/hash/blake.h index 801b867766..fb91c9969f 100644 --- a/include/nbl/core/hash/blake.h +++ b/include/nbl/core/hash/blake.h @@ -4,10 +4,13 @@ #ifndef _NBL_CORE_HASH_BLAKE3_H_INCLUDED_ #define _NBL_CORE_HASH_BLAKE3_H_INCLUDED_ + +#include "nbl/config/BuildConfigOptions.h" #include "blake3.h" #include + namespace nbl::core { struct blake3_hash_t final diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index 2b424e9a20..7f5e73c13f 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -1,19 +1,15 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_BSDF_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_BSDF_H_INCLUDED_ -#ifndef __C_ELEMENT_BSDF_H_INCLUDED__ -#define __C_ELEMENT_BSDF_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/CElementTexture.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +namespace nbl::ext::MitsubaLoader +{ class CElementBSDF : public IElement { @@ -293,6 +289,10 @@ class CElementBSDF : public IElement CElementTexture::SpectrumOrTexture diffuseReflectance = 0.5f; }; + // + static AddPropertyMap compAddPropertyMap(); + + // inline CElementBSDF(const char* id) : IElement(id), type(Type::INVALID) { } @@ -373,27 +373,28 @@ class CElementBSDF : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::BSDF; } + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::BSDF; + inline IElement::Type getType() const override { return ElementType; } std::string getLogName() const override { return "bsdf"; } bool processChildData(IElement* _child, const std::string& name) override; - bool isMeta() const + inline bool isMeta() const { switch (type) { - case COATING: [[fallthrough]]; - case ROUGHCOATING: [[fallthrough]]; - case TWO_SIDED: [[fallthrough]]; - case MASK: [[fallthrough]]; - case BLEND_BSDF: [[fallthrough]]; - case MIXTURE_BSDF: [[fallthrough]]; - case BUMPMAP: - return true; - default: - return false; + case COATING: [[fallthrough]]; + case ROUGHCOATING: [[fallthrough]]; + case TWO_SIDED: [[fallthrough]]; + case MASK: [[fallthrough]]; + case BLEND_BSDF: [[fallthrough]]; + case MIXTURE_BSDF: [[fallthrough]]; + case BUMPMAP: + return true; + default: + return false; } } @@ -422,9 +423,5 @@ class CElementBSDF : public IElement }; - } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index 972cf3915e..331abf2873 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -1,34 +1,32 @@ // Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_EMISSION_PROFILE_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_EMISSION_PROFILE_H_INCLUDED_ -#ifndef __C_ELEMENT_EMISSION_PROFILE_H_INCLUDED__ -#define __C_ELEMENT_EMISSION_PROFILE_H_INCLUDED__ -#include "vectorSIMD.h" #include "nbl/ext/MitsubaLoader/CElementTexture.h" #include "nbl/ext/MitsubaLoader/CElementTransform.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { -struct CElementEmissionProfile : public IElement { +struct CElementEmissionProfile final : public IElement +{ + static AddPropertyMap compAddPropertyMap(); - CElementEmissionProfile(const char* id) : IElement(id), normalization(EN_NONE), flatten(0.0) /*no blending by default*/ {} - CElementEmissionProfile() : IElement(""), normalization(EN_NONE) {} - CElementEmissionProfile(const CElementEmissionProfile& other) : IElement("") + inline CElementEmissionProfile(const char* id) : IElement(id), normalization(EN_NONE), flatten(0.0) /*no blending by default*/ {} + inline CElementEmissionProfile() : IElement(""), normalization(EN_NONE) {} + inline CElementEmissionProfile(const CElementEmissionProfile& other) : IElement("") { operator=(other); } - CElementEmissionProfile(CElementEmissionProfile&& other) : IElement("") + inline CElementEmissionProfile(CElementEmissionProfile&& other) : IElement("") { operator=(std::move(other)); } + inline ~CElementEmissionProfile() {} inline CElementEmissionProfile& operator=(const CElementEmissionProfile& other) { @@ -44,34 +42,27 @@ struct CElementEmissionProfile : public IElement { return *this; } - virtual ~CElementEmissionProfile() - { - } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override { - return true; - } + inline bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override {return true;} bool processChildData(IElement* _child, const std::string& name) override; - IElement::Type getType() const override { return IElement::Type::EMISSION_PROFILE; } - std::string getLogName() const override { return "emissionprofile "; } + + constexpr static inline auto ElementType = IElement::Type::EMISSION_PROFILE; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "emissionprofile "; } - enum E_NORMALIZE + enum E_NORMALIZE : uint8_t { EN_UNIT_MAX, //! normalize the intensity by dividing out the maximum intensity - EN_UNIT_AVERAGE_OVER_IMPLIED_DOMAIN, //! normlize by energy - integrate the profile over the hemisphere as well as the solid angles where the profile has emission above 0. + EN_UNIT_AVERAGE_OVER_IMPLIED_DOMAIN, //! normalize by energy - integrate the profile over the hemisphere as well as the solid angles where the profile has emission above 0. EN_UNIT_AVERAGE_OVER_FULL_DOMAIN, //! similar to UNIT_AVERAGE_OVER_IMPLIED_DOMAIN but in this case we presume the soild angle of the domain is (CIESProfile::vAngles.front()-CIESProfile::vAngles.back())*4.f EN_NONE //! no normalization }; - std::string filename; + std::string filename; // TODO: test destructor runs E_NORMALIZE normalization; - float flatten; + float flatten; // TODO: why is this named this way? }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementEmitter.h b/include/nbl/ext/MitsubaLoader/CElementEmitter.h index 87afdc860d..5de6861d7f 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmitter.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmitter.h @@ -1,24 +1,19 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_EMITTER_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_EMITTER_H_INCLUDED_ -#ifndef __C_ELEMENT_EMITTER_H_INCLUDED__ -#define __C_ELEMENT_EMITTER_H_INCLUDED__ -#include - -#include "vectorSIMD.h" #include "nbl/ext/MitsubaLoader/CElementTexture.h" #include "nbl/ext/MitsubaLoader/CElementEmissionProfile.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +#include + + +namespace nbl::ext::MitsubaLoader { - class CElementEmitter : public IElement { public: @@ -92,7 +87,7 @@ class CElementEmitter : public IElement };*/ struct EnvMap : SampledEmitter { - SPropertyElementData filename; + SPropertyElementData filename; // TODO: make sure destructor runs float scale = 1.f; float gamma = NAN; //bool cache = false; @@ -102,16 +97,19 @@ class CElementEmitter : public IElement core::vectorSIMDf radiance = core::vectorSIMDf(1.f); // Watts Meter^-2 Steradian^-1 }; + // + static AddPropertyMap compAddPropertyMap(); - CElementEmitter(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform() + // + inline CElementEmitter(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform() { } - CElementEmitter() : CElementEmitter("") {} - CElementEmitter(const CElementEmitter& other) : IElement(""), transform() + inline CElementEmitter() : CElementEmitter("") {} + inline CElementEmitter(const CElementEmitter& other) : IElement(""), transform() { operator=(other); } - CElementEmitter(CElementEmitter&& other) : IElement(""), transform() + inline CElementEmitter(CElementEmitter&& other) : IElement(""), transform() { operator=(std::move(other)); } @@ -205,9 +203,10 @@ class CElementEmitter : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::EMITTER; } + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::EMITTER; + inline IElement::Type getType() const override { return ElementType; } std::string getLogName() const override { return "emitter"; } bool processChildData(IElement* _child, const std::string& name) override @@ -302,10 +301,5 @@ class CElementEmitter : public IElement }; }; - - } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementFactory.h b/include/nbl/ext/MitsubaLoader/CElementFactory.h deleted file mode 100644 index 7543504b1d..0000000000 --- a/include/nbl/ext/MitsubaLoader/CElementFactory.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. -// This file is part of the "Nabla Engine". -// For conditions of distribution and use, see copyright notice in nabla.h - -#ifndef __I_ELEMENT_FACTORY_H_INCLUDED__ -#define __I_ELEMENT_FACTORY_H_INCLUDED__ - -#include "nbl/ext/MitsubaLoader/CElementSensor.h" -#include "nbl/ext/MitsubaLoader/CElementIntegrator.h" -#include "nbl/ext/MitsubaLoader/CElementShape.h" - -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ - -class ParserManager; - -class CElementFactory -{ - public: - using return_type = std::pair; - using element_creation_func = return_type(*)(const char**, ParserManager*); - const static core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> createElementTable; - - //constructs certain elements based on element's name and its attributes - template - static return_type createElement(const char** _atts, ParserManager* _util); - // - static return_type processAlias(const char** _atts, ParserManager* _util); - static return_type processRef(const char** _atts, ParserManager* _util); -}; - - -} -} -} - -#endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index afe929180c..986a5a5cbe 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -1,26 +1,20 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_FILM_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_FILM_H_INCLUDED_ -#ifndef __C_ELEMENT_FILM_H_INCLUDED__ -#define __C_ELEMENT_FILM_H_INCLUDED__ - -#include "nbl/macros.h" #include "nbl/ext/MitsubaLoader/CElementRFilter.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +namespace nbl::ext::MitsubaLoader +{ -class CElementFilm : public IElement +class CElementFilm final : public IElement { public: - enum Type + enum Type : uint8_t { INVALID, HDR_FILM, @@ -28,7 +22,17 @@ class CElementFilm : public IElement LDR_FILM, MFILM }; - enum PixelFormat + static inline core::unordered_map compStringToTypeMap() + { + return { + {"hdrfilm", Type::HDR_FILM}, + {"tiledhdrfilm",Type::TILED_HDR}, + {"ldrfilm", Type::LDR_FILM}, + {"mfilm", Type::MFILM} + }; + } + + enum PixelFormat : uint8_t { LUMINANCE, LUMINANCE_ALPHA, @@ -39,7 +43,7 @@ class CElementFilm : public IElement SPECTRUM, SPECTRUM_ALPHA }; - enum FileFormat + enum FileFormat : uint8_t { OPENEXR, RGBE, @@ -50,7 +54,7 @@ class CElementFilm : public IElement MATHEMATICA, NUMPY }; - enum ComponentFormat + enum ComponentFormat : uint8_t { FLOAT16, FLOAT32, @@ -84,25 +88,47 @@ class CElementFilm : public IElement variable[4] = 0; } int32_t digits; - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxVarNameLen = 63; // matlab + constexpr static inline size_t MaxVarNameLen = 63; // matlab char variable[MaxVarNameLen+1]; }; - CElementFilm(const char* id) : IElement(id), type(Type::HDR_FILM), + inline CElementFilm(const char* id) : IElement(id), type(Type::HDR_FILM), width(768), height(576), cropOffsetX(0), cropOffsetY(0), cropWidth(INT_MAX), cropHeight(INT_MAX), fileFormat(OPENEXR), pixelFormat(RGB), componentFormat(FLOAT16), banner(true), highQualityEdges(false), rfilter("") { hdrfilm = HDR(); } - virtual ~CElementFilm() + virtual inline ~CElementFilm() { } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::FILM; } - std::string getLogName() const override { return "film"; } + inline void initialize() + { + switch (type) + { + case CElementFilm::Type::LDR_FILM: + fileFormat = CElementFilm::FileFormat::PNG; + //componentFormat = UINT8; + ldrfilm = CElementFilm::LDR(); + break; + case CElementFilm::Type::MFILM: + width = 1; + height = 1; + fileFormat = CElementFilm::FileFormat::MATLAB; + pixelFormat = CElementFilm::PixelFormat::LUMINANCE; + mfilm = CElementFilm::M(); + break; + default: + break; + } + } + + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::FILM; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "film"; } inline bool processChildData(IElement* _child, const std::string& name) override { @@ -134,7 +160,7 @@ class CElementFilm : public IElement M mfilm; }; - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxPathLen = 256; + constexpr static inline size_t MaxPathLen = 256; char outputFilePath[MaxPathLen+1] = {0}; char denoiserBloomFilePath[MaxPathLen+1] = {0}; int32_t cascadeCount = 1; @@ -142,14 +168,11 @@ class CElementFilm : public IElement float cascadeLuminanceStart = core::nan(); float denoiserBloomScale = 0.0f; float denoiserBloomIntensity = 0.0f; - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxTonemapperArgsLen = 128; + constexpr static inline size_t MaxTonemapperArgsLen = 128; char denoiserTonemapperArgs[MaxTonemapperArgsLen+1] = {0}; float envmapRegularizationFactor = 0.5f; // 1.0f means based envmap luminance, 0.0f means uniform }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index 4a171f717b..94ea85b7b6 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -1,26 +1,22 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_INTEGRATOR_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_INTEGRATOR_H_INCLUDED_ -#ifndef __C_ELEMENT_INTEGRATOR_H_INCLUDED__ -#define __C_ELEMENT_INTEGRATOR_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/IElement.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader + +namespace nbl::ext::MitsubaLoader { -class CElementIntegrator : public IElement +class CElementIntegrator final : public IElement { public: - enum Type + enum Type : uint8_t { - INVALID, AO, DIRECT, PATH, @@ -38,8 +34,33 @@ class CElementIntegrator : public IElement VPL, IRR_CACHE, MULTI_CHANNEL, - FIELD_EXTRACT + FIELD_EXTRACT, + INVALID }; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"ao", Type::AO}, + {"direct", Type::DIRECT}, + {"path", Type::PATH}, + {"volpath_simple", Type::VOL_PATH_SIMPLE}, + {"volpath", Type::VOL_PATH}, + {"bdpt", Type::BDPT}, + {"photonmapper", Type::PHOTONMAPPER}, + {"ppm", Type::PPM}, + {"sppm", Type::SPPM}, + {"pssmlt", Type::PSSMLT}, + {"mlt", Type::MLT}, + {"erpt", Type::ERPT}, + {"ptracer", Type::ADJ_P_TRACER}, + {"adaptive", Type::ADAPTIVE}, + {"vpl", Type::VPL}, + {"irrcache", Type::IRR_CACHE}, + {"multichannel", Type::MULTI_CHANNEL}, + {"field", Type::FIELD_EXTRACT} + }; + } + struct AmbientOcclusion { int32_t shadingSamples = 1; @@ -52,8 +73,8 @@ class CElementIntegrator : public IElement }; struct DirectIllumination : EmitterHideableBase { - int32_t emitterSamples = 0xdeadbeefu; - int32_t bsdfSamples = 0xdeadbeefu; + int32_t emitterSamples = static_cast(0xdeadbeefu); + int32_t bsdfSamples = static_cast(0xdeadbeefu); bool strictNormals = false; }; struct MonteCarloTracingBase @@ -164,7 +185,7 @@ class CElementIntegrator : public IElement } Type field; - SPropertyElementData undefined; + SPropertyElementData undefined; // TODO: test destructor runs }; struct MetaIntegrator { @@ -194,85 +215,105 @@ class CElementIntegrator : public IElement { }; - CElementIntegrator(const char* id) : IElement(id), type(Type::INVALID) + // + static AddPropertyMap compAddPropertyMap(); + + // + inline CElementIntegrator(const char* id) : IElement(id), type(Type::INVALID) { } - virtual ~CElementIntegrator() + inline ~CElementIntegrator() { } - inline CElementIntegrator& operator=(const CElementIntegrator& other) + template + inline void visit(Visitor&& visitor) { - IElement::operator=(other); - type = other.type; switch (type) { case CElementIntegrator::Type::AO: - ao = other.ao; + visitor(ao); break; case CElementIntegrator::Type::DIRECT: - direct = other.direct; + visitor(direct); break; case CElementIntegrator::Type::PATH: - path = other.path; + visitor(path); break; case CElementIntegrator::Type::VOL_PATH_SIMPLE: - volpath_simple = other.volpath_simple; + visitor(volpath_simple); break; case CElementIntegrator::Type::VOL_PATH: - volpath = other.volpath; + visitor(volpath); break; case CElementIntegrator::Type::BDPT: - bdpt = other.bdpt; + visitor(bdpt); break; case CElementIntegrator::Type::PHOTONMAPPER: - photonmapper = other.photonmapper; + visitor(photonmapper); break; case CElementIntegrator::Type::PPM: - ppm = other.ppm; + visitor(ppm); break; case CElementIntegrator::Type::SPPM: - sppm = other.sppm; + visitor(sppm); break; case CElementIntegrator::Type::PSSMLT: - pssmlt = other.pssmlt; + visitor(pssmlt); break; case CElementIntegrator::Type::MLT: - mlt = other.mlt; + visitor(mlt); break; case CElementIntegrator::Type::ERPT: - erpt = other.erpt; + visitor(erpt); break; case CElementIntegrator::Type::ADJ_P_TRACER: - ptracer = other.ptracer; + visitor(ptracer); break; case CElementIntegrator::Type::ADAPTIVE: - adaptive = other.adaptive; + visitor(adaptive); break; case CElementIntegrator::Type::VPL: - vpl = other.vpl; + visitor(vpl); break; case CElementIntegrator::Type::IRR_CACHE: - irrcache = other.irrcache; + visitor(irrcache); break; case CElementIntegrator::Type::MULTI_CHANNEL: - multichannel = other.multichannel; + visitor(multichannel); break; case CElementIntegrator::Type::FIELD_EXTRACT: - field = other.field; + visitor(field); break; default: break; } + } + template + inline void visit(Visitor&& visitor) const + { + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); + } + + inline CElementIntegrator& operator=(const CElementIntegrator& other) + { + IElement::operator=(other); + type = other.type; + IElement::copyVariant(this,&other); return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::INTEGRATOR; } - std::string getLogName() const override { return "integrator"; } + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::INTEGRATOR; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "integrator"; } - bool processChildData(IElement* _child, const std::string& name) override + inline bool processChildData(IElement* _child, const std::string& name) override { if (!_child) return true; @@ -334,9 +375,5 @@ class CElementIntegrator : public IElement }; - } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementRFilter.h b/include/nbl/ext/MitsubaLoader/CElementRFilter.h index aa2da6dee3..b3673c9e35 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.h @@ -1,26 +1,22 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_R_FILTER_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_R_FILTER_H_INCLUDED_ -#ifndef __C_ELEMENT_R_FILTER_H_INCLUDED__ -#define __C_ELEMENT_R_FILTER_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/PropertyElement.h" - #include "nbl/ext/MitsubaLoader/IElement.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader + +namespace nbl::ext::MitsubaLoader { -class CElementRFilter : public IElement +class CElementRFilter final : public IElement { public: - enum Type + enum Type : uint8_t { INVALID, BOX, @@ -30,6 +26,7 @@ class CElementRFilter : public IElement CATMULLROM, LANCZOS }; + struct Gaussian { float sigma = NAN; // can't look at mitsuba source to figure out the default it uses @@ -44,16 +41,70 @@ class CElementRFilter : public IElement int32_t lobes = 3; }; - CElementRFilter(const char* id) : IElement(id), type(GAUSSIAN) + using variant_list_t = core::type_list< + Gaussian, + MitchellNetravali, + LanczosSinc + >; + static inline core::unordered_map compStringToTypeMap() + { + return { + std::make_pair("box", Type::BOX), + std::make_pair("tent", Type::TENT), + std::make_pair("gaussian", Type::GAUSSIAN), + std::make_pair("mitchell", Type::MITCHELL), + std::make_pair("catmullrom", Type::CATMULLROM), + std::make_pair("lanczos", Type::LANCZOS) + }; + } + static AddPropertyMap compAddPropertyMap(); + + inline CElementRFilter(const char* id) : IElement(id), type(GAUSSIAN) { gaussian = Gaussian(); } - virtual ~CElementRFilter() {} + inline ~CElementRFilter() {} - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::RFILTER; } - std::string getLogName() const override { return "rfilter"; } + template + inline void visit(Visitor&& visitor) + { + switch (type) + { + case Type::BOX: + [[fallthrough]]; + case Type::TENT: + break; + case Type::GAUSSIAN: + visit(gaussian); + break; + case Type::MITCHELL: + visit(mitchell); + break; + case Type::CATMULLROM: + visit(catmullrom); + break; + case Type::LANCZOS: + visit(lanczos); + break; + default: + break; + } + } + template + inline void visit(Visitor&& visitor) const + { + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); + } + + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::RFILTER; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "rfilter"; } // make these public Type type; @@ -70,7 +121,4 @@ class CElementRFilter : public IElement } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementSampler.h b/include/nbl/ext/MitsubaLoader/CElementSampler.h index 621623770d..9b9bc2b820 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSampler.h +++ b/include/nbl/ext/MitsubaLoader/CElementSampler.h @@ -1,56 +1,87 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_SAMPLER_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_SAMPLER_H_INCLUDED_ -#ifndef __C_ELEMENT_SAMPLER_H_INCLUDED__ -#define __C_ELEMENT_SAMPLER_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/IElement.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +namespace nbl::ext::MitsubaLoader +{ class CGlobalMitsubaMetadata; class CElementSampler : public IElement { public: - enum Type + enum Type : uint8_t { - INVALID, INDEPENDENT, STRATIFIED, LDSAMPLER, HALTON, HAMMERSLEY, - SOBOL + SOBOL, + INVALID }; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"independent", Type::INDEPENDENT}, + {"stratified", Type::STRATIFIED}, + {"ldsampler", Type::LDSAMPLER}, + {"halton", Type::HALTON}, + {"hammersley", Type::HAMMERSLEY}, + {"sobol", Type::SOBOL} + }; + } + static AddPropertyMap compAddPropertyMap(); - CElementSampler(const char* id) : IElement(id), type(INVALID), sampleCount(4) {} - virtual ~CElementSampler() {} + inline CElementSampler(const char* id) : IElement(id), type(INVALID), sampleCount(4) {} + inline ~CElementSampler() {} - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::SAMPLER; } - std::string getLogName() const override { return "sampler"; } + inline void initialize() + { + sampleCount = 4; + switch (type) + { + case CElementSampler::Type::STRATIFIED: + [[fallthrough]]; + case CElementSampler::Type::LDSAMPLER: + dimension = 4; + break; + case CElementSampler::Type::HALTON: + [[fallthrough]]; + case CElementSampler::Type::HAMMERSLEY: + scramble = -1; + break; + case CElementSampler::Type::SOBOL: + scramble = 0; + break; + default: + break; + } + } + + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::SAMPLER; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "sampler"; } // make these public + // TODO: these should be bitfields of a uint64_t, or pack into 8 bytes somehow Type type; int32_t sampleCount; union { int32_t dimension; + // TODO: document scramble seed? int32_t scramble; }; }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementSensor.h b/include/nbl/ext/MitsubaLoader/CElementSensor.h index c8214dd64c..4ef41e42d5 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSensor.h +++ b/include/nbl/ext/MitsubaLoader/CElementSensor.h @@ -1,9 +1,9 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_SENSOR_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_SENSOR_H_INCLUDED_ -#ifndef __C_ELEMENT_SENSOR_H_INCLUDED__ -#define __C_ELEMENT_SENSOR_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/IElement.h" #include "nbl/ext/MitsubaLoader/CElementTransform.h" @@ -11,20 +11,14 @@ #include "nbl/ext/MitsubaLoader/CElementSampler.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { - -class CElementSensor : public IElement +class CElementSensor final : public IElement { public: - enum Type + enum Type : uint8_t { - INVALID, PERSPECTIVE, THINLENS, ORTHOGRAPHIC, @@ -33,14 +27,16 @@ class CElementSensor : public IElement IRRADIANCEMETER, RADIANCEMETER, FLUENCEMETER, - PERSPECTIVE_RDIST + PERSPECTIVE_RDIST, + INVALID }; + constexpr static inline uint8_t MaxClipPlanes = 6u; struct ShutterSensor { - core::vectorSIMDf up = core::vectorSIMDf(0,1,0); - core::vectorSIMDf clipPlanes[MaxClipPlanes] = {}; + hlsl::float32_t3 up = hlsl::float32_t3(0,1,0); + hlsl::float32_t4 clipPlanes[MaxClipPlanes] = {}; float moveSpeed = core::nan(); float zoomSpeed = core::nan(); float rotateSpeed = core::nan(); @@ -54,6 +50,8 @@ class CElementSensor : public IElement }; struct PerspectivePinhole : CameraBase { + constexpr static inline Type VariantType = Type::PERSPECTIVE; + enum class FOVAxis { INVALID, @@ -76,6 +74,7 @@ class CElementSensor : public IElement }; struct Orthographic : CameraBase { + constexpr static inline Type VariantType = Type::ORTHOGRAPHIC; }; struct DepthOfFieldBase { @@ -84,83 +83,131 @@ class CElementSensor : public IElement }; struct PerspectiveThinLens : PerspectivePinhole, DepthOfFieldBase { + constexpr static inline Type VariantType = Type::THINLENS; }; struct TelecentricLens : Orthographic, DepthOfFieldBase { + constexpr static inline Type VariantType = Type::TELECENTRIC; }; struct SphericalCamera : CameraBase { + constexpr static inline Type VariantType = Type::SPHERICAL; }; struct IrradianceMeter : ShutterSensor { + constexpr static inline Type VariantType = Type::IRRADIANCEMETER; }; struct RadianceMeter : ShutterSensor { + constexpr static inline Type VariantType = Type::RADIANCEMETER; }; struct FluenceMeter : ShutterSensor { + constexpr static inline Type VariantType = Type::FLUENCEMETER; };/* struct PerspectivePinholeRadialDistortion : PerspectivePinhole { kc; };*/ - CElementSensor(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), film(""), sampler("") + using variant_list_t = core::type_list< + PerspectivePinhole, + PerspectiveThinLens, + Orthographic, + TelecentricLens, + SphericalCamera, + IrradianceMeter, + RadianceMeter, + FluenceMeter + >; + static inline core::unordered_map compStringToTypeMap() { + return { + {"perspective", Type::PERSPECTIVE}, + {"thinlens", Type::THINLENS}, + {"orthographic", Type::ORTHOGRAPHIC}, + {"telecentric", Type::TELECENTRIC}, + {"spherical", Type::SPHERICAL}, + {"irradiancemeter", Type::IRRADIANCEMETER}, + {"radiancemeter", Type::RADIANCEMETER}, + {"fluencemeter", Type::FLUENCEMETER}/*, + {"perspective_rdist", PERSPECTIVE_RDIST}*/ + }; } - CElementSensor(const CElementSensor& other) : IElement(""), transform(), film(""), sampler("") + static AddPropertyMap compAddPropertyMap(); + + inline CElementSensor(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), film(""), sampler("") + { + } + inline CElementSensor(const CElementSensor& other) : IElement(""), transform(), film(""), sampler("") { operator=(other); } - virtual ~CElementSensor() + inline ~CElementSensor() { } - inline CElementSensor& operator=(const CElementSensor& other) + template + inline void visit(Visitor&& visitor) { - IElement::operator=(other); - type = other.type; - transform = other.transform; switch (type) { case CElementSensor::Type::PERSPECTIVE: - perspective = other.perspective; + visitor(perspective); break; case CElementSensor::Type::THINLENS: - thinlens = other.thinlens; + visitor(thinlens); break; case CElementSensor::Type::ORTHOGRAPHIC: - orthographic = other.orthographic; + visitor(orthographic); break; case CElementSensor::Type::TELECENTRIC: - telecentric = other.telecentric; + visitor(telecentric); break; case CElementSensor::Type::SPHERICAL: - spherical = other.spherical; + visitor(spherical); break; case CElementSensor::Type::IRRADIANCEMETER: - irradiancemeter = other.irradiancemeter; + visitor(irradiancemeter); break; case CElementSensor::Type::RADIANCEMETER: - radiancemeter = other.radiancemeter; + visitor(radiancemeter); break; case CElementSensor::Type::FLUENCEMETER: - fluencemeter = other.fluencemeter; + visitor(fluencemeter); break; default: break; } + } + template + inline void visit(Visitor&& visitor) const + { + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); + } + + inline CElementSensor& operator=(const CElementSensor& other) + { + IElement::operator=(other); + type = other.type; + transform = other.transform; + IElement::copyVariant(this,&other); film = other.film; sampler = other.sampler; return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::SENSOR; } - std::string getLogName() const override { return "sensor"; } + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::SENSOR; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "sensor"; } - bool processChildData(IElement* _child, const std::string& name) override + inline bool processChildData(IElement* _child, const std::string& name) override { if (!_child) return true; @@ -186,12 +233,12 @@ class CElementSensor : public IElement break;*/ case IElement::Type::FILM: film = *static_cast(_child); - if (film.type != CElementFilm::Type::INVALID) + if (film.type!=CElementFilm::Type::INVALID) return true; break; case IElement::Type::SAMPLER: sampler = *static_cast(_child); - if (sampler.type != CElementSampler::Type::INVALID) + if (sampler.type!=CElementSampler::Type::INVALID) return true; break; } @@ -226,7 +273,4 @@ class CElementSensor : public IElement } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementShape.h b/include/nbl/ext/MitsubaLoader/CElementShape.h index 205023afea..23018079a1 100644 --- a/include/nbl/ext/MitsubaLoader/CElementShape.h +++ b/include/nbl/ext/MitsubaLoader/CElementShape.h @@ -1,9 +1,9 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_SHAPE_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_SHAPE_H_INCLUDED_ -#ifndef __C_ELEMENT_SHAPE_H_INCLUDED__ -#define __C_ELEMENT_SHAPE_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/IElement.h" #include "nbl/ext/MitsubaLoader/CElementTransform.h" @@ -11,15 +11,11 @@ #include "nbl/ext/MitsubaLoader/CElementEmitter.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { -class CElementShape : public IElement +class CElementShape final : public IElement { public: enum Type @@ -103,18 +99,20 @@ class CElementShape : public IElement CElementTexture* texture; };*/ - CElementShape(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), bsdf(nullptr), emitter(nullptr) + static AddPropertyMap compAddPropertyMap(); + + inline CElementShape(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), bsdf(nullptr), emitter(nullptr) { } - CElementShape(const CElementShape& other) : IElement(""), transform(), bsdf(nullptr), emitter(nullptr) + inline CElementShape(const CElementShape& other) : IElement(""), transform(), bsdf(nullptr), emitter(nullptr) { operator=(other); } - CElementShape(CElementShape&& other) : IElement(""), transform(), bsdf(nullptr), emitter(nullptr) + inline CElementShape(CElementShape&& other) : IElement(""), transform(), bsdf(nullptr), emitter(nullptr) { operator=(std::move(other)); } - virtual ~CElementShape() + inline ~CElementShape() { } @@ -219,20 +217,22 @@ class CElementShape : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::SHAPE; } - std::string getLogName() const override { return "shape"; } + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::SHAPE; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "shape"; } - inline core::matrix3x4SIMD getAbsoluteTransform() const + inline hlsl::float32_t3x4 getAbsoluteTransform() const { - auto local = transform.matrix.extractSub3x4(); + // explicit truncation + auto local = hlsl::float32_t3x4(transform.matrix); // TODO restore at some point (and make it actually work??) // note: INSTANCE can only contain SHAPEGROUP and the latter doesnt have its own transform //if (type==CElementShape::INSTANCE && instance.parent) - // return core::concatenateBFollowedByA(local,instance.parent->getAbsoluteTransform()); + // return mul(instance.parent->getAbsoluteTransform(),local); return local; } @@ -281,7 +281,4 @@ class CElementShape : public IElement } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index 1f3dc3ad7a..ece070785e 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -1,20 +1,16 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_TEXTURE_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_TEXTURE_H_INCLUDED_ -#ifndef __C_ELEMENT_TEXTURE_H_INCLUDED__ -#define __C_ELEMENT_TEXTURE_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/PropertyElement.h" #include "nbl/ext/MitsubaLoader/IElement.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +namespace nbl::ext::MitsubaLoader +{ class CElementTexture : public IElement { @@ -137,7 +133,7 @@ class CElementTexture : public IElement Z*/ }; - SPropertyElementData filename; + SPropertyElementData filename; // TODO: make sure destructor runs WRAP_MODE wrapModeU = REPEAT; WRAP_MODE wrapModeV = REPEAT; float gamma = NAN; @@ -159,18 +155,22 @@ class CElementTexture : public IElement float scale; }; - CElementTexture(const char* id) : IElement(id), type(Type::INVALID) + // + static AddPropertyMap compAddPropertyMap(); + + // + inline CElementTexture(const char* id) : IElement(id), type(Type::INVALID) { } - CElementTexture(const CElementTexture& other) : CElementTexture("") + inline CElementTexture(const CElementTexture& other) : CElementTexture("") { operator=(other); } - CElementTexture(CElementTexture&& other) : CElementTexture("") + inline CElementTexture(CElementTexture&& other) : CElementTexture("") { operator=(std::move(other)); } - virtual ~CElementTexture() + inline virtual ~CElementTexture() { } @@ -239,10 +239,11 @@ class CElementTexture : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; - IElement::Type getType() const override { return IElement::Type::TEXTURE; } - std::string getLogName() const override { return "texture"; } + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; + + constexpr static inline auto ElementType = IElement::Type::TEXTURE; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "texture"; } bool processChildData(IElement* _child, const std::string& name) override; @@ -256,9 +257,5 @@ class CElementTexture : public IElement }; - } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CElementTransform.h b/include/nbl/ext/MitsubaLoader/CElementTransform.h index d518f69e6c..45612174ad 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTransform.h +++ b/include/nbl/ext/MitsubaLoader/CElementTransform.h @@ -1,31 +1,29 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_TRANSFORM_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_TRANSFORM_H_INCLUDED_ -#ifndef __C_ELEMENT_TRANSFORM_H_INCLUDED__ -#define __C_ELEMENT_TRANSFORM_H_INCLUDED__ #include "nbl/ext/MitsubaLoader/IElement.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { - -class CElementTransform : public IElement +class CElementTransform final : public IElement { public: - CElementTransform() : IElement(""), matrix() {} - virtual ~CElementTransform() {} + static AddPropertyMap compAddPropertyMap(); + + inline CElementTransform() : IElement(""), matrix() {} + inline ~CElementTransform() {} - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override { return true; } - IElement::Type getType() const override { return IElement::Type::TRANSFORM; } - std::string getLogName() const override { return "transform"; } + inline bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override {return true;} + + constexpr static inline auto ElementType = IElement::Type::TRANSFORM; + inline IElement::Type getType() const override { return ElementType; } + inline std::string getLogName() const override { return "transform"; } /* inline CElementTransform& operator=(const CElementTransform& other) { @@ -35,11 +33,8 @@ class CElementTransform : public IElement } */ - core::matrix4SIMD matrix; + hlsl::float32_t4x4 matrix; }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h index e61ab3fa87..95b2f45c41 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h @@ -1,18 +1,15 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_MITSUBA_LOADER_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_MITSUBA_LOADER_H_INCLUDED_ -#ifndef __C_MITSUBA_LOADER_H_INCLUDED__ -#define __C_MITSUBA_LOADER_H_INCLUDED__ #include "nbl/asset/asset.h" -#include "IFileSystem.h" -#include "nbl/asset/utils/ICPUVirtualTexture.h" - #include "nbl/ext/MitsubaLoader/CSerializedLoader.h" -#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" -#include "nbl/ext/MitsubaLoader/CElementShape.h" +#include "nbl/ext/MitsubaLoader/ParserUtil.h" +//#include "nbl/ext/MitsubaLoader/CElementShape.h" #include "nbl/ext/MitsubaLoader/SContext.h" @@ -23,8 +20,7 @@ namespace nbl::ext::MitsubaLoader class CElementBSDF; class CMitsubaMaterialCompilerFrontend; - -// TODO: we need a GLSL to C++ compatibility wrapper +#if 0 // TODO //#include "nbl/builtin/glsl/ext/MitsubaLoader/instance_data_struct.glsl" #define uint uint32_t #define uvec2 uint64_t @@ -50,25 +46,18 @@ struct nbl_glsl_ext_Mitsuba_Loader_instance_data_t #undef mat4x3 #undef nbl_glsl_MC_material_data_t using instance_data_t = nbl_glsl_ext_Mitsuba_Loader_instance_data_t; +#endif - -class CMitsubaLoader : public asset::IRenderpassIndependentPipelineLoader +class CMitsubaLoader final : public asset::ISceneLoader { - friend class CMitsubaMaterialCompilerFrontend; - public: - //! Constructor - CMitsubaLoader(asset::IAssetManager* _manager, io::IFileSystem* _fs); +// friend class CMitsubaMaterialCompilerFrontend; - void initialize() override; - - protected: - io::IFileSystem* m_filesystem; + const ParserManager m_parser; + core::smart_refctd_ptr m_system; //! Destructor virtual ~CMitsubaLoader() = default; - - static core::smart_refctd_ptr createPipelineLayout(asset::IAssetManager* _manager, const asset::ICPUVirtualTexture* _vt); - +#if 0 // core::vector getMesh(SContext& ctx, uint32_t hierarchyLevel, CElementShape* shape); core::vector loadShapeGroup(SContext& ctx, uint32_t hierarchyLevel, const CElementShape::ShapeGroup* shapegroup, const core::matrix3x4SIMD& relTform); @@ -82,24 +71,21 @@ class CMitsubaLoader : public asset::IRenderpassIndependentPipelineLoader template core::smart_refctd_ptr createDS0(const SContext& _ctx, asset::ICPUPipelineLayout* _layout, const asset::material_compiler::CMaterialCompilerGLSLBackendCommon::result_t& _compResult, Iter meshBegin, Iter meshEnd); - +#endif public: - //! Check if the file might be loaded by this class - /** Check might look into the file. - \param file File handle to check. - \return True if file seems to be loadable. */ - bool isALoadableFileFormat(io::IReadFile* _file) const override; + //! Constructor + inline CMitsubaLoader(core::smart_refctd_ptr&& _system) : m_parser(), m_system(std::move(_system)) {} - //! Returns an array of string literals terminated by nullptr - const char** getAssociatedFileExtensions() const override; + bool isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger=nullptr) const override; - //! Returns the assets loaded by the loader - /** Bits of the returned value correspond to each IAsset::E_TYPE - enumeration member, and the return value cannot be 0. */ - uint64_t getSupportedAssetTypesBitfield() const override { return asset::IAsset::ET_MESH/*|asset::IAsset::ET_SCENE|asset::IAsset::ET_IMPLEMENTATION_SPECIFIC_METADATA*/; } + inline const char** getAssociatedFileExtensions() const override + { + static const char* ext[]{ "xml", nullptr }; + return ext; + } //! Loads an asset from an opened file, returns nullptr in case of failure. - asset::SAssetBundle loadAsset(io::IReadFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override = nullptr, uint32_t _hierarchyLevel = 0u) override; + asset::SAssetBundle loadAsset(system::IFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override=nullptr, uint32_t _hierarchyLevel=0u) override; }; } diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h b/include/nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h index 42bad88655..5ef55d4e54 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h @@ -1,13 +1,11 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _C_MITSUBA_MATERIAL_COMPILER_FRONTEND_H_INCLUDED_ +#define _C_MITSUBA_MATERIAL_COMPILER_FRONTEND_H_INCLUDED_ -#ifndef __C_MITSUBA_MATERIAL_COMPILER_FRONTEND_H_INCLUDED__ -#define __C_MITSUBA_MATERIAL_COMPILER_FRONTEND_H_INCLUDED__ -#include "nbl/core/Types.h" - -#include "nbl/asset/material_compiler/IR.h" +//#include "nbl/asset/material_compiler/IR.h" #include "nbl/ext/MitsubaLoader/CElementBSDF.h" #include "nbl/ext/MitsubaLoader/CElementEmitter.h" @@ -23,6 +21,7 @@ struct SContext; class CMitsubaMaterialCompilerFrontend { public: +#ifdef 0 using IRNode = asset::material_compiler::IR::INode; using EmitterNode = asset::material_compiler::IR::CEmitterNode; enum E_IMAGE_VIEW_SEMANTIC : uint8_t @@ -60,8 +59,8 @@ class CMitsubaMaterialCompilerFrontend tex_ass_type getErrorTexture(const E_IMAGE_VIEW_SEMANTIC semantic) const; IRNode* createIRNode(asset::material_compiler::IR* ir, const CElementBSDF* _bsdf); +#endif }; } - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h index 087d59b772..6f24951c50 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h @@ -1,29 +1,24 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_MITSUBA_METADATA_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_MITSUBA_METADATA_H_INCLUDED_ -#ifndef __NBL_C_MITSUBA_METADATA_H_INCLUDED__ -#define __NBL_C_MITSUBA_METADATA_H_INCLUDED__ -#include "nbl/core/compile_config.h" #include "nbl/asset/metadata/IAssetMetadata.h" #include "nbl/asset/ICPUImage.h" -#include "nbl/ext/MitsubaLoader/SContext.h" -#include "nbl/ext/MitsubaLoader/CElementEmitter.h" +//#include "nbl/ext/MitsubaLoader/SContext.h" +//#include "nbl/ext/MitsubaLoader/CElementEmitter.h" #include "nbl/ext/MitsubaLoader/CElementIntegrator.h" #include "nbl/ext/MitsubaLoader/CElementSensor.h" -#include "nbl/ext/MitsubaLoader/CElementShape.h" +//#include "nbl/ext/MitsubaLoader/CElementShape.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader + +namespace nbl::ext::MitsubaLoader { //! A class to derive mitsuba mesh loader metadata objects from - class CMitsubaMetadata : public asset::IAssetMetadata { public: @@ -32,121 +27,46 @@ class CMitsubaMetadata : public asset::IAssetMetadata public: std::string m_id; }; - class CDerivativeMap : public asset::IImageMetadata - { - public: - CDerivativeMap() : m_scale(1.f) {} - explicit CDerivativeMap(float scale) : m_scale(scale) {} - - float m_scale; - }; - class CRenderpassIndependentPipeline : public asset::IRenderpassIndependentPipelineMetadata - { - public: - CRenderpassIndependentPipeline() : IRenderpassIndependentPipelineMetadata(), m_ds0() {} - template - CRenderpassIndependentPipeline(core::smart_refctd_ptr&& _ds0, Args&&... args) : IRenderpassIndependentPipelineMetadata(std::forward(args)...), m_ds0(std::move(_ds0)) - { - } - - inline CRenderpassIndependentPipeline& operator=(CRenderpassIndependentPipeline&& other) - { - IRenderpassIndependentPipelineMetadata::operator=(std::move(other)); - std::swap(m_ds0, other.m_ds0); - return *this; - } - - core::smart_refctd_ptr m_ds0; - }; +#if 0 class CMesh : public asset::IMeshMetadata, public CID { public: - CMesh() : IMeshMetadata(), CID(), m_instanceAuxData(nullptr,nullptr), type(CElementShape::Type::INVALID) {} + CMesh() : IMeshMetadata(), CID(), type(CElementShape::Type::INVALID) {} ~CMesh() {} - struct SInstanceAuxilaryData - { - SInstanceAuxilaryData& operator=(SInstanceAuxilaryData&& other) - { - frontEmitter = std::move(other.frontEmitter); - backEmitter = std::move(other.backEmitter); - bsdf = std::move(other.bsdf); - return *this; - } - - CElementEmitter frontEmitter; // type is invalid if not used - CElementEmitter backEmitter; // type is invalid if not used - CMitsubaMaterialCompilerFrontend::front_and_back_t bsdf; - }; - - core::SRange m_instanceAuxData; - CElementShape::Type type; }; +#endif struct SGlobal { public: - SGlobal() : m_integrator("invalid") {}// TODO - - inline uint32_t getVTStorageViewCount() const { return m_VT->getFloatViews().size(); } + inline SGlobal() : m_integrator("invalid") {}// TODO CElementIntegrator m_integrator; core::vector m_sensors; - core::vector m_emitters; - core::smart_refctd_ptr m_VT; - core::smart_refctd_ptr m_ds0; - core::vector> m_envMapImages; - //has to go after #version and before required user-provided descriptors and functions - std::string m_materialCompilerGLSL_declarations; - //has to go after required user-provided descriptors and functions and before the rest of shader (especially entry point function) - std::string m_materialCompilerGLSL_source; } m_global; - CMitsubaMetadata() : - IAssetMetadata(), m_metaPplnStorage(), m_semanticStorage(), m_metaPplnStorageIt(nullptr), - m_metaMeshStorage(), m_metaMeshInstanceStorage(), m_metaMeshInstanceAuxStorage(), - m_meshStorageIt(nullptr), m_instanceStorageIt(nullptr), m_instanceAuxStorageIt(nullptr) + inline CMitsubaMetadata() : IAssetMetadata()/*, m_metaMeshStorage(), m_metaMeshInstanceStorage(), m_metaMeshInstanceAuxStorage(), + m_meshStorageIt(nullptr), m_instanceStorageIt(nullptr), m_instanceAuxStorageIt(nullptr)*/ { } - _NBL_STATIC_INLINE_CONSTEXPR const char* LoaderName = "ext::MitsubaLoader::CMitsubaLoader"; - const char* getLoaderName() const override { return LoaderName; } - + constexpr static inline const char* LoaderName = "ext::MitsubaLoader::CMitsubaLoader"; + const char* getLoaderName() const override {return LoaderName;} +#if 0 //! - inline const CRenderpassIndependentPipeline* getAssetSpecificMetadata(const asset::ICPURenderpassIndependentPipeline* asset) const - { - const auto found = IAssetMetadata::getAssetSpecificMetadata(asset); - return static_cast(found); - } inline const CMesh* getAssetSpecificMetadata(const asset::ICPUMesh* asset) const { const auto found = IAssetMetadata::getAssetSpecificMetadata(asset); return static_cast(found); } - +#endif private: - friend class CMitsubaLoader; - - meta_container_t m_metaPplnStorage; - core::smart_refctd_dynamic_array m_semanticStorage; - CRenderpassIndependentPipeline* m_metaPplnStorageIt; - +// friend class CMitsubaLoader; +#if 0 meta_container_t m_metaMeshStorage; - core::smart_refctd_dynamic_array m_metaMeshInstanceStorage; - core::smart_refctd_dynamic_array m_metaMeshInstanceAuxStorage; CMesh* m_meshStorageIt; - CMesh::SInstance* m_instanceStorageIt; - CMesh::SInstanceAuxilaryData* m_instanceAuxStorageIt; - meta_container_t m_metaDerivMapStorage; - CDerivativeMap* m_metaDerivMapStorageIt; - - inline void reservePplnStorage(uint32_t pplnCount, core::smart_refctd_dynamic_array&& _semanticStorage) - { - m_metaPplnStorage = IAssetMetadata::createContainer(pplnCount); - m_semanticStorage = std::move(_semanticStorage); - m_metaPplnStorageIt = m_metaPplnStorage->begin(); - } inline void reserveMeshStorage(uint32_t meshCount, uint32_t instanceCount) { m_metaMeshStorage = IAssetMetadata::createContainer(meshCount); @@ -156,17 +76,6 @@ class CMitsubaMetadata : public asset::IAssetMetadata m_instanceStorageIt = m_metaMeshInstanceStorage->begin(); m_instanceAuxStorageIt = m_metaMeshInstanceAuxStorage->begin(); } - inline void reserveDerivMapStorage(uint32_t count) - { - m_metaDerivMapStorage = IAssetMetadata::createContainer(count); - m_metaDerivMapStorageIt = m_metaDerivMapStorage->begin(); - } - inline void addPplnMeta(const asset::ICPURenderpassIndependentPipeline* ppln, core::smart_refctd_ptr&& _ds0) - { - *m_metaPplnStorageIt = CMitsubaMetadata::CRenderpassIndependentPipeline(std::move(_ds0),core::SRange(m_semanticStorage->begin(),m_semanticStorage->end())); - IAssetMetadata::insertAssetSpecificMetadata(ppln,m_metaPplnStorageIt); - m_metaPplnStorageIt++; - } template inline uint32_t addMeshMeta(const asset::ICPUMesh* mesh, std::string&& id, const CElementShape::Type type, InstanceIterator instancesBegin, InstanceIterator instancesEnd) { @@ -195,16 +104,8 @@ class CMitsubaMetadata : public asset::IAssetMetadata return meta->m_instances.size(); } - inline void addDerivMapMeta(const asset::ICPUImage* derivmap, float scale) - { - auto* meta = m_metaDerivMapStorageIt++; - meta->m_scale = scale; - IAssetMetadata::insertAssetSpecificMetadata(derivmap, meta); - } +#endif }; } -} -} - #endif diff --git a/include/nbl/ext/MitsubaLoader/CSerializedLoader.h b/include/nbl/ext/MitsubaLoader/CSerializedLoader.h index 1ac08aba79..44bb0739c5 100644 --- a/include/nbl/ext/MitsubaLoader/CSerializedLoader.h +++ b/include/nbl/ext/MitsubaLoader/CSerializedLoader.h @@ -21,7 +21,7 @@ class CSerializedLoader final : public asset::IGeometryLoader public: inline CSerializedLoader() = default; - inline bool isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger = nullptr) const override + inline bool isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger=nullptr) const override { FileHeader header; diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 8f6fa24ea7..4da3dbb848 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -1,23 +1,34 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_I_ELEMENT_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_I_ELEMENT_H_INCLUDED_ -#ifndef __I_ELEMENT_H_INCLUDED__ -#define __I_ELEMENT_H_INCLUDED__ +#include "nbl/core/algorithm/utility.h" #include "nbl/asset/interchange/IAssetLoader.h" + #include "nbl/ext/MitsubaLoader/PropertyElement.h" -namespace nbl +namespace nbl::ext::MitsubaLoader { -namespace ext +class CMitsubaMetadata; + +namespace impl { -namespace MitsubaLoader +template class Pred, typename... Args> +struct ToUnaryPred { + template + struct type : bool_constant::value> {}; +}; - -class CMitsubaMetadata; +template +struct mpl_of_passing; +template +using mpl_of_passing_t = mpl_of_passing::type; +} class IElement { @@ -53,15 +64,15 @@ class IElement virtual IElement::Type getType() const = 0; virtual std::string getLogName() const = 0; - virtual bool addProperty(SNamedPropertyElement&& _property) = 0; - virtual bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) = 0; + virtual bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) = 0; //! default implementation for elements that doesnt have any children virtual bool processChildData(IElement* _child, const std::string& name) { return !_child; } + // - static inline bool getTypeIDAndNameStrings(std::add_lvalue_reference::type outType, std::add_lvalue_reference::type outID, std::string& name, const char** _atts) + static inline bool getTypeIDAndNameStrings(std::add_lvalue_reference_t outType, std::add_lvalue_reference_t outID, std::string& name, const char** _atts) { outType = nullptr; outID = nullptr; @@ -81,7 +92,7 @@ class IElement } return outType; } - static inline bool getIDAndName(std::add_lvalue_reference::type id, std::string& name, const char** _atts) + static inline bool getIDAndName(std::add_lvalue_reference_t id, std::string& name, const char** _atts) { const char* thrownAwayType; getTypeIDAndNameStrings(thrownAwayType,id,name,_atts); @@ -111,10 +122,92 @@ class IElement return _atts[attrCount]; } + + // if we used `variant` instead of union we could default implement this + //template + //static inline void defaultVisit(Derived* this) + //{ + // generated switch / visit of `Variant` + //} + template + static inline void copyVariant(Derived* to, const Derived* from) + { + to->visit([from](auto& selfEl)->void + { + from->visit([&selfEl](const auto& otherEl)->void + { + if constexpr (std::is_same_v,std::decay_t>) + selfEl = otherEl; + } + ); + } + ); + } + + // could move it to `nbl/builtin/hlsl/mpl` + template + struct mpl_array + { + constexpr static inline Type data[] = { values... }; + }; + // + template + struct AddPropertyCallback + { + using element_t = Derived; + // TODO: list or map of supported variants (if `visit` is present) + using func_t = bool(*)(Derived*,SNamedPropertyElement&&,const system::logger_opt_ptr); + + inline bool operator()(Derived* d, SNamedPropertyElement&& p, const system::logger_opt_ptr l) const {return func(d,std::move(p),l);} + + func_t func; + // will usually point at + std::span allowedVariantTypes = {}; + }; + template + using PropertyNameCallbackMap = core::unordered_map,core::CaseInsensitiveHash,core::CaseInsensitiveEquals>; + template + class AddPropertyMap + { + template + inline void registerCallback(const SNamedPropertyElement::Type type, std::string&& propertyName, AddPropertyCallback cb) + { + if constexpr (sizeof...(types)) + cb.allowedVariantTypes = mpl_array::data; + registerCallback(type,std::move(propertyName),cb); + } + + public: + using element_type = Derived; + + inline void registerCallback(const SNamedPropertyElement::Type type, std::string&& propertyName, const AddPropertyCallback& cb) + { + auto [nameIt,inserted] = byPropertyType[type].emplace(std::move(propertyName),cb); + assert(inserted); + } + template class Pred, typename... Args> + inline void registerCallback(const SNamedPropertyElement::Type type, std::string&& propertyName, AddPropertyCallback::func_t cb) + { + AddPropertyCallback callback = {.func=cb}; + using UnaryPred = impl::ToUnaryPred; + using passing_types = core::filter_t; + if constexpr (core::type_list_size_v) + callback.allowedVariantTypes = impl::mpl_of_passing_t::data; + registerCallback(type,std::move(propertyName),callback); + } + + std::array,SNamedPropertyElement::Type::INVALID> byPropertyType = {}; + }; }; -} -} +namespace impl +{ +template +struct mpl_of_passing> +{ + using type = IElement::mpl_array; +}; } +} #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 65c8e1fb58..5c2b3efbef 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -1,50 +1,38 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_I_PARSER_UTIL_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_I_PARSER_UTIL_H_INCLUDED_ -#ifndef __I_PARSER_UTIL_H_INCLUDED__ -#define __I_PARSER_UTIL_H_INCLUDED__ - -//#include "nbl/core/core.h" - -//#include "IFileSystem.h" #include "nbl/asset/interchange/IAssetLoader.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" - -#include "expat/lib/expat.h" +#include "nbl/ext/MitsubaLoader/CElementIntegrator.h" +#include "nbl/ext/MitsubaLoader/CElementSensor.h" +#include "nbl/ext/MitsubaLoader/CElementFilm.h" +#include "nbl/ext/MitsubaLoader/CElementRFilter.h" +#include "nbl/ext/MitsubaLoader/CElementSampler.h" +#include "nbl/ext/MitsubaLoader/CElementShape.h" +#include "nbl/ext/MitsubaLoader/CElementBSDF.h" +#include "nbl/ext/MitsubaLoader/CElementTexture.h" +#include "nbl/ext/MitsubaLoader/CElementEmitter.h" +#include "nbl/ext/MitsubaLoader/CElementEmissionProfile.h" #include +// don't leak expat headers +struct XML_ParserStruct; +typedef struct XML_ParserStruct* XML_Parser; -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ - - -class ParserLog +namespace nbl::ext::MitsubaLoader { -public: - static inline void setLogger(const system::logger_opt_ptr& logger) { ParserLog::logger = logger; }; - - /*prints this message: - Mitsuba loader error: - Invalid .xml file structure: message */ - static void invalidXMLFileStructure(const std::string& errorMessage); - -private: - static system::logger_opt_ptr logger; -}; - +class IElement; +// TODO: replace with common Class for Material Compiler V3 Node Pool template -class ElementPool // : public std::tuple...> +class ElementPool // similar to : public std::tuple...> { core::SimpleBlockBasedAllocator,core::aligned_allocator> poolAllocator; public: @@ -59,80 +47,117 @@ class ElementPool // : public std::tuple...> }; //struct, which will be passed to expat handlers as user data (first argument) see: XML_StartElementHandler or XML_EndElementHandler in expat.h -class ParserManager +class ParserManager final { - protected: - struct Context - { - ParserManager* manager; - XML_Parser parser; - system::path currentXMLDir; - }; public: //! Constructor - ParserManager(system::ISystem* _system, asset::IAssetLoader::IAssetLoaderOverride* _override) : - m_system(_system), m_override(_override), m_sceneDeclCount(0), - m_metadata(core::make_smart_refctd_ptr()) - { - } + ParserManager(); // static void elementHandlerStart(void* _data, const char* _el, const char** _atts); static void elementHandlerEnd(void* _data, const char* _el); - // - inline void killParseWithError(const Context& ctx, const std::string& message) + struct Params { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure(message); - XML_StopParser(ctx.parser, false); - } - - bool parse(system::IFile* _file, const system::logger_opt_ptr& _logger); - - void parseElement(const Context& ctx, const char* _el, const char** _atts); - - void onEnd(const Context& ctx, const char* _el); - - // - core::vector > shapegroups; - // - core::smart_refctd_ptr m_metadata; - - private: - // - void processProperty(const Context& ctx, const char* _el, const char** _atts); + system::logger_opt_ptr logger; + // for opening included XML files + system::ISystem* system; + asset::IAssetLoader::IAssetLoaderOverride* _override; + }; + struct Result + { + explicit inline operator bool() const {return bool(metadata);} - // - system::ISystem* m_system; - asset::IAssetLoader::IAssetLoaderOverride* m_override; - // - uint32_t m_sceneDeclCount; - // - ElementPool< + // note that its shared between per-file contexts + core::smart_refctd_ptr metadata = nullptr; + // + core::vector > shapegroups = {}; + }; + Result parse(system::IFile* _file, const Params& _params) const; + + // Properties are simple XML nodes which are not `IElement` and neither children of an` IElement` + // If we match any ` propertyElements; + const CPropertyElementManager propertyElementManager; + + using supported_elements_t = core::type_list< CElementIntegrator, CElementSensor, CElementFilm, CElementRFilter, CElementSampler, - CElementShape, - CElementBSDF, - CElementTexture, - CElementEmitter - > objects; - // aliases and names - core::unordered_map handles; - - /*stack of currently processed elements - each element of index N is parent of the element of index N+1 - the scene element is a parent of all elements of index 0 */ - core::stack > elements; - - friend class CElementFactory; +/// CElementShape, +/// CElementBSDF, +/// CElementTexture, +/// CElementEmitter, + CElementEmissionProfile + >; + + private: + const core::tuple_transform_t addPropertyMaps; + + struct SNamedElement + { + IElement* element = nullptr; + core::string name = {}; + }; + // the XMLs can include each other, so this stores the stuff across files + struct SessionContext + { + // prints this message: + // Mitsuba loader error: + // Invalid .xml file structure: message + inline void invalidXMLFileStructure(const std::string& errorMessage) const + { + ::nbl::ext::MitsubaLoader::invalidXMLFileStructure(params->logger,errorMessage); + } + // meant for parsing one file in an include chain + bool parse(system::IFile* _file); + + Result* const result; + const Params* const params; + const ParserManager* const manager; + // + uint32_t sceneDeclCount = 0; + // TODO: This leaks memory all over the place because destructors are not ran! + ElementPool<> objects = {}; + // aliases and names (in Mitsbua XML you can give nodes names and `ref` them) + core::unordered_map handles = {}; + // stack of currently processed elements, each element of index N is parent of the element of index N+1 + // the scene element is a parent of all elements of index 0 + core::stack elements = {}; + }; + // This is for a single XML File + struct XMLContext + { + // + void killParseWithError(const std::string& message) const; + void parseElement(const char* _el, const char** _atts); + void onEnd(const char* _el); + + SessionContext* const session; + // + const system::path currentXMLDir; + // + XML_Parser parser; + }; + + struct SElementCreator + { + // we still push nullptr (failed creation) onto the stack, we only stop parse on catastrphic failure later on if a use of the element pops up + // this is why we don't need XMLCOntext for `killParseWithError` + using func_t = SNamedElement(*)(const char**/*attributes*/,SessionContext*); + func_t create; + bool retvalGoesOnStack; + }; + const core::unordered_map createElementTable; + // + template + struct CreateElement; + // + static SNamedElement processAlias(const char** _atts, SessionContext* ctx); + static SNamedElement processRef(const char** _atts, SessionContext* ctx); }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/PropertyElement.h b/include/nbl/ext/MitsubaLoader/PropertyElement.h index ac257bd4b3..320e12712e 100644 --- a/include/nbl/ext/MitsubaLoader/PropertyElement.h +++ b/include/nbl/ext/MitsubaLoader/PropertyElement.h @@ -1,24 +1,29 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_PROPERTY_ELEMENT_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_PROPERTY_ELEMENT_H_INCLUDED_ -#ifndef __PROPERTY_ELEMENT_H_INCLUDED__ -#define __PROPERTY_ELEMENT_H_INCLUDED__ #include "nbl/core/declarations.h" -#include "matrix4SIMD.h" -#include +#include "nbl/builtin/hlsl/cpp_compat.hlsl" -namespace nbl -{ -namespace ext + +namespace nbl::ext::MitsubaLoader { -namespace MitsubaLoader +// maybe move somewhere +inline void invalidXMLFileStructure(system::logger_opt_ptr logger, const std::string& errorMessage) { + // TODO: print the line in the XML or something + std::string message = "Mitsuba loader error - Invalid .xml file structure: \'" + errorMessage + '\''; + logger.log(message,system::ILogger::E_LOG_LEVEL::ELL_ERROR); + _NBL_DEBUG_BREAK_IF(true); +} struct SPropertyElementData { - enum Type + // TODO: enum class, and smaller type + enum Type : uint32_t { FLOAT, INTEGER, @@ -37,14 +42,12 @@ struct SPropertyElementData VECTOR, INVALID }; - - static const core::unordered_map StringToType; - _NBL_STATIC_INLINE_CONSTEXPR uint32_t MaxAttributes = 5u; - static const char* attributeStrings[Type::INVALID][MaxAttributes]; + // + constexpr static inline uint32_t MaxAttributes = 5u; inline SPropertyElementData() : type(Type::INVALID) { - std::fill(mvalue.pointer(), mvalue.pointer() + 16, 0.f); + memset(&fvalue,0,sizeof(mvalue)); } inline SPropertyElementData(const SPropertyElementData& other) : SPropertyElementData() { @@ -54,17 +57,11 @@ struct SPropertyElementData { operator=(std::move(other)); } - inline SPropertyElementData(const std::string& _type) : SPropertyElementData() - { - auto found = StringToType.find(_type); - if (found != StringToType.end()) - type = found->second; - } inline explicit SPropertyElementData(float value) : type(FLOAT) { fvalue = value; } inline explicit SPropertyElementData(int32_t value) : type(INTEGER) { ivalue = value; } inline explicit SPropertyElementData(bool value) : type(BOOLEAN) { bvalue = value; } //explicit SPropertyElementData(const std::string& value) : type(STRING) { #error } - inline explicit SPropertyElementData(Type _type, const core::vectorSIMDf& value): type(INVALID) + inline explicit SPropertyElementData(Type _type, const hlsl::float32_t4& value): type(INVALID) { switch (_type) { @@ -80,9 +77,9 @@ struct SPropertyElementData break; }; } - ~SPropertyElementData() + inline ~SPropertyElementData() { - if (type == Type::STRING) + if (type==Type::STRING) _NBL_ALIGNED_FREE((void*)svalue); } @@ -129,7 +126,7 @@ struct SPropertyElementData mvalue = other.mvalue; break; default: - std::fill(mvalue.pointer(), mvalue.pointer()+16, 0.f); + memset(&fvalue,0,sizeof(mvalue)); break; } return *this; @@ -171,17 +168,19 @@ struct SPropertyElementData mvalue = other.mvalue; break; default: - std::fill(other.mvalue.pointer(), other.mvalue.pointer() + 16, 0.f); + memset(&fvalue,0,sizeof(mvalue)); break; } return *this; } - + // TODO: enum class on the template param + template + struct get_type; template - struct get_typename; + using get_type_t = typename get_type::type; template - const typename get_typename::type& getProperty() const; + const get_type_t& getProperty() const; inline uint8_t getVectorDimension() const { @@ -201,63 +200,85 @@ struct SPropertyElementData int32_t ivalue; bool bvalue; const char* svalue; - core::vectorSIMDf vvalue; // rgb, srgb, vector, point - core::matrix4SIMD mvalue; // matrix, translate, rotate, scale, lookat + hlsl::float32_t4 vvalue; // rgb, srgb, vector, point + hlsl::float32_t4x4 mvalue; // matrix, translate, rotate, scale, lookat }; }; struct SNamedPropertyElement : SPropertyElementData { - SNamedPropertyElement() : SPropertyElementData(), name("") + inline SNamedPropertyElement() : SPropertyElementData(), name("") { } - SNamedPropertyElement(const std::string& _type) : SNamedPropertyElement() - { - auto found = SPropertyElementData::StringToType.find(_type); - if (found != SPropertyElementData::StringToType.end()) - type = found->second; - } - SNamedPropertyElement(const SNamedPropertyElement& other) : SNamedPropertyElement() + inline SNamedPropertyElement(const SNamedPropertyElement& other) : SNamedPropertyElement() { SNamedPropertyElement::operator=(other); } - SNamedPropertyElement(SNamedPropertyElement&& other) : SNamedPropertyElement() + inline SNamedPropertyElement(SNamedPropertyElement&& other) : SNamedPropertyElement() { SNamedPropertyElement::operator=(std::move(other)); } - bool initialize(const char** _atts, const char** outputMatch) + inline bool initialize(const char** _atts, const char** outputMatch) { - if (type == Type::INVALID || !_atts) + if (type==Type::INVALID || !_atts) return false; - for (auto it = _atts; *it; it++) + constexpr const char* AttributeStrings[SPropertyElementData::Type::INVALID][SPropertyElementData::MaxAttributes] = { + {"value"}, // FLOAT + {"value"}, // INTEGER + {"value"}, // BOOLEAN + {"value"}, // STRING + {"value","intent"}, // RGB + {"value","intent"}, // SRGB + {"value","intent","filename"}, // SPECTRUM + {"temperature","scale"}, // BLACKBODY + {"value"}, // MATRIX + {"x","y","z"}, // TRANSLATE + {"angle","x","y","z"}, // ROTATE + {"value","x","y","z"}, // SCALE + {"origin","target","up"}, // LOOKAT + {"x","y","z"}, // POINT + {"x","y","z","w"} // VECTOR + }; + // TODO: some magical constexpr thing to count up + //constexpr size_t AttributeCount[SPropertyElementData::Type::INVALID][SPropertyElementData::MaxAttributes] = {}; + + for (auto it=_atts; *it; it++) { - if (core::strcmpi(*it, "name") == 0) + // found the name attribute + if (core::strcmpi(*it,"name") == 0) { + // value follows the attribute name it++; if (*it) { + // next attribute is the actual name, first is just the `name=` name = *it; continue; } - else + else // no name present e.g. `name=""` return false; } - for (auto i = 0u; i < SPropertyElementData::MaxAttributes; i++) + // now go through the expected attributes + for (auto i=0u; i struct SPropertyElementData::get_typename +template<> struct SPropertyElementData::get_type { using type = float; }; -template<> struct SPropertyElementData::get_typename +template<> struct SPropertyElementData::get_type { using type = int32_t; }; -template<> struct SPropertyElementData::get_typename +template<> struct SPropertyElementData::get_type { using type = bool; }; -template<> struct SPropertyElementData::get_typename +template<> struct SPropertyElementData::get_type { using type = const char*; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::vectorSIMDf; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::vectorSIMDf; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::vectorSIMDf; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::vectorSIMDf; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::vectorSIMDf; }; -template<> struct SPropertyElementData::get_typename +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4; }; +template<> struct SPropertyElementData::get_type { using type = void; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::matrix4SIMD; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::matrix4SIMD; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::matrix4SIMD; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::matrix4SIMD; }; -template<> struct SPropertyElementData::get_typename -{ using type = core::matrix4SIMD; }; -template<> struct SPropertyElementData::get_typename +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4x4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4x4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4x4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4x4; }; +template<> struct SPropertyElementData::get_type +{ using type = hlsl::float32_t4x4; }; +template<> struct SPropertyElementData::get_type { using type = void; }; +// TODO: rewrite rest to be less `::` verbose +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return fvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return ivalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return bvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return svalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return vvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return vvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return vvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return vvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return vvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return mvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return mvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return mvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return mvalue; } +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return mvalue; } -class CPropertyElementManager +class CPropertyElementManager final : public core::Unmovable { - public: - static std::pair createPropertyData(const char* _el, const char** _atts); + const core::unordered_map StringToType; - static bool retrieveBooleanValue(const std::string& _data, bool& success); - static core::matrix4SIMD retrieveMatrix(const std::string& _data, bool& success); - static core::vectorSIMDf retrieveVector(const std::string& _data, bool& success); - static core::vectorSIMDf retrieveHex(const std::string& _data, bool& success); + static std::optional retrieveBooleanValue(const std::string_view& _data, system::logger_opt_ptr logger); + static hlsl::float32_t4x4 retrieveMatrix(const std::string_view& _data, system::logger_opt_ptr logger); + static hlsl::float32_t4 retrieveVector(const std::string_view& _data, system::logger_opt_ptr logger); + static hlsl::float32_t4 retrieveHex(const std::string_view& _data, system::logger_opt_ptr logger); + + public: + CPropertyElementManager(); +#if 0 + inline SPropertyElementData(const std::string& _type) : SPropertyElementData() + { + auto found = StringToType.find(_type); + if (found != StringToType.end()) + type = found->second; + } + SNamedPropertyElement(const std::string& _type) : SNamedPropertyElement() + { + auto found = SPropertyElementData::StringToType.find(_type); + if (found != SPropertyElementData::StringToType.end()) + type = found->second; + } +#endif + std::optional createPropertyData(const char* _el, const char** _atts, system::logger_opt_ptr logger) const; }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/SContext.h b/include/nbl/ext/MitsubaLoader/SContext.h index 687f97054d..c1d9c6d9b1 100644 --- a/include/nbl/ext/MitsubaLoader/SContext.h +++ b/include/nbl/ext/MitsubaLoader/SContext.h @@ -1,48 +1,40 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_EXT_MISTUBA_LOADER_C_MITSUBA_LOADER_CONTEXT_H_INCLUDED_ +#define _NBL_EXT_MISTUBA_LOADER_C_MITSUBA_LOADER_CONTEXT_H_INCLUDED_ -#ifndef __C_MITSUBA_LOADER_CONTEXT_H_INCLUDED__ -#define __C_MITSUBA_LOADER_CONTEXT_H_INCLUDED__ - -#include "nbl/asset/ICPUMesh.h" -#include "nbl/asset/utils/IGeometryCreator.h" -#include "nbl/asset/material_compiler/CMaterialCompilerGLSLRasterBackend.h" +#include "nbl/asset/ICPUPolygonGeometry.h" +//#include "nbl/asset/utils/IGeometryCreator.h" #include "nbl/asset/interchange/CIESProfileLoader.h" -#include "nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h" -#include "nbl/ext/MitsubaLoader/CElementShape.h" +//#include "nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h" +//#include "nbl/ext/MitsubaLoader/CElementShape.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { +class CMitsubaMetadata; + struct SContext { public: SContext( - const asset::IGeometryCreator* _geomCreator, - const asset::IMeshManipulator* _manipulator, +// const asset::IGeometryCreator* _geomCreator, +// const asset::IMeshManipulator* _manipulator, const asset::IAssetLoader::SAssetLoadContext& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* _metadata ); - const asset::IGeometryCreator* creator; - const asset::IMeshManipulator* manipulator; +// const asset::IGeometryCreator* creator; +// const asset::IMeshManipulator* manipulator; const asset::IAssetLoader::SAssetLoadContext inner; asset::IAssetLoader::IAssetLoaderOverride* override_; CMitsubaMetadata* meta; - _NBL_STATIC_INLINE_CONSTEXPR uint32_t VT_PAGE_SZ_LOG2 = 7u;//128 - _NBL_STATIC_INLINE_CONSTEXPR uint32_t VT_PHYSICAL_PAGE_TEX_TILES_PER_DIM_LOG2 = 4u;//16 - _NBL_STATIC_INLINE_CONSTEXPR uint32_t VT_PAGE_PADDING = 8u; - _NBL_STATIC_INLINE_CONSTEXPR uint32_t VT_MAX_ALLOCATABLE_TEX_SZ_LOG2 = 12u;//4096 - +#if 0 // using group_ass_type = core::vector>; //core::map groupCache; @@ -171,21 +163,6 @@ struct SContext return params; } - inline core::smart_refctd_ptr getSampler(const asset::ICPUSampler::SParams& params) const - { - const std::string samplerKey = samplerCacheKey(params); - const asset::IAsset::E_TYPE types[2] = {asset::IAsset::ET_SAMPLER,asset::IAsset::ET_TERMINATING_ZERO}; - auto samplerBundle = override_->findCachedAsset(samplerKey,types,inner,0u); - if (samplerBundle.getContents().empty()) - { - auto sampler = core::make_smart_refctd_ptr(params); - override_->insertAssetIntoCache(asset::SAssetBundle(nullptr,{sampler}),samplerKey,inner,0); - return sampler; - } - else - return core::smart_refctd_ptr_static_cast(samplerBundle.getContents().begin()[0]); - } - //index of root node in IR using bsdf_type = const CMitsubaMaterialCompilerFrontend::front_and_back_t; //caches instr buffer instr-wise offset (.first) and instruction count (.second) for each bsdf node @@ -214,67 +191,14 @@ struct SContext }; core::unordered_multimap mapMesh2instanceData; - struct SPipelineCacheKey - { - asset::SVertexInputParams vtxParams; - asset::SPrimitiveAssemblyParams primParams; - - inline bool operator==(const SPipelineCacheKey& rhs) const - { - return memcmp(&vtxParams, &rhs.vtxParams, sizeof(vtxParams)) == 0 && memcmp(&primParams, &rhs.primParams, sizeof(primParams)) == 0; - } - - struct hash - { - inline size_t operator()(const SPipelineCacheKey& k) const - { - constexpr size_t BYTESZ = sizeof(k.vtxParams) + sizeof(k.primParams); - uint8_t mem[BYTESZ]{}; - uint8_t* ptr = mem; - memcpy(ptr, &k.vtxParams, sizeof(k.vtxParams)); - ptr += sizeof(k.vtxParams); - memcpy(ptr, &k.primParams, sizeof(k.primParams)); - ptr += sizeof(k.primParams); - - return std::hash{}(std::string_view(reinterpret_cast(mem), BYTESZ)); - } - }; - }; core::unordered_map, SPipelineCacheKey::hash> pipelineCache; - +#endif //material compiler - core::smart_refctd_ptr ir; - CMitsubaMaterialCompilerFrontend frontend; - asset::material_compiler::CMaterialCompilerGLSLRasterBackend::SContext backend_ctx; - asset::material_compiler::CMaterialCompilerGLSLRasterBackend backend; +// core::smart_refctd_ptr ir; +// CMitsubaMaterialCompilerFrontend frontend; private: - // TODO: commonalize this to all loaders - static std::string samplerCacheKey(const asset::ICPUSampler::SParams& samplerParams) - { - std::string samplerCacheKey = "__Sampler"; - - if (samplerParams.MinFilter==asset::ISampler::ETF_LINEAR) - samplerCacheKey += "?trilinear"; - else - samplerCacheKey += "?nearest"; - - static const char* wrapModeName[] = - { - "?repeat", - "?clamp_to_edge", - "?clamp_to_border", - "?mirror", - "?mirror_clamp_to_edge", - "?mirror_clamp_to_border" - }; - samplerCacheKey += wrapModeName[samplerParams.TextureWrapU]; - samplerCacheKey += wrapModeName[samplerParams.TextureWrapV]; - - return samplerCacheKey; - } }; -}}} - +} #endif \ No newline at end of file diff --git a/include/nbl/system/declarations.h b/include/nbl/system/declarations.h index 2e66498a61..ebc5a890ae 100644 --- a/include/nbl/system/declarations.h +++ b/include/nbl/system/declarations.h @@ -5,6 +5,7 @@ #define _NBL_SYSTEM_DECLARATIONS_H_INCLUDED_ #include "nbl/core/declarations.h" +#include "nbl/core/definitions.h" // basic stuff #include "nbl/system/DynamicLibraryFunctionPointer.h" diff --git a/src/nbl/asset/interchange/CIESProfileLoader.h b/src/nbl/asset/interchange/CIESProfileLoader.h index 64ef9688ee..d0b116a3c3 100644 --- a/src/nbl/asset/interchange/CIESProfileLoader.h +++ b/src/nbl/asset/interchange/CIESProfileLoader.h @@ -1,16 +1,17 @@ // Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#ifndef __NBL_ASSET_C_IES_PROFILE_LOADER_H_INCLUDED__ -#define __NBL_ASSET_C_IES_PROFILE_LOADER_H_INCLUDED__ +#ifndef _NBL_ASSET_C_IES_PROFILE_LOADER_H_INCLUDED_ +#define _NBL_ASSET_C_IES_PROFILE_LOADER_H_INCLUDED_ #include "nbl/asset/ICPUImage.h" -#include "nbl/asset/ICPUShader.h" #include "nbl/asset/IAssetManager.h" - #include "nbl/asset/interchange/IAssetLoader.h" -#include "nbl/asset/utils/CIESProfileParser.h" + +#if 0 // TODO: Arek + +#include "nbl/asset/utils/CIESProfileParser.h" // TODO: move to `src/asset/interchange` #include "nbl/asset/metadata/CIESProfileMetadata.h" namespace nbl::asset @@ -62,4 +63,6 @@ class CIESProfileLoader final : public asset::IAssetLoader uint32_t _hierarchyLevel = 0u) override; }; } // namespace nbl::asset +#endif // end TODO: Arek + #endif // __NBL_ASSET_C_IES_PROFILE_LOADER_H_INCLUDED__ diff --git a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp index a9620c18a2..93187d723f 100644 --- a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp @@ -807,12 +807,7 @@ bool CElementBSDF::processChildData(IElement* _child, const std::string& name) bool CElementBSDF::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* metadata) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: Validation { diff --git a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp index 2bc7fc727a..0f360ccba0 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp @@ -1,72 +1,62 @@ -// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - -#include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" #include "nbl/ext/MitsubaLoader/CElementEmissionProfile.h" +#include "nbl/ext/MitsubaLoader/ParserUtil.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +namespace nbl::ext::MitsubaLoader { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr, ""); - - CElementEmissionProfile* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); - - return CElementFactory::return_type(obj, std::move(name)); -} -bool CElementEmissionProfile::addProperty(SNamedPropertyElement&& _property) { - if (_property.name == "filename") { - if (_property.type != SPropertyElementData::Type::STRING) { +bool CElementEmissionProfile::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) +{ + if (_property.name=="filename") + { + if (_property.type!=SPropertyElementData::Type::STRING) + { + invalidXMLFileStructure(logger,"'s `filename` must be a string type, instead it's: "+_property.type); return false; } filename = _property.getProperty(); return true; } - else if (_property.name == "normalization") { - if (_property.type != SPropertyElementData::Type::STRING) + else if (_property.name=="normalization") + { + if (_property.type!=SPropertyElementData::Type::STRING) + { + invalidXMLFileStructure(logger,"'s `normalization` must be a string type, instead it's: "+_property.type); return false; + } const auto normalizeS = std::string(_property.getProperty()); - if (normalizeS == "UNIT_MAX") + if (normalizeS=="UNIT_MAX") normalization = EN_UNIT_MAX; - else if(normalizeS == "UNIT_AVERAGE_OVER_IMPLIED_DOMAIN") + else if(normalizeS=="UNIT_AVERAGE_OVER_IMPLIED_DOMAIN") normalization = EN_UNIT_AVERAGE_OVER_IMPLIED_DOMAIN; - else if(normalizeS == "UNIT_AVERAGE_OVER_FULL_DOMAIN") + else if(normalizeS=="UNIT_AVERAGE_OVER_FULL_DOMAIN") normalization = EN_UNIT_AVERAGE_OVER_FULL_DOMAIN; else + { + invalidXMLFileStructure(logger,"'s `normalization` is unrecognized: "+ normalizeS); normalization = EN_NONE; + } return true; } - else if (_property.name == "flatten") + else if (_property.name=="flatten") { - if (_property.type != SPropertyElementData::Type::FLOAT) + if (_property.type!=SPropertyElementData::Type::FLOAT) return false; flatten = _property.getProperty(); - return true; } - else { - ParserLog::invalidXMLFileStructure("No emission profile can have such property set with name: " + _property.name); + else + { + invalidXMLFileStructure(logger,"No emission profile can have such property set with name: "+_property.name); return false; } } @@ -78,6 +68,4 @@ bool CElementEmissionProfile::processChildData(IElement* _child, const std::stri return false; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementFactory.cpp b/src/nbl/ext/MitsubaLoader/CElementFactory.cpp deleted file mode 100644 index c7690089cd..0000000000 --- a/src/nbl/ext/MitsubaLoader/CElementFactory.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. -// This file is part of the "Nabla Engine". -// For conditions of distribution and use, see copyright notice in nabla.h - -#include "nbl/ext/MitsubaLoader/CElementFactory.h" - -#include "nbl/ext/MitsubaLoader/ParserUtil.h" - -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ - - -CElementFactory::return_type CElementFactory::processAlias(const char** _atts, ParserManager* _util) -{ - const char* id = nullptr; - const char* as = nullptr; - std::string name; - if (IElement::areAttributesInvalid(_atts, 4u)) - return CElementFactory::return_type(nullptr,std::move(name)); - - while (*_atts) - { - if (core::strcmpi(_atts[0], "id")==0) - id = _atts[1]; - else if (core::strcmpi(_atts[0], "as")==0) - as = _atts[1]; - else if (core::strcmpi(_atts[0], "name")==0) - name = _atts[1]; - _atts += 2; - } - - if (!id || !as) - return CElementFactory::return_type(nullptr,std::move(name)); - - auto* original = _util->handles[id]; - _util->handles[as] = original; - return CElementFactory::return_type(original,std::move(name)); -} - -CElementFactory::return_type CElementFactory::processRef(const char** _atts, ParserManager* _util) -{ - const char* id; - std::string name; - if (!IElement::getIDAndName(id,name,_atts)) - { - os::Printer::log("[ERROR] Malformed `` element!", ELL_ERROR); - return CElementFactory::return_type(nullptr, std::move(name)); - } - auto* original = _util->handles[id]; - if (!original) - os::Printer::log(std::string("[ERROR] Used a `` element but referenced element not defined in preceeding XML!", ELL_ERROR); - return CElementFactory::return_type(original, std::move(name)); -} - - -const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> CElementFactory::createElementTable = -{ - {"integrator", {CElementFactory::createElement,true}}, - {"sensor", {CElementFactory::createElement,true}}, - {"film", {CElementFactory::createElement,true}}, - {"rfilter", {CElementFactory::createElement,true}}, - {"sampler", {CElementFactory::createElement,true}}, - {"shape", {CElementFactory::createElement,true}}, - {"transform", {CElementFactory::createElement,true}}, - //{"animation", {CElementFactory::createElement,true}}, - {"bsdf", {CElementFactory::createElement,true}}, - {"texture", {CElementFactory::createElement,true}}, - {"emitter", {CElementFactory::createElement,true}}, - {"emissionprofile", {CElementFactory::createElement,true}}, - {"alias", {CElementFactory::processAlias,true}}, - {"ref", {CElementFactory::processRef,true}} -}; - -} -} -} \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp index ba22c58fb9..7f17cbe64d 100644 --- a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp @@ -1,75 +1,18 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - +#include "nbl/ext/MitsubaLoader/CElementFilm.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ - - -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +namespace nbl::ext::MitsubaLoader { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr, ""); - - static const core::unordered_map StringToType = - { - {"hdrfilm", CElementFilm::Type::HDR_FILM}, - {"tiledhdrfilm",CElementFilm::Type::TILED_HDR}, - {"ldrfilm", CElementFilm::Type::LDR_FILM}, - {"mfilm", CElementFilm::Type::MFILM} - }; - - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } - CElementFilm* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); - - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementFilm::Type::LDR_FILM: - obj->fileFormat = CElementFilm::FileFormat::PNG; - //obj->componentFormat = UINT8; - obj->ldrfilm = CElementFilm::LDR(); - break; - case CElementFilm::Type::MFILM: - obj->width = 1; - obj->height = 1; - obj->fileFormat = CElementFilm::FileFormat::MATLAB; - obj->pixelFormat = CElementFilm::PixelFormat::LUMINANCE; - obj->mfilm = CElementFilm::M(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} - - -bool CElementFilm::addProperty(SNamedPropertyElement&& _property) +bool CElementFilm::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { +#if 0 bool error = type==Type::INVALID; #define SET_PROPERTY(MEMBER,PROPERTY_TYPE) [&]() -> void { \ if (_property.type!=PROPERTY_TYPE) { \ @@ -311,16 +254,19 @@ bool CElementFilm::addProperty(SNamedPropertyElement&& _property) auto found = SetPropertyMap.find(_property.name); if (found == SetPropertyMap.end()) { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("No Film can have such property set with name: " + _property.name+"\nRemember we don't support \"render-time annotations\""); + + invalidXMLFileStructure(logger,"No Film can have such property set with name: " + _property.name+"\nRemember we don't support \"render-time annotations\""); return false; } found->second(); return !error; +#endif + assert(false); + return false; } -bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* metadata) +bool CElementFilm::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { cropOffsetX = std::max(cropOffsetX,0); cropOffsetY = std::max(cropOffsetY,0); @@ -339,8 +285,8 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case PFM: break; default: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this file format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this file format"); + return false; }; break; @@ -350,8 +296,8 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case OPENEXR: break; default: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this file format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this file format"); + return false; }; break; @@ -363,8 +309,8 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case JPEG: break; default: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this file format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this file format"); + return false; }; switch (pixelFormat) @@ -378,8 +324,8 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case XYZ: [[fallthrough]]; case XYZA: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this pixel format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this pixel format"); + return false; break; default: @@ -396,8 +342,8 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case NUMPY: break; default: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this file format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this file format"); + return false; }; switch (pixelFormat) @@ -405,8 +351,8 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case XYZ: [[fallthrough]]; case XYZA: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this pixel format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this pixel format"); + return false; break; default: @@ -417,14 +363,14 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override case FLOAT32: break; default: - ParserLog::invalidXMLFileStructure(getLogName() + ": film type does not support this component format"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": film type does not support this component format"); + return false; }; break; default: - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,getLogName() + ": type not specified"); + return false; } @@ -432,6 +378,4 @@ bool CElementFilm::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index 7843cd30eb..04227927be 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -1,198 +1,26 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - -#include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" - +#include "nbl/ext/MitsubaLoader/CElementIntegrator.h" #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" -#include +#include "nbl/ext/MitsubaLoader/ElementMacros.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +#include "nbl/type_traits.h" // legacy stuff for `is_any_of` +#include -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +namespace nbl::ext::MitsubaLoader { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr,""); - - static const core::unordered_map StringToType = - { - {"ao", CElementIntegrator::Type::AO}, - {"direct", CElementIntegrator::Type::DIRECT}, - {"path", CElementIntegrator::Type::PATH}, - {"volpath_simple", CElementIntegrator::Type::VOL_PATH_SIMPLE}, - {"volpath", CElementIntegrator::Type::VOL_PATH}, - {"bdpt", CElementIntegrator::Type::BDPT}, - {"photonmapper", CElementIntegrator::Type::PHOTONMAPPER}, - {"ppm", CElementIntegrator::Type::PPM}, - {"sppm", CElementIntegrator::Type::SPPM}, - {"pssmlt", CElementIntegrator::Type::PSSMLT}, - {"mlt", CElementIntegrator::Type::MLT}, - {"erpt", CElementIntegrator::Type::ERPT}, - {"ptracer", CElementIntegrator::Type::ADJ_P_TRACER}, - {"adaptive", CElementIntegrator::Type::ADAPTIVE}, - {"vpl", CElementIntegrator::Type::VPL}, - {"irrcache", CElementIntegrator::Type::IRR_CACHE}, - {"multichannel", CElementIntegrator::Type::MULTI_CHANNEL}, - {"field", CElementIntegrator::Type::FIELD_EXTRACT} - }; - - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } - - CElementIntegrator* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementIntegrator::Type::AO: - obj->ao = CElementIntegrator::AmbientOcclusion(); - break; - case CElementIntegrator::Type::DIRECT: - obj->direct = CElementIntegrator::DirectIllumination(); - break; - case CElementIntegrator::Type::PATH: - obj->path = CElementIntegrator::PathTracing(); - break; - case CElementIntegrator::Type::VOL_PATH_SIMPLE: - obj->volpath_simple = CElementIntegrator::SimpleVolumetricPathTracing(); - break; - case CElementIntegrator::Type::VOL_PATH: - obj->volpath = CElementIntegrator::ExtendedVolumetricPathTracing(); - break; - case CElementIntegrator::Type::BDPT: - obj->bdpt = CElementIntegrator::BiDirectionalPathTracing(); - break; - case CElementIntegrator::Type::PHOTONMAPPER: - obj->photonmapper = CElementIntegrator::PhotonMapping(); - break; - case CElementIntegrator::Type::PPM: - obj->ppm = CElementIntegrator::ProgressivePhotonMapping(); - break; - case CElementIntegrator::Type::SPPM: - obj->sppm = CElementIntegrator::StochasticProgressivePhotonMapping(); - break; - case CElementIntegrator::Type::PSSMLT: - obj->pssmlt = CElementIntegrator::PrimarySampleSpaceMetropolisLightTransport(); - break; - case CElementIntegrator::Type::MLT: - obj->mlt = CElementIntegrator::PathSpaceMetropolisLightTransport(); - break; - case CElementIntegrator::Type::ERPT: - obj->erpt = CElementIntegrator::EnergyRedistributionPathTracing(); - break; - case CElementIntegrator::Type::ADJ_P_TRACER: - obj->ptracer = CElementIntegrator::AdjointParticleTracing(); - break; - case CElementIntegrator::Type::ADAPTIVE: - obj->adaptive = CElementIntegrator::AdaptiveIntegrator(); - break; - case CElementIntegrator::Type::VPL: - obj->vpl = CElementIntegrator::VirtualPointLights(); - break; - case CElementIntegrator::Type::IRR_CACHE: - obj->irrcache = CElementIntegrator::IrradianceCacheIntegrator(); - break; - case CElementIntegrator::Type::MULTI_CHANNEL: - obj->multichannel = CElementIntegrator::MultiChannelIntegrator(); - break; - case CElementIntegrator::Type::FIELD_EXTRACT: - obj->field = CElementIntegrator::FieldExtraction(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} - -bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property) +bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { + if (type>=Type::INVALID) + return false; bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) - { - case CElementIntegrator::Type::AO: - func(ao); - break; - case CElementIntegrator::Type::DIRECT: - func(direct); - break; - case CElementIntegrator::Type::PATH: - func(path); - break; - case CElementIntegrator::Type::VOL_PATH_SIMPLE: - func(volpath_simple); - break; - case CElementIntegrator::Type::VOL_PATH: - func(volpath); - break; - case CElementIntegrator::Type::BDPT: - func(bdpt); - break; - case CElementIntegrator::Type::PHOTONMAPPER: - func(photonmapper); - break; - case CElementIntegrator::Type::PPM: - func(ppm); - break; - case CElementIntegrator::Type::SPPM: - func(sppm); - break; - case CElementIntegrator::Type::PSSMLT: - func(pssmlt); - break; - case CElementIntegrator::Type::MLT: - func(mlt); - break; - case CElementIntegrator::Type::ERPT: - func(erpt); - break; - case CElementIntegrator::Type::ADJ_P_TRACER: - func(ptracer); - break; - case CElementIntegrator::Type::ADAPTIVE: - func(adaptive); - break; - case CElementIntegrator::Type::VPL: - func(vpl); - break; - case CElementIntegrator::Type::IRR_CACHE: - func(irrcache); - break; - case CElementIntegrator::Type::MULTI_CHANNEL: - func(multichannel); - break; - case CElementIntegrator::Type::FIELD_EXTRACT: - func(field); - break; - default: - error = true; - break; - } - }; - +#if 0 #define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ + visit([&](auto& state) -> void { \ if constexpr (is_any_of::type,__VA_ARGS__>::value) \ { \ if (_property.type!=PROPERTY_TYPE) { \ @@ -209,7 +37,7 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property) auto processBSDFSamples = SET_PROPERTY_TEMPLATE(bsdfSamples,SNamedPropertyElement::Type::INTEGER,DirectIllumination); auto processShadingSamples = [&]() -> void { - dispatch([&](auto& state) -> void { + visit([&](auto& state) -> void { using state_type = std::remove_reference::type; if constexpr (std::is_same::value) @@ -276,7 +104,7 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property) auto processClamping = SET_PROPERTY_TEMPLATE(clamping,SNamedPropertyElement::Type::FLOAT,VirtualPointLights); auto processField = [&]() -> void { - dispatch([&](auto& state) -> void + visit([&](auto& state) -> void { using state_type = std::remove_reference::type; if constexpr (std::is_same::value) @@ -308,7 +136,7 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property) }; auto processUndefined = [&]() -> void { - dispatch([&](auto& state) -> void { + visit([&](auto& state) -> void { using state_type = std::remove_reference::type; if constexpr (std::is_same::value) @@ -397,23 +225,18 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property) auto found = SetPropertyMap.find(_property.name); if (found==SetPropertyMap.end()) { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("No Integrator can have such property set with name: "+_property.name); + invalidXMLFileStructure(logger,"No Integrator can have such property set with name: "+_property.name); return false; } found->second(); +#endif return !error; } -bool CElementIntegrator::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* metadata) +bool CElementIntegrator::onEndTag(CMitsubaMetadata* metadata, system::logger_opt_ptr logger) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: Validation { @@ -421,8 +244,7 @@ bool CElementIntegrator::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _ov if (metadata->m_global.m_integrator.type!=Type::INVALID) { - ParserLog::invalidXMLFileStructure(getLogName() + ": already specified an integrator"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,"already specified an integrator, NOT overwriting."); return true; } metadata->m_global.m_integrator = *this; @@ -430,6 +252,4 @@ bool CElementIntegrator::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _ov return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp b/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp index 160fd5aadb..de5bdf2255 100644 --- a/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp @@ -1,92 +1,30 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - #include "nbl/core/string/stringutil.h" +#include "nbl/ext/MitsubaLoader/CElementRFilter.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +#include "nbl/ext/MitsubaLoader/ElementMacros.h" -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +namespace nbl::ext::MitsubaLoader { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr, ""); - - static const core::unordered_map StringToType = - { - std::make_pair("box", CElementRFilter::Type::BOX), - std::make_pair("tent", CElementRFilter::Type::TENT), - std::make_pair("gaussian", CElementRFilter::Type::GAUSSIAN), - std::make_pair("mitchell", CElementRFilter::Type::MITCHELL), - std::make_pair("catmullrom", CElementRFilter::Type::CATMULLROM), - std::make_pair("lanczos", CElementRFilter::Type::LANCZOS) - }; - - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } - - CElementRFilter* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); - - obj->type = found->second; - //validation - switch (obj->type) - { - case CElementRFilter::Type::BOX: - [[fallthrough]]; - case CElementRFilter::Type::TENT: - break; - case CElementRFilter::Type::GAUSSIAN: - obj->gaussian = CElementRFilter::Gaussian(); - break; - case CElementRFilter::Type::MITCHELL: - obj->mitchell = CElementRFilter::MitchellNetravali(); - break; - case CElementRFilter::Type::CATMULLROM: - obj->catmullrom = CElementRFilter::MitchellNetravali(); - break; - case CElementRFilter::Type::LANCZOS: - obj->lanczos = CElementRFilter::LanczosSinc(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} -bool CElementRFilter::addProperty(SNamedPropertyElement&& _property) +bool CElementRFilter::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { if (_property.type == SNamedPropertyElement::Type::INTEGER) { if (core::strcmpi(_property.name,std::string("lobes"))) { - ParserLog::invalidXMLFileStructure("\"lobes\" must be an integer property"); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,"\"lobes\" must be an integer property"); return false; } lanczos.lobes = _property.ivalue; return true; } - else - if (_property.type == SNamedPropertyElement::Type::FLOAT) + else if (_property.type == SNamedPropertyElement::Type::FLOAT) { if (core::strcmpi(_property.name,std::string("b"))==0) { @@ -109,31 +47,21 @@ bool CElementRFilter::addProperty(SNamedPropertyElement&& _property) return true; } else - ParserLog::invalidXMLFileStructure("unsupported rfilter property called: "+_property.name); + invalidXMLFileStructure(logger,"unsupported rfilter property called: "+_property.name); } else - { - ParserLog::invalidXMLFileStructure("this reconstruction filter type does not take this parameter type for parameter: " + _property.name); - _NBL_DEBUG_BREAK_IF(true); - } + invalidXMLFileStructure(logger,"this reconstruction filter type does not take this parameter type for parameter: " + _property.name); return false; } -bool CElementRFilter::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) +bool CElementRFilter::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: Validation return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementSampler.cpp b/src/nbl/ext/MitsubaLoader/CElementSampler.cpp index 01306d2201..b862a754fb 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSampler.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSampler.cpp @@ -1,138 +1,78 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - +#include "nbl/ext/MitsubaLoader/CElementSampler.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" - -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +#include "nbl/ext/MitsubaLoader/ElementMacros.h" -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +namespace nbl::ext::MitsubaLoader { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr, ""); - - static const core::unordered_map StringToType = - { - std::make_pair("independent", CElementSampler::Type::INDEPENDENT), - std::make_pair("stratified", CElementSampler::Type::STRATIFIED), - std::make_pair("ldsampler", CElementSampler::Type::LDSAMPLER), - std::make_pair("halton", CElementSampler::Type::HALTON), - std::make_pair("hammersley", CElementSampler::Type::HAMMERSLEY), - std::make_pair("sobol", CElementSampler::Type::SOBOL) - }; - - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } - - CElementSampler* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); - - obj->type = found->second; - obj->sampleCount = 4; - //validation - switch (obj->type) - { - case CElementSampler::Type::STRATIFIED: - [[fallthrough]]; - case CElementSampler::Type::LDSAMPLER: - obj->dimension = 4; - break; - case CElementSampler::Type::HALTON: - [[fallthrough]]; - case CElementSampler::Type::HAMMERSLEY: - obj->scramble = -1; - break; - case CElementSampler::Type::SOBOL: - obj->scramble = 0; - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} - -bool CElementSampler::addProperty(SNamedPropertyElement&& _property) + +auto CElementSampler::compAddPropertyMap() -> AddPropertyMap { - if (_property.type == SNamedPropertyElement::Type::INTEGER && - _property.name == "sampleCount") - { - sampleCount = _property.ivalue; - switch (type) + using this_t = CElementSampler; + AddPropertyMap retval; + + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("sampleCount",INTEGER) { - case Type::STRATIFIED: - sampleCount = ceilf(sqrtf(sampleCount)); - break; - case Type::LDSAMPLER: - //sampleCount = core::roundUpToPoT(sampleCount); - break; - default: - break; + auto& sampleCount = _this->sampleCount; + sampleCount = _property.ivalue; + switch (_this->type) + { + case Type::STRATIFIED: + sampleCount = ceilf(sqrtf(sampleCount)); + break; + case Type::LDSAMPLER: + //sampleCount = core::roundUpToPoT(sampleCount); + break; + default: + break; + } + return true; } - } - else - if (_property.type == SNamedPropertyElement::Type::INTEGER && - _property.name == "dimension") - { - dimension = _property.ivalue; - if (type == Type::INDEPENDENT || type == Type::HALTON || type == Type::HAMMERSLEY) + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("dimension",INTEGER) { - ParserLog::invalidXMLFileStructure("this sampler type does not take these parameters"); - _NBL_DEBUG_BREAK_IF(true); - return false; + _this->dimension = _property.ivalue; + switch (_this->type) + { + case Type::INDEPENDENT: [[fallthrough]]; + case Type::HALTON: [[fallthrough]]; + case Type::HAMMERSLEY: + invalidXMLFileStructure(logger,"this sampler type ("+std::to_string(_this->type)+") does not take these parameters"); + return false; + default: + return true; + } } - } - else - if (_property.type == SNamedPropertyElement::Type::INTEGER && - _property.name == "scramble") - { - scramble = _property.ivalue; - if (type==Type::INDEPENDENT || type==Type::STRATIFIED || type == Type::LDSAMPLER) + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("scramble",INTEGER) { - ParserLog::invalidXMLFileStructure("this sampler type does not take these parameters"); - _NBL_DEBUG_BREAK_IF(true); - return false; + _this->scramble = _property.ivalue; + switch (_this->type) + { + case Type::INDEPENDENT: [[fallthrough]]; + case Type::HALTON: [[fallthrough]]; + case Type::HAMMERSLEY: + invalidXMLFileStructure(logger,"this sampler type ("+std::to_string(_this->type)+") does not take these parameters"); + return false; + default: + return true; + } } - } - else - { - _NBL_DEBUG_BREAK_IF(true); - return false; - } + }); - return true; + return retval; } -bool CElementSampler::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) +bool CElementSampler::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: Validation return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp index 06d8c53737..d8ab85bb26 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp @@ -1,253 +1,91 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - +#include "nbl/ext/MitsubaLoader/CElementSensor.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" +#include "nbl/ext/MitsubaLoader/ElementMacros.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ - -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) -{ - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr,""); - - static const core::unordered_map StringToType = - { - {"perspective", CElementSensor::Type::PERSPECTIVE}, - {"thinlens", CElementSensor::Type::THINLENS}, - {"orthographic", CElementSensor::Type::ORTHOGRAPHIC}, - {"telecentric", CElementSensor::Type::TELECENTRIC}, - {"spherical", CElementSensor::Type::SPHERICAL}, - {"irradiancemeter", CElementSensor::Type::IRRADIANCEMETER}, - {"radiancemeter", CElementSensor::Type::RADIANCEMETER}, - {"fluencemeter", CElementSensor::Type::FLUENCEMETER}/*, - {"perspective_rdist", CElementSensor::PERSPECTIVE_RDIST}*/ - }; - - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } - - CElementSensor* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementSensor::Type::PERSPECTIVE: - obj->perspective = CElementSensor::PerspectivePinhole(); - break; - case CElementSensor::Type::THINLENS: - obj->thinlens = CElementSensor::PerspectiveThinLens(); - break; - case CElementSensor::Type::ORTHOGRAPHIC: - obj->orthographic = CElementSensor::Orthographic(); - break; - case CElementSensor::Type::TELECENTRIC: - obj->telecentric = CElementSensor::TelecentricLens(); - break; - case CElementSensor::Type::SPHERICAL: - obj->spherical = CElementSensor::SphericalCamera(); - break; - case CElementSensor::Type::IRRADIANCEMETER: - obj->irradiancemeter = CElementSensor::IrradianceMeter(); - break; - case CElementSensor::Type::RADIANCEMETER: - obj->radiancemeter = CElementSensor::RadianceMeter(); - break; - case CElementSensor::Type::FLUENCEMETER: - obj->fluencemeter = CElementSensor::FluenceMeter(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} +namespace nbl::ext::MitsubaLoader +{ -bool CElementSensor::addProperty(SNamedPropertyElement&& _property) +auto CElementSensor::compAddPropertyMap() -> AddPropertyMap { - bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) + using this_t = CElementSensor; + AddPropertyMap retval; + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(up,VECTOR,derived_from,ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shiftX,FLOAT,derived_from,PerspectivePinhole); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shiftY,FLOAT,derived_from,PerspectivePinhole); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(fov,FLOAT,derived_from,PerspectivePinhole); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("fovAxis",STRING,derived_from,PerspectivePinhole) { - case CElementSensor::Type::PERSPECTIVE: - func(perspective); - break; - case CElementSensor::Type::THINLENS: - func(thinlens); - break; - case CElementSensor::Type::ORTHOGRAPHIC: - func(orthographic); - break; - case CElementSensor::Type::TELECENTRIC: - func(telecentric); - break; - case CElementSensor::Type::SPHERICAL: - func(spherical); - break; - case CElementSensor::Type::IRRADIANCEMETER: - func(irradiancemeter); - break; - case CElementSensor::Type::RADIANCEMETER: - func(radiancemeter); - break; - case CElementSensor::Type::FLUENCEMETER: - func(fluencemeter); - break; - default: - error = true; - break; + auto& state = _this->perspective; + // TODO: check if this gives problem with delay loads + static const core::unordered_map StringToType = + { + {"x", PerspectivePinhole::FOVAxis::X}, + {"y", PerspectivePinhole::FOVAxis::Y}, + {"diagonal",PerspectivePinhole::FOVAxis::DIAGONAL}, + {"smaller", PerspectivePinhole::FOVAxis::SMALLER}, + {"larger", PerspectivePinhole::FOVAxis::LARGER} + }; + auto found = StringToType.find(_property.svalue); + if (found!=StringToType.end()) + state.fovAxis = found->second; + else + state.fovAxis = PerspectivePinhole::FOVAxis::INVALID; + return true; } - }; - -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE,BASE) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (std::is_base_of::type >::value) \ - { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ - } \ - }); \ - } - - auto setUp = SET_PROPERTY_TEMPLATE(up,SNamedPropertyElement::Type::VECTOR,ShutterSensor); - auto setClipPlane = [&]() -> void + ); + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shutterOpen,FLOAT,derived_from,ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shutterClose,FLOAT,derived_from,ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(moveSpeed,FLOAT,derived_from,ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(zoomSpeed,FLOAT,derived_from,ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(rotateSpeed,FLOAT,derived_from,ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(nearClip,FLOAT,derived_from,CameraBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(farClip,FLOAT,derived_from,CameraBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(focusDistance,FLOAT,derived_from,DepthOfFieldBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(apertureRadius,FLOAT,derived_from,DepthOfFieldBase); + + // special + auto setClipPlane = [](this_t* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool { - dispatch([&](auto& state) -> void + if (_property.getVectorDimension()!=4) { - if (_property.type!=SNamedPropertyElement::Type::VECTOR || _property.getVectorDimension()==4) - { - error = true; - return; - } - constexpr std::string_view Name = "clipPlane"; - const std::string_view sv(_property.name); - if (sv.length()!=Name.length()+1 || sv.find(Name)!=0) - { - error = true; - return; - } - const auto index = std::atoi(sv.data()+Name.length()); - if (index>MaxClipPlanes) - { - error = true; - return; - } - state.clipPlanes[index] = _property.vvalue; - }); - }; - auto setShiftX = SET_PROPERTY_TEMPLATE(shiftX,SNamedPropertyElement::Type::FLOAT,PerspectivePinhole); - auto setShiftY = SET_PROPERTY_TEMPLATE(shiftY,SNamedPropertyElement::Type::FLOAT,PerspectivePinhole); - auto setFov = SET_PROPERTY_TEMPLATE(fov,SNamedPropertyElement::Type::FLOAT,PerspectivePinhole); - auto setFovAxis = [&]() -> void - { - dispatch([&](auto& state) -> void + return false; + } + constexpr std::string_view Name = "clipPlane"; + const std::string_view sv(_property.name); + if (sv.length()!=Name.length()+1 || sv.find(Name)!=0) { - using state_type = std::remove_reference::type; - if constexpr (std::is_base_of::value) - { - if (_property.type!=SNamedPropertyElement::Type::STRING) - { - error = true; - return; - } - static const core::unordered_map StringToType = - { - {"x", PerspectivePinhole::FOVAxis::X}, - {"y", PerspectivePinhole::FOVAxis::Y}, - {"diagonal",PerspectivePinhole::FOVAxis::DIAGONAL}, - {"smaller", PerspectivePinhole::FOVAxis::SMALLER}, - {"larger", PerspectivePinhole::FOVAxis::LARGER} - }; - auto found = StringToType.find(_property.svalue); - if (found!=StringToType.end()) - state.fovAxis = found->second; - else - state.fovAxis = PerspectivePinhole::FOVAxis::INVALID; - } - }); - }; - auto setShutterOpen = SET_PROPERTY_TEMPLATE(shutterOpen,SNamedPropertyElement::Type::FLOAT,ShutterSensor); - auto setShutterClose = SET_PROPERTY_TEMPLATE(shutterClose,SNamedPropertyElement::Type::FLOAT,ShutterSensor); - auto setMoveSpeed = SET_PROPERTY_TEMPLATE(moveSpeed,SNamedPropertyElement::Type::FLOAT,ShutterSensor); - auto setZoomSpeed = SET_PROPERTY_TEMPLATE(zoomSpeed,SNamedPropertyElement::Type::FLOAT,ShutterSensor); - auto setRotateSpeed = SET_PROPERTY_TEMPLATE(rotateSpeed,SNamedPropertyElement::Type::FLOAT,ShutterSensor); - auto setNearClip = SET_PROPERTY_TEMPLATE(nearClip,SNamedPropertyElement::Type::FLOAT,CameraBase); - auto setFarClip = SET_PROPERTY_TEMPLATE(farClip,SNamedPropertyElement::Type::FLOAT,CameraBase); - auto setFocusDistance = SET_PROPERTY_TEMPLATE(focusDistance,SNamedPropertyElement::Type::FLOAT,DepthOfFieldBase); - auto setApertureRadius = SET_PROPERTY_TEMPLATE(apertureRadius,SNamedPropertyElement::Type::FLOAT,DepthOfFieldBase); - //auto setKc = SET_PROPERTY_TEMPLATE(apertureRadius,SNamedPropertyElement::Type::STRING,PerspectivePinholeRadialDistortion); - - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - //{"focalLength", noIdeaHowToProcessValue}, - {"up", setUp}, - {"clipPlane0", setClipPlane}, - {"clipPlane1", setClipPlane}, - {"clipPlane2", setClipPlane}, - {"clipPlane3", setClipPlane}, - {"clipPlane4", setClipPlane}, - {"clipPlane5", setClipPlane}, - // UPDATE WHENEVER `MaxClipPlanes` changes! - {"shiftX", setShiftX}, - {"shiftY", setShiftY}, - {"fov", setFov}, - {"fovAxis", setFovAxis}, - {"shutterOpen", setShutterOpen}, - {"shuttterClose", setShutterClose}, - {"moveSpeed", setMoveSpeed}, - {"zoomSpeed", setZoomSpeed}, - {"rotateSpeed", setRotateSpeed}, - {"nearClip", setNearClip}, - {"farClip", setFarClip}, - {"focusDistance", setFocusDistance}, - {"apertureRadius", setApertureRadius}/*, - {"kc", setKc}*/ + return false; + } + const auto index = std::atoi(sv.data()+Name.length()); + if (index>MaxClipPlanes) + { + return false; + } + // everyone inherits from this + _this->perspective.clipPlanes[index] = _property.vvalue; + return true; }; - + for (auto i=0; isecond(); - return !error; + return retval; } -bool CElementSensor::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* meta) +bool CElementSensor::onEndTag(CMitsubaMetadata* meta, system::logger_opt_ptr logger) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: some validation @@ -257,6 +95,4 @@ bool CElementSensor::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _overri return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementShape.cpp b/src/nbl/ext/MitsubaLoader/CElementShape.cpp index 8e6c468821..0af5b97172 100644 --- a/src/nbl/ext/MitsubaLoader/CElementShape.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementShape.cpp @@ -274,14 +274,9 @@ bool CElementShape::processChildData(IElement* _child, const std::string& name) return false; } -bool CElementShape::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) +bool CElementShape::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: some validation diff --git a/src/nbl/ext/MitsubaLoader/CElementTexture.cpp b/src/nbl/ext/MitsubaLoader/CElementTexture.cpp index 1ae16b8c07..410ab8508f 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTexture.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTexture.cpp @@ -1,17 +1,13 @@ -// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - #include "nbl/ext/MitsubaLoader/ParserUtil.h" #include "nbl/ext/MitsubaLoader/CElementFactory.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader + +namespace nbl::ext::MitsubaLoader { @@ -284,14 +280,9 @@ bool CElementTexture::processChildData(IElement* _child, const std::string& name return true; } -bool CElementTexture::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) +bool CElementTexture::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { - if (type == Type::INVALID) - { - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); - _NBL_DEBUG_BREAK_IF(true); - return true; - } + NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); // TODO: Validation { @@ -300,6 +291,4 @@ bool CElementTexture::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _overr return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp index 7d7f2922f1..cb583c211c 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp @@ -1,56 +1,33 @@ // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h - +#include "nbl/ext/MitsubaLoader/CElementTransform.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ - -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +namespace nbl::ext::MitsubaLoader { - if (IElement::invalidAttributeCount(_atts, 2u)) - return CElementFactory::return_type(nullptr,""); - if (core::strcmpi(_atts[0], "name")) - return CElementFactory::return_type(nullptr,""); - - return CElementFactory::return_type(_util->objects.construct(),_atts[1]); -} -bool CElementTransform::addProperty(SNamedPropertyElement&& _property) +auto CElementTransform::compAddPropertyMap() -> AddPropertyMap { - switch (_property.type) + using this_t = CElementTransform; + AddPropertyMap retval; + + auto setMatrix = [](this_t* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool { - case SNamedPropertyElement::Type::MATRIX: - [[fallthrough]]; - case SNamedPropertyElement::Type::TRANSLATE: - [[fallthrough]]; - case SNamedPropertyElement::Type::ROTATE: - [[fallthrough]]; - case SNamedPropertyElement::Type::SCALE: - [[fallthrough]]; - case SNamedPropertyElement::Type::LOOKAT: - matrix = core::concatenateBFollowedByA(_property.mvalue, matrix); - break; - default: - { - ParserLog::invalidXMLFileStructure("The transform element does not take child property: "+_property.type); - _NBL_DEBUG_BREAK_IF(true); - return false; - } - break; - } + _this->matrix = _property.mvalue; + return true; + }; + for (const auto& type : { + SNamedPropertyElement::Type::MATRIX, + SNamedPropertyElement::Type::TRANSLATE, + SNamedPropertyElement::Type::ROTATE, + SNamedPropertyElement::Type::SCALE, + SNamedPropertyElement::Type::LOOKAT + }) + retval.registerCallback(type,"",{.func=setMatrix}); - return true; + return retval; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index 6efa07ba23..7bedf035b8 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -4,43 +4,43 @@ set(NBL_EXT_INTERNAL_INCLUDE_DIR "${NBL_ROOT_PATH}/include/nbl/ext/MitsubaLoader set(NBL_EXT_MITSUBA_LOADER_H -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/PropertyElement.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/IElement.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaMetadata.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementIntegrator.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementSensor.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementFilm.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementRFilter.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementSampler.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementTransform.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementShape.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementBSDF.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementTexture.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementEmitter.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementFactory.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaSerializedMetadata.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/ParserUtil.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/PropertyElement.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/IElement.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaMetadata.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementIntegrator.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementSensor.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementFilm.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementRFilter.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementSampler.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementTransform.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementShape.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementBSDF.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementTexture.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementEmitter.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CElementEmissionProfile.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaSerializedMetadata.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/ParserUtil.h ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CSerializedLoader.h -# ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaLoader.h + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaLoader.h # ${NBL_EXT_INTERNAL_INCLUDE_DIR}/CMitsubaMaterialCompilerFrontend.h ) set(NBL_EXT_MITSUBA_LOADER_SRC -# PropertyElement.cpp -# CElementIntegrator.cpp -# CElementSensor.cpp -# CElementFilm.cpp -# CElementRFilter.cpp -# CElementSampler.cpp -# CElementTransform.cpp + PropertyElement.cpp + CElementIntegrator.cpp + CElementSensor.cpp + CElementFilm.cpp + CElementRFilter.cpp + CElementSampler.cpp + CElementTransform.cpp # CElementShape.cpp # CElementBSDF.cpp # CElementTexture.cpp # CElementEmitter.cpp -# CElementFactory.cpp -# ParserUtil.cpp + CElementEmissionProfile.cpp + ParserUtil.cpp CSerializedLoader.cpp -# CMitsubaLoader.cpp + CMitsubaLoader.cpp # CMitsubaMaterialCompilerFrontend.cpp ) diff --git a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp index 093a5b0624..df9d8c776e 100644 --- a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp +++ b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp @@ -1,19 +1,19 @@ -#include "..\..\..\..\include\nbl\ext\MitsubaLoader\CMitsubaLoader.h" // Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O. // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#include "os.h" #include #include "nbl/ext/MitsubaLoader/CMitsubaLoader.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" +#if 0 #include "nbl/asset/utils/CDerivativeMapCreator.h" #include "nbl/ext/MitsubaLoader/CMitsubaSerializedMetadata.h" #include "nbl/ext/MitsubaLoader/CGLSLMitsubaLoaderBuiltinIncludeLoader.h" +#endif #if defined(_NBL_DEBUG) || defined(_NBL_RELWITHDEBINFO) @@ -24,57 +24,10 @@ namespace nbl { using namespace asset; -namespace ext -{ -namespace MitsubaLoader -{ - -_NBL_STATIC_INLINE_CONSTEXPR const char* DUMMY_VERTEX_SHADER = -R"(#version 430 core - -layout (location = 0) in vec3 vPosition; -layout (location = 2) in vec2 vUV; -layout (location = 3) in vec3 vNormal; - -layout (location = 0) out vec3 WorldPos; -layout (location = 1) flat out uint InstanceIndex; -layout (location = 2) out vec3 Normal; -layout (location = 3) out vec2 UV; - -#include -#include - -#ifndef _NBL_VERT_SET1_BINDINGS_DEFINED_ -#define _NBL_VERT_SET1_BINDINGS_DEFINED_ -layout (set = 1, binding = 0, row_major, std140) uniform UBO { - nbl_glsl_SBasicViewParameters params; -} CamData; -#endif //_NBL_VERT_SET1_BINDINGS_DEFINED_ - -#include - -layout (set = 0, binding = 5, row_major, std430) readonly restrict buffer InstDataBuffer { - nbl_glsl_ext_Mitsuba_Loader_instance_data_t data[]; -} InstData; - -void main() +namespace ext::MitsubaLoader { - mat4x3 tform = InstData.data[gl_InstanceIndex].tform; - mat4 mvp = nbl_glsl_pseudoMul4x4with4x3(CamData.params.MVP, tform); - gl_Position = nbl_glsl_pseudoMul4x4with3x1(mvp, vPosition); - WorldPos = nbl_glsl_pseudoMul3x4with3x1(tform, vPosition); - mat3 normalMat = mat3(InstData.data[gl_InstanceIndex].normalMatrixRow0,InstData.data[gl_InstanceIndex].normalMatrixRow1,InstData.data[gl_InstanceIndex].normalMatrixRow2); - Normal = transpose(normalMat)*normalize(vNormal); - UV = vUV; - InstanceIndex = gl_InstanceIndex; -} -)"; - -_NBL_STATIC_INLINE_CONSTEXPR const char* FRAGMENT_SHADER_PROLOGUE = -R"(#version 430 core -#extension GL_EXT_shader_integer_mix : require -)"; +#if 0 // old material compiler _NBL_STATIC_INLINE_CONSTEXPR const char* FRAGMENT_SHADER_INPUT_OUTPUT = R"( layout (location = 0) in vec3 WorldPos; @@ -166,62 +119,9 @@ void main() } #endif )"; - -_NBL_STATIC_INLINE_CONSTEXPR const char* VERTEX_SHADER_CACHE_KEY = "nbl/builtin/specialized_shader/loaders/mitsuba_xml/default"; - -_NBL_STATIC_INLINE_CONSTEXPR uint32_t PAGE_TAB_TEX_BINDING = 0u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t PHYS_PAGE_VIEWS_BINDING = 1u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t PRECOMPUTED_VT_DATA_BINDING = 2u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t INSTR_BUF_BINDING = 3u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t BSDF_BUF_BINDING = 4u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t INSTANCE_DATA_BINDING = 5u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t PREFETCH_INSTR_BUF_BINDING = 6u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t EMITTER_DATA_BUF_BINDING = 7u; -_NBL_STATIC_INLINE_CONSTEXPR uint32_t DS0_BINDING_COUNT_WO_VT = 6u; - -template -static void insertAssetIntoCache(core::smart_refctd_ptr& asset, const char* path, IAssetManager* _assetMgr) // TODO: @Crisspl this is duplicate code -{ - asset::SAssetBundle bundle(nullptr,{ asset }); - _assetMgr->changeAssetKey(bundle, path); - _assetMgr->insertAssetIntoCache(bundle); -} -// @Crisspl TODO this needs to use the IAssetLoaderOverride instead -template -static auto getBuiltinAsset(const char* _key, IAssetManager* _assetMgr) -> std::enable_if_t, core::smart_refctd_ptr> -{ - size_t storageSz = 1ull; - asset::SAssetBundle bundle; - const IAsset::E_TYPE types[]{ assetType, static_cast(0u) }; - - _assetMgr->findAssets(storageSz, &bundle, _key, types); - auto assets = bundle.getContents(); - if (assets.empty()) - return nullptr; - //assert(!assets.empty()); - - return core::smart_refctd_ptr_static_cast(assets.begin()[0]); -} - -static core::smart_refctd_ptr createSpecShader(const char* _glsl, asset::ISpecializedShader::E_SHADER_STAGE _stage) -{ - auto shader = core::make_smart_refctd_ptr(_glsl); - asset::ICPUSpecializedShader::SInfo info(nullptr, nullptr, "main", _stage); - auto specd = core::make_smart_refctd_ptr(std::move(shader), std::move(info)); - - return specd; -} -static core::smart_refctd_ptr createAndCacheVertexShader(asset::IAssetManager* _manager, const char* _glsl) -{ - auto vs = createSpecShader(_glsl, asset::ISpecializedShader::ESS_VERTEX); - - insertAssetIntoCache(vs, VERTEX_SHADER_CACHE_KEY, _manager); - - return vs; -} static core::smart_refctd_ptr createFragmentShader(const asset::material_compiler::CMaterialCompilerGLSLBackendCommon::result_t& _mcRes, size_t _VTstorageViewCount) { - std::string source = + std::string source = FRAGMENT_SHADER_PROLOGUE + _mcRes.fragmentShaderSource_declarations + FRAGMENT_SHADER_INPUT_OUTPUT + @@ -232,44 +132,25 @@ static core::smart_refctd_ptr createFragmentShader return createSpecShader(source.c_str(), asset::ISpecializedShader::ESS_FRAGMENT); } -static core::smart_refctd_ptr createPipeline(core::smart_refctd_ptr&& _layout, core::smart_refctd_ptr&& _vertshader, core::smart_refctd_ptr&& _fragshader) -{ - auto vs = std::move(_vertshader); - auto fs = std::move(_fragshader); - asset::ICPUSpecializedShader* shaders[2]{ vs.get(), fs.get() }; - - SRasterizationParams rasterParams; - rasterParams.faceCullingMode = asset::EFCM_NONE; - rasterParams.frontFaceIsCCW = 1; - auto pipeline = core::make_smart_refctd_ptr( - std::move(_layout), - shaders, shaders+2, - //all the params will be overriden with those loaded with meshes - SVertexInputParams(), - SBlendParams(), - SPrimitiveAssemblyParams(), - rasterParams - ); - - return pipeline; -} +#endif -static core::smart_refctd_ptr createImageView(core::smart_refctd_ptr&& _img) // TODO: this should seriously be a utility somewhere +#if 0 +static core::smart_refctd_ptr createImageView(core::smart_refctd_ptr&& _img) // TODO: this should seriously be a utility somewhere { const auto& iparams = _img->getCreationParameters(); - asset::ICPUImageView::SCreationParams params; + ICPUImageView::SCreationParams params; params.format = iparams.format; params.subresourceRange.baseArrayLayer = 0u; params.subresourceRange.layerCount = iparams.arrayLayers; assert(params.subresourceRange.layerCount == 1u); params.subresourceRange.baseMipLevel = 0u; params.subresourceRange.levelCount = iparams.mipLevels; - params.viewType = asset::IImageView::ET_2D; - params.flags = static_cast::E_CREATE_FLAGS>(0); + params.viewType = IImageView::ET_2D; + params.flags = static_cast::E_CREATE_FLAGS>(0); params.image = std::move(_img); - return asset::ICPUImageView::create(std::move(params)); + return ICPUImageView::create(std::move(params)); } static core::smart_refctd_ptr createDerivMap(SContext& ctx, asset::ICPUImage* _heightMap, const ICPUSampler::SParams& _samplerParams, bool fromNormalMap) { @@ -363,158 +244,82 @@ static core::smart_refctd_ptr createSingleChannelImage(const a return outImg; } - -core::smart_refctd_ptr CMitsubaLoader::createPipelineLayout(asset::IAssetManager* _manager, const asset::ICPUVirtualTexture* _vt) -{ - core::smart_refctd_ptr ds0layout; - { - auto sizes = _vt->getDSlayoutBindings(nullptr, nullptr); - auto bindings = core::make_refctd_dynamic_array>(sizes.first + DS0_BINDING_COUNT_WO_VT); - auto samplers = core::make_refctd_dynamic_array< core::smart_refctd_dynamic_array>>(sizes.second); - - _vt->getDSlayoutBindings(bindings->data(), samplers->data(), PAGE_TAB_TEX_BINDING, PHYS_PAGE_VIEWS_BINDING); - auto* b = bindings->data() + (bindings->size() - DS0_BINDING_COUNT_WO_VT); - b[0].binding = PRECOMPUTED_VT_DATA_BINDING; - b[0].count = 1u; - b[0].samplers = nullptr; - b[0].stageFlags = asset::ISpecializedShader::ESS_FRAGMENT; - b[0].type = asset::EDT_STORAGE_BUFFER; - - b[1].binding = INSTR_BUF_BINDING; - b[1].count = 1u; - b[1].samplers = nullptr; - b[1].stageFlags = asset::ISpecializedShader::ESS_FRAGMENT; - b[1].type = asset::EDT_STORAGE_BUFFER; - - b[2].binding = BSDF_BUF_BINDING; - b[2].count = 1u; - b[2].samplers = nullptr; - b[2].stageFlags = asset::ISpecializedShader::ESS_FRAGMENT; - b[2].type = asset::EDT_STORAGE_BUFFER; - - b[3].binding = INSTANCE_DATA_BINDING; - b[3].count = 1u; - b[3].samplers = nullptr; - b[3].stageFlags = static_cast(asset::ISpecializedShader::ESS_FRAGMENT | asset::ISpecializedShader::ESS_VERTEX); - b[3].type = asset::EDT_STORAGE_BUFFER; - - b[4].binding = PREFETCH_INSTR_BUF_BINDING; - b[4].count = 1u; - b[4].samplers = nullptr; - b[4].stageFlags = asset::ISpecializedShader::ESS_FRAGMENT; - b[4].type = asset::EDT_STORAGE_BUFFER; - - b[5].binding = EMITTER_DATA_BUF_BINDING; - b[5].count = 1u; - b[5].samplers = nullptr; - b[5].stageFlags = asset::ISpecializedShader::ESS_FRAGMENT; - b[5].type = asset::EDT_STORAGE_BUFFER; - - ds0layout = core::make_smart_refctd_ptr(bindings->data(), bindings->data() + bindings->size()); - } - auto ds1layout = getBuiltinAsset("nbl/builtin/descriptor_set_layout/basic_view_parameters", _manager); - - return core::make_smart_refctd_ptr(nullptr, nullptr, std::move(ds0layout), std::move(ds1layout), nullptr, nullptr); -} - -CMitsubaLoader::CMitsubaLoader(asset::IAssetManager* _manager, io::IFileSystem* _fs) : asset::IRenderpassIndependentPipelineLoader(_manager), m_filesystem(_fs) -{ -#ifdef _NBL_DEBUG - setDebugName("CMitsubaLoader"); #endif -} -void CMitsubaLoader::initialize() +bool CMitsubaLoader::isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger) const { - IRenderpassIndependentPipelineLoader::initialize(); - - auto* glslc = m_assetMgr->getGLSLCompiler(); - - glslc->getIncludeHandler()->addBuiltinIncludeLoader(core::make_smart_refctd_ptr(m_filesystem)); -} - -bool CMitsubaLoader::isALoadableFileFormat(io::IReadFile* _file) const -{ - constexpr uint32_t stackSize = 16u*1024u; + constexpr uint32_t stackSize = 16u<<10u; char tempBuff[stackSize+1]; tempBuff[stackSize] = 0; static const char* stringsToFind[] = { " 2u*maxStringSize, "WTF?"); + static_assert(stackSize>2u*maxStringSize); - const size_t prevPos = _file->getPos(); const auto fileSize = _file->getSize(); - if (fileSize < maxStringSize) + if (fileSizeseek(0); - _file->read(tempBuff, 3u); - bool utf16 = false; - if (tempBuff[0]==0xEFu && tempBuff[1]==0xBBu && tempBuff[2]==0xBFu) - utf16 = false; - else if (reinterpret_cast(tempBuff)[0]==0xFEFFu) + size_t pos = 3; + bool utf16; { - utf16 = true; - _file->seek(2); + system::IFile::success_t success; + _file->read(success,tempBuff,0,pos); + if (!success) + return false; + if (tempBuff[0] == 0xEFu && tempBuff[1] == 0xBBu && tempBuff[2] == 0xBFu) + utf16 = false; + else if (reinterpret_cast(tempBuff)[0] == 0xFEFFu) + { + utf16 = true; + pos = 2; + } + else + pos = 0; } - else - _file->seek(0); - while (true) + + while (posgetPos(); - if (pos >= fileSize) - break; - if (pos > maxStringSize) - _file->seek(_file->getPos()-maxStringSize); - _file->read(tempBuff,stackSize); + if (pos>maxStringSize) + pos -= maxStringSize; + system::ISystem::future_t bytesRead; + _file->read(bytesRead,tempBuff,pos,stackSize); + if (!bytesRead.wait()) + return false; + tempBuff[bytesRead.copy()] = '\0'; + // TODO: should we require all 3 are found? for (auto i=0u; i(tempBuff),stringsToFindW[i])!=nullptr):(strstr(tempBuff, stringsToFind[i])!=nullptr)) - { - _file->seek(prevPos); + if (utf16 ? (wcsstr(reinterpret_cast(tempBuff),stringsToFindW[i])!=nullptr):(strstr(tempBuff,stringsToFind[i])!=nullptr)) return true; - } } - _file->seek(prevPos); return false; } -const char** CMitsubaLoader::getAssociatedFileExtensions() const -{ - static const char* ext[]{ "xml", nullptr }; - return ext; -} - -asset::SAssetBundle CMitsubaLoader::loadAsset(io::IReadFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, uint32_t _hierarchyLevel) +SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _file, const IAssetLoader::SAssetLoadParams& _params, IAssetLoader::IAssetLoaderOverride* _override, uint32_t _hierarchyLevel) { - ParserManager parserManager(m_assetMgr->getFileSystem(),_override); - if (!parserManager.parse(_file)) + auto result = m_parser.parse(_file,{.logger=_params.logger,.system=m_system.get(),._override=_override}); + if (!result) return {}; - if (_params.loaderFlags & IAssetLoader::ELPF_LOAD_METADATA_ONLY) + auto scene = core::make_smart_refctd_ptr(); + if (_params.loaderFlags&IAssetLoader::ELPF_LOAD_METADATA_ONLY) { - auto emptyMesh = core::make_smart_refctd_ptr(); - return SAssetBundle(std::move(parserManager.m_metadata),{ std::move(emptyMesh) }); + return SAssetBundle(std::move(result.metadata),{std::move(scene)}); } else { - // - auto currentDir = io::IFileSystem::getFileDir(_file->getFileName()) + "/"; +#if 0 SContext ctx( - m_assetMgr->getGeometryCreator(), - m_assetMgr->getMeshManipulator(), - asset::IAssetLoader::SAssetLoadContext{ - asset::IAssetLoader::SAssetLoadParams(_params.decryptionKeyLen, _params.decryptionKey, _params.cacheFlags, currentDir.c_str()), +// m_assetMgr->getGeometryCreator(), +// m_assetMgr->getMeshManipulator(), + IAssetLoader::SAssetLoadContext{ + IAssetLoader::SAssetLoadParams(_params.decryptionKeyLen,_params.decryptionKey,_params.cacheFlags,_params.logger,_file->getFileName().parent_path()), _file }, _override, parserManager.m_metadata.get() ); - if (!getBuiltinAsset(VERTEX_SHADER_CACHE_KEY, m_assetMgr)) - { - createAndCacheVertexShader(m_assetMgr, DUMMY_VERTEX_SHADER); - } core::map,std::pair> meshes; for (auto& shapepair : parserManager.shapegroups) @@ -545,7 +350,9 @@ asset::SAssetBundle CMitsubaLoader::loadAsset(io::IReadFile* _file, const asset: for (auto mb : mesh.first.get()->getMeshBuffers()) mb->setInstanceCount(instanceCount); } +#endif +#if 0 // TODO: put IR and stuff in metadata so that we can recompile the materials after load auto compResult = ctx.backend.compile(&ctx.backend_ctx, ctx.ir.get(), decltype(ctx.backend)::EGST_PRESENT_WITH_AOV_EXTRACTION); ctx.backend_ctx.vt.commitAll(); @@ -623,11 +430,12 @@ asset::SAssetBundle CMitsubaLoader::loadAsset(io::IReadFile* _file, const asset: parserManager.m_metadata->m_global.m_envMapImages.push_back(core::smart_refctd_ptr_static_cast(*contentRange.begin())); } } - - return asset::SAssetBundle(std::move(parserManager.m_metadata),std::move(meshSmartPtrArray)); +#endif + return asset::SAssetBundle(std::move(result.metadata),{std::move(scene)}); } } +#if 0 core::vector CMitsubaLoader::getMesh(SContext& ctx, uint32_t hierarchyLevel, CElementShape* shape) { if (!shape) @@ -1379,27 +1187,20 @@ inline core::smart_refctd_ptr CMitsubaLoader::createDS return ds0; } +#endif using namespace std::string_literals; SContext::SContext( - const asset::IGeometryCreator* _geomCreator, - const asset::IMeshManipulator* _manipulator, +// const asset::IGeometryCreator* _geomCreator, +// const asset::IMeshManipulator* _manipulator, const asset::IAssetLoader::SAssetLoadContext& _ctx, asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* _metadata -) : creator(_geomCreator), manipulator(_manipulator), inner(_ctx), override_(_override), meta(_metadata), - ir(core::make_smart_refctd_ptr()), frontend(this) +) : /*creator(_geomCreator), manipulator(_manipulator),*/ inner(_ctx), override_(_override), meta(_metadata) +//,ir(core::make_smart_refctd_ptr()), frontend(this) { - backend_ctx.vt = core::make_smart_refctd_ptr( - [](asset::E_FORMAT_CLASS) -> uint32_t { return VT_PHYSICAL_PAGE_TEX_TILES_PER_DIM_LOG2; }, // 16x16 tiles per layer for all dynamically created storages - VT_PAGE_SZ_LOG2, - VT_PAGE_PADDING, - VT_MAX_ALLOCATABLE_TEX_SZ_LOG2 - ); - meta->m_global.m_VT = core::smart_refctd_ptr(backend_ctx.vt.getCPUVirtualTexture()); } -} } } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h new file mode 100644 index 0000000000..7a210c3b0a --- /dev/null +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -0,0 +1,145 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#include "nbl/ext/MitsubaLoader/IElement.h" +#include "nbl/ext/MitsubaLoader/ParserUtil.h" + + +#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(NAME,PROP_TYPE) retval.registerCallback(SNamedPropertyElement::Type::PROP_TYPE,NAME,{\ + .func=[](this_t* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool + +#define NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(NAME,PROP_TYPE) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(#NAME,PROP_TYPE) {\ + _this->NAME = _property.getProperty(); \ + return true;}}) + + +#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) retval.template registerCallback( \ + SNamedPropertyElement::Type::PROP_TYPE,NAME,[](this_t* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool + +#define NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED(#NAME,PROP_TYPE,CONSTRAINT,__VA_ARGS__) {\ + _this->visit([&_property](auto& state)->void{ \ + if constexpr (CONSTRAINT,__VA_ARGS__>::value) \ + state. ## NAME = _property.getProperty(); \ + }); return true;}) + + +// just to reverse `is_base_of` +namespace nbl::ext::MitsubaLoader +{ +template +struct derived_from : std::is_base_of {}; +} + +/* +template<> +CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +{ + const char* type; + const char* id; + std::string name; + if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) + return CElementFactory::return_type(nullptr, ""); + + static const core::unordered_map StringToType = + { + {"independent", CElementSampler::Type::INDEPENDENT}, + {"stratified", CElementSampler::Type::STRATIFIED}, + {"ldsampler", CElementSampler::Type::LDSAMPLER}, + {"halton", CElementSampler::Type::HALTON}, + {"hammersley", CElementSampler::Type::HAMMERSLEY}, + {"sobol", CElementSampler::Type::SOBOL} + }; + + auto found = StringToType.find(type); + if (found==StringToType.end()) + { + ParserLog::invalidXMLFileStructure("unknown type"); + _NBL_DEBUG_BREAK_IF(false); + return CElementFactory::return_type(nullptr, ""); + } + + CElementSampler* obj = _util->objects.construct(id); + if (!obj) + return CElementFactory::return_type(nullptr, ""); + + obj->type = found->second; + obj->sampleCount = 4; + //validation + switch (obj->type) + { + case CElementSampler::Type::STRATIFIED: + [[fallthrough]]; + case CElementSampler::Type::LDSAMPLER: + obj->dimension = 4; + break; + case CElementSampler::Type::HALTON: + [[fallthrough]]; + case CElementSampler::Type::HAMMERSLEY: + obj->scramble = -1; + break; + case CElementSampler::Type::SOBOL: + obj->scramble = 0; + break; + default: + break; + } + return CElementFactory::return_type(obj, std::move(name)); +} + +bool CElementSampler::addProperty(SNamedPropertyElement&& _property) +{ + if (_property.type == SNamedPropertyElement::Type::INTEGER && + _property.name == "sampleCount") + { + sampleCount = _property.ivalue; + switch (type) + { + case Type::STRATIFIED: + sampleCount = ceilf(sqrtf(sampleCount)); + break; + case Type::LDSAMPLER: + //sampleCount = core::roundUpToPoT(sampleCount); + break; + default: + break; + } + } + else + if (_property.type == SNamedPropertyElement::Type::INTEGER && + _property.name == "dimension") + { + dimension = _property.ivalue; + if (type == Type::INDEPENDENT || type == Type::HALTON || type == Type::HAMMERSLEY) + { + ParserLog::invalidXMLFileStructure("this sampler type does not take these parameters"); + _NBL_DEBUG_BREAK_IF(true); + return false; + } + } + else + if (_property.type == SNamedPropertyElement::Type::INTEGER && + _property.name == "scramble") + { + scramble = _property.ivalue; + if (type==Type::INDEPENDENT || type==Type::STRATIFIED || type == Type::LDSAMPLER) + { + ParserLog::invalidXMLFileStructure("this sampler type does not take these parameters"); + _NBL_DEBUG_BREAK_IF(true); + return false; + } + } + else + { + _NBL_DEBUG_BREAK_IF(true); + return false; + } + + return true; +} +*/ + +#define NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(NON_FATAL) if (type==Type::INVALID) \ +{ \ + invalidXMLFileStructure(logger,getLogName()+": type not specified"); \ + return NON_FATAL; \ +} \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 785fe622dc..a79fdbb906 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -2,88 +2,101 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h + #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" +#include "nbl/ext/MitsubaLoader/CElementIntegrator.h" +#include "nbl/ext/MitsubaLoader/CElementSensor.h" +#include "nbl/ext/MitsubaLoader/CElementFilm.h" +#include "nbl/ext/MitsubaLoader/CElementRFilter.h" +#include "nbl/ext/MitsubaLoader/CElementSampler.h" +//#include "nbl/ext/MitsubaLoader/CElementShape.h" +#include "nbl/ext/MitsubaLoader/CElementTransform.h" +//#include "nbl/ext/MitsubaLoader/CElementAnimation.h" +//#include "nbl/ext/MitsubaLoader/CElementBSDF.h" +//#include "nbl/ext/MitsubaLoader/CElementTexture.h" +//#include "nbl/ext/MitsubaLoader/CElementEmitter.h" +#include "nbl/ext/MitsubaLoader/CElementEmissionProfile.h" #include "expat/lib/expat.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ -system::logger_opt_ptr ParserLog::logger = nullptr; - -void ParserLog::invalidXMLFileStructure(const std::string& errorMessage) +namespace nbl::ext::MitsubaLoader { - std::string message = "Mitsuba loader error - Invalid .xml file structure: \'" - + errorMessage + '\''; - - //ParserLog::logger.log(message, system::ILogger::E_LOG_LEVEL::ELL_ERROR); - _NBL_DEBUG_BREAK_IF(true); -} +using namespace nbl::system; -void ParserManager::elementHandlerStart(void* _data, const char* _el, const char** _atts) +auto ParserManager::parse(IFile* _file, const Params& _params) const -> Result { - auto ctx = *reinterpret_cast(_data); - - ctx.manager->parseElement(ctx, _el, _atts); +// CMitsubaMetadata* obj = new CMitsubaMetadata(); + Result result = { + .metadata = core::make_smart_refctd_ptr() + }; + SessionContext ctx = { + .result = &result, + .params = &_params, + .manager = this + }; + + if (!ctx.parse(_file)) + return {}; + + return result; } -void ParserManager::elementHandlerEnd(void* _data, const char* _el) +bool ParserManager::SessionContext::parse(IFile* _file) { - auto ctx = *reinterpret_cast(_data); - - ctx.manager->onEnd(ctx,_el); -} - - + auto logger = params->logger; -bool ParserManager::parse(system::IFile* _file, const system::logger_opt_ptr& _logger) -{ XML_Parser parser = XML_ParserCreate(nullptr); if (!parser) { - _logger.log("Could not create XML Parser!", system::ILogger::E_LOG_LEVEL::ELL_ERROR); + logger.log("Could not create XML Parser!",ILogger::E_LOG_LEVEL::ELL_ERROR); return false; } - XML_SetElementHandler(parser, elementHandlerStart, elementHandlerEnd); + XML_SetElementHandler(parser,elementHandlerStart,elementHandlerEnd); //from now data (instance of ParserData struct) will be visible to expat handlers - Context ctx = {this,parser,_file->getFileName().parent_path()/""}; - XML_SetUserData(parser, &ctx); - - - char* buff = (char*)_NBL_ALIGNED_MALLOC(_file->getSize(), 4096u); - - system::future future; - _file->read(future, (void*)buff, 0u, _file->getSize()); - future.get(); + XMLContext ctx = { + .session = this, + .currentXMLDir = _file->getFileName().parent_path()/"", + .parser = parser + }; + XML_SetUserData(parser,&ctx); + + const size_t size = _file->getSize(); + const char* buff = reinterpret_cast(const_cast(_file)->getMappedPointer()); + if (!buff) + { + buff = reinterpret_cast(_NBL_ALIGNED_MALLOC(size,4096u)); + IFile::success_t success; + _file->read(success,const_cast(buff),0u,size); + if (!success) + { + logger.log("Could read the file into XML Parser Buffer!",ILogger::E_LOG_LEVEL::ELL_ERROR); + return false; + } + } + XML_Status parseStatus = XML_Parse(parser,buff,size,0); + if (_file->getMappedPointer()!=buff) + _NBL_ALIGNED_FREE(const_cast(buff)); - XML_Status parseStatus = XML_Parse(parser, buff, _file->getSize(), 0); - _NBL_ALIGNED_FREE(buff); XML_ParserFree(parser); switch (parseStatus) { case XML_STATUS_ERROR: { - _logger.log("Parse status: XML_STATUS_ERROR", system::ILogger::E_LOG_LEVEL::ELL_ERROR); + logger.log("Parse status: XML_STATUS_ERROR",ILogger::E_LOG_LEVEL::ELL_ERROR); return false; } break; case XML_STATUS_OK: - #ifdef _NBL_DEBUG - _logger.log("Parse status: XML_STATUS_OK", system::ILogger::E_LOG_LEVEL::ELL_INFO); - #endif + logger.log("Parse status: XML_STATUS_OK",ILogger::E_LOG_LEVEL::ELL_INFO); break; case XML_STATUS_SUSPENDED: { - _logger.log("Parse status: XML_STATUS_SUSPENDED", system::ILogger::E_LOG_LEVEL::ELL_INFO); + logger.log("Parse status: XML_STATUS_SUSPENDED",ILogger::E_LOG_LEVEL::ELL_INFO); return false; } break; @@ -92,160 +105,378 @@ bool ParserManager::parse(system::IFile* _file, const system::logger_opt_ptr& _l return true; } -static const core::unordered_set propertyElements = { - "float", "string", "boolean", "integer", - "rgb", "srgb", "spectrum", "blackbody", - "point", "vector", - "matrix", "rotate", "translate", "scale", "lookat" -}; +void ParserManager::elementHandlerStart(void* _data, const char* _el, const char** _atts) +{ + auto& ctx = *reinterpret_cast(_data); + + ctx.parseElement(_el,_atts); +} -void ParserManager::parseElement(const Context& ctx, const char* _el, const char** _atts) +void ParserManager::XMLContext::killParseWithError(const std::string& message) const { - if (core::strcmpi(_el, "scene") == 0) + session->invalidXMLFileStructure(message); + XML_StopParser(parser,false); +} + +void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts) +{ + if (core::strcmpi(_el,"scene")==0) { auto count = 0u; while (_atts && _atts[count]) { count++; } - if (count != 2u) + if (count!=2u) { - killParseWithError(ctx,"Wrong number of attributes for scene element"); + killParseWithError("Wrong number of attributes for scene element"); return; } - if (core::strcmpi(_atts[0], "version")) + if (core::strcmpi(_atts[0],"version")) { - ParserLog::invalidXMLFileStructure(std::string(_atts[0]) + " is not an attribute of scene element"); + session->invalidXMLFileStructure(core::string(_atts[0]) + " is not an attribute of scene element"); return; } - else if (core::strcmpi(_atts[1], "0.5.0")) + else if (core::strcmpi(_atts[1],"0.5.0")) { - ParserLog::invalidXMLFileStructure("Version " + std::string(_atts[1]) + " is unsupported"); + session->invalidXMLFileStructure("Version " + core::string(_atts[1]) + " is unsupported"); return; } - m_sceneDeclCount++; + session->sceneDeclCount++; return; } - if (m_sceneDeclCount==0u) + if (session->sceneDeclCount==0u) { - killParseWithError(ctx,"there is no scene element"); + killParseWithError("there is no scene element"); return; } - if (core::strcmpi(_el, "include") == 0) + const ParserManager* manager = session->manager; + if (core::strcmpi(_el,"include")==0) { - system::ISystem::future_t> future; - bool validInput = m_system->createFile(future, ctx.currentXMLDir.string()+_atts[1], system::IFile::ECF_READ); - if (!validInput) // try global path - validInput = m_system->createFile(future, _atts[1], system::IFile::ECF_READ); - if (!validInput) + core::smart_refctd_ptr file; + auto tryOpen = [&](const system::path& path)->bool + { + for (auto i=0; i<2; i++) + { + ISystem::future_t> future; + auto flags = IFile::ECF_READ; + if (i==0) + flags |= IFile::ECF_MAPPABLE; + session->params->system->createFile(future,currentXMLDir/_atts[1],flags); + if (future.wait()) + future.acquire().move_into(file); + if (file) + return true; + } + return false; + }; + // first try as relative path, then as global + if (!tryOpen(currentXMLDir/_atts[1])) + if (!tryOpen(_atts[1])) { - ParserLog::invalidXMLFileStructure(std::string("Could not open include file: ") + _atts[1]); + session->invalidXMLFileStructure(std::string("Could not open include file: ")+_atts[1]); return; } - auto file = future.get(); - parse(file.get(), system::logger_opt_ptr(nullptr)); // TODO: fix + if (!session->parse(file.get())) + killParseWithError(core::string("Could not parse include file: ")+_atts[1]); return; } + const auto& propertyElements = manager->propertyElements; if (propertyElements.find(_el)!=propertyElements.end()) { - processProperty(ctx, _el, _atts); + auto& elements = session->elements; + if (elements.empty()) + { + killParseWithError("cannot set a property with no element on the stack."); + return; + } + auto* element = elements.top().element; + if (!element) + { + session->invalidXMLFileStructure("cannot set property on element that failed to be created."); + return; + } + + auto optProperty = manager->propertyElementManager.createPropertyData(_el,_atts,session->params->logger); + if (!optProperty.has_value()) + { + session->invalidXMLFileStructure("could not create property data."); + return; + } + + bool unsupportedElement = true; + auto run = [&](const auto& map)->void + { + using element_t = std::remove_cvref_t::element_type; + if (element_t::ElementType==element->getType()) + { + unsupportedElement = false; + auto& property = optProperty.value(); + const auto& typeMap = map.byPropertyType[property.type]; + if (typeMap.empty()) + { + session->invalidXMLFileStructure("There's no property supported by ElementType (TODO) with PropertyType (TODO)"); + return; + } + auto nameIt = typeMap.find(property.name); + // special, find callback that matches all names (registered with empty name) + if (nameIt==typeMap.end()) + nameIt = typeMap.find(""); + if (nameIt==typeMap.end()) + { + session->invalidXMLFileStructure("There's no Property named (TODO) of Type (TODO) supported by ElementType (TODO)"); + return; + } + const auto& callback = nameIt->second; + auto* typedElement = static_cast(element); + if constexpr (!std::is_same_v) + if (std::find(callback.allowedVariantTypes.begin(),callback.allowedVariantTypes.end(),typedElement->type)==callback.allowedVariantTypes.end()) + { + session->invalidXMLFileStructure("There's no Property named (TODO) of Type (TODO) not supported on ElementType (TODO) of Variant (TODO)"); + return; + } + callback(typedElement,std::move(property),session->params->logger); + } + }; + std::apply([&run](const auto&... maps)->void + { + (run(maps), ...); + },manager->addPropertyMaps + ); + if (unsupportedElement) + { + session->invalidXMLFileStructure("Current Element Type doesn't have a AddPropertyMap at all (no property adding supported)!"); + return; + } return; } - const auto& _map = CElementFactory::createElementTable; + // TODO: don't have this table be a global + const auto& _map = manager->createElementTable; auto found = _map.find(_el); if (found==_map.end()) { - ParserLog::invalidXMLFileStructure(std::string("Could not process element ") + _el); - elements.push({nullptr,""}); + session->invalidXMLFileStructure(std::string("Could not process element ")+_el); + session->elements.push({nullptr,""}); return; } - auto el = found->second.first(_atts, this); - bool goesOnStack = found->second.second; - if (!goesOnStack) + auto created = found->second.create(_atts,session); + // we still push nullptr (failed creation) onto the stack, we only stop parse on catastrphic failure + if (!found->second.retvalGoesOnStack) return; - - - elements.push(el); - if (el.first && el.first->id.size()) - handles[el.first->id] = el.first; + if (created.element && created.name.size()) + session->handles[created.name] = created.element; + session->elements.push(std::move(created)); } -void ParserManager::processProperty(const Context& ctx, const char* _el, const char** _atts) +void ParserManager::elementHandlerEnd(void* _data, const char* _el) { - if (elements.empty()) - { - killParseWithError(ctx,"cannot set a property with no element on the stack."); - return; - } - if (!elements.top().first) - { - ParserLog::invalidXMLFileStructure("cannot set property on element that failed to be created."); - return; - } - - auto optProperty = CPropertyElementManager::createPropertyData(_el, _atts); - - if (optProperty.first == false) - { - ParserLog::invalidXMLFileStructure("could not create property data."); - return; - } - - elements.top().first->addProperty(std::move(optProperty.second)); + auto& ctx = *reinterpret_cast(_data); - return; + ctx.onEnd(_el); } -void ParserManager::onEnd(const Context& ctx, const char* _el) +void ParserManager::XMLContext::onEnd(const char* _el) { - if (propertyElements.find(_el) != propertyElements.end()) + const auto& propertyElements = session->manager->propertyElements; + if (propertyElements.find(_el)!=propertyElements.end()) return; - if (core::strcmpi(_el, "scene") == 0) + if (core::strcmpi(_el,"scene")==0) { - m_sceneDeclCount--; + session->sceneDeclCount--; return; } + auto& elements = session->elements; if (elements.empty()) return; - auto element = elements.top(); elements.pop(); - if (element.first && !element.first->onEndTag(m_override,m_metadata.get())) + auto& result = *session->result; + if (element.element && !element.element->onEndTag(result.metadata.get(),session->params->logger)) { - killParseWithError(ctx,element.first->getLogName() + " could not onEndTag"); + killParseWithError(element.element->getLogName()+" could not onEndTag"); return; } if (!elements.empty()) { - IElement* parent = elements.top().first; - if (parent && !parent->processChildData(element.first, element.second)) + IElement* parent = elements.top().element; + if (parent && !parent->processChildData(element.element,element.name)) { - if (element.first) - killParseWithError(ctx,element.first->getLogName() + " could not processChildData with name: " + element.second); + if (element.element) + killParseWithError(element.element->getLogName()+" could not processChildData with name: "+element.name); else - killParseWithError(ctx,"Failed to add a nullptr child with name: " + element.second); + killParseWithError("Failed to add a nullptr child with name: "+element.name); } return; } - if (element.first && element.first->getType()==IElement::Type::SHAPE) + if (element.element && element.element->getType()==IElement::Type::SHAPE) { - auto shape = static_cast(element.first); + auto shape = static_cast(element.element); if (shape) - shapegroups.emplace_back(shape,std::move(element.second)); + result.shapegroups.emplace_back(shape,std::move(element.name)); } } +// special specs +template<> +struct ParserManager::CreateElement +{ + static inline SNamedElement __call(const char** _atts, SessionContext* ctx) + { + if (IElement::invalidAttributeCount(_atts,2u)) + return {}; + if (core::strcmpi(_atts[0],"name")) + return {}; + + return {ctx->objects.construct(),_atts[1]}; + }; +}; +template<> +struct ParserManager::CreateElement +{ + static inline SNamedElement __call(const char** _atts, SessionContext* ctx) + { + const char* type; + const char* id; + std::string name; + if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) + return {}; + + CElementEmissionProfile* obj = ctx->objects.construct(id); + if (!obj) + return {}; + + return { obj,std::move(name) }; + }; +}; +// default spec +template +concept HasTypeMap = requires() { + { T::compStringToTypeMap() } -> std::same_as>; +}; +template +concept HasVisit = requires() { + { std::declval().visit([](auto& selfV)->void {}) } -> std::same_as; +}; +template requires HasTypeMap +struct ParserManager::CreateElement +{ + static inline SNamedElement __call(const char** _atts, SessionContext* ctx) + { + const char* type; + const char* id; + std::string name; + if (!IElement::getTypeIDAndNameStrings(type,id,name,_atts)) + return {}; + + static const auto StringToTypeMap = Element::compStringToTypeMap(); // TODO: make a const member cause of DLL delay load + auto found = StringToTypeMap.find(type); + if (found==StringToTypeMap.end()) + { + ctx->invalidXMLFileStructure("unknown type"); + return {}; + } + + Element* obj = ctx->objects.construct(id); + if (!obj) + return {}; + + obj->type = found->second; + if constexpr (HasVisit) + obj->visit([](auto& selfV)->void + { + selfV = {}; + } + ); + else + obj->initialize(); + return {obj,std::move(name)}; + } +}; + +// +ParserManager::ParserManager() : propertyElements({ + "float", "string", "boolean", "integer", + "rgb", "srgb", "spectrum", "blackbody", + "point", "vector", + "matrix", "rotate", "translate", "scale", "lookat" +}), propertyElementManager(), createElementTable({ + {"integrator", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"sensor", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"film", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"rfilter", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"sampler", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, +// {"shape", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"transform", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, +// {"animation", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, +// {"bsdf", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, +// {"texture", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, +// {"emitter", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"emissionprofile", {.create=ParserManager::CreateElement::__call,.retvalGoesOnStack=true}}, + {"alias", {.create=processAlias,.retvalGoesOnStack=true}}, + {"ref", {.create=processRef,.retvalGoesOnStack=true}} +}), addPropertyMaps({ + CElementSensor::compAddPropertyMap() +}) { } + +auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SNamedElement +{ + const char* id = nullptr; + const char* as = nullptr; + if (IElement::areAttributesInvalid(_atts,4u)) + { + ctx->invalidXMLFileStructure("Invalid attributes for "); + return {}; + } + + core::string name; + while (*_atts) + { + if (core::strcmpi(_atts[0], "id")==0) + id = _atts[1]; + else if (core::strcmpi(_atts[0], "as")==0) + as = _atts[1]; + else if (core::strcmpi(_atts[0], "name")==0) + name = _atts[1]; + _atts += 2; + } + // not finding the alias doesn't kill XML parse + if (!id || !as) + { + ctx->invalidXMLFileStructure("Alias ID and what we're aliasing is not found"); + return {nullptr,std::move(name)}; + } + + auto& handles = ctx->handles; + auto* original = handles[id]; + handles[as] = original; + return {original,std::move(name)}; } + +auto ParserManager::processRef(const char** _atts, SessionContext* ctx) -> SNamedElement +{ + const char* id; + std::string name; + if (!IElement::getIDAndName(id,name,_atts)) + { + ctx->invalidXMLFileStructure("Malformed `` element!"); + return {nullptr,std::move(name)}; + } + + auto* original = ctx->handles[id]; + if (!original) + ctx->invalidXMLFileStructure(core::string("Used a `` element but referenced element not defined in preceeding XML!"); + return {original,std::move(name)}; } + } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/PropertyElement.cpp b/src/nbl/ext/MitsubaLoader/PropertyElement.cpp index 66f0e40343..d6144b6919 100644 --- a/src/nbl/ext/MitsubaLoader/PropertyElement.cpp +++ b/src/nbl/ext/MitsubaLoader/PropertyElement.cpp @@ -2,51 +2,23 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -#include "quaternion.h" -#include "matrix3x4SIMD.h" -#include "matrix4SIMD.h" -#include "nbl/asset/format/decodePixels.h" + +//#include "quaternion.h" +//#include "matrix3x4SIMD.h" +//#include "matrix4SIMD.h" +//#include "nbl/asset/format/decodePixels.h" #include "nbl/ext/MitsubaLoader/PropertyElement.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +#include "nbl/builtin/hlsl/math/linalg/transform.hlsl" +#include "glm/gtc/matrix_transform.hpp" -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return fvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return ivalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return bvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return svalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return vvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return vvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return vvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return vvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return vvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return mvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return mvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return mvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return mvalue; } -template<> const typename SPropertyElementData::get_typename::type& SPropertyElementData::getProperty() const -{ return mvalue; } -const core::unordered_map SPropertyElementData::StringToType = { +namespace nbl::ext::MitsubaLoader +{ + +CPropertyElementManager::CPropertyElementManager() : StringToType({ {"float", SPropertyElementData::Type::FLOAT}, {"integer", SPropertyElementData::Type::INTEGER}, {"boolean", SPropertyElementData::Type::BOOLEAN}, @@ -62,38 +34,31 @@ const core::unordered_map CPropertyElementManager::createPropertyData(const char* _el, const char** _atts) +std::optional CPropertyElementManager::createPropertyData(const char* _el, const char** _atts, system::logger_opt_ptr logger) const { - SNamedPropertyElement result(_el); + SNamedPropertyElement result = {}; + auto found = StringToType.find(_el); + if (found!=StringToType.end()) + result.type = found->second; + // initialization returns strings from `_atts` which match expected attributes const char* desiredAttributes[SPropertyElementData::MaxAttributes] = { nullptr }; - if (!result.initialize(_atts, desiredAttributes)) + if (!result.initialize(_atts,desiredAttributes)) { - _NBL_DEBUG_BREAK_IF(true); - return std::make_pair(false, SNamedPropertyElement()); + invalidXMLFileStructure(logger,"Failed to Intialize Named Property Element."); + return {}; } - bool success = true; - #define FAIL_IF_ATTRIBUTE_NULL(N) if (!desiredAttributes[N]) {success = false; break;} + auto printFailure = [&](const uint8_t attrId)->void{invalidXMLFileStructure(logger,"invalid element, name:\'"+result.name+"\' value:\'"+desiredAttributes[attrId]+"\'");}; + + #define FAIL_IF_ATTRIBUTE_NULL(N) if (!desiredAttributes[N]) \ + { \ + invalidXMLFileStructure(logger,"Invalid element, name:\'"+result.name+"\' Attribute #"+std::to_string(N)+"not found"); \ + return {}; \ + } switch (result.type) { case SPropertyElementData::Type::FLOAT: @@ -106,35 +71,52 @@ std::pair CPropertyElementManager::createPropertyDa break; case SPropertyElementData::Type::BOOLEAN: FAIL_IF_ATTRIBUTE_NULL(0u) - result.bvalue = retrieveBooleanValue(desiredAttributes[0],success); + if (auto ret=retrieveBooleanValue(desiredAttributes[0],logger); ret.has_value()) + result.bvalue = ret.value(); + else + { + printFailure(0); + return {}; + } break; case SPropertyElementData::Type::STRING: FAIL_IF_ATTRIBUTE_NULL(0u) { auto len = strlen(desiredAttributes[0]); - auto* tmp = (char*)_NBL_ALIGNED_MALLOC(len + 1u, 64u); - strcpy(tmp, desiredAttributes[0]); tmp[len] = 0; + auto* tmp = (char*)_NBL_ALIGNED_MALLOC(len+1u,64u); + strcpy(tmp,desiredAttributes[0]); tmp[len]=0; result.svalue = tmp; } break; case SPropertyElementData::Type::RGB: FAIL_IF_ATTRIBUTE_NULL(0u) - result.vvalue = retrieveVector(desiredAttributes[0], success); + result.vvalue = retrieveVector(desiredAttributes[0],logger); + if (core::isnan(result.vvalue[0])) + { + printFailure(0); + return {}; + } break; case SPropertyElementData::Type::SRGB: FAIL_IF_ATTRIBUTE_NULL(0u) { - bool tryVec = true; - result.vvalue = retrieveVector(desiredAttributes[0], tryVec); - if (!tryVec) - result.vvalue = retrieveHex(desiredAttributes[0], success); + result.vvalue = retrieveVector(desiredAttributes[0],logger); + if (core::isnan(result.vvalue[0])) + { + result.vvalue = retrieveHex(desiredAttributes[0],logger); + if (core::isnan(result.vvalue[0])) + { + printFailure(0); + return {}; + } + } for (auto i=0; i<3u; i++) result.vvalue[i] = core::srgb2lin(result.vvalue[i]); result.type = SPropertyElementData::Type::RGB; // now its an RGB value } break; case SPropertyElementData::Type::VECTOR: - result.vvalue.set(core::nan(),core::nan(),core::nan(),core::nan()); + result.vvalue = hlsl::float32_t4(core::nan()); for (auto i=0u; i<4u; i++) { if (desiredAttributes[i]) @@ -144,31 +126,46 @@ std::pair CPropertyElementManager::createPropertyDa // once a component is missing, the rest need to be missing too for (auto j=i+1; j<4u; j++) if (desiredAttributes[j]) - success = false; + { + printFailure(0); + return {}; + } break; } } break; case SPropertyElementData::Type::POINT: - result.vvalue.set(0.f, 0.f, 0.f); + result.vvalue = hlsl::float32_t4(0.f,0.f,0.f,core::nan()); for (auto i=0u; i<3u; i++) { if (desiredAttributes[i]) result.vvalue[i] = atof(desiredAttributes[i]); else { - success = false; - break; + printFailure(0); + return {}; } } break; case SPropertyElementData::Type::SPECTRUM: - assert(!desiredAttributes[1]); // no intent, TODO - assert(!desiredAttributes[2]); // does not come from a file + if (desiredAttributes[1]||desiredAttributes[2]) { - std::string data(desiredAttributes[0]); - assert(data.find(':')==std::string::npos); // no hand specified wavelengths - result.vvalue = retrieveVector(data,success); // TODO: convert between mitsuba spectral buckets and Rec. 709 + invalidXMLFileStructure(logger,"Spectrum intent and loading from file unsupported!"); + return {}; + } + { + std::string_view data(desiredAttributes[0]); + if (data.find(':')!=std::string::npos) + { + invalidXMLFileStructure(logger,"Manually specified wavelengths for spectral curve knots are unsupported!"); + return {}; + } + result.vvalue = retrieveVector(data,logger); // TODO: convert between mitsuba spectral buckets and Rec. 709 + if (core::isnan(result.vvalue[0])) + { + printFailure(0); + return {}; + } } break; case SPropertyElementData::Type::BLACKBODY: @@ -176,66 +173,78 @@ std::pair CPropertyElementManager::createPropertyDa break; case SPropertyElementData::Type::MATRIX: FAIL_IF_ATTRIBUTE_NULL(0u) - result.mvalue = retrieveMatrix(desiredAttributes[0],success); + result.mvalue = retrieveMatrix(desiredAttributes[0],logger); + if (core::isnan(result.mvalue[0][0])) + { + printFailure(0); + return {}; + } break; case SPropertyElementData::Type::TRANSLATE: - result.vvalue.set(0.f, 0.f, 0.f); + result.mvalue = hlsl::float32_t4x4(1.f); + // we're a bit more lax about what items we need present for (auto i=0u; i<3u; i++) if (desiredAttributes[i]) - result.vvalue[i] = atof(desiredAttributes[i]); - { - core::matrix3x4SIMD m; - m.setTranslation(result.vvalue); - result.mvalue = core::matrix4SIMD(m); - } + result.mvalue[i][3] = atof(desiredAttributes[i]); break; case SPropertyElementData::Type::ROTATE: FAIL_IF_ATTRIBUTE_NULL(0u) // have to have an angle - result.vvalue.set(0.f, 0.f, 0.f); - for (auto i=0u; i<3u; i++) - if (desiredAttributes[i+1]) - result.vvalue[i] = atof(desiredAttributes[i+1]); - if ((core::vectorSIMDf(0.f) == result.vvalue).all()) + result.mvalue = hlsl::float32_t4x4(1.f); { - success = false; - break; - } - result.vvalue = core::normalize(result.vvalue); - { - core::matrix3x4SIMD m; - m.setRotation(core::quaternion::fromAngleAxis(core::radians(atof(desiredAttributes[0])),result.vvalue)); - result.mvalue = core::matrix4SIMD(m); + auto axis = hlsl::float32_t3(0.f); + // again some laxness + for (auto i=0u; i<3u; i++) + if (desiredAttributes[i+1]) + axis[i] = atof(desiredAttributes[i+1]); + axis = hlsl::normalize(axis); + if (core::isnan(axis.x)) + { + invalidXMLFileStructure(logger,"Invalid element, name:\'"+result.name+"\' Axis can't be (0,0,0)"); + return {}; + } + using namespace nbl::hlsl::math;//::linalg; + result.mvalue = linalg::promote_affine<4,4>(linalg::rotation_mat(hlsl::radians(atof(desiredAttributes[0])),axis)); } break; case SPropertyElementData::Type::SCALE: - result.vvalue.set(1.f, 1.f, 1.f); + result.mvalue = hlsl::float32_t4x4(1.f); if (desiredAttributes[0]) { - float uniformScale = atof(desiredAttributes[0]); - result.vvalue.set(uniformScale, uniformScale, uniformScale); + const float uniformScale = atof(desiredAttributes[0]); + for (auto i=0u; i<3u; i++) + result.mvalue[i][i] = uniformScale; } else - for (auto i=0u; i<3u; i++) - if (desiredAttributes[i+1u]) - result.vvalue[i] = atof(desiredAttributes[i+1u]); { - core::matrix3x4SIMD m; - m.setScale(result.vvalue); - result.mvalue = core::matrix4SIMD(m); + for (auto i=0u; i<3u; i++) + if (desiredAttributes[i+1u]) + result.mvalue[i][i] = atof(desiredAttributes[i+1u]); } break; case SPropertyElementData::Type::LOOKAT: FAIL_IF_ATTRIBUTE_NULL(0u) FAIL_IF_ATTRIBUTE_NULL(1u) + result.mvalue = hlsl::float32_t4x4(1.f); { - core::vectorSIMDf origin,target,up; - origin = retrieveVector(desiredAttributes[0u], success); - target = retrieveVector(desiredAttributes[1u], success); + const hlsl::float32_t3 origin = retrieveVector(desiredAttributes[0u],logger).xyz; + if (core::isnan(origin.x)) + { + printFailure(0); + return {}; + } + const hlsl::float32_t3 target = retrieveVector(desiredAttributes[1u],logger).xyz; + if (core::isnan(target.x)) + { + printFailure(1); + return {}; + } + auto up = hlsl::float32_t3(core::nan()); if (desiredAttributes[2u]) - up = retrieveVector(desiredAttributes[2u],success); - else + up = retrieveVector(desiredAttributes[2u],logger).xyz; + if (core::isnan(up.x)) { - auto viewDirection = target - origin; + up = hlsl::float32_t3(0.f); + const auto viewDirection = target - origin; float maxDot = viewDirection[0]; uint32_t index = 0u; for (auto i = 1u; i < 3u; i++) @@ -247,74 +256,65 @@ std::pair CPropertyElementManager::createPropertyDa up[index] = 1.f; } // mitsuba understands look-at and right-handed camera little bit differently than I do - core::matrix4SIMD(core::matrix3x4SIMD::buildCameraLookAtMatrixLH(origin,target,up)).getInverseTransform(result.mvalue); + const auto actualLookAt = reinterpret_cast(glm::lookAtLH(origin,target,up)); + result.mvalue = hlsl::inverse(actualLookAt); } break; default: - success = false; - break; + invalidXMLFileStructure(logger,"Unsupported element type, name:\'"+result.name+"\'"); + return {}; } + #undef FAIL_IF_ATTRIBUTE_NULL - _NBL_DEBUG_BREAK_IF(!success); - if (success) - return std::make_pair(true, std::move(result)); - - ParserLog::invalidXMLFileStructure("invalid element, name:\'" + result.name + "\'"); // in the future print values - return std::make_pair(false, SNamedPropertyElement()); + return result; } -bool CPropertyElementManager::retrieveBooleanValue(const std::string& _data, bool& success) +std::optional CPropertyElementManager::retrieveBooleanValue(const std::string_view& _data, system::logger_opt_ptr logger) { - if (_data == "true") - { + if (_data=="true") return true; - } - else if (_data == "false") - { + else if (_data=="false") return false; - } else { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("Invalid boolean specified."); - success = false; - return false; // so GCC doesn't moan + invalidXMLFileStructure(logger,"Invalid boolean specified."); + return {}; } } -core::matrix4SIMD CPropertyElementManager::retrieveMatrix(const std::string& _data, bool& success) +hlsl::float32_t4x4 CPropertyElementManager::retrieveMatrix(const std::string_view& _data, system::logger_opt_ptr logger) { - std::string str = _data; - std::replace(str.begin(), str.end(), ',', ' '); + std::string str(_data); + std::replace(str.begin(),str.end(),',',' '); - core::matrix4SIMD matrixData; + hlsl::float32_t4x4 matrixData; std::stringstream ss; ss << str; - for (auto i=0u; i<16u; i++) + for (auto r=0u; r<16u; r++) + for (auto c=0u; c<16u; c++) { float f = std::numeric_limits::quiet_NaN(); ss >> f; - if (isnan(f)) + if (core::isnan(f)) { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("Invalid matrix specified."); - success = false; - return core::matrix4SIMD(); + invalidXMLFileStructure(logger,"Invalid matrix specified."); + matrixData[0][0] = f; + return matrixData; } - matrixData.pointer()[i] = f; + matrixData[r][c] = f; } return matrixData; } -core::vectorSIMDf CPropertyElementManager::retrieveVector(const std::string& _data, bool& success) +hlsl::float32_t4 CPropertyElementManager::retrieveVector(const std::string_view& _data, system::logger_opt_ptr logger) { - std::string str = _data; + std::string str(_data); std::replace(str.begin(), str.end(), ',', ' '); - float vectorData[4]; + hlsl::float32_t4 retval; std::stringstream ss; ss << str; @@ -323,55 +323,49 @@ core::vectorSIMDf CPropertyElementManager::retrieveVector(const std::string& _da float f = std::numeric_limits::quiet_NaN(); ss >> f; - vectorData[i] = f; + retval[i] = f; if (isnan(f)) { - if (i == 1) + if (i==1) // second not present { - vectorData[2] = vectorData[1] = vectorData[0]; - vectorData[3] = 0.0f; - break; + // make monochrome RGB or scalar XYZ + retval[2] = retval[1] = retval[0]; + retval[3] = 0.0f; } - else if (i == 3) + else if (i==3) // last not present { - vectorData[3] = 0.0f; - break; + // allow last coordinate to be 0 + retval[3] = 0.0f; } - success = false; - return core::vectorSIMDf(); + return retval; } } - return core::vectorSIMDf(vectorData); + return retval; } -core::vectorSIMDf CPropertyElementManager::retrieveHex(const std::string& _data, bool& success) +hlsl::float32_t4 CPropertyElementManager::retrieveHex(const std::string_view& _data, system::logger_opt_ptr logger) { - core::vectorSIMDf zero; auto ptr = _data.begin(); + const auto invalid = hlsl::float32_t4(std::numeric_limits::quiet_NaN()); + // not a hex if (_data.size()!=7u || *ptr!='#') - { - success = false; - return zero; - } + return invalid; - core::vectorSIMDf retval(0.f, 0.f, 0.f, 255.f); - for (auto i = 0; i < 3; i++) - for (auto j = 4; j >=0;j-=4) + hlsl::float32_t4 retval(0.f, 0.f, 0.f, 255.f); + for (auto i=0; i<3; i++) + for (auto j=4; j>=0;j-=4) { char c = *(++ptr); if (!isxdigit(c)) - { - success = false; - return zero; - } + return invalid; + // case insensitiveness int intval = (c >= 'A') ? (c - 'A' + 10) : (c - '0'); - retval[i] += float(intval <