From fe4600c03a8d658776ed7f54f11baa942c4b9fd9 Mon Sep 17 00:00:00 2001 From: devsh Date: Sat, 27 Sep 2025 15:19:20 +0200 Subject: [PATCH 01/30] make mitsuba loader compile by default --- CMakeLists.txt | 2 +- CMakePresets.json | 2 +- examples_tests | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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..850ca5d414 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit fd8ebfeacaf42f3cf63b1545cccce03809f9c8d6 +Subproject commit 850ca5d41412d8182a72fb88dd4e9e61df55e19b From 8b6b21077d466628b09fbaa0469a8db9074168c6 Mon Sep 17 00:00:00 2001 From: devsh Date: Sat, 27 Sep 2025 23:48:13 +0200 Subject: [PATCH 02/30] draft the scene asset --- include/nbl/asset/IAsset.h | 36 ++++++------- include/nbl/asset/ICPUMorphTargets.h | 4 +- include/nbl/asset/ICPUScene.h | 54 ++++++++++++++++++++ include/nbl/asset/IScene.h | 23 +++++++++ include/nbl/asset/interchange/ISceneLoader.h | 30 +++++++++++ 5 files changed, 127 insertions(+), 20 deletions(-) create mode 100644 include/nbl/asset/ICPUScene.h create mode 100644 include/nbl/asset/IScene.h create mode 100644 include/nbl/asset/interchange/ISceneLoader.h 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/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 From ab9e7b8e397a649580149bf04e7d1fc82ccf241b Mon Sep 17 00:00:00 2001 From: devsh Date: Sat, 27 Sep 2025 23:48:36 +0200 Subject: [PATCH 03/30] start reworking the Mitsuba Loader into a Scene Loader --- .../nbl/ext/MitsubaLoader/CMitsubaLoader.h | 19 ++- .../nbl/ext/MitsubaLoader/CMitsubaMetadata.h | 110 +---------------- include/nbl/ext/MitsubaLoader/SContext.h | 112 +++--------------- 3 files changed, 30 insertions(+), 211 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h index e61ab3fa87..c844e8dde4 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/CMitsubaMetadata.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 @@ -52,7 +48,7 @@ struct nbl_glsl_ext_Mitsuba_Loader_instance_data_t using instance_data_t = nbl_glsl_ext_Mitsuba_Loader_instance_data_t; -class CMitsubaLoader : public asset::IRenderpassIndependentPipelineLoader +class CMitsubaLoader : public asset::ISceneLoader { friend class CMitsubaMaterialCompilerFrontend; public: @@ -67,8 +63,6 @@ class CMitsubaLoader : public asset::IRenderpassIndependentPipelineLoader //! Destructor virtual ~CMitsubaLoader() = default; - static core::smart_refctd_ptr createPipelineLayout(asset::IAssetManager* _manager, const asset::ICPUVirtualTexture* _vt); - // 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); @@ -101,6 +95,7 @@ class CMitsubaLoader : public asset::IRenderpassIndependentPipelineLoader //! 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; }; +#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..b7c2a398cb 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h @@ -1,11 +1,10 @@ -// 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" @@ -15,15 +14,11 @@ #include "nbl/ext/MitsubaLoader/CElementSensor.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,55 +27,12 @@ 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; - }; 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; }; struct SGlobal @@ -92,14 +44,6 @@ class CMitsubaMetadata : public asset::IAssetMetadata 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() : @@ -113,11 +57,6 @@ class CMitsubaMetadata : public asset::IAssetMetadata const char* getLoaderName() const override { return LoaderName; } //! - 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); @@ -127,26 +66,9 @@ class CMitsubaMetadata : public asset::IAssetMetadata private: friend class CMitsubaLoader; - meta_container_t m_metaPplnStorage; - core::smart_refctd_dynamic_array m_semanticStorage; - CRenderpassIndependentPipeline* m_metaPplnStorageIt; - 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 +78,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 +106,7 @@ 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 diff --git a/include/nbl/ext/MitsubaLoader/SContext.h b/include/nbl/ext/MitsubaLoader/SContext.h index 687f97054d..572a927fba 100644 --- a/include/nbl/ext/MitsubaLoader/SContext.h +++ b/include/nbl/ext/MitsubaLoader/SContext.h @@ -1,48 +1,38 @@ -// 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 { 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 +// 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 +// CMitsubaMetadata* meta; +#if 0 // using group_ass_type = core::vector>; //core::map groupCache; @@ -171,21 +161,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 +189,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; 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 From 99c1b8a4038a9f52cb3d2fdd4dd123d3488107fd Mon Sep 17 00:00:00 2001 From: devsh Date: Thu, 9 Oct 2025 12:37:22 +0200 Subject: [PATCH 04/30] start the loader --- examples_tests | 2 +- include/nbl/asset/asset.h | 1 + include/nbl/asset/interchange/IAssetLoader.h | 4 +- include/nbl/asset/interchange/IImageLoader.h | 5 +- .../nbl/ext/MitsubaLoader/CMitsubaLoader.h | 32 +- .../CMitsubaMaterialCompilerFrontend.h | 11 +- .../nbl/ext/MitsubaLoader/CSerializedLoader.h | 2 +- include/nbl/ext/MitsubaLoader/ParserUtil.h | 46 ++- include/nbl/ext/MitsubaLoader/SContext.h | 10 +- src/nbl/asset/interchange/CIESProfileLoader.h | 13 +- src/nbl/ext/MitsubaLoader/CMakeLists.txt | 4 +- src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp | 280 +++--------------- 12 files changed, 103 insertions(+), 307 deletions(-) diff --git a/examples_tests b/examples_tests index 850ca5d414..38be9e2711 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 850ca5d41412d8182a72fb88dd4e9e61df55e19b +Subproject commit 38be9e27119e574fd9424bbbe3b955dfdd4616a4 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..35bff3acab 100644 --- a/include/nbl/asset/interchange/IAssetLoader.h +++ b/include/nbl/asset/interchange/IAssetLoader.h @@ -86,8 +86,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/ext/MitsubaLoader/CMitsubaLoader.h b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h index c844e8dde4..09275963b3 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h @@ -46,17 +46,15 @@ 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::ISceneLoader { - friend class CMitsubaMaterialCompilerFrontend; +// friend class CMitsubaMaterialCompilerFrontend; public: //! Constructor - CMitsubaLoader(asset::IAssetManager* _manager, io::IFileSystem* _fs); - - void initialize() override; - + inline CMitsubaLoader() = default; +#if 0 protected: io::IFileSystem* m_filesystem; @@ -78,24 +76,18 @@ class CMitsubaLoader : public asset::ISceneLoader core::smart_refctd_ptr createDS0(const SContext& _ctx, asset::ICPUPipelineLayout* _layout, const asset::material_compiler::CMaterialCompilerGLSLBackendCommon::result_t& _compResult, Iter meshBegin, Iter meshEnd); 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; - - //! Returns an array of string literals terminated by nullptr - const char** getAssociatedFileExtensions() const override; +#endif + 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; }; -#endif } #endif \ No newline at end of file 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/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/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 65c8e1fb58..981884554e 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -1,50 +1,39 @@ // 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 "nbl/ext/MitsubaLoader/CElementFactory.h" +//#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" #include "expat/lib/expat.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { - - - class ParserLog { -public: - static inline void setLogger(const system::logger_opt_ptr& logger) { ParserLog::logger = logger; }; + public: + static inline void setLogger(const system::logger_opt_ptr& _logger) {logger=_logger;} - /*prints this message: - Mitsuba loader error: - Invalid .xml file structure: message */ - static void invalidXMLFileStructure(const std::string& errorMessage); + /*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; + private: + static system::logger_opt_ptr logger; }; template -class ElementPool // : public std::tuple...> +class ElementPool // similar to : public std::tuple...> { core::SimpleBlockBasedAllocator,core::aligned_allocator> poolAllocator; public: @@ -68,7 +57,9 @@ class ParserManager XML_Parser parser; system::path currentXMLDir; }; + public: +#if 0 //! Constructor ParserManager(system::ISystem* _system, asset::IAssetLoader::IAssetLoaderOverride* _override) : m_system(_system), m_override(_override), m_sceneDeclCount(0), @@ -127,12 +118,9 @@ class ParserManager 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; - +#endif friend class CElementFactory; }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/SContext.h b/include/nbl/ext/MitsubaLoader/SContext.h index 572a927fba..c1d9c6d9b1 100644 --- a/include/nbl/ext/MitsubaLoader/SContext.h +++ b/include/nbl/ext/MitsubaLoader/SContext.h @@ -15,6 +15,8 @@ namespace nbl::ext::MitsubaLoader { +class CMitsubaMetadata; + struct SContext { public: @@ -23,14 +25,14 @@ struct SContext // const asset::IMeshManipulator* _manipulator, const asset::IAssetLoader::SAssetLoadContext& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, -// CMitsubaMetadata* _metadata + CMitsubaMetadata* _metadata ); // const asset::IGeometryCreator* creator; // const asset::IMeshManipulator* manipulator; const asset::IAssetLoader::SAssetLoadContext inner; asset::IAssetLoader::IAssetLoaderOverride* override_; -// CMitsubaMetadata* meta; + CMitsubaMetadata* meta; #if 0 // @@ -192,8 +194,8 @@ struct SContext core::unordered_map, SPipelineCacheKey::hash> pipelineCache; #endif //material compiler - core::smart_refctd_ptr ir; - CMitsubaMaterialCompilerFrontend frontend; +// core::smart_refctd_ptr ir; +// CMitsubaMaterialCompilerFrontend frontend; private: }; 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/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index 6efa07ba23..f321324b60 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -21,7 +21,7 @@ set(NBL_EXT_MITSUBA_LOADER_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 ) @@ -40,7 +40,7 @@ set(NBL_EXT_MITSUBA_LOADER_SRC # CElementFactory.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..cb6c9fc365 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,28 +132,9 @@ 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 +#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(); @@ -363,139 +244,68 @@ 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() -{ - IRenderpassIndependentPipelineLoader::initialize(); - auto* glslc = m_assetMgr->getGLSLCompiler(); - - glslc->getIncludeHandler()->addBuiltinIncludeLoader(core::make_smart_refctd_ptr(m_filesystem)); -} - -bool CMitsubaLoader::isALoadableFileFormat(io::IReadFile* _file) const +bool CMitsubaLoader::isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger) 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) +asset::SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, uint32_t _hierarchyLevel) { - ParserManager parserManager(m_assetMgr->getFileSystem(),_override); - if (!parserManager.parse(_file)) +// ParserManager parserManager(m_assetMgr->getFileSystem(),_override); +// if (!parserManager.parse(_file)) return {}; - +#if 0 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) }); + auto emptyScene = core::make_smart_refctd_ptr(); + return SAssetBundle(std::move(parserManager.m_metadata),{ std::move(emptyScene) }); } else { @@ -626,8 +436,10 @@ asset::SAssetBundle CMitsubaLoader::loadAsset(io::IReadFile* _file, const asset: return asset::SAssetBundle(std::move(parserManager.m_metadata),std::move(meshSmartPtrArray)); } +#endif } +#if 0 core::vector CMitsubaLoader::getMesh(SContext& ctx, uint32_t hierarchyLevel, CElementShape* shape) { if (!shape) @@ -1399,7 +1211,7 @@ SContext::SContext( ); meta->m_global.m_VT = core::smart_refctd_ptr(backend_ctx.vt.getCPUVirtualTexture()); } +#endif -} } } \ No newline at end of file From 972fd5791272c596a73e421f7f984f5158e1ca77 Mon Sep 17 00:00:00 2001 From: devsh Date: Thu, 9 Oct 2025 16:39:09 +0200 Subject: [PATCH 05/30] Note that `nbl::ext::MitsubaLoader::ParserManager::ElementPool` probably leaks memory --- examples_tests | 2 +- .../nbl/ext/MitsubaLoader/CMitsubaLoader.h | 17 +-- .../nbl/ext/MitsubaLoader/CMitsubaMetadata.h | 30 ++-- include/nbl/ext/MitsubaLoader/ParserUtil.h | 77 +++++----- src/nbl/ext/MitsubaLoader/CMakeLists.txt | 2 +- src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp | 11 +- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 141 +++++++++--------- 7 files changed, 142 insertions(+), 138 deletions(-) diff --git a/examples_tests b/examples_tests index 38be9e2711..bfcff8a686 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 38be9e27119e574fd9424bbbe3b955dfdd4616a4 +Subproject commit bfcff8a686409dd7c0d55607bb8cb6bcc0e0b80a diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h index 09275963b3..f43b88c8a4 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h @@ -48,19 +48,14 @@ struct nbl_glsl_ext_Mitsuba_Loader_instance_data_t using instance_data_t = nbl_glsl_ext_Mitsuba_Loader_instance_data_t; #endif -class CMitsubaLoader : public asset::ISceneLoader +class CMitsubaLoader final : public asset::ISceneLoader { // friend class CMitsubaMaterialCompilerFrontend; - public: - //! Constructor - inline CMitsubaLoader() = default; -#if 0 - protected: - io::IFileSystem* m_filesystem; + core::smart_refctd_ptr m_system; //! Destructor virtual ~CMitsubaLoader() = default; - +#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); @@ -74,9 +69,11 @@ class CMitsubaLoader : public asset::ISceneLoader template core::smart_refctd_ptr createDS0(const SContext& _ctx, asset::ICPUPipelineLayout* _layout, const asset::material_compiler::CMaterialCompilerGLSLBackendCommon::result_t& _compResult, Iter meshBegin, Iter meshEnd); - - public: #endif + public: + //! Constructor + inline CMitsubaLoader(core::smart_refctd_ptr&& _system) : m_system(std::move(_system)) {} + bool isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger=nullptr) const override; inline const char** getAssociatedFileExtensions() const override diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h index b7c2a398cb..bf24e9d1ff 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h @@ -8,11 +8,11 @@ #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/CElementIntegrator.h" -#include "nbl/ext/MitsubaLoader/CElementSensor.h" -#include "nbl/ext/MitsubaLoader/CElementShape.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" namespace nbl::ext::MitsubaLoader @@ -27,6 +27,7 @@ class CMitsubaMetadata : public asset::IAssetMetadata public: std::string m_id; }; +#if 0 class CMesh : public asset::IMeshMetadata, public CID { public: @@ -45,27 +46,25 @@ class CMitsubaMetadata : public asset::IAssetMetadata CElementIntegrator m_integrator; core::vector m_sensors; } 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) +#endif + 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 CMesh* getAssetSpecificMetadata(const asset::ICPUMesh* asset) const { const auto found = IAssetMetadata::getAssetSpecificMetadata(asset); return static_cast(found); } - +#endif private: friend class CMitsubaLoader; - +#if 0 meta_container_t m_metaMeshStorage; CMesh* m_meshStorageIt; @@ -106,6 +105,7 @@ class CMitsubaMetadata : public asset::IAssetMetadata return meta->m_instances.size(); } +#endif }; } diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 981884554e..575fa037b2 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -8,7 +8,7 @@ #include "nbl/asset/interchange/IAssetLoader.h" //#include "nbl/ext/MitsubaLoader/CElementFactory.h" -//#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" +#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" #include "expat/lib/expat.h" @@ -17,21 +17,9 @@ namespace nbl::ext::MitsubaLoader { -class ParserLog -{ - public: - static inline void setLogger(const system::logger_opt_ptr& _logger) {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 // similar to : public std::tuple...> { @@ -51,56 +39,68 @@ class ElementPool // similar to : public std::tuple...> class ParserManager { protected: + // TODO: need per-file/per-parse contexts and per-load (one shapegroup, one metadata, one stack, etc. - basically the members of `ParserManager` now) struct Context { + /*prints this message: + Mitsuba loader error: + Invalid .xml file structure: message */ + void invalidXMLFileStructure(const std::string& errorMessage) const; + + // + inline void killParseWithError(const std::string& message) const + { + invalidXMLFileStructure(message); + XML_StopParser(parser,false); + } + + system::path currentXMLDir; + // ParserManager* manager; + system::logger_opt_ptr logger; + // XML_Parser parser; - system::path currentXMLDir; }; public: -#if 0 //! 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()) - { - } + inline ParserManager(system::ISystem* _system, asset::IAssetLoader::IAssetLoaderOverride* _override) : + propertyElements({ + "float", "string", "boolean", "integer", + "rgb", "srgb", "spectrum", "blackbody", + "point", "vector", + "matrix", "rotate", "translate", "scale", "lookat" + }), m_system(_system), m_override(_override), m_metadata(core::make_smart_refctd_ptr()) {} // 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) - { - _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); +#if 0 // core::vector > shapegroups; - // +#endif + // note that its shared between per-file contexts core::smart_refctd_ptr m_metadata; private: // void processProperty(const Context& ctx, const char* _el, const char** _atts); - // + const core::unordered_set propertyElements; + // TODO: re-architect this and move into context so the PArserManager can be persistent system::ISystem* m_system; asset::IAssetLoader::IAssetLoaderOverride* m_override; // - uint32_t m_sceneDeclCount; - // - ElementPool< + uint32_t m_sceneDeclCount = 0; + // TODO: This leaks memory all over the place because destructors are not ran! + ElementPool objects; + 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; -#endif + friend class CElementFactory; }; diff --git a/src/nbl/ext/MitsubaLoader/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index f321324b60..e4fc746049 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -38,7 +38,7 @@ set(NBL_EXT_MITSUBA_LOADER_SRC # CElementTexture.cpp # CElementEmitter.cpp # CElementFactory.cpp -# ParserUtil.cpp + ParserUtil.cpp CSerializedLoader.cpp CMitsubaLoader.cpp # CMitsubaMaterialCompilerFrontend.cpp diff --git a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp index cb6c9fc365..6f75d0c110 100644 --- a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp +++ b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp @@ -298,15 +298,16 @@ bool CMitsubaLoader::isALoadableFileFormat(system::IFile* _file, const system::l asset::SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _file, const asset::IAssetLoader::SAssetLoadParams& _params, asset::IAssetLoader::IAssetLoaderOverride* _override, uint32_t _hierarchyLevel) { -// ParserManager parserManager(m_assetMgr->getFileSystem(),_override); -// if (!parserManager.parse(_file)) + ParserManager parserManager(m_system.get(),_override); + if (!parserManager.parse(_file,_params.logger)) return {}; -#if 0 - if (_params.loaderFlags & IAssetLoader::ELPF_LOAD_METADATA_ONLY) + + //if (_params.loaderFlags&IAssetLoader::ELPF_LOAD_METADATA_ONLY) { auto emptyScene = core::make_smart_refctd_ptr(); - return SAssetBundle(std::move(parserManager.m_metadata),{ std::move(emptyScene) }); + return SAssetBundle(std::move(parserManager.m_metadata),{std::move(emptyScene)}); } +#if 0 else { // diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 785fe622dc..4d21ea1f77 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -2,6 +2,7 @@ // 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" @@ -9,21 +10,16 @@ #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ -system::logger_opt_ptr ParserLog::logger = nullptr; +namespace nbl::ext::MitsubaLoader +{ +using namespace nbl::system; -void ParserLog::invalidXMLFileStructure(const std::string& errorMessage) +void ParserManager::Context::invalidXMLFileStructure(const std::string& errorMessage) const { - std::string message = "Mitsuba loader error - Invalid .xml file structure: \'" - + errorMessage + '\''; + std::string message = "Mitsuba loader error - Invalid .xml file structure: \'" + errorMessage + '\''; - //ParserLog::logger.log(message, system::ILogger::E_LOG_LEVEL::ELL_ERROR); + logger.log(message,ILogger::E_LOG_LEVEL::ELL_ERROR); _NBL_DEBUG_BREAK_IF(true); } @@ -42,48 +38,53 @@ void ParserManager::elementHandlerEnd(void* _data, const char* _el) } - -bool ParserManager::parse(system::IFile* _file, const system::logger_opt_ptr& _logger) +bool ParserManager::parse(IFile* _file, const 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); + Context ctx = {_file->getFileName().parent_path()/"",this,_logger,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)); - char* buff = (char*)_NBL_ALIGNED_MALLOC(_file->getSize(), 4096u); - - system::future future; - _file->read(future, (void*)buff, 0u, _file->getSize()); - future.get(); - - 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,33 +93,26 @@ 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::parseElement(const Context& ctx, const char* _el, const char** _atts) { - if (core::strcmpi(_el, "scene") == 0) + 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"); + ctx.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"); + ctx.invalidXMLFileStructure(std::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"); + ctx.invalidXMLFileStructure("Version " + std::string(_atts[1]) + " is unsupported"); return; } m_sceneDeclCount++; @@ -127,26 +121,40 @@ void ParserManager::parseElement(const Context& ctx, const char* _el, const char if (m_sceneDeclCount==0u) { - killParseWithError(ctx,"there is no scene element"); + ctx.killParseWithError("there is no scene element"); return; } - if (core::strcmpi(_el, "include") == 0) + 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; + m_system->createFile(future,ctx.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(ctx.currentXMLDir/_atts[1])) + if (!tryOpen(_atts[1])) { - ParserLog::invalidXMLFileStructure(std::string("Could not open include file: ") + _atts[1]); + ctx.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 + parse(file.get(),ctx.logger); return; } - +#if 0 if (propertyElements.find(_el)!=propertyElements.end()) { processProperty(ctx, _el, _atts); @@ -157,7 +165,7 @@ void ParserManager::parseElement(const Context& ctx, const char* _el, const char auto found = _map.find(_el); if (found==_map.end()) { - ParserLog::invalidXMLFileStructure(std::string("Could not process element ") + _el); + invalidXMLFileStructure(std::string("Could not process element ") + _el); elements.push({nullptr,""}); return; } @@ -171,37 +179,38 @@ void ParserManager::parseElement(const Context& ctx, const char* _el, const char elements.push(el); if (el.first && el.first->id.size()) handles[el.first->id] = el.first; +#endif } void ParserManager::processProperty(const Context& ctx, const char* _el, const char** _atts) { if (elements.empty()) { - killParseWithError(ctx,"cannot set a property with no element on the stack."); + ctx.killParseWithError("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."); + ctx.invalidXMLFileStructure("cannot set property on element that failed to be created."); return; } - auto optProperty = CPropertyElementManager::createPropertyData(_el, _atts); +#if 0 + auto optProperty = CPropertyElementManager::createPropertyData(_el,_atts); if (optProperty.first == false) { - ParserLog::invalidXMLFileStructure("could not create property data."); + invalidXMLFileStructure("could not create property data."); return; } elements.top().first->addProperty(std::move(optProperty.second)); - - return; +#endif } void ParserManager::onEnd(const Context& ctx, const char* _el) { - if (propertyElements.find(_el) != propertyElements.end()) + if (propertyElements.find(_el)!=propertyElements.end()) return; if (core::strcmpi(_el, "scene") == 0) @@ -209,11 +218,10 @@ void ParserManager::onEnd(const Context& ctx, const char* _el) m_sceneDeclCount--; return; } - +#if 0 if (elements.empty()) return; - auto element = elements.top(); elements.pop(); @@ -243,9 +251,8 @@ void ParserManager::onEnd(const Context& ctx, const char* _el) if (shape) shapegroups.emplace_back(shape,std::move(element.second)); } +#endif } -} -} } \ No newline at end of file From 1ab734c0202dbcd9601739a7bd62900e268264cf Mon Sep 17 00:00:00 2001 From: devsh Date: Fri, 10 Oct 2025 18:05:01 +0200 Subject: [PATCH 06/30] remove global variables and rewrite `PropertyElement.h` and `PropertyElement.cpp` --- .../nbl/ext/MitsubaLoader/PropertyElement.h | 233 +++++++----- src/nbl/ext/MitsubaLoader/PropertyElement.cpp | 352 +++++++++--------- 2 files changed, 321 insertions(+), 264 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/PropertyElement.h b/include/nbl/ext/MitsubaLoader/PropertyElement.h index ac257bd4b3..f5a6e9266b 100644 --- a/include/nbl/ext/MitsubaLoader/PropertyElement.h +++ b/include/nbl/ext/MitsubaLoader/PropertyElement.h @@ -1,24 +1,28 @@ -// 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) { + 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 +41,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 +56,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 +76,9 @@ struct SPropertyElementData break; }; } - ~SPropertyElementData() + inline ~SPropertyElementData() { - if (type == Type::STRING) + if (type==Type::STRING) _NBL_ALIGNED_FREE((void*)svalue); } @@ -129,7 +125,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 +167,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 +199,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<> auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return fvalue; } +template<> auto SPropertyElementData::getProperty() const -> const get_type_t& +{ return ivalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return bvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return svalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return vvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return vvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return vvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return vvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return vvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return mvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return mvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return mvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return mvalue; } +template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +{ return mvalue; } -class CPropertyElementManager +class CPropertyElementManager final { - 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/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 < Date: Tue, 14 Oct 2025 17:39:25 +0200 Subject: [PATCH 07/30] get rid of `CElementFactory`, rewrite ParserUtil to be threadsafe and DLL Delay Load compatible --- .../nbl/ext/MitsubaLoader/CElementFactory.h | 41 --- include/nbl/ext/MitsubaLoader/IElement.h | 18 +- include/nbl/ext/MitsubaLoader/ParserUtil.h | 164 ++++++----- .../nbl/ext/MitsubaLoader/PropertyElement.h | 2 +- src/nbl/ext/MitsubaLoader/CElementFactory.cpp | 80 ------ src/nbl/ext/MitsubaLoader/CMakeLists.txt | 34 ++- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 262 ++++++++++++------ 7 files changed, 288 insertions(+), 313 deletions(-) delete mode 100644 include/nbl/ext/MitsubaLoader/CElementFactory.h delete mode 100644 src/nbl/ext/MitsubaLoader/CElementFactory.cpp 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/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 8f6fa24ea7..421e44f0f1 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -1,22 +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_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/asset/interchange/IAssetLoader.h" #include "nbl/ext/MitsubaLoader/PropertyElement.h" - -namespace nbl -{ -namespace ext +namespace nbl::ext::MitsubaLoader { -namespace MitsubaLoader -{ - - class CMitsubaMetadata; class IElement @@ -114,7 +107,4 @@ class IElement }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 575fa037b2..c0e8aba0cd 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -7,7 +7,8 @@ #include "nbl/asset/interchange/IAssetLoader.h" -//#include "nbl/ext/MitsubaLoader/CElementFactory.h" +#include "nbl/ext/MitsubaLoader/PropertyElement.h" +#include "nbl/ext/MitsubaLoader/CElementShape.h" #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" #include "expat/lib/expat.h" @@ -36,89 +37,112 @@ class ElementPool // similar to : 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: - // TODO: need per-file/per-parse contexts and per-load (one shapegroup, one metadata, one stack, etc. - basically the members of `ParserManager` now) - struct Context + public: + //! Constructor + ParserManager(); + + // + static void elementHandlerStart(void* _data, const char* _el, const char** _atts); + static void elementHandlerEnd(void* _data, const char* _el); + + struct Params + { + 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);} + + // 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; + + private: + struct SNamedElement { - /*prints this message: - Mitsuba loader error: - Invalid .xml file structure: message */ - void invalidXMLFileStructure(const std::string& errorMessage) const; + 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 + { // inline void killParseWithError(const std::string& message) const { - invalidXMLFileStructure(message); + session->invalidXMLFileStructure(message); XML_StopParser(parser,false); } + void parseElement(const char* _el, const char** _atts); + void onEnd(const char* _el); - system::path currentXMLDir; + SessionContext* const session; // - ParserManager* manager; - system::logger_opt_ptr logger; + const system::path currentXMLDir; // XML_Parser parser; }; - - public: - //! Constructor - inline ParserManager(system::ISystem* _system, asset::IAssetLoader::IAssetLoaderOverride* _override) : - propertyElements({ - "float", "string", "boolean", "integer", - "rgb", "srgb", "spectrum", "blackbody", - "point", "vector", - "matrix", "rotate", "translate", "scale", "lookat" - }), m_system(_system), m_override(_override), m_metadata(core::make_smart_refctd_ptr()) {} - - // - static void elementHandlerStart(void* _data, const char* _el, const char** _atts); - static void elementHandlerEnd(void* _data, const char* _el); - - 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); - -#if 0 - // - core::vector > shapegroups; -#endif - // note that its shared between per-file contexts - core::smart_refctd_ptr m_metadata; - - private: - // - void processProperty(const Context& ctx, const char* _el, const char** _atts); - - const core::unordered_set propertyElements; - // TODO: re-architect this and move into context so the PArserManager can be persistent - system::ISystem* m_system; - asset::IAssetLoader::IAssetLoaderOverride* m_override; + + 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; // - uint32_t m_sceneDeclCount = 0; - // TODO: This leaks memory all over the place because destructors are not ran! - ElementPool 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; + static SNamedElement processAlias(const char** _atts, SessionContext* ctx); + static SNamedElement processRef(const char** _atts, SessionContext* ctx); }; } diff --git a/include/nbl/ext/MitsubaLoader/PropertyElement.h b/include/nbl/ext/MitsubaLoader/PropertyElement.h index f5a6e9266b..4453c59ad6 100644 --- a/include/nbl/ext/MitsubaLoader/PropertyElement.h +++ b/include/nbl/ext/MitsubaLoader/PropertyElement.h @@ -364,7 +364,7 @@ template<> const SPropertyElementData::get_type_t StringToType; 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/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index e4fc746049..d4c361f84d 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -4,29 +4,28 @@ 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}/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}/CMitsubaMaterialCompilerFrontend.h ) set(NBL_EXT_MITSUBA_LOADER_SRC -# PropertyElement.cpp + PropertyElement.cpp # CElementIntegrator.cpp # CElementSensor.cpp # CElementFilm.cpp @@ -37,7 +36,6 @@ set(NBL_EXT_MITSUBA_LOADER_SRC # CElementBSDF.cpp # CElementTexture.cpp # CElementEmitter.cpp -# CElementFactory.cpp ParserUtil.cpp CSerializedLoader.cpp CMitsubaLoader.cpp diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 4d21ea1f77..3eedeb6ae6 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -4,7 +4,7 @@ #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" +// TODO: all of the element types #include "expat/lib/expat.h" @@ -15,42 +15,42 @@ namespace nbl::ext::MitsubaLoader { using namespace nbl::system; -void ParserManager::Context::invalidXMLFileStructure(const std::string& errorMessage) const +auto ParserManager::parse(IFile* _file, const Params& _params) const -> Result { - std::string message = "Mitsuba loader error - Invalid .xml file structure: \'" + errorMessage + '\''; - - logger.log(message,ILogger::E_LOG_LEVEL::ELL_ERROR); - _NBL_DEBUG_BREAK_IF(true); -} - -void ParserManager::elementHandlerStart(void* _data, const char* _el, const char** _atts) -{ - auto ctx = *reinterpret_cast(_data); - - ctx.manager->parseElement(ctx, _el, _atts); + 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(IFile* _file, const logger_opt_ptr& _logger) -{ XML_Parser parser = XML_ParserCreate(nullptr); if (!parser) { - _logger.log("Could not create XML Parser!",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); //from now data (instance of ParserData struct) will be visible to expat handlers - Context ctx = {_file->getFileName().parent_path()/"",this,_logger,parser}; + XMLContext ctx = { + .session = this, + .currentXMLDir = _file->getFileName().parent_path()/"", + .parser = parser + }; XML_SetUserData(parser,&ctx); const size_t size = _file->getSize(); @@ -62,7 +62,7 @@ bool ParserManager::parse(IFile* _file, const logger_opt_ptr& _logger) _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); + logger.log("Could read the file into XML Parser Buffer!",ILogger::E_LOG_LEVEL::ELL_ERROR); return false; } } @@ -75,16 +75,16 @@ bool ParserManager::parse(IFile* _file, const logger_opt_ptr& _logger) { case XML_STATUS_ERROR: { - _logger.log("Parse status: XML_STATUS_ERROR",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: - _logger.log("Parse status: XML_STATUS_OK",ILogger::E_LOG_LEVEL::ELL_INFO); + 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",ILogger::E_LOG_LEVEL::ELL_INFO); + logger.log("Parse status: XML_STATUS_SUSPENDED",ILogger::E_LOG_LEVEL::ELL_INFO); return false; } break; @@ -93,38 +93,46 @@ bool ParserManager::parse(IFile* _file, const logger_opt_ptr& _logger) return true; } -void ParserManager::parseElement(const Context& ctx, const char* _el, const char** _atts) +void ParserManager::elementHandlerStart(void* _data, const char* _el, const char** _atts) +{ + auto& ctx = *reinterpret_cast(_data); + + ctx.parseElement(_el,_atts); +} + +void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts) { - if (core::strcmpi(_el, "scene")==0) + if (core::strcmpi(_el,"scene")==0) { auto count = 0u; while (_atts && _atts[count]) { count++; } if (count!=2u) { - ctx.killParseWithError("Wrong number of attributes for scene element"); + killParseWithError("Wrong number of attributes for scene element"); return; } if (core::strcmpi(_atts[0],"version")) { - ctx.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")) { - ctx.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) { - ctx.killParseWithError("there is no scene element"); + killParseWithError("there is no scene element"); return; } + const ParserManager* manager = session->manager; if (core::strcmpi(_el,"include")==0) { core::smart_refctd_ptr file; @@ -136,7 +144,7 @@ void ParserManager::parseElement(const Context& ctx, const char* _el, const char auto flags = IFile::ECF_READ; if (i==0) flags |= IFile::ECF_MAPPABLE; - m_system->createFile(future,ctx.currentXMLDir/_atts[1],flags); + session->params->system->createFile(future,currentXMLDir/_atts[1],flags); if (future.wait()) future.acquire().move_into(file); if (file) @@ -145,114 +153,190 @@ void ParserManager::parseElement(const Context& ctx, const char* _el, const char return false; }; // first try as relative path, then as global - if (!tryOpen(ctx.currentXMLDir/_atts[1])) + if (!tryOpen(currentXMLDir/_atts[1])) if (!tryOpen(_atts[1])) { - ctx.invalidXMLFileStructure(std::string("Could not open include file: ")+_atts[1]); + session->invalidXMLFileStructure(std::string("Could not open include file: ")+_atts[1]); return; } - parse(file.get(),ctx.logger); + if (!session->parse(file.get())) + killParseWithError(core::string("Could not parse include file: ")+_atts[1]); return; } -#if 0 + + 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; + } + if (!elements.top().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; + } + + elements.top().element->addProperty(std::move(optProperty.value())); 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()) { - 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; -#endif + 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()) - { - ctx.killParseWithError("cannot set a property with no element on the stack."); - return; - } - if (!elements.top().first) - { - ctx.invalidXMLFileStructure("cannot set property on element that failed to be created."); - return; - } - -#if 0 - auto optProperty = CPropertyElementManager::createPropertyData(_el,_atts); + auto& ctx = *reinterpret_cast(_data); - if (optProperty.first == false) - { - invalidXMLFileStructure("could not create property data."); - return; - } - - elements.top().first->addProperty(std::move(optProperty.second)); -#endif + ctx.onEnd(_el); } -void ParserManager::onEnd(const Context& ctx, const char* _el) +void ParserManager::XMLContext::onEnd(const char* _el) { + 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; } -#if 0 + + 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(session->params->_override,result.metadata.get())) { - 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)); } +} + +// +ParserManager::ParserManager() : propertyElements({ + "float", "string", "boolean", "integer", + "rgb", "srgb", "spectrum", "blackbody", + "point", "vector", + "matrix", "rotate", "translate", "scale", "lookat" +}), propertyElementManager(), createElementTable({ +#if 0 // TODO + {"integrator", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"sensor", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"film", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"rfilter", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"sampler", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"shape", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"transform", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + //{"animation", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"bsdf", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"texture", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"emitter", {CElementFactory::createElement,.retvalGoesOnStack=true}}, + {"emissionprofile", {CElementFactory::createElement,.retvalGoesOnStack=true}}, #endif + {"alias", {.create=processAlias,.retvalGoesOnStack=true}}, + {"ref", {.create=processRef,.retvalGoesOnStack=true}} +}){} + +auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SElementCreator +{ + 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) -> SElementCreator +{ + 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("Used a `` element but referenced element not defined in preceeding XML!"); + return {original, std::move(name)}; +} } \ No newline at end of file From 3446e19b94a7fe2b3e1b102fcba271c6c2285a2b Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 15 Oct 2025 09:09:55 +0200 Subject: [PATCH 08/30] add good header guards --- include/nbl/ext/MitsubaLoader/CElementBSDF.h | 18 ++---- .../MitsubaLoader/CElementEmissionProfile.h | 14 +---- .../nbl/ext/MitsubaLoader/CElementEmitter.h | 24 +++---- include/nbl/ext/MitsubaLoader/CElementFilm.h | 16 ++--- .../ext/MitsubaLoader/CElementIntegrator.h | 15 ++--- .../nbl/ext/MitsubaLoader/CElementRFilter.h | 17 ++--- .../nbl/ext/MitsubaLoader/CElementSampler.h | 15 ++--- .../nbl/ext/MitsubaLoader/CElementSensor.h | 13 +--- include/nbl/ext/MitsubaLoader/CElementShape.h | 15 ++--- .../nbl/ext/MitsubaLoader/CElementTexture.h | 18 ++---- .../nbl/ext/MitsubaLoader/CElementTransform.h | 15 ++--- .../nbl/ext/MitsubaLoader/CMitsubaLoader.h | 6 +- include/nbl/ext/MitsubaLoader/IElement.h | 1 + include/nbl/ext/MitsubaLoader/ParserUtil.h | 14 ++--- .../nbl/ext/MitsubaLoader/PropertyElement.h | 28 ++++----- src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp | 62 ++++++++----------- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 14 +++-- 17 files changed, 108 insertions(+), 197 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index 2b424e9a20..b1e8183d4b 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 { @@ -422,9 +418,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..025b48f3d1 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -1,20 +1,15 @@ // 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 { @@ -71,7 +66,4 @@ struct CElementEmissionProfile : public IElement { }; } -} -} - #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..27e12b3718 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: @@ -302,10 +297,5 @@ class CElementEmitter : public IElement }; }; - - } -} -} - #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..9e9c9f08fd 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -1,21 +1,16 @@ // 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 { @@ -149,7 +144,4 @@ class CElementFilm : public IElement } -} -} - #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..df7aeac3fd 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -1,17 +1,14 @@ // 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 { @@ -334,9 +331,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..0905e40a2f 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.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_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 { @@ -70,7 +66,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..2df888cce6 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSampler.h +++ b/include/nbl/ext/MitsubaLoader/CElementSampler.h @@ -1,19 +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_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 @@ -50,7 +46,4 @@ class CElementSampler : public IElement } -} -} - #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..f8b69cc1c5 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,11 +11,7 @@ #include "nbl/ext/MitsubaLoader/CElementSampler.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { @@ -226,7 +222,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..41e7fdbc1c 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,11 +11,7 @@ #include "nbl/ext/MitsubaLoader/CElementEmitter.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { @@ -281,7 +277,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..3bcd92001a 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 { @@ -256,9 +252,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..c1ca0203ea 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTransform.h +++ b/include/nbl/ext/MitsubaLoader/CElementTransform.h @@ -1,18 +1,14 @@ -// 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 { @@ -39,7 +35,4 @@ class CElementTransform : public IElement }; } -} -} - #endif \ No newline at end of file diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h index f43b88c8a4..95b2f45c41 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaLoader.h @@ -8,7 +8,7 @@ #include "nbl/asset/asset.h" #include "nbl/ext/MitsubaLoader/CSerializedLoader.h" -//#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" +#include "nbl/ext/MitsubaLoader/ParserUtil.h" //#include "nbl/ext/MitsubaLoader/CElementShape.h" #include "nbl/ext/MitsubaLoader/SContext.h" @@ -51,6 +51,8 @@ using instance_data_t = nbl_glsl_ext_Mitsuba_Loader_instance_data_t; class CMitsubaLoader final : public asset::ISceneLoader { // friend class CMitsubaMaterialCompilerFrontend; + + const ParserManager m_parser; core::smart_refctd_ptr m_system; //! Destructor @@ -72,7 +74,7 @@ class CMitsubaLoader final : public asset::ISceneLoader #endif public: //! Constructor - inline CMitsubaLoader(core::smart_refctd_ptr&& _system) : m_system(std::move(_system)) {} + inline CMitsubaLoader(core::smart_refctd_ptr&& _system) : m_parser(), m_system(std::move(_system)) {} bool isALoadableFileFormat(system::IFile* _file, const system::logger_opt_ptr logger=nullptr) const override; diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 421e44f0f1..c3a4eb6e20 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -8,6 +8,7 @@ #include "nbl/asset/interchange/IAssetLoader.h" #include "nbl/ext/MitsubaLoader/PropertyElement.h" + namespace nbl::ext::MitsubaLoader { class CMitsubaMetadata; diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index c0e8aba0cd..a0dc8a9c27 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -7,14 +7,16 @@ #include "nbl/asset/interchange/IAssetLoader.h" +#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" #include "nbl/ext/MitsubaLoader/PropertyElement.h" #include "nbl/ext/MitsubaLoader/CElementShape.h" -#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" - -#include "expat/lib/expat.h" #include +// don't leak expat headers +struct XML_ParserStruct; +typedef struct XML_ParserStruct* XML_Parser; + namespace nbl::ext::MitsubaLoader { @@ -116,11 +118,7 @@ class ParserManager final struct XMLContext { // - inline void killParseWithError(const std::string& message) const - { - session->invalidXMLFileStructure(message); - XML_StopParser(parser,false); - } + void killParseWithError(const std::string& message) const; void parseElement(const char* _el, const char** _atts); void onEnd(const char* _el); diff --git a/include/nbl/ext/MitsubaLoader/PropertyElement.h b/include/nbl/ext/MitsubaLoader/PropertyElement.h index 4453c59ad6..8ecdce7fdd 100644 --- a/include/nbl/ext/MitsubaLoader/PropertyElement.h +++ b/include/nbl/ext/MitsubaLoader/PropertyElement.h @@ -334,33 +334,33 @@ template<> struct SPropertyElementData::get_type struct SPropertyElementData::get_type { using type = void; }; // TODO: rewrite rest to be less `::` verbose -template<> auto SPropertyElementData::getProperty() const -> const get_type_t& +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return fvalue; } -template<> auto SPropertyElementData::getProperty() const -> const get_type_t& +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return ivalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return bvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return svalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return vvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return vvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return vvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return vvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return vvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return mvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return mvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return mvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return mvalue; } -template<> const SPropertyElementData::get_type_t& SPropertyElementData::getProperty() const +template<> inline auto SPropertyElementData::getProperty() const -> const get_type_t& { return mvalue; } diff --git a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp index 6f75d0c110..df9d8c776e 100644 --- a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp +++ b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp @@ -135,22 +135,22 @@ static core::smart_refctd_ptr createFragmentShader #endif #if 0 -static core::smart_refctd_ptr createImageView(core::smart_refctd_ptr&& _img) // TODO: this should seriously be a utility somewhere +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) { @@ -296,36 +296,30 @@ bool CMitsubaLoader::isALoadableFileFormat(system::IFile* _file, const system::l return false; } -asset::SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _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_system.get(),_override); - if (!parserManager.parse(_file,_params.logger)) + 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 emptyScene = core::make_smart_refctd_ptr(); - return SAssetBundle(std::move(parserManager.m_metadata),{std::move(emptyScene)}); + return SAssetBundle(std::move(result.metadata),{std::move(scene)}); } -#if 0 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) @@ -356,7 +350,9 @@ asset::SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _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(); @@ -434,10 +430,9 @@ asset::SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _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 @@ -1192,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()); } -#endif } } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 3eedeb6ae6..4dce78c475 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -100,6 +100,12 @@ void ParserManager::elementHandlerStart(void* _data, const char* _el, const char ctx.parseElement(_el,_atts); } +void ParserManager::XMLContext::killParseWithError(const std::string& message) const +{ + session->invalidXMLFileStructure(message); + XML_StopParser(parser,false); +} + void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts) { if (core::strcmpi(_el,"scene")==0) @@ -289,7 +295,7 @@ ParserManager::ParserManager() : propertyElements({ {"ref", {.create=processRef,.retvalGoesOnStack=true}} }){} -auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SElementCreator +auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SNamedElement { const char* id = nullptr; const char* as = nullptr; @@ -323,7 +329,7 @@ auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SEl return {original,std::move(name)}; } -auto ParserManager::processRef(const char** _atts, SessionContext* ctx) -> SElementCreator +auto ParserManager::processRef(const char** _atts, SessionContext* ctx) -> SNamedElement { const char* id; std::string name; @@ -335,8 +341,8 @@ auto ParserManager::processRef(const char** _atts, SessionContext* ctx) -> SElem auto* original = ctx->handles[id]; if (!original) - ctx->invalidXMLFileStructure("Used a `` element but referenced element not defined in preceeding XML!"); - return {original, std::move(name)}; + 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 From 36c6aa6a312715a830acde85abe95d952c2b6574 Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 15 Oct 2025 09:21:03 +0200 Subject: [PATCH 09/30] really need that new PCH and lib breakdown --- include/nbl/asset/interchange/IAssetLoader.h | 2 ++ include/nbl/system/declarations.h | 1 + src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 1 + 3 files changed, 4 insertions(+) diff --git a/include/nbl/asset/interchange/IAssetLoader.h b/include/nbl/asset/interchange/IAssetLoader.h index 35bff3acab..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 { 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/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 4dce78c475..d34a2524fd 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -17,6 +17,7 @@ using namespace nbl::system; auto ParserManager::parse(IFile* _file, const Params& _params) const -> Result { +// CMitsubaMetadata* obj = new CMitsubaMetadata(); Result result = { .metadata = core::make_smart_refctd_ptr() }; From f850ce7881f3a852a584cf4c46ba60c7b8a8ac21 Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 15 Oct 2025 14:13:12 +0200 Subject: [PATCH 10/30] enable a few elements and get stuff parsing (with unhandled element errors) --- include/nbl/core/hash/blake.h | 3 + include/nbl/ext/MitsubaLoader/CElementBSDF.h | 2 +- .../MitsubaLoader/CElementEmissionProfile.h | 28 ++++----- .../nbl/ext/MitsubaLoader/CElementEmitter.h | 2 +- include/nbl/ext/MitsubaLoader/CElementFilm.h | 25 ++++---- .../ext/MitsubaLoader/CElementIntegrator.h | 14 ++--- .../nbl/ext/MitsubaLoader/CElementRFilter.h | 14 ++--- .../nbl/ext/MitsubaLoader/CElementSampler.h | 12 ++-- .../nbl/ext/MitsubaLoader/CElementSensor.h | 21 +++---- include/nbl/ext/MitsubaLoader/CElementShape.h | 23 +++---- .../nbl/ext/MitsubaLoader/CElementTexture.h | 2 +- .../nbl/ext/MitsubaLoader/CElementTransform.h | 15 +++-- include/nbl/ext/MitsubaLoader/IElement.h | 7 ++- include/nbl/ext/MitsubaLoader/ParserUtil.h | 3 + .../MitsubaLoader/CElementEmissionProfile.cpp | 62 ++++++++++--------- .../ext/MitsubaLoader/CElementIntegrator.cpp | 22 +++---- src/nbl/ext/MitsubaLoader/CElementSampler.cpp | 13 +--- src/nbl/ext/MitsubaLoader/CElementSensor.cpp | 34 +++++----- .../ext/MitsubaLoader/CElementTransform.cpp | 32 ++++------ src/nbl/ext/MitsubaLoader/CMakeLists.txt | 4 +- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 41 +++++++----- 21 files changed, 186 insertions(+), 193 deletions(-) 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 b1e8183d4b..e11b2421a8 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -369,7 +369,7 @@ class CElementBSDF : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; IElement::Type getType() const override { return IElement::Type::BSDF; } std::string getLogName() const override { return "bsdf"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index 025b48f3d1..12491a9a70 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -12,15 +12,15 @@ namespace nbl::ext::MitsubaLoader { -struct CElementEmissionProfile : public IElement { - - 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("") +struct CElementEmissionProfile final : public 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)); } @@ -39,22 +39,22 @@ struct CElementEmissionProfile : public IElement { return *this; } - virtual ~CElementEmissionProfile() + inline ~CElementEmissionProfile() { } - bool addProperty(SNamedPropertyElement&& _property) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override { + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; + inline bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) 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 "; } + inline IElement::Type getType() const override { return IElement::Type::EMISSION_PROFILE; } + 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 @@ -62,7 +62,7 @@ struct CElementEmissionProfile : public IElement { std::string filename; E_NORMALIZE normalization; - float flatten; + float flatten; // TODO: why is this named this way? }; } diff --git a/include/nbl/ext/MitsubaLoader/CElementEmitter.h b/include/nbl/ext/MitsubaLoader/CElementEmitter.h index 27e12b3718..eb80657c54 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmitter.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmitter.h @@ -200,7 +200,7 @@ class CElementEmitter : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; IElement::Type getType() const override { return IElement::Type::EMITTER; } std::string getLogName() const override { return "emitter"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index 9e9c9f08fd..a16ff5d7ac 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -5,17 +5,16 @@ #define _NBL_EXT_MISTUBA_LOADER_C_ELEMENT_FILM_H_INCLUDED_ -#include "nbl/macros.h" #include "nbl/ext/MitsubaLoader/CElementRFilter.h" namespace nbl::ext::MitsubaLoader { -class CElementFilm : public IElement +class CElementFilm final : public IElement { public: - enum Type + enum Type : uint8_t { INVALID, HDR_FILM, @@ -23,7 +22,7 @@ class CElementFilm : public IElement LDR_FILM, MFILM }; - enum PixelFormat + enum PixelFormat : uint8_t { LUMINANCE, LUMINANCE_ALPHA, @@ -34,7 +33,7 @@ class CElementFilm : public IElement SPECTRUM, SPECTRUM_ALPHA }; - enum FileFormat + enum FileFormat : uint8_t { OPENEXR, RGBE, @@ -45,7 +44,7 @@ class CElementFilm : public IElement MATHEMATICA, NUMPY }; - enum ComponentFormat + enum ComponentFormat : uint8_t { FLOAT16, FLOAT32, @@ -79,11 +78,11 @@ 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("") @@ -94,10 +93,10 @@ class CElementFilm : public IElement { } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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 IElement::Type getType() const override { return IElement::Type::FILM; } + inline std::string getLogName() const override { return "film"; } inline bool processChildData(IElement* _child, const std::string& name) override { @@ -129,7 +128,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; @@ -137,7 +136,7 @@ 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 }; diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index df7aeac3fd..72201f6cbb 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -12,7 +12,7 @@ namespace nbl::ext::MitsubaLoader { -class CElementIntegrator : public IElement +class CElementIntegrator final : public IElement { public: enum Type @@ -191,10 +191,10 @@ class CElementIntegrator : public IElement { }; - CElementIntegrator(const char* id) : IElement(id), type(Type::INVALID) + inline CElementIntegrator(const char* id) : IElement(id), type(Type::INVALID) { } - virtual ~CElementIntegrator() + inline ~CElementIntegrator() { } @@ -264,12 +264,12 @@ class CElementIntegrator : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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"; } + inline IElement::Type getType() const override { return IElement::Type::INTEGRATOR; } + 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; diff --git a/include/nbl/ext/MitsubaLoader/CElementRFilter.h b/include/nbl/ext/MitsubaLoader/CElementRFilter.h index 0905e40a2f..631dc4e82c 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.h @@ -13,10 +13,10 @@ namespace nbl::ext::MitsubaLoader { -class CElementRFilter : public IElement +class CElementRFilter final : public IElement { public: - enum Type + enum Type : uint8_t { INVALID, BOX, @@ -40,16 +40,16 @@ class CElementRFilter : public IElement int32_t lobes = 3; }; - CElementRFilter(const char* id) : IElement(id), type(GAUSSIAN) + inline CElementRFilter(const char* id) : IElement(id), type(GAUSSIAN) { gaussian = Gaussian(); } - virtual ~CElementRFilter() {} + inline ~CElementRFilter() {} - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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"; } + inline IElement::Type getType() const override { return IElement::Type::RFILTER; } + inline std::string getLogName() const override { return "rfilter"; } // make these public Type type; diff --git a/include/nbl/ext/MitsubaLoader/CElementSampler.h b/include/nbl/ext/MitsubaLoader/CElementSampler.h index 2df888cce6..313e649b2e 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSampler.h +++ b/include/nbl/ext/MitsubaLoader/CElementSampler.h @@ -15,7 +15,7 @@ class CGlobalMitsubaMetadata; class CElementSampler : public IElement { public: - enum Type + enum Type : uint8_t { INVALID, INDEPENDENT, @@ -26,13 +26,13 @@ class CElementSampler : public IElement SOBOL }; - 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 addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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 IElement::Type getType() const override { return IElement::Type::SAMPLER; } + inline std::string getLogName() const override { return "sampler"; } // make these public Type type; diff --git a/include/nbl/ext/MitsubaLoader/CElementSensor.h b/include/nbl/ext/MitsubaLoader/CElementSensor.h index f8b69cc1c5..fa8bc07509 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSensor.h +++ b/include/nbl/ext/MitsubaLoader/CElementSensor.h @@ -14,8 +14,7 @@ namespace nbl::ext::MitsubaLoader { - -class CElementSensor : public IElement +class CElementSensor final : public IElement { public: enum Type @@ -35,8 +34,8 @@ class CElementSensor : public IElement 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_t3 clipPlanes[MaxClipPlanes] = {}; float moveSpeed = core::nan(); float zoomSpeed = core::nan(); float rotateSpeed = core::nan(); @@ -101,14 +100,14 @@ class CElementSensor : public IElement kc; };*/ - CElementSensor(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), film(""), sampler("") + inline CElementSensor(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), film(""), sampler("") { } - CElementSensor(const CElementSensor& other) : IElement(""), transform(), film(""), sampler("") + inline CElementSensor(const CElementSensor& other) : IElement(""), transform(), film(""), sampler("") { operator=(other); } - virtual ~CElementSensor() + inline ~CElementSensor() { } @@ -151,12 +150,12 @@ class CElementSensor : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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"; } + inline IElement::Type getType() const override { return IElement::Type::SENSOR; } + 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; diff --git a/include/nbl/ext/MitsubaLoader/CElementShape.h b/include/nbl/ext/MitsubaLoader/CElementShape.h index 41e7fdbc1c..39e163a5c4 100644 --- a/include/nbl/ext/MitsubaLoader/CElementShape.h +++ b/include/nbl/ext/MitsubaLoader/CElementShape.h @@ -15,7 +15,7 @@ namespace nbl::ext::MitsubaLoader { -class CElementShape : public IElement +class CElementShape final : public IElement { public: enum Type @@ -99,18 +99,18 @@ class CElementShape : public IElement CElementTexture* texture; };*/ - CElementShape(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), bsdf(nullptr), emitter(nullptr) + 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() { } @@ -215,20 +215,21 @@ class CElementShape : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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"; } + inline IElement::Type getType() const override { return IElement::Type::SHAPE; } + 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; } diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index 3bcd92001a..8a4f2b4c87 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -235,7 +235,7 @@ class CElementTexture : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementTransform.h b/include/nbl/ext/MitsubaLoader/CElementTransform.h index c1ca0203ea..701296664b 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTransform.h +++ b/include/nbl/ext/MitsubaLoader/CElementTransform.h @@ -11,17 +11,16 @@ namespace nbl::ext::MitsubaLoader { - -class CElementTransform : public IElement +class CElementTransform final : public IElement { public: - CElementTransform() : IElement(""), matrix() {} - virtual ~CElementTransform() {} + inline CElementTransform() : IElement(""), matrix() {} + inline ~CElementTransform() {} - bool addProperty(SNamedPropertyElement&& _property) override; + bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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 IElement::Type getType() const override { return IElement::Type::TRANSFORM; } + inline std::string getLogName() const override { return "transform"; } /* inline CElementTransform& operator=(const CElementTransform& other) { @@ -31,7 +30,7 @@ class CElementTransform : public IElement } */ - core::matrix4SIMD matrix; + hlsl::float32_t4x4 matrix; }; } diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index c3a4eb6e20..9128e1b274 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -6,6 +6,7 @@ #include "nbl/asset/interchange/IAssetLoader.h" + #include "nbl/ext/MitsubaLoader/PropertyElement.h" @@ -47,7 +48,7 @@ class IElement virtual IElement::Type getType() const = 0; virtual std::string getLogName() const = 0; - virtual bool addProperty(SNamedPropertyElement&& _property) = 0; + virtual bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) = 0; virtual bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) = 0; //! default implementation for elements that doesnt have any children virtual bool processChildData(IElement* _child, const std::string& name) @@ -55,7 +56,7 @@ class IElement 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; @@ -75,7 +76,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); diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index a0dc8a9c27..11d2d30170 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -139,6 +139,9 @@ class ParserManager final }; const core::unordered_map createElementTable; // + template requires std::is_base_of_v + static SNamedElement createElement(const char** _atts, SessionContext* ctx); + // static SNamedElement processAlias(const char** _atts, SessionContext* ctx); static SNamedElement processRef(const char** _atts, SessionContext* ctx); }; diff --git a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp index 2bc7fc727a..11e68d619d 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp @@ -1,72 +1,78 @@ -// 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 + +namespace nbl::ext::MitsubaLoader { template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement { const char* type; const char* id; std::string name; if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr, ""); + return {}; - CElementEmissionProfile* obj = _util->objects.construct(id); + CElementEmissionProfile* obj = ctx->objects.construct(id); if (!obj) - return CElementFactory::return_type(nullptr, ""); + return {}; - return CElementFactory::return_type(obj, std::move(name)); + return {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 +84,4 @@ bool CElementEmissionProfile::processChildData(IElement* _child, const std::stri return false; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index 7843cd30eb..dbff6ed1c9 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -1,30 +1,24 @@ // 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/CElementIntegrator.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" - #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +namespace nbl::ext::MitsubaLoader +{ template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement { const char* type; const char* id; std::string name; if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr,""); + return {}; static const core::unordered_map StringToType = { @@ -53,12 +47,12 @@ CElementFactory::return_type CElementFactory::createElement( { ParserLog::invalidXMLFileStructure("unknown type"); _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); + return {}; } CElementIntegrator* obj = _util->objects.construct(id); if (!obj) - return CElementFactory::return_type(nullptr, ""); + return {}; obj->type = found->second; // defaults @@ -430,6 +424,4 @@ bool CElementIntegrator::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _ov 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..aff64d6b24 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSampler.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSampler.cpp @@ -1,17 +1,12 @@ // 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/CElementSampler.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#include "nbl/ext/MitsubaLoader/CElementFactory.h" -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +namespace nbl::ext::MitsubaLoader +{ template<> CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) @@ -133,6 +128,4 @@ bool CElementSampler::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _overr 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..d2f336cad2 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp @@ -2,28 +2,27 @@ // 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 -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader + +namespace nbl::ext::MitsubaLoader { - + template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement { const char* type; const char* id; std::string name; if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr,""); + return {}; - static const core::unordered_map StringToType = + // TODO: initialize this separately + static const core::unordered_map StringToType = { {"perspective", CElementSensor::Type::PERSPECTIVE}, {"thinlens", CElementSensor::Type::THINLENS}, @@ -39,14 +38,13 @@ CElementFactory::return_type CElementFactory::createElement(cons auto found = StringToType.find(type); if (found==StringToType.end()) { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); + ctx->invalidXMLFileStructure("unknown type"); + return {}; } - CElementSensor* obj = _util->objects.construct(id); + CElementSensor* obj = ctx->objects.construct(id); if (!obj) - return CElementFactory::return_type(nullptr, ""); + return {}; obj->type = found->second; // defaults @@ -79,7 +77,7 @@ CElementFactory::return_type CElementFactory::createElement(cons default: break; } - return CElementFactory::return_type(obj, std::move(name)); + return {obj,std::move(name)}; } bool CElementSensor::addProperty(SNamedPropertyElement&& _property) @@ -242,7 +240,7 @@ bool CElementSensor::addProperty(SNamedPropertyElement&& _property) bool CElementSensor::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* meta) { - if (type == Type::INVALID) + if (type==Type::INVALID) { ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); _NBL_DEBUG_BREAK_IF(true); @@ -257,6 +255,4 @@ bool CElementSensor::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _overri 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..6520cd8c90 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp @@ -1,30 +1,25 @@ // 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 -{ +namespace nbl::ext::MitsubaLoader +{ template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement { - if (IElement::invalidAttributeCount(_atts, 2u)) - return CElementFactory::return_type(nullptr,""); - if (core::strcmpi(_atts[0], "name")) - return CElementFactory::return_type(nullptr,""); + if (IElement::invalidAttributeCount(_atts,2u)) + return {}; + if (core::strcmpi(_atts[0],"name")) + return {}; - return CElementFactory::return_type(_util->objects.construct(),_atts[1]); + return {ctx->objects.construct(),_atts[1]}; } -bool CElementTransform::addProperty(SNamedPropertyElement&& _property) +bool CElementTransform::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { switch (_property.type) { @@ -37,12 +32,11 @@ bool CElementTransform::addProperty(SNamedPropertyElement&& _property) case SNamedPropertyElement::Type::SCALE: [[fallthrough]]; case SNamedPropertyElement::Type::LOOKAT: - matrix = core::concatenateBFollowedByA(_property.mvalue, matrix); + matrix = hlsl::mul(matrix,_property.mvalue); break; default: { - ParserLog::invalidXMLFileStructure("The transform element does not take child property: "+_property.type); - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,"The transform element does not take child property: "+_property.type); return false; } break; @@ -51,6 +45,4 @@ bool CElementTransform::addProperty(SNamedPropertyElement&& _property) return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index d4c361f84d..2adc31d7b6 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -17,6 +17,7 @@ set(NBL_EXT_MITSUBA_LOADER_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 @@ -31,11 +32,12 @@ set(NBL_EXT_MITSUBA_LOADER_SRC # CElementFilm.cpp # CElementRFilter.cpp # CElementSampler.cpp -# CElementTransform.cpp + CElementTransform.cpp # CElementShape.cpp # CElementBSDF.cpp # CElementTexture.cpp # CElementEmitter.cpp + CElementEmissionProfile.cpp ParserUtil.cpp CSerializedLoader.cpp CMitsubaLoader.cpp diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index d34a2524fd..5dbf6a7e93 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -4,7 +4,18 @@ #include "nbl/ext/MitsubaLoader/ParserUtil.h" -// TODO: all of the element types +#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" @@ -193,7 +204,7 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts return; } - elements.top().element->addProperty(std::move(optProperty.value())); + elements.top().element->addProperty(std::move(optProperty.value()),session->params->logger); return; } @@ -278,20 +289,18 @@ ParserManager::ParserManager() : propertyElements({ "point", "vector", "matrix", "rotate", "translate", "scale", "lookat" }), propertyElementManager(), createElementTable({ -#if 0 // TODO - {"integrator", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"sensor", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"film", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"rfilter", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"sampler", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"shape", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"transform", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - //{"animation", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"bsdf", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"texture", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"emitter", {CElementFactory::createElement,.retvalGoesOnStack=true}}, - {"emissionprofile", {CElementFactory::createElement,.retvalGoesOnStack=true}}, -#endif +// {"integrator", {.create=createElement,.retvalGoesOnStack=true}}, +// {"sensor", {.create=createElement,.retvalGoesOnStack=true}}, +// {"film", {.create=createElement,.retvalGoesOnStack=true}}, +// {"rfilter", {.create=createElement,.retvalGoesOnStack=true}}, +// {"sampler", {.create=createElement,.retvalGoesOnStack=true}}, +// {"shape", {.create=createElement,.retvalGoesOnStack=true}}, + {"transform", {.create=createElement,.retvalGoesOnStack=true}}, +// {"animation", {.create=createElement,.retvalGoesOnStack=true}}, +// {"bsdf", {.create=createElement,.retvalGoesOnStack=true}}, +// {"texture", {.create=createElement,.retvalGoesOnStack=true}}, +// {"emitter", {.create=createElement,.retvalGoesOnStack=true}}, + {"emissionprofile", {.create=createElement,.retvalGoesOnStack=true}}, {"alias", {.create=processAlias,.retvalGoesOnStack=true}}, {"ref", {.create=processRef,.retvalGoesOnStack=true}} }){} From 1eb3eb988b7c878509c7a27bb007061af6445c93 Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 15 Oct 2025 17:14:15 +0200 Subject: [PATCH 11/30] get some parsing going --- include/nbl/ext/MitsubaLoader/CElementBSDF.h | 22 +-- .../MitsubaLoader/CElementEmissionProfile.h | 6 +- .../nbl/ext/MitsubaLoader/CElementEmitter.h | 4 +- include/nbl/ext/MitsubaLoader/CElementFilm.h | 33 ++++- .../ext/MitsubaLoader/CElementIntegrator.h | 95 +++++++++---- .../nbl/ext/MitsubaLoader/CElementRFilter.h | 49 ++++++- .../nbl/ext/MitsubaLoader/CElementSampler.h | 42 +++++- .../nbl/ext/MitsubaLoader/CElementSensor.h | 66 ++++++--- include/nbl/ext/MitsubaLoader/CElementShape.h | 2 +- .../nbl/ext/MitsubaLoader/CElementTexture.h | 9 +- .../nbl/ext/MitsubaLoader/CElementTransform.h | 2 +- .../nbl/ext/MitsubaLoader/CMitsubaMetadata.h | 13 +- include/nbl/ext/MitsubaLoader/IElement.h | 19 ++- include/nbl/ext/MitsubaLoader/ParserUtil.h | 4 +- .../nbl/ext/MitsubaLoader/PropertyElement.h | 1 + src/nbl/ext/MitsubaLoader/CElementBSDF.cpp | 7 +- .../MitsubaLoader/CElementEmissionProfile.cpp | 16 --- src/nbl/ext/MitsubaLoader/CElementFilm.cpp | 108 ++++----------- .../ext/MitsubaLoader/CElementIntegrator.cpp | 131 ++---------------- src/nbl/ext/MitsubaLoader/CElementRFilter.cpp | 92 ++---------- src/nbl/ext/MitsubaLoader/CElementSampler.cpp | 86 ++---------- src/nbl/ext/MitsubaLoader/CElementSensor.cpp | 88 ++---------- src/nbl/ext/MitsubaLoader/CElementShape.cpp | 9 +- src/nbl/ext/MitsubaLoader/CElementTexture.cpp | 21 +-- .../ext/MitsubaLoader/CElementTransform.cpp | 11 -- src/nbl/ext/MitsubaLoader/CMakeLists.txt | 10 +- src/nbl/ext/MitsubaLoader/ElementMacros.h | 119 ++++++++++++++++ src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 106 ++++++++++++-- 28 files changed, 574 insertions(+), 597 deletions(-) create mode 100644 src/nbl/ext/MitsubaLoader/ElementMacros.h diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index e11b2421a8..1d4a823e30 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -370,7 +370,7 @@ class CElementBSDF : public IElement } bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; IElement::Type getType() const override { return IElement::Type::BSDF; } std::string getLogName() const override { return "bsdf"; } @@ -380,16 +380,16 @@ class CElementBSDF : public IElement { 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; } } diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index 12491a9a70..a4b1d22485 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -44,9 +44,7 @@ struct CElementEmissionProfile final : public IElement } bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - inline 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; inline IElement::Type getType() const override { return IElement::Type::EMISSION_PROFILE; } inline std::string getLogName() const override { return "emissionprofile "; } @@ -60,7 +58,7 @@ struct CElementEmissionProfile final : public IElement }; - std::string filename; + std::string filename; // TODO: test destructor runs E_NORMALIZE normalization; float flatten; // TODO: why is this named this way? }; diff --git a/include/nbl/ext/MitsubaLoader/CElementEmitter.h b/include/nbl/ext/MitsubaLoader/CElementEmitter.h index eb80657c54..389ec31fd5 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmitter.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmitter.h @@ -87,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; @@ -201,7 +201,7 @@ class CElementEmitter : public IElement } bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; IElement::Type getType() const override { return IElement::Type::EMITTER; } std::string getLogName() const override { return "emitter"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index a16ff5d7ac..dcd7402132 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -22,6 +22,16 @@ class CElementFilm final : public IElement LDR_FILM, MFILM }; + 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, @@ -93,8 +103,29 @@ class CElementFilm final : public IElement { } + 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 addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; inline IElement::Type getType() const override { return IElement::Type::FILM; } inline std::string getLogName() const override { return "film"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index 72201f6cbb..d683204439 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -15,9 +15,8 @@ namespace nbl::ext::MitsubaLoader class CElementIntegrator final : public IElement { public: - enum Type + enum Type : uint8_t { - INVALID, AO, DIRECT, PATH, @@ -35,8 +34,33 @@ class CElementIntegrator final : 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; @@ -49,8 +73,8 @@ class CElementIntegrator final : 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 @@ -161,7 +185,7 @@ class CElementIntegrator final : public IElement } Type field; - SPropertyElementData undefined; + SPropertyElementData undefined; // TODO: test destructor runs }; struct MetaIntegrator { @@ -198,74 +222,89 @@ class CElementIntegrator final : public IElement { } - 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, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; inline IElement::Type getType() const override { return IElement::Type::INTEGRATOR; } inline std::string getLogName() const override { return "integrator"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementRFilter.h b/include/nbl/ext/MitsubaLoader/CElementRFilter.h index 631dc4e82c..0ca2426d73 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.h @@ -26,6 +26,18 @@ class CElementRFilter final : public IElement CATMULLROM, LANCZOS }; + 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) + }; + } + struct Gaussian { float sigma = NAN; // can't look at mitsuba source to figure out the default it uses @@ -46,8 +58,43 @@ class CElementRFilter final : public IElement } inline ~CElementRFilter() {} + 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 addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; inline IElement::Type getType() const override { return IElement::Type::RFILTER; } inline std::string getLogName() const override { return "rfilter"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementSampler.h b/include/nbl/ext/MitsubaLoader/CElementSampler.h index 313e649b2e..02e3ae6f6b 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSampler.h +++ b/include/nbl/ext/MitsubaLoader/CElementSampler.h @@ -17,29 +17,65 @@ class CElementSampler : public IElement public: 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} + }; + } inline CElementSampler(const char* id) : IElement(id), type(INVALID), sampleCount(4) {} inline ~CElementSampler() {} + 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 addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; inline IElement::Type getType() const override { return IElement::Type::SAMPLER; } 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; }; }; diff --git a/include/nbl/ext/MitsubaLoader/CElementSensor.h b/include/nbl/ext/MitsubaLoader/CElementSensor.h index fa8bc07509..655a50b3e8 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSensor.h +++ b/include/nbl/ext/MitsubaLoader/CElementSensor.h @@ -17,9 +17,8 @@ namespace nbl::ext::MitsubaLoader class CElementSensor final : public IElement { public: - enum Type + enum Type : uint8_t { - INVALID, PERSPECTIVE, THINLENS, ORTHOGRAPHIC, @@ -28,8 +27,24 @@ class CElementSensor final : public IElement IRRADIANCEMETER, RADIANCEMETER, FLUENCEMETER, - PERSPECTIVE_RDIST + PERSPECTIVE_RDIST, + INVALID }; + 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}*/ + }; + } + constexpr static inline uint8_t MaxClipPlanes = 6u; struct ShutterSensor @@ -111,47 +126,62 @@ class CElementSensor final : public IElement { } - 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, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; inline IElement::Type getType() const override { return IElement::Type::SENSOR; } inline std::string getLogName() const override { return "sensor"; } @@ -181,12 +211,12 @@ class CElementSensor final : 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; } diff --git a/include/nbl/ext/MitsubaLoader/CElementShape.h b/include/nbl/ext/MitsubaLoader/CElementShape.h index 39e163a5c4..08dfa75783 100644 --- a/include/nbl/ext/MitsubaLoader/CElementShape.h +++ b/include/nbl/ext/MitsubaLoader/CElementShape.h @@ -216,7 +216,7 @@ class CElementShape final : public IElement } bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; - bool onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* globalMetadata) override; + bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; inline IElement::Type getType() const override { return IElement::Type::SHAPE; } inline std::string getLogName() const override { return "shape"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index 8a4f2b4c87..ec2ff2d1bf 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -133,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; @@ -236,9 +236,10 @@ class CElementTexture : public IElement } bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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; + + inline IElement::Type getType() const override { return IElement::Type::TEXTURE; } + inline std::string getLogName() const override { return "texture"; } bool processChildData(IElement* _child, const std::string& name) override; diff --git a/include/nbl/ext/MitsubaLoader/CElementTransform.h b/include/nbl/ext/MitsubaLoader/CElementTransform.h index 701296664b..292a081bba 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTransform.h +++ b/include/nbl/ext/MitsubaLoader/CElementTransform.h @@ -18,7 +18,7 @@ class CElementTransform final : public IElement inline ~CElementTransform() {} bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) 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;} inline IElement::Type getType() const override { return IElement::Type::TRANSFORM; } inline std::string getLogName() const override { return "transform"; } /* diff --git a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h index bf24e9d1ff..6f24951c50 100644 --- a/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h +++ b/include/nbl/ext/MitsubaLoader/CMitsubaMetadata.h @@ -10,8 +10,8 @@ //#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/CElementIntegrator.h" +#include "nbl/ext/MitsubaLoader/CElementSensor.h" //#include "nbl/ext/MitsubaLoader/CElementShape.h" @@ -36,17 +36,16 @@ class CMitsubaMetadata : public asset::IAssetMetadata 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; } m_global; -#endif + inline CMitsubaMetadata() : IAssetMetadata()/*, m_metaMeshStorage(), m_metaMeshInstanceStorage(), m_metaMeshInstanceAuxStorage(), m_meshStorageIt(nullptr), m_instanceStorageIt(nullptr), m_instanceAuxStorageIt(nullptr)*/ { @@ -63,7 +62,7 @@ class CMitsubaMetadata : public asset::IAssetMetadata } #endif private: - friend class CMitsubaLoader; +// friend class CMitsubaLoader; #if 0 meta_container_t m_metaMeshStorage; CMesh* m_meshStorageIt; diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 9128e1b274..b0f2d34c3b 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -49,12 +49,13 @@ class IElement virtual std::string getLogName() const = 0; virtual bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) = 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_t outType, std::add_lvalue_reference_t outID, std::string& name, const char** _atts) { @@ -106,6 +107,22 @@ class IElement return _atts[attrCount]; } + + // + 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; + } + ); + } + ); + } }; } diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 11d2d30170..997d95f68a 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -139,8 +139,8 @@ class ParserManager final }; const core::unordered_map createElementTable; // - template requires std::is_base_of_v - static SNamedElement createElement(const char** _atts, SessionContext* ctx); + template + struct CreateElement; // static SNamedElement processAlias(const char** _atts, SessionContext* ctx); static SNamedElement processRef(const char** _atts, SessionContext* ctx); diff --git a/include/nbl/ext/MitsubaLoader/PropertyElement.h b/include/nbl/ext/MitsubaLoader/PropertyElement.h index 8ecdce7fdd..320e12712e 100644 --- a/include/nbl/ext/MitsubaLoader/PropertyElement.h +++ b/include/nbl/ext/MitsubaLoader/PropertyElement.h @@ -14,6 +14,7 @@ namespace nbl::ext::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); 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 11e68d619d..0f360ccba0 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp @@ -10,22 +10,6 @@ namespace nbl::ext::MitsubaLoader { -template<> -auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement -{ - 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)}; -} - bool CElementEmissionProfile::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { if (_property.name=="filename") 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 dbff6ed1c9..964bbe4211 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -2,125 +2,20 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h #include "nbl/ext/MitsubaLoader/CElementIntegrator.h" -#include "nbl/ext/MitsubaLoader/ParserUtil.h" #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" +#include "nbl/ext/MitsubaLoader/ElementMacros.h" + #include namespace nbl::ext::MitsubaLoader { -template<> -auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement -{ - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return {}; - - 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 {}; - } - - CElementIntegrator* obj = _util->objects.construct(id); - if (!obj) - return {}; - - 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) { bool error = false; +#if 0 auto dispatch = [&](auto func) -> void { switch (type) @@ -391,23 +286,20 @@ 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("No Integrator can have such property set with name: "+_property.name); return false; } found->second(); return !error; +#endif + assert(false); + return false; } -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 { @@ -415,8 +307,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; 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 aff64d6b24..3dbb2db9f7 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSampler.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSampler.cpp @@ -2,71 +2,16 @@ // 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/ElementMacros.h" namespace nbl::ext::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 = - { - 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) +bool CElementSampler::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { - if (_property.type == SNamedPropertyElement::Type::INTEGER && - _property.name == "sampleCount") + if (_property.type==SNamedPropertyElement::Type::INTEGER && _property.name=="sampleCount") { sampleCount = _property.ivalue; switch (type) @@ -81,47 +26,36 @@ bool CElementSampler::addProperty(SNamedPropertyElement&& _property) break; } } - else - if (_property.type == SNamedPropertyElement::Type::INTEGER && - _property.name == "dimension") + 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); + invalidXMLFileStructure(logger,"this sampler type ("+std::to_string(type)+") does not take these parameters"); return false; } } - else - if (_property.type == SNamedPropertyElement::Type::INTEGER && - _property.name == "scramble") + 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); + invalidXMLFileStructure(logger,"this sampler type ("+std::to_string(type)+") does not take these parameters"); return false; } } else { - _NBL_DEBUG_BREAK_IF(true); + invalidXMLFileStructure(logger,"unknown property named `"+_property.name+"` of type "+std::to_string(_property.type)); return false; } return true; } -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 diff --git a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp index d2f336cad2..ccc0cfb40e 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp @@ -5,6 +5,7 @@ #include "nbl/ext/MitsubaLoader/CElementSensor.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" +#include "nbl/ext/MitsubaLoader/ElementMacros.h" #include @@ -12,77 +13,10 @@ namespace nbl::ext::MitsubaLoader { -template<> -auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement -{ - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return {}; - - // TODO: initialize this separately - 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()) - { - ctx->invalidXMLFileStructure("unknown type"); - return {}; - } - - CElementSensor* obj = ctx->objects.construct(id); - if (!obj) - return {}; - - 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 {obj,std::move(name)}; -} - -bool CElementSensor::addProperty(SNamedPropertyElement&& _property) +bool CElementSensor::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { bool error = false; +#if 0 auto dispatch = [&](auto func) -> void { switch (type) @@ -221,8 +155,8 @@ bool CElementSensor::addProperty(SNamedPropertyElement&& _property) {"nearClip", setNearClip}, {"farClip", setFarClip}, {"focusDistance", setFocusDistance}, - {"apertureRadius", setApertureRadius}/*, - {"kc", setKc}*/ + {"apertureRadius", setApertureRadius} +//, {"kc", setKc} }; @@ -236,16 +170,14 @@ bool CElementSensor::addProperty(SNamedPropertyElement&& _property) found->second(); return !error; +#endif + assert(false); + return false; } -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 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 6520cd8c90..60496ad714 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp @@ -7,17 +7,6 @@ namespace nbl::ext::MitsubaLoader { - -template<> -auto ParserManager::createElement(const char** _atts, SessionContext* ctx) -> SNamedElement -{ - if (IElement::invalidAttributeCount(_atts,2u)) - return {}; - if (core::strcmpi(_atts[0],"name")) - return {}; - - return {ctx->objects.construct(),_atts[1]}; -} bool CElementTransform::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { diff --git a/src/nbl/ext/MitsubaLoader/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index 2adc31d7b6..7bedf035b8 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -27,11 +27,11 @@ set(NBL_EXT_MITSUBA_LOADER_H set(NBL_EXT_MITSUBA_LOADER_SRC PropertyElement.cpp -# CElementIntegrator.cpp -# CElementSensor.cpp -# CElementFilm.cpp -# CElementRFilter.cpp -# CElementSampler.cpp + CElementIntegrator.cpp + CElementSensor.cpp + CElementFilm.cpp + CElementRFilter.cpp + CElementSampler.cpp CElementTransform.cpp # CElementShape.cpp # CElementBSDF.cpp diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h new file mode 100644 index 0000000000..4f87e8ebc1 --- /dev/null +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -0,0 +1,119 @@ +// 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" + +/* +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 5dbf6a7e93..5f01edf95a 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -254,7 +254,7 @@ void ParserManager::XMLContext::onEnd(const char* _el) elements.pop(); auto& result = *session->result; - if (element.element && !element.element->onEndTag(session->params->_override,result.metadata.get())) + if (element.element && !element.element->onEndTag(result.metadata.get(),session->params->logger)) { killParseWithError(element.element->getLogName()+" could not onEndTag"); return; @@ -282,6 +282,84 @@ void ParserManager::XMLContext::onEnd(const char* _el) } } +// 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", @@ -289,21 +367,21 @@ ParserManager::ParserManager() : propertyElements({ "point", "vector", "matrix", "rotate", "translate", "scale", "lookat" }), propertyElementManager(), createElementTable({ -// {"integrator", {.create=createElement,.retvalGoesOnStack=true}}, -// {"sensor", {.create=createElement,.retvalGoesOnStack=true}}, -// {"film", {.create=createElement,.retvalGoesOnStack=true}}, -// {"rfilter", {.create=createElement,.retvalGoesOnStack=true}}, -// {"sampler", {.create=createElement,.retvalGoesOnStack=true}}, -// {"shape", {.create=createElement,.retvalGoesOnStack=true}}, - {"transform", {.create=createElement,.retvalGoesOnStack=true}}, -// {"animation", {.create=createElement,.retvalGoesOnStack=true}}, -// {"bsdf", {.create=createElement,.retvalGoesOnStack=true}}, -// {"texture", {.create=createElement,.retvalGoesOnStack=true}}, -// {"emitter", {.create=createElement,.retvalGoesOnStack=true}}, - {"emissionprofile", {.create=createElement,.retvalGoesOnStack=true}}, + {"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}} -}){} +}) {} auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SNamedElement { From 9745682ae0e430b4be9cacc4d48b454e94cf94ab Mon Sep 17 00:00:00 2001 From: devsh Date: Thu, 16 Oct 2025 15:32:27 +0200 Subject: [PATCH 12/30] I am very sick in the head. --- include/nbl/core/algorithm/utility.h | 24 +++ .../nbl/ext/MitsubaLoader/CElementSensor.h | 55 +++++-- include/nbl/ext/MitsubaLoader/IElement.h | 85 +++++++++- include/nbl/ext/MitsubaLoader/ParserUtil.h | 28 ++-- .../ext/MitsubaLoader/CElementIntegrator.cpp | 81 ++-------- src/nbl/ext/MitsubaLoader/CElementSensor.cpp | 149 +++++++----------- src/nbl/ext/MitsubaLoader/ElementMacros.h | 3 + src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 37 ++++- 8 files changed, 270 insertions(+), 192 deletions(-) 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/ext/MitsubaLoader/CElementSensor.h b/include/nbl/ext/MitsubaLoader/CElementSensor.h index 655a50b3e8..d40b19bc5e 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSensor.h +++ b/include/nbl/ext/MitsubaLoader/CElementSensor.h @@ -30,27 +30,13 @@ class CElementSensor final : public IElement PERSPECTIVE_RDIST, INVALID }; - 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}*/ - }; - } constexpr static inline uint8_t MaxClipPlanes = 6u; struct ShutterSensor { hlsl::float32_t3 up = hlsl::float32_t3(0,1,0); - hlsl::float32_t3 clipPlanes[MaxClipPlanes] = {}; + hlsl::float32_t4 clipPlanes[MaxClipPlanes] = {}; float moveSpeed = core::nan(); float zoomSpeed = core::nan(); float rotateSpeed = core::nan(); @@ -64,6 +50,8 @@ class CElementSensor final : public IElement }; struct PerspectivePinhole : CameraBase { + constexpr static inline Type VariantType = Type::PERSPECTIVE; + enum class FOVAxis { INVALID, @@ -86,6 +74,7 @@ class CElementSensor final : public IElement }; struct Orthographic : CameraBase { + constexpr static inline Type VariantType = Type::ORTHOGRAPHIC; }; struct DepthOfFieldBase { @@ -94,27 +83,59 @@ class CElementSensor final : 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; };*/ + 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}*/ + }; + } + static AddPropertyMap compAddPropertyMap(); + inline CElementSensor(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), film(""), sampler("") { } @@ -182,7 +203,9 @@ class CElementSensor final : public IElement bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::SENSOR; } + + constexpr static inline auto ElementType = IElement::Type::SENSOR; + inline IElement::Type getType() const override { return ElementType; } inline std::string getLogName() const override { return "sensor"; } inline bool processChildData(IElement* _child, const std::string& name) override diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index b0f2d34c3b..20780a21c4 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -5,6 +5,7 @@ #define _NBL_EXT_MISTUBA_LOADER_I_ELEMENT_H_INCLUDED_ +#include "nbl/core/algorithm/utility.h" #include "nbl/asset/interchange/IAssetLoader.h" #include "nbl/ext/MitsubaLoader/PropertyElement.h" @@ -14,6 +15,21 @@ namespace nbl::ext::MitsubaLoader { class CMitsubaMetadata; +namespace impl +{ +template class Pred, typename... Args> +struct ToUnaryPred +{ + template + struct type : bool_constant::value> {}; +}; + +template +struct mpl_of_passing; +template +using mpl_of_passing_t = mpl_of_passing::type; +} + class IElement { public: @@ -108,7 +124,12 @@ 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) { @@ -123,7 +144,69 @@ class IElement } ); } + + // 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: + 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 997d95f68a..5787cc6c62 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -9,6 +9,7 @@ #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" #include "nbl/ext/MitsubaLoader/PropertyElement.h" +#include "nbl/ext/MitsubaLoader/CElementSensor.h" #include "nbl/ext/MitsubaLoader/CElementShape.h" #include @@ -72,7 +73,22 @@ class ParserManager final const core::unordered_set propertyElements; const CPropertyElementManager propertyElementManager; + using supported_elements_t = core::type_list< +// CElementIntegrator, + CElementSensor +// CElementFilm, +// CElementRFilter, +// CElementSampler, +/// CElementShape, +/// CElementBSDF, +/// CElementTexture, +/// CElementEmitter, +// CElementEmissionProfile + >; + private: + const core::tuple_transform_t addPropertyMaps; + struct SNamedElement { IElement* element = nullptr; @@ -97,17 +113,7 @@ class ParserManager final // uint32_t sceneDeclCount = 0; // TODO: This leaks memory all over the place because destructors are not ran! - ElementPool objects = {}; + 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 diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index 964bbe4211..04227927be 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -6,6 +6,7 @@ #include "nbl/ext/MitsubaLoader/ElementMacros.h" +#include "nbl/type_traits.h" // legacy stuff for `is_any_of` #include @@ -14,74 +15,12 @@ namespace nbl::ext::MitsubaLoader bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { + if (type>=Type::INVALID) + return false; bool error = false; #if 0 - 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; - } - }; - #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) { \ @@ -98,7 +37,7 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system:: 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) @@ -165,7 +104,7 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system:: 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) @@ -197,7 +136,7 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system:: }; auto processUndefined = [&]() -> void { - dispatch([&](auto& state) -> void { + visit([&](auto& state) -> void { using state_type = std::remove_reference::type; if constexpr (std::is_same::value) @@ -286,15 +225,13 @@ bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system:: auto found = SetPropertyMap.find(_property.name); if (found==SetPropertyMap.end()) { - 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(); - return !error; #endif - assert(false); - return false; + return !error; } bool CElementIntegrator::onEndTag(CMitsubaMetadata* metadata, system::logger_opt_ptr logger) diff --git a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp index ccc0cfb40e..86724403b4 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp @@ -9,47 +9,74 @@ #include +template +struct derived_from : std::is_base_of {}; namespace nbl::ext::MitsubaLoader { +auto CElementSensor::compAddPropertyMap() -> AddPropertyMap +{ + using this_t = CElementSensor; + AddPropertyMap retval; + +// auto setUp = SET_PROPERTY_TEMPLATE(up, SNamedPropertyElement::Type::VECTOR, ShutterSensor); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(VECTOR,"clipPlane") + { + if (_property.getVectorDimension()!=4) + { + 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) + { + 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; + } + }); + +// 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); + retval.template registerCallback(SNamedPropertyElement::Type::STRING,"fovAxis",[](CElementSensor* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool + { + auto& state = _this->perspective; + 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; + } + ); + + return retval; +} + bool CElementSensor::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { + if (type >= Type::INVALID) + return false; bool error = false; + #if 0 - auto dispatch = [&](auto func) -> void - { - switch (type) - { - 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; - } - }; #define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE,BASE) [&]() -> void { \ dispatch([&](auto& state) -> void { \ @@ -65,62 +92,6 @@ bool CElementSensor::addProperty(SNamedPropertyElement&& _property, system::logg } auto setUp = SET_PROPERTY_TEMPLATE(up,SNamedPropertyElement::Type::VECTOR,ShutterSensor); - auto setClipPlane = [&]() -> void - { - dispatch([&](auto& state) -> void - { - 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 - { - 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); diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index 4f87e8ebc1..9492032ca1 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -4,6 +4,9 @@ #include "nbl/ext/MitsubaLoader/IElement.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" + +#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(PROP_TYPE,NAME) retval.registerCallback(SNamedPropertyElement::Type::PROP_TYPE,NAME,{.func=[](this_t* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool + /* template<> CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 5f01edf95a..468fc92ce6 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -191,7 +191,8 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts killParseWithError("cannot set a property with no element on the stack."); return; } - if (!elements.top().element) + auto* element = elements.top().element; + if (!element) { session->invalidXMLFileStructure("cannot set property on element that failed to be created."); return; @@ -204,7 +205,35 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts return; } - elements.top().element->addProperty(std::move(optProperty.value()),session->params->logger); + bool unsupportedElement = true; + auto run = [&](const auto& map)->void + { + using element_t = std::remove_cvref_t::mapped_type::mapped_type::element_t; + if (element_t::ElementType==element->getType()) + { + unsupportedElement = false; + auto& property = optProperty.value(); + auto typeIt = map.find(property.type); + if (typeIt==map.end()) + { + session->invalidXMLFileStructure("There's no property supported by ElementType (TODO) with PropertyType (TODO)"); + return; + } + auto nameIt = typeIt->second.find(property.name); + if (nameIt==typeIt->second.end()) + { + session->invalidXMLFileStructure("There's no Property named (TODO) of Type (TODO) supported by ElementType (TODO)"); + return; + } + // TODO: visit variant type checks + nameIt->second(static_cast(element),std::move(property),session->params->logger); + } + }; + std::apply([&run](const auto&... maps)->void + { + (run(maps), ...); + },manager->addPropertyMaps + ); return; } @@ -381,7 +410,9 @@ ParserManager::ParserManager() : propertyElements({ {"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 { From 35d4a0a1261b1752c7c3f225c4ff3fa353a6306c Mon Sep 17 00:00:00 2001 From: devsh Date: Thu, 16 Oct 2025 15:48:17 +0200 Subject: [PATCH 13/30] now get it to compile --- include/nbl/ext/MitsubaLoader/IElement.h | 2 ++ src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 26 +++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 20780a21c4..68c2958fb2 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -179,6 +179,8 @@ class IElement } 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); diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 468fc92ce6..0ba2bad8d0 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -208,25 +208,32 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts bool unsupportedElement = true; auto run = [&](const auto& map)->void { - using element_t = std::remove_cvref_t::mapped_type::mapped_type::element_t; + using element_t = std::remove_cvref_t::element_type; if (element_t::ElementType==element->getType()) { unsupportedElement = false; auto& property = optProperty.value(); - auto typeIt = map.find(property.type); - if (typeIt==map.end()) + 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 = typeIt->second.find(property.name); - if (nameIt==typeIt->second.end()) + auto nameIt = typeMap.find(property.name); + if (nameIt==typeMap.end()) { session->invalidXMLFileStructure("There's no Property named (TODO) of Type (TODO) supported by ElementType (TODO)"); return; } - // TODO: visit variant type checks - nameIt->second(static_cast(element),std::move(property),session->params->logger); + 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 @@ -234,6 +241,11 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts (run(maps), ...); },manager->addPropertyMaps ); + if (unsupportedElement) + { + session->invalidXMLFileStructure("Current Element Type doesn't have a AddPropertyMap at all (no property adding supported)!"); + return; + } return; } From 51dc3aa1a08d458bc18c2498fd1dbcf27d824d79 Mon Sep 17 00:00:00 2001 From: devsh Date: Thu, 16 Oct 2025 16:19:25 +0200 Subject: [PATCH 14/30] This is a neat rewrite! --- src/nbl/ext/MitsubaLoader/CElementSensor.cpp | 148 ++++++------------- src/nbl/ext/MitsubaLoader/ElementMacros.h | 25 +++- 2 files changed, 71 insertions(+), 102 deletions(-) diff --git a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp index 86724403b4..6982870fc6 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp @@ -9,8 +9,6 @@ #include -template -struct derived_from : std::is_base_of {}; namespace nbl::ext::MitsubaLoader { @@ -20,36 +18,14 @@ auto CElementSensor::compAddPropertyMap() -> AddPropertyMap using this_t = CElementSensor; AddPropertyMap retval; -// auto setUp = SET_PROPERTY_TEMPLATE(up, SNamedPropertyElement::Type::VECTOR, ShutterSensor); - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(VECTOR,"clipPlane") - { - if (_property.getVectorDimension()!=4) - { - 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) - { - 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; - } - }); - -// 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); - retval.template registerCallback(SNamedPropertyElement::Type::STRING,"fovAxis",[](CElementSensor* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool + 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) { auto& state = _this->perspective; + // TODO: check if this gives problem with delay loads static const core::unordered_map StringToType = { {"x", PerspectivePinhole::FOVAxis::X}, @@ -67,81 +43,51 @@ auto CElementSensor::compAddPropertyMap() -> AddPropertyMap } ); - return 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(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 + { + if (_property.getVectorDimension()!=4) + { + 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) + { + 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; i= Type::INVALID) - return false; - bool error = false; - -#if 0 - -#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 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); + // TODOs: //auto setKc = SET_PROPERTY_TEMPLATE(apertureRadius,SNamedPropertyElement::Type::STRING,PerspectivePinholeRadialDistortion); + //{"focalLength", noIdeaHowToProcessValue}, - 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 retval; +} - 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); - return false; - } - - found->second(); - return !error; -#endif +bool CElementSensor::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) +{ assert(false); return false; } diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index 9492032ca1..7a210c3b0a 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -5,7 +5,30 @@ #include "nbl/ext/MitsubaLoader/ParserUtil.h" -#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(PROP_TYPE,NAME) 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_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<> From 0e1d4c2381c00e053d530817061b8428147ed96b Mon Sep 17 00:00:00 2001 From: devsh Date: Tue, 21 Oct 2025 23:35:44 +0200 Subject: [PATCH 15/30] try to pick up where I left off --- include/nbl/ext/MitsubaLoader/CElementBSDF.h | 11 ++- .../MitsubaLoader/CElementEmissionProfile.h | 11 +-- .../nbl/ext/MitsubaLoader/CElementEmitter.h | 16 ++-- include/nbl/ext/MitsubaLoader/CElementFilm.h | 7 +- .../ext/MitsubaLoader/CElementIntegrator.h | 9 +- .../nbl/ext/MitsubaLoader/CElementRFilter.h | 34 +++++--- .../nbl/ext/MitsubaLoader/CElementSampler.h | 6 +- .../nbl/ext/MitsubaLoader/CElementSensor.h | 1 - include/nbl/ext/MitsubaLoader/CElementShape.h | 7 +- .../nbl/ext/MitsubaLoader/CElementTexture.h | 16 ++-- .../nbl/ext/MitsubaLoader/CElementTransform.h | 7 +- include/nbl/ext/MitsubaLoader/IElement.h | 1 - include/nbl/ext/MitsubaLoader/ParserUtil.h | 21 +++-- src/nbl/ext/MitsubaLoader/CElementSampler.cpp | 87 +++++++++++-------- src/nbl/ext/MitsubaLoader/CElementSensor.cpp | 9 -- .../ext/MitsubaLoader/CElementTransform.cpp | 38 ++++---- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 3 + 17 files changed, 164 insertions(+), 120 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index 1d4a823e30..7f5e73c13f 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -289,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) { } @@ -369,14 +373,15 @@ class CElementBSDF : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - IElement::Type getType() const override { return IElement::Type::BSDF; } + + 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) { diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index a4b1d22485..331abf2873 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -14,6 +14,8 @@ namespace nbl::ext::MitsubaLoader struct CElementEmissionProfile final : public IElement { + static AddPropertyMap compAddPropertyMap(); + 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("") @@ -24,6 +26,7 @@ struct CElementEmissionProfile final : public IElement { operator=(std::move(other)); } + inline ~CElementEmissionProfile() {} inline CElementEmissionProfile& operator=(const CElementEmissionProfile& other) { @@ -39,14 +42,12 @@ struct CElementEmissionProfile final : public IElement return *this; } - inline ~CElementEmissionProfile() - { - } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; inline bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override {return true;} bool processChildData(IElement* _child, const std::string& name) override; - inline IElement::Type getType() const override { return IElement::Type::EMISSION_PROFILE; } + + 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 : uint8_t diff --git a/include/nbl/ext/MitsubaLoader/CElementEmitter.h b/include/nbl/ext/MitsubaLoader/CElementEmitter.h index 389ec31fd5..5de6861d7f 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmitter.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmitter.h @@ -97,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)); } @@ -200,9 +203,10 @@ class CElementEmitter : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - IElement::Type getType() const override { return IElement::Type::EMITTER; } + + 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 diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index dcd7402132..986a5a5cbe 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -99,7 +99,7 @@ class CElementFilm final : public IElement { hdrfilm = HDR(); } - virtual ~CElementFilm() + virtual inline ~CElementFilm() { } @@ -124,9 +124,10 @@ class CElementFilm final : public IElement } } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::FILM; } + + 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 diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index d683204439..94ea85b7b6 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -215,6 +215,10 @@ class CElementIntegrator final : public IElement { }; + // + static AddPropertyMap compAddPropertyMap(); + + // inline CElementIntegrator(const char* id) : IElement(id), type(Type::INVALID) { } @@ -303,9 +307,10 @@ class CElementIntegrator final : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::INTEGRATOR; } + + constexpr static inline auto ElementType = IElement::Type::INTEGRATOR; + inline IElement::Type getType() const override { return ElementType; } inline std::string getLogName() const override { return "integrator"; } inline bool processChildData(IElement* _child, const std::string& name) override diff --git a/include/nbl/ext/MitsubaLoader/CElementRFilter.h b/include/nbl/ext/MitsubaLoader/CElementRFilter.h index 0ca2426d73..b3673c9e35 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.h @@ -26,17 +26,6 @@ class CElementRFilter final : public IElement CATMULLROM, LANCZOS }; - 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) - }; - } struct Gaussian { @@ -52,6 +41,24 @@ class CElementRFilter final : public IElement int32_t lobes = 3; }; + 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(); @@ -93,9 +100,10 @@ class CElementRFilter final : public IElement ); } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::RFILTER; } + + 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 diff --git a/include/nbl/ext/MitsubaLoader/CElementSampler.h b/include/nbl/ext/MitsubaLoader/CElementSampler.h index 02e3ae6f6b..9b9bc2b820 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSampler.h +++ b/include/nbl/ext/MitsubaLoader/CElementSampler.h @@ -36,6 +36,7 @@ class CElementSampler : public IElement {"sobol", Type::SOBOL} }; } + static AddPropertyMap compAddPropertyMap(); inline CElementSampler(const char* id) : IElement(id), type(INVALID), sampleCount(4) {} inline ~CElementSampler() {} @@ -63,9 +64,10 @@ class CElementSampler : public IElement } } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::SAMPLER; } + + 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 diff --git a/include/nbl/ext/MitsubaLoader/CElementSensor.h b/include/nbl/ext/MitsubaLoader/CElementSensor.h index d40b19bc5e..4ef41e42d5 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSensor.h +++ b/include/nbl/ext/MitsubaLoader/CElementSensor.h @@ -201,7 +201,6 @@ class CElementSensor final : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; constexpr static inline auto ElementType = IElement::Type::SENSOR; diff --git a/include/nbl/ext/MitsubaLoader/CElementShape.h b/include/nbl/ext/MitsubaLoader/CElementShape.h index 08dfa75783..23018079a1 100644 --- a/include/nbl/ext/MitsubaLoader/CElementShape.h +++ b/include/nbl/ext/MitsubaLoader/CElementShape.h @@ -99,6 +99,8 @@ class CElementShape final : public IElement CElementTexture* texture; };*/ + static AddPropertyMap compAddPropertyMap(); + inline CElementShape(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), bsdf(nullptr), emitter(nullptr) { } @@ -215,9 +217,10 @@ class CElementShape final : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::SHAPE; } + + constexpr static inline auto ElementType = IElement::Type::SHAPE; + inline IElement::Type getType() const override { return ElementType; } inline std::string getLogName() const override { return "shape"; } diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index ec2ff2d1bf..ece070785e 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -155,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() { } @@ -235,10 +239,10 @@ class CElementTexture : public IElement return *this; } - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override; - inline IElement::Type getType() const override { return IElement::Type::TEXTURE; } + 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; diff --git a/include/nbl/ext/MitsubaLoader/CElementTransform.h b/include/nbl/ext/MitsubaLoader/CElementTransform.h index 292a081bba..45612174ad 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTransform.h +++ b/include/nbl/ext/MitsubaLoader/CElementTransform.h @@ -14,12 +14,15 @@ namespace nbl::ext::MitsubaLoader class CElementTransform final : public IElement { public: + static AddPropertyMap compAddPropertyMap(); + inline CElementTransform() : IElement(""), matrix() {} inline ~CElementTransform() {} - bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) override; inline bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override {return true;} - inline IElement::Type getType() const override { return IElement::Type::TRANSFORM; } + + 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) diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 68c2958fb2..4da3dbb848 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -64,7 +64,6 @@ class IElement virtual IElement::Type getType() const = 0; virtual std::string getLogName() const = 0; - virtual bool addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) = 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) diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 5787cc6c62..5c2b3efbef 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -8,9 +8,16 @@ #include "nbl/asset/interchange/IAssetLoader.h" #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" -#include "nbl/ext/MitsubaLoader/PropertyElement.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 @@ -74,16 +81,16 @@ class ParserManager final const CPropertyElementManager propertyElementManager; using supported_elements_t = core::type_list< -// CElementIntegrator, - CElementSensor -// CElementFilm, -// CElementRFilter, -// CElementSampler, + CElementIntegrator, + CElementSensor, + CElementFilm, + CElementRFilter, + CElementSampler, /// CElementShape, /// CElementBSDF, /// CElementTexture, /// CElementEmitter, -// CElementEmissionProfile + CElementEmissionProfile >; private: diff --git a/src/nbl/ext/MitsubaLoader/CElementSampler.cpp b/src/nbl/ext/MitsubaLoader/CElementSampler.cpp index 3dbb2db9f7..b862a754fb 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSampler.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSampler.cpp @@ -1,56 +1,69 @@ -// 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/ElementMacros.h" namespace nbl::ext::MitsubaLoader { - - -bool CElementSampler::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) + +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) { - invalidXMLFileStructure(logger,"this sampler type ("+std::to_string(type)+") does not take these parameters"); - 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) { - invalidXMLFileStructure(logger,"this sampler type ("+std::to_string(type)+") does not take these parameters"); - 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 - { - invalidXMLFileStructure(logger,"unknown property named `"+_property.name+"` of type "+std::to_string(_property.type)); - return false; - } + }); - return true; + return retval; } bool CElementSampler::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) diff --git a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp index 6982870fc6..d8ab85bb26 100644 --- a/src/nbl/ext/MitsubaLoader/CElementSensor.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementSensor.cpp @@ -1,8 +1,6 @@ // 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/ElementMacros.h" @@ -43,7 +41,6 @@ auto CElementSensor::compAddPropertyMap() -> AddPropertyMap } ); - 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(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); @@ -86,12 +83,6 @@ auto CElementSensor::compAddPropertyMap() -> AddPropertyMap return retval; } -bool CElementSensor::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) -{ - assert(false); - return false; -} - bool CElementSensor::onEndTag(CMitsubaMetadata* meta, system::logger_opt_ptr logger) { NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); diff --git a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp index 60496ad714..cb583c211c 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp @@ -8,30 +8,26 @@ namespace nbl::ext::MitsubaLoader { -bool CElementTransform::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) +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 = hlsl::mul(matrix,_property.mvalue); - break; - default: - { - invalidXMLFileStructure(logger,"The transform element does not take child property: "+_property.type); - 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/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 0ba2bad8d0..a79fdbb906 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -220,6 +220,9 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts 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)"); From 85c3b5a1afc61f35b36cdb93135c9c129a242021 Mon Sep 17 00:00:00 2001 From: devsh Date: Sun, 21 Dec 2025 17:15:38 +0100 Subject: [PATCH 16/30] make CElementFilm work --- include/nbl/ext/MitsubaLoader/CElementFilm.h | 64 +++- src/nbl/ext/MitsubaLoader/CElementFilm.cpp | 344 ++++++------------ .../ext/MitsubaLoader/CElementIntegrator.cpp | 8 + src/nbl/ext/MitsubaLoader/ElementMacros.h | 9 +- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 7 +- 5 files changed, 188 insertions(+), 244 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index 986a5a5cbe..267cd57938 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -22,16 +22,7 @@ class CElementFilm final : public IElement LDR_FILM, MFILM }; - 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, @@ -62,10 +53,14 @@ class CElementFilm final : public IElement }; struct HDR { + constexpr static inline Type VariantType = Type::HDR_FILM; + bool attachLog = true; }; struct LDR { + constexpr static inline Type VariantType = Type::LDR_FILM; + enum TonemapMethod { GAMMA, @@ -79,7 +74,9 @@ class CElementFilm final : public IElement }; struct M { - M() : digits(4) + constexpr static inline Type VariantType = Type::MFILM; + + inline M() : digits(4) { variable[0] = 'd'; variable[1] = 'a'; @@ -92,6 +89,23 @@ class CElementFilm final : public IElement char variable[MaxVarNameLen+1]; }; + // + using variant_list_t = core::type_list< + HDR, + LDR, + M + >; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"hdrfilm", Type::HDR_FILM}, + {"tiledhdrfilm",Type::TILED_HDR}, + {"ldrfilm", Type::LDR_FILM}, + {"mfilm", Type::MFILM} + }; + } + static AddPropertyMap compAddPropertyMap(); + 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), @@ -124,6 +138,32 @@ class CElementFilm final : public IElement } } + template + inline void visit(Visitor&& visitor) + { + switch (type) + { + case CElementFilm::Type::LDR_FILM: + visitor(ldrfilm); + break; + case CElementFilm::Type::MFILM: + visitor(mfilm); + break; + default: + visitor(hdrfilm); + 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::FILM; @@ -147,7 +187,7 @@ class CElementFilm final : public IElement Type type; int32_t width,height; int32_t cropOffsetX,cropOffsetY,cropWidth,cropHeight; - FileFormat fileFormat; + FileFormat fileFormat = OPENEXR; PixelFormat pixelFormat; ComponentFormat componentFormat; bool banner; diff --git a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp index 7f17cbe64d..361fc4fd55 100644 --- a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp @@ -4,266 +4,150 @@ #include "nbl/ext/MitsubaLoader/CElementFilm.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" +#include "nbl/ext/MitsubaLoader/ElementMacros.h" #include namespace nbl::ext::MitsubaLoader { -bool CElementFilm::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) + +inline bool setLimitedString(const std::string_view memberName, std::span out, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger) { -#if 0 - bool error = type==Type::INVALID; -#define SET_PROPERTY(MEMBER,PROPERTY_TYPE) [&]() -> void { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - MEMBER = _property.getProperty(); \ - } - auto setWidth = SET_PROPERTY(width,SNamedPropertyElement::Type::INTEGER); - auto setHeight = SET_PROPERTY(height,SNamedPropertyElement::Type::INTEGER); - auto setCropOffsetX = SET_PROPERTY(cropOffsetX,SNamedPropertyElement::Type::INTEGER); - auto setCropOffsetY = SET_PROPERTY(cropOffsetY,SNamedPropertyElement::Type::INTEGER); - auto setCropWidth = SET_PROPERTY(cropWidth,SNamedPropertyElement::Type::INTEGER); - auto setCropHeight = SET_PROPERTY(cropHeight,SNamedPropertyElement::Type::INTEGER); - auto setFileFormat = [&]() -> void - { - if (_property.type!=SNamedPropertyElement::Type::STRING) - { - error = true; - return; - } - static const core::unordered_map StringToType = - { - {"openexr", OPENEXR}, - {"png", PNG}, - {"rgbe", RGBE}, - {"pfm", PFM}, - {"matlab", MATLAB}, - {"mathematica", MATHEMATICA}, - {"numpy", NUMPY} - }; - auto found = StringToType.find(_property.svalue); - if (found==StringToType.end()) - { - error = true; - return; - } - fileFormat = found->second; - }; - auto setPixelFormat = [&]() -> void - { - if (_property.type!=SNamedPropertyElement::Type::STRING) - { - error = true; - return; - } - static const core::unordered_map StringToType = - { - {"luminance", LUMINANCE}, - {"luminanceAlpha", LUMINANCE_ALPHA}, - {"rgb", RGB}, - {"rgba", RGBA}, - {"xyz", XYZ}, - {"xyza", XYZA}, - {"spectrum", SPECTRUM}, - {"spectrumAlpha", SPECTRUM_ALPHA} - }; - auto found = StringToType.find(_property.svalue); - if (found==StringToType.end()) + auto len = strlen(_property.svalue); + if (len>=out.size()) + logger.log( + "String property assigned to %s is too long, max allowed length %d, is %d, property value: \"%s\"", + system::ILogger::ELL_ERROR,memberName.data(),out.size(),len,_property.svalue + ); + len = std::min(out.size()-1,len); + memcpy(out.data(),_property.svalue,len); + out[len] = 0; + return true; +} + +auto CElementFilm::compAddPropertyMap() -> AddPropertyMap +{ + using this_t = CElementFilm; + AddPropertyMap retval; + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(width,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(height,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cropOffsetX,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cropOffsetY,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cropWidth,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cropHeight,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("fileFormat",STRING) { - error = true; - return; + static const core::unordered_map StringToType = + { + {"openexr", OPENEXR}, + {"png", PNG}, + {"rgbe", RGBE}, + {"pfm", PFM}, + {"matlab", MATLAB}, + {"mathematica", MATHEMATICA}, + {"numpy", NUMPY} + }; + auto found = StringToType.find(_property.svalue); + if (found==StringToType.end()) + return false; + _this->fileFormat = found->second; + return true; } - pixelFormat = found->second; - }; - auto setComponentFormat = [&]() -> void - { - if (_property.type!=SNamedPropertyElement::Type::STRING || type==Type::LDR_FILM || type==Type::MFILM) + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("pixelFormat",STRING) { - error = true; - return; + static const core::unordered_map StringToType = + { + {"luminance", LUMINANCE}, + {"luminanceAlpha", LUMINANCE_ALPHA}, + {"rgb", RGB}, + {"rgba", RGBA}, + {"xyz", XYZ}, + {"xyza", XYZA}, + {"spectrum", SPECTRUM}, + {"spectrumAlpha", SPECTRUM_ALPHA} + }; + auto found = StringToType.find(_property.svalue); + if (found==StringToType.end()) + return false; + _this->pixelFormat = found->second; + return true; } - static const core::unordered_map StringToType = + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("setComponentFormat",STRING) { - {"float16", FLOAT16}, - {"float32", FLOAT32}, - {"uint32", UINT32} - }; - auto found = StringToType.find(_property.svalue); - if (found==StringToType.end()) - { - error = true; - return; + static const core::unordered_map StringToType = + { + {"float16", FLOAT16}, + {"float32", FLOAT32}, + {"uint32", UINT32} + }; + auto found = StringToType.find(_property.svalue); + if (found==StringToType.end()) + return false; + _this->componentFormat = found->second; + return true; } - componentFormat = found->second; - }; - auto setBanner = SET_PROPERTY(banner,SNamedPropertyElement::Type::BOOLEAN); - auto setHighQualityEdges= SET_PROPERTY(highQualityEdges,SNamedPropertyElement::Type::BOOLEAN); + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(banner,BOOLEAN); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(highQualityEdges,BOOLEAN); - - auto dispatch = [&](auto func) -> void - { - switch (type) + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(attachLog,BOOLEAN,std::is_same,HDR); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("tonemapMethod",STRING,std::is_same,LDR) { - case CElementFilm::Type::HDR_FILM: - func(hdrfilm); - break; - case CElementFilm::Type::LDR_FILM: - func(ldrfilm); - break; - case CElementFilm::Type::MFILM: - func(mfilm); - break; - default: - error = true; - break; + static const core::unordered_map StringToType = + { + {"gamma", LDR::GAMMA}, + {"reinhard",LDR::REINHARD} + }; + auto found = StringToType.find(_property.svalue); + if (found==StringToType.end()) + return false; + _this->ldrfilm.tonemapMethod = found->second; + return true; } - }; -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ - } \ - }); \ - } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(gamma,FLOAT,std::is_same,LDR); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(exposure,FLOAT,std::is_same,LDR); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(key,FLOAT,std::is_same,LDR); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(burn,FLOAT,std::is_same,LDR); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(attachLog,INTEGER,std::is_same,HDR); - auto setAttachLog = SET_PROPERTY_TEMPLATE(attachLog, SNamedPropertyElement::Type::BOOLEAN, HDR); - auto setTonemapMethod = [&]() -> void - { - if (_property.type != SNamedPropertyElement::Type::STRING || type == Type::LDR_FILM) + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("variable",STRING,std::is_same,M) { - error = true; - return; + return setLimitedString("variable",_this->outputFilePath,std::move(_property),logger); } - static const core::unordered_map StringToType = + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("outputFilePath",STRING) { - {"gamma", LDR::GAMMA}, - {"reinhard",LDR::REINHARD} - }; - auto found = StringToType.find(_property.svalue); - if (found != StringToType.end()) - { - error = true; - return; + return setLimitedString("outputFilePath",_this->outputFilePath,std::move(_property),logger); } - ldrfilm.tonemapMethod = found->second; - }; - auto setGamma = SET_PROPERTY_TEMPLATE(gamma, SNamedPropertyElement::Type::FLOAT, LDR); - auto setExposure = SET_PROPERTY_TEMPLATE(exposure, SNamedPropertyElement::Type::FLOAT, LDR); - auto setKey = SET_PROPERTY_TEMPLATE(key, SNamedPropertyElement::Type::FLOAT, LDR); - auto setBurn = SET_PROPERTY_TEMPLATE(burn, SNamedPropertyElement::Type::FLOAT, LDR); - auto setDigits = SET_PROPERTY_TEMPLATE(digits, SNamedPropertyElement::Type::INTEGER, M); - auto setVariable = [&]() -> void - { - if (_property.type != SNamedPropertyElement::Type::STRING || type == Type::MFILM) + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("bloomFilePath",STRING) { - error = true; - return; + return setLimitedString("bloomFilePath",_this->denoiserTonemapperArgs,std::move(_property),logger); } - size_t len = std::min(strlen(_property.svalue),M::MaxVarNameLen); - memcpy(mfilm.variable,_property.svalue,len); - mfilm.variable[len] = 0; - }; - auto setOutputFilePath = [&]() -> void - { - if (_property.type != SNamedPropertyElement::Type::STRING) + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("tonemapper",STRING) { - error = true; - return; + return setLimitedString("tonemapper",_this->denoiserTonemapperArgs,std::move(_property),logger); } + }); - size_t len = std::min(strlen(_property.svalue),MaxPathLen); - memcpy(outputFilePath,_property.svalue,len); - outputFilePath[len] = 0; - }; - - auto setBloomFilePath = [&]() -> void - { - if (_property.type != SNamedPropertyElement::Type::STRING) - { - error = true; - return; - } - - size_t len = std::min(strlen(_property.svalue),MaxPathLen); - memcpy(denoiserBloomFilePath,_property.svalue,len); - denoiserBloomFilePath[len] = 0; - }; - - auto setTonemapperArgs = [&]() -> void - { - if (_property.type != SNamedPropertyElement::Type::STRING) - { - error = true; - return; - } + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cascadeCount,INTEGER); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cascadeLuminanceBase,FLOAT); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cascadeLuminanceStart,FLOAT); - size_t len = std::min(strlen(_property.svalue),MaxTonemapperArgsLen); - memcpy(denoiserTonemapperArgs,_property.svalue,len); - denoiserTonemapperArgs[len] = 0; - }; + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(denoiserBloomScale,FLOAT); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(denoiserBloomIntensity,FLOAT); - auto setCascadeCount = SET_PROPERTY(cascadeCount,SNamedPropertyElement::Type::INTEGER); - auto setCascadeLuminanceBase = SET_PROPERTY(cascadeLuminanceBase,SNamedPropertyElement::Type::FLOAT); - auto setCascadeLuminanceStart = SET_PROPERTY(cascadeLuminanceStart,SNamedPropertyElement::Type::FLOAT); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(envmapRegularizationFactor,FLOAT); - auto setBloomScale = SET_PROPERTY(denoiserBloomScale,SNamedPropertyElement::Type::FLOAT); - auto setBloomIntensity = SET_PROPERTY(denoiserBloomIntensity,SNamedPropertyElement::Type::FLOAT); - - auto setEnvmapRegularizationFactor = SET_PROPERTY(envmapRegularizationFactor,SNamedPropertyElement::Type::FLOAT); - - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - {"width", setWidth}, - {"height", setHeight}, - {"cropOffsetX", setCropOffsetX}, - {"cropOffsetY", setCropOffsetY}, - {"cropWidth", setCropWidth}, - {"cropHeight", setCropHeight}, - {"fileFormat", setFileFormat}, - {"pixelFormat", setPixelFormat}, - {"componentFormat", setComponentFormat}, - {"banner", setBanner}, - {"highQualityEdges", setHighQualityEdges}, - {"attachLog", setAttachLog}, - {"tonemapMethod", setTonemapMethod}, - {"gamma", setGamma}, - {"exposure", setExposure}, - {"key", setKey}, - {"burn", setBurn}, - {"digits", setDigits}, - {"variable", setVariable}, - {"outputFilePath", setOutputFilePath}, - {"bloomFilePath", setBloomFilePath}, - {"cascadeCount", setCascadeCount}, - {"cascadeLuminanceBase", setCascadeLuminanceBase}, - {"cascadeLuminanceStart", setCascadeLuminanceStart}, - {"bloomScale", setBloomScale}, - {"bloomIntensity", setBloomIntensity}, - {"tonemapper", setTonemapperArgs}, - {"envmapRegularizationFactor", setEnvmapRegularizationFactor} - }; - - auto found = SetPropertyMap.find(_property.name); - if (found == SetPropertyMap.end()) - { - - 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; + return retval; } bool CElementFilm::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index 04227927be..b87e4d370c 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -13,6 +13,14 @@ namespace nbl::ext::MitsubaLoader { +auto CElementFilm::compAddPropertyMap() -> AddPropertyMap +{ + using this_t = CElementFilm; + AddPropertyMap retval; + + return retval; +} + bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) { if (type>=Type::INVALID) diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index 7a210c3b0a..b214882ff1 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -5,17 +5,24 @@ #include "nbl/ext/MitsubaLoader/ParserUtil.h" +// Return value is if there's no error during the setting once basic checks are done +// For when you want to do custom handling of when property with string NAME and SNamedPropertyElement::Type::PROP_TYPE is getting added to this_t #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 +// when you know that there's a member of `this_t` with identifier equal to NAME #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;}}) - +// Similar to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` but for `this_t` which declare `variant_list_t` (list of union types) +// this adds a compile-time filter against the constraint, such that only variant types matching the constraint are visited. +// Useful when multiple variants derive from the same base struct, or have the same member. #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 +// This it to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED` what `NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY` is to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` +// So basically you know the member is the same across the constraint filtered types #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) \ diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index a79fdbb906..0fe612e2ec 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -426,7 +426,12 @@ ParserManager::ParserManager() : propertyElements({ {"alias", {.create=processAlias,.retvalGoesOnStack=true}}, {"ref", {.create=processRef,.retvalGoesOnStack=true}} }), addPropertyMaps({ - CElementSensor::compAddPropertyMap() + CElementIntegrator::compAddPropertyMap(), + CElementSensor::compAddPropertyMap(), + CElementFilm::compAddPropertyMap(), + CElementRFilter::compAddPropertyMap(), + CElementSampler::compAddPropertyMap(), + CElementEmissionProfile::compAddPropertyMap() }) { } auto ParserManager::processAlias(const char** _atts, SessionContext* ctx) -> SNamedElement From ade7a8a187ca50d43fae637af05659f55e68db74 Mon Sep 17 00:00:00 2001 From: devsh Date: Sun, 21 Dec 2025 23:09:37 +0100 Subject: [PATCH 17/30] refactor CElementIntegrator --- .../ext/MitsubaLoader/CElementIntegrator.h | 85 +++- .../ext/MitsubaLoader/CElementIntegrator.cpp | 371 +++++++----------- 2 files changed, 221 insertions(+), 235 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index 94ea85b7b6..760f87fe5b 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -61,8 +61,10 @@ class CElementIntegrator final : public IElement }; } - struct AmbientOcclusion + struct AmbientOcclusion final { + constexpr static inline Type VariantType = Type::AO; + int32_t shadingSamples = 1; float rayLength = -1.f; }; @@ -71,8 +73,10 @@ class CElementIntegrator final : public IElement bool hideEmitters = false; bool hideEnvironment = false; }; - struct DirectIllumination : EmitterHideableBase + struct DirectIllumination final : EmitterHideableBase { + constexpr static inline Type VariantType = Type::DIRECT; + int32_t emitterSamples = static_cast(0xdeadbeefu); int32_t bsdfSamples = static_cast(0xdeadbeefu); bool strictNormals = false; @@ -84,16 +88,22 @@ class CElementIntegrator final : public IElement }; struct PathTracing : MonteCarloTracingBase,EmitterHideableBase { + constexpr static inline Type VariantType = Type::PATH; + bool strictNormals = false; }; struct SimpleVolumetricPathTracing : PathTracing { + constexpr static inline Type VariantType = Type::VOL_PATH_SIMPLE; }; struct ExtendedVolumetricPathTracing : SimpleVolumetricPathTracing { + constexpr static inline Type VariantType = Type::VOL_PATH; }; - struct BiDirectionalPathTracing : MonteCarloTracingBase + struct BiDirectionalPathTracing final : MonteCarloTracingBase { + constexpr static inline Type VariantType = Type::BDPT; + bool lightImage = true; bool sampleDirect = true; }; @@ -101,26 +111,31 @@ class CElementIntegrator final : public IElement { int32_t granularity = 0; }; - struct PhotonMapping : PhotonMappingBase, EmitterHideableBase + struct PhotonMapping final : PhotonMappingBase, EmitterHideableBase { + constexpr static inline Type VariantType = Type::PHOTONMAPPER; + int32_t directSamples = 16; int32_t glossySamples = 32; int32_t globalPhotons = 250000; int32_t causticPhotons = 250000; int32_t volumePhotons = 250000; - float globalLURadius = 0.05; - float causticLURadius = 0.0125; - int32_t LUSize = 120; + float globalLookupRadius = 0.05; + float causticLookupRadius = 0.0125; + int32_t lookupSize = 120; }; struct ProgressivePhotonMapping : PhotonMappingBase { + constexpr static inline Type VariantType = Type::PPM; + int32_t photonCount = 250000; float initialRadius = 0.f; float alpha = 0.7f; int32_t maxPasses = -1; }; - struct StochasticProgressivePhotonMapping : ProgressivePhotonMapping + struct StochasticProgressivePhotonMapping final : ProgressivePhotonMapping { + constexpr static inline Type VariantType = Type::SPPM; }; struct MetropolisLightTransportBase : MonteCarloTracingBase { @@ -128,8 +143,10 @@ class CElementIntegrator final : public IElement int32_t luminanceSamples = 100000; bool twoStage = false; }; - struct PrimarySampleSpaceMetropolisLightTransport : MetropolisLightTransportBase + struct PrimarySampleSpaceMetropolisLightTransport final : MetropolisLightTransportBase { + constexpr static inline Type VariantType = Type::PSSMLT; + bool bidirectional = true; float pLarge = 0.3f; }; @@ -141,30 +158,40 @@ class CElementIntegrator final : public IElement bool manifoldPerturbation = false; float lambda = 50.f; }; - struct PathSpaceMetropolisLightTransport : MetropolisLightTransportBase, PerturbateableBase + struct PathSpaceMetropolisLightTransport final : MetropolisLightTransportBase, PerturbateableBase { + constexpr static inline Type VariantType = Type::MLT; + bool bidirectionalMutation = true; }; - struct EnergyRedistributionPathTracing : MonteCarloTracingBase, PerturbateableBase + struct EnergyRedistributionPathTracing final : MonteCarloTracingBase, PerturbateableBase { + constexpr static inline Type VariantType = Type::ERPT; + float numChains = 1.f; float maxChains = 0.f; int32_t chainLength = 1; int32_t directSamples = 16; }; - struct AdjointParticleTracing : MonteCarloTracingBase + struct AdjointParticleTracing final : MonteCarloTracingBase { + constexpr static inline Type VariantType = Type::ADJ_P_TRACER; + uint32_t granularity = 200000; bool bruteForce = false; }; - struct VirtualPointLights + struct VirtualPointLights final { + constexpr static inline Type VariantType = Type::VPL; + int32_t maxPathDepth = 5; int32_t shadowMap = 512; float clamping = 0.1f; }; struct FieldExtraction { + constexpr static inline Type VariantType = Type::FIELD_EXTRACT; + enum Type { INVALID, @@ -193,14 +220,18 @@ class CElementIntegrator final : public IElement size_t childCount = 0u; CElementIntegrator* children[maxChildCount] = { nullptr }; }; - struct AdaptiveIntegrator : MetaIntegrator + struct AdaptiveIntegrator final : MetaIntegrator { + constexpr static inline Type VariantType = Type::ADAPTIVE; + float maxError = 0.05f; float pValue = 0.05f; int32_t maxSampleFactor = 32; }; - struct IrradianceCacheIntegrator : MetaIntegrator + struct IrradianceCacheIntegrator final : MetaIntegrator { + constexpr static inline Type VariantType = Type::IRR_CACHE; + int32_t resolution = 14; float quality = 1.f; bool gradients = true; @@ -211,10 +242,32 @@ class CElementIntegrator final : public IElement bool indirectOnly = false; bool debug = false; }; - struct MultiChannelIntegrator : MetaIntegrator + struct MultiChannelIntegrator final : MetaIntegrator { + constexpr static inline Type VariantType = Type::MULTI_CHANNEL; }; + // + using variant_list_t = core::type_list< + AmbientOcclusion, + DirectIllumination, + SimpleVolumetricPathTracing, + ExtendedVolumetricPathTracing, + PathTracing, + BiDirectionalPathTracing, + PhotonMapping, + ProgressivePhotonMapping, + StochasticProgressivePhotonMapping, + PrimarySampleSpaceMetropolisLightTransport, + PathSpaceMetropolisLightTransport, + EnergyRedistributionPathTracing, + AdjointParticleTracing, + AdaptiveIntegrator, + VirtualPointLights, + IrradianceCacheIntegrator, + MultiChannelIntegrator, + FieldExtraction + >; // static AddPropertyMap compAddPropertyMap(); diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index b87e4d370c..c487ab3933 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -13,233 +13,166 @@ namespace nbl::ext::MitsubaLoader { -auto CElementFilm::compAddPropertyMap() -> AddPropertyMap +auto CElementIntegrator::compAddPropertyMap() -> AddPropertyMap { - using this_t = CElementFilm; - AddPropertyMap retval; + using this_t = CElementIntegrator; + AddPropertyMap retval; - return retval; -} - -bool CElementIntegrator::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) -{ - if (type>=Type::INVALID) - return false; - bool error = false; -#if 0 -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - visit([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ - } \ - }); \ - } - - auto processRayLength = SET_PROPERTY_TEMPLATE(rayLength,SNamedPropertyElement::Type::FLOAT,AmbientOcclusion); - auto processEmitterSamples = SET_PROPERTY_TEMPLATE(emitterSamples,SNamedPropertyElement::Type::INTEGER,DirectIllumination); - auto processBSDFSamples = SET_PROPERTY_TEMPLATE(bsdfSamples,SNamedPropertyElement::Type::INTEGER,DirectIllumination); - auto processShadingSamples = [&]() -> void - { - visit([&](auto& state) -> void { - using state_type = std::remove_reference::type; + // ambient + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shadingSamples,INTEGER,std::is_same,AmbientOcclusion); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(rayLength,FLOAT,std::is_same,AmbientOcclusion); - if constexpr (std::is_same::value) + // emitter hideables + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(hideEmitters,BOOLEAN,derived_from,DirectIllumination); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(hideEnvironment,BOOLEAN,derived_from,DirectIllumination); + + // this one has really funny legacy behaviour which Mitsuba allowed contrary to its PDF docs + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("shadingSamples",INTEGER,std::is_same,DirectIllumination) + { + _this->direct.emitterSamples = _this->direct.bsdfSamples = _property.ivalue; + return true; + } + ); + // direct + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(emitterSamples,INTEGER,std::is_same,DirectIllumination); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(bsdfSamples,INTEGER,std::is_same,DirectIllumination); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(strictNormals,BOOLEAN,std::is_same,DirectIllumination); + + // monte carlo base + // Not using `NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED` because members have different names than XML names + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("maxDepth",INTEGER,derived_from,MonteCarloTracingBase) + { + _this->path.maxPathDepth = _property.ivalue; + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("rrDepth",INTEGER,derived_from,MonteCarloTracingBase) + { + _this->path.russianRouletteDepth = _property.ivalue; + return true; + } + ); + + // path tracing + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(strictNormals,BOOLEAN,derived_from,PathTracing); + + // bidirectional path tracing + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lightImage,BOOLEAN,std::is_same,BiDirectionalPathTracing); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(sampleDirect,BOOLEAN,std::is_same,BiDirectionalPathTracing); + + // photon mapping base + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(granularity,INTEGER,derived_from,PhotonMappingBase); + + // photon mapping + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(directSamples,INTEGER,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(glossySamples,INTEGER,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(globalPhotons,INTEGER,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(causticPhotons,INTEGER,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(volumePhotons,INTEGER,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(globalLookupRadius,FLOAT,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(globalLookupRadius,FLOAT,std::is_same,PhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lookupSize,INTEGER,std::is_same,PhotonMapping); + + // progressive + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(photonCount,INTEGER,derived_from,ProgressivePhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(initialRadius,FLOAT,derived_from,ProgressivePhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(alpha,FLOAT,derived_from,ProgressivePhotonMapping); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxPasses,INTEGER,derived_from,ProgressivePhotonMapping); + + // metropolis base + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(directSamples,INTEGER,derived_from,MetropolisLightTransportBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(luminanceSamples,INTEGER,derived_from,MetropolisLightTransportBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(twoStage,BOOLEAN,derived_from,MetropolisLightTransportBase); + + // primary sample space + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(bidirectional,BOOLEAN,std::is_same,PrimarySampleSpaceMetropolisLightTransport); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(pLarge,FLOAT,std::is_same,PrimarySampleSpaceMetropolisLightTransport); + + // permutable base + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lensPerturbation,BOOLEAN,derived_from,PerturbateableBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(multiChainPerturbation,BOOLEAN,derived_from,PerturbateableBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(causticPerturbation,BOOLEAN,derived_from,PerturbateableBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(manifoldPerturbation,BOOLEAN,derived_from,PerturbateableBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lambda,FLOAT,derived_from,PerturbateableBase); + + // path space metropolis + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(bidirectionalMutation,BOOLEAN,std::is_same,PathSpaceMetropolisLightTransport); + + // energy redistribution + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(numChains,FLOAT,std::is_same,EnergyRedistributionPathTracing); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxChains,FLOAT,std::is_same,EnergyRedistributionPathTracing); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(chainLength,INTEGER,std::is_same,EnergyRedistributionPathTracing); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(directSamples,INTEGER,std::is_same,EnergyRedistributionPathTracing); + + // adjoint + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(granularity,INTEGER,std::is_same,AdjointParticleTracing); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(bruteForce,BOOLEAN,std::is_same,AdjointParticleTracing); + + // vpl + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxPathDepth,INTEGER,std::is_same,VirtualPointLights); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shadowMap,INTEGER,std::is_same,VirtualPointLights); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(clamping,FLOAT,std::is_same,VirtualPointLights); + + // field extraction + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("field",STRING,std::is_same,FieldExtraction) + { + static const core::unordered_map StringToType = { - if (_property.type!=SNamedPropertyElement::Type::INTEGER) - { - error = true; - return; - } - state.shadingSamples = _property.getProperty(); - } + {"position",FieldExtraction::Type::POSITION}, + {"relPosition",FieldExtraction::Type::RELATIVE_POSITION}, + {"distance",FieldExtraction::Type::DISTANCE}, + {"geoNormal",FieldExtraction::Type::GEOMETRIC_NORMAL}, + {"shNormal",FieldExtraction::Type::SHADING_NORMAL}, + {"uv",FieldExtraction::Type::UV_COORD}, + {"albedo",FieldExtraction::Type::ALBEDO}, + {"shapeIndex",FieldExtraction::Type::SHAPE_INDEX}, + {"primIndex",FieldExtraction::Type::PRIMITIVE_INDEX} + }; + auto found = StringToType.find(_property.svalue); + if (found!=StringToType.end()) + _this->field.field = found->second; else - { - if constexpr (std::is_same::value) - { - processEmitterSamples(); - processBSDFSamples(); - } - } - }); - }; - auto processStrictNormals = SET_PROPERTY_TEMPLATE(strictNormals,SNamedPropertyElement::Type::BOOLEAN,DirectIllumination,PathTracing); - auto processHideEmitters = SET_PROPERTY_TEMPLATE(hideEmitters,SNamedPropertyElement::Type::BOOLEAN,DirectIllumination,PathTracing,PhotonMapping); - auto processHideEnvironment = SET_PROPERTY_TEMPLATE(hideEnvironment,SNamedPropertyElement::Type::BOOLEAN,DirectIllumination,PathTracing,PhotonMapping); -#define ALL_PHOTONMAPPING_TYPES PhotonMapping,ProgressivePhotonMapping,StochasticProgressivePhotonMapping -#define ALL_MLT_TYPES PrimarySampleSpaceMetropolisLightTransport,PathSpaceMetropolisLightTransport -#define ALL_MC_TYPES PathTracing,SimpleVolumetricPathTracing,ExtendedVolumetricPathTracing,BiDirectionalPathTracing, \ - ALL_PHOTONMAPPING_TYPES,ALL_MLT_TYPES,EnergyRedistributionPathTracing,AdjointParticleTracing - auto processMaxDepth = SET_PROPERTY_TEMPLATE(maxPathDepth,SNamedPropertyElement::Type::INTEGER,ALL_MC_TYPES, VirtualPointLights); - auto processRRDepth = SET_PROPERTY_TEMPLATE(russianRouletteDepth,SNamedPropertyElement::Type::INTEGER,ALL_MC_TYPES); -#undef ALL_MC_TYPES - auto processLightImage = SET_PROPERTY_TEMPLATE(lightImage,SNamedPropertyElement::Type::BOOLEAN,BiDirectionalPathTracing); - auto processSampleDirect = SET_PROPERTY_TEMPLATE(sampleDirect,SNamedPropertyElement::Type::BOOLEAN,BiDirectionalPathTracing); - auto processGranularity = SET_PROPERTY_TEMPLATE(granularity,SNamedPropertyElement::Type::INTEGER,ALL_PHOTONMAPPING_TYPES,AdjointParticleTracing); -#undef ALL_PHOTONMAPPING_TYPES - auto processDirectSamples = SET_PROPERTY_TEMPLATE(directSamples,SNamedPropertyElement::Type::INTEGER,PhotonMapping,ALL_MLT_TYPES,EnergyRedistributionPathTracing); - auto processGlossySamples = SET_PROPERTY_TEMPLATE(glossySamples,SNamedPropertyElement::Type::INTEGER,PhotonMapping); - auto processGlobalPhotons = SET_PROPERTY_TEMPLATE(globalPhotons,SNamedPropertyElement::Type::INTEGER,PhotonMapping); - auto processCausticPhotons = SET_PROPERTY_TEMPLATE(causticPhotons,SNamedPropertyElement::Type::INTEGER,PhotonMapping); - auto processVolumePhotons = SET_PROPERTY_TEMPLATE(volumePhotons,SNamedPropertyElement::Type::INTEGER,PhotonMapping); - auto processGlobalLookupRadius = SET_PROPERTY_TEMPLATE(globalLURadius,SNamedPropertyElement::Type::FLOAT,PhotonMapping); - auto processCausticLookupRadius = SET_PROPERTY_TEMPLATE(causticLURadius,SNamedPropertyElement::Type::FLOAT,PhotonMapping); - auto processLookupSize = SET_PROPERTY_TEMPLATE(LUSize,SNamedPropertyElement::Type::INTEGER,PhotonMapping); - auto processPhotonCount = SET_PROPERTY_TEMPLATE(photonCount,SNamedPropertyElement::Type::INTEGER,ProgressivePhotonMapping,StochasticProgressivePhotonMapping); - auto processInitialRadius = SET_PROPERTY_TEMPLATE(initialRadius,SNamedPropertyElement::Type::FLOAT,ProgressivePhotonMapping,StochasticProgressivePhotonMapping); - auto processAlpha = SET_PROPERTY_TEMPLATE(alpha,SNamedPropertyElement::Type::FLOAT,ProgressivePhotonMapping,StochasticProgressivePhotonMapping); - auto processMaxPasses = SET_PROPERTY_TEMPLATE(maxPasses,SNamedPropertyElement::Type::INTEGER,ProgressivePhotonMapping,StochasticProgressivePhotonMapping); - auto processLuminanceSamples = SET_PROPERTY_TEMPLATE(luminanceSamples,SNamedPropertyElement::Type::INTEGER,ALL_MLT_TYPES); - auto processTwoStage = SET_PROPERTY_TEMPLATE(twoStage,SNamedPropertyElement::Type::BOOLEAN,ALL_MLT_TYPES); -#undef ALL_MLT_TYPES - auto processBidirectional = SET_PROPERTY_TEMPLATE(bidirectional,SNamedPropertyElement::Type::BOOLEAN,PrimarySampleSpaceMetropolisLightTransport); - auto processPLarge = SET_PROPERTY_TEMPLATE(pLarge,SNamedPropertyElement::Type::FLOAT,PrimarySampleSpaceMetropolisLightTransport); - auto processLensPerturbation = SET_PROPERTY_TEMPLATE(lensPerturbation,SNamedPropertyElement::Type::BOOLEAN,PathSpaceMetropolisLightTransport,EnergyRedistributionPathTracing); - auto processMultiChainPerturbation = SET_PROPERTY_TEMPLATE(multiChainPerturbation,SNamedPropertyElement::Type::BOOLEAN,PathSpaceMetropolisLightTransport,EnergyRedistributionPathTracing); - auto processCausticPerturbation = SET_PROPERTY_TEMPLATE(causticPerturbation,SNamedPropertyElement::Type::BOOLEAN,PathSpaceMetropolisLightTransport,EnergyRedistributionPathTracing); - auto processManifoldPerturbation = SET_PROPERTY_TEMPLATE(manifoldPerturbation,SNamedPropertyElement::Type::BOOLEAN,PathSpaceMetropolisLightTransport,EnergyRedistributionPathTracing); - auto processLambda = SET_PROPERTY_TEMPLATE(lambda,SNamedPropertyElement::Type::FLOAT,PathSpaceMetropolisLightTransport,EnergyRedistributionPathTracing); - auto processBidirectionalMutation = SET_PROPERTY_TEMPLATE(bidirectionalMutation,SNamedPropertyElement::Type::BOOLEAN,PathSpaceMetropolisLightTransport); - auto processNumChains = SET_PROPERTY_TEMPLATE(numChains,SNamedPropertyElement::Type::FLOAT,EnergyRedistributionPathTracing); - auto processMaxChains = SET_PROPERTY_TEMPLATE(maxChains,SNamedPropertyElement::Type::FLOAT,EnergyRedistributionPathTracing); - auto processChainLength = SET_PROPERTY_TEMPLATE(chainLength,SNamedPropertyElement::Type::INTEGER,EnergyRedistributionPathTracing); - auto processBruteForce = SET_PROPERTY_TEMPLATE(bruteForce,SNamedPropertyElement::Type::BOOLEAN,AdjointParticleTracing); - auto processShadowMap = SET_PROPERTY_TEMPLATE(shadowMap,SNamedPropertyElement::Type::INTEGER,VirtualPointLights); - auto processClamping = SET_PROPERTY_TEMPLATE(clamping,SNamedPropertyElement::Type::FLOAT,VirtualPointLights); - auto processField = [&]() -> void - { - visit([&](auto& state) -> void + _this->field.field = FieldExtraction::Type::INVALID; + return true; + } + ); + // TODO: redo + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("undefined",FLOAT,std::is_same,FieldExtraction) { - using state_type = std::remove_reference::type; - if constexpr (std::is_same::value) - { - if (_property.type != SNamedPropertyElement::Type::STRING) - { - error = true; - return; - } - static const core::unordered_map StringToType = - { - {"position",FieldExtraction::Type::POSITION}, - {"relPosition",FieldExtraction::Type::RELATIVE_POSITION}, - {"distance",FieldExtraction::Type::DISTANCE}, - {"geoNormal",FieldExtraction::Type::GEOMETRIC_NORMAL}, - {"shNormal",FieldExtraction::Type::SHADING_NORMAL}, - {"uv",FieldExtraction::Type::UV_COORD}, - {"albedo",FieldExtraction::Type::ALBEDO}, - {"shapeIndex",FieldExtraction::Type::SHAPE_INDEX}, - {"primIndex",FieldExtraction::Type::PRIMITIVE_INDEX} - }; - auto found = StringToType.find(_property.svalue); - if (found!=StringToType.end()) - state.field = found->second; - else - state.field = FieldExtraction::Type::INVALID; - } - }); - }; - auto processUndefined = [&]() -> void - { - visit([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - if (_property.type != SNamedPropertyElement::Type::FLOAT && _property.type != SNamedPropertyElement::Type::SPECTRUM) - { - error = true; - return; - } - state.undefined = _property; // TODO: redo - } - }); - }; - auto processMaxError = SET_PROPERTY_TEMPLATE(maxError,SNamedPropertyElement::Type::FLOAT,AdaptiveIntegrator); - auto processPValue = SET_PROPERTY_TEMPLATE(pValue,SNamedPropertyElement::Type::FLOAT,AdaptiveIntegrator); - auto processMaxSampleFactor = SET_PROPERTY_TEMPLATE(maxSampleFactor,SNamedPropertyElement::Type::INTEGER,AdaptiveIntegrator); - auto processResolution = SET_PROPERTY_TEMPLATE(resolution,SNamedPropertyElement::Type::INTEGER,IrradianceCacheIntegrator); - auto processQuality = SET_PROPERTY_TEMPLATE(quality,SNamedPropertyElement::Type::FLOAT,IrradianceCacheIntegrator); - auto processGradients = SET_PROPERTY_TEMPLATE(gradients,SNamedPropertyElement::Type::BOOLEAN,IrradianceCacheIntegrator); - auto processClampNeighbour = SET_PROPERTY_TEMPLATE(clampNeighbour,SNamedPropertyElement::Type::BOOLEAN,IrradianceCacheIntegrator); - auto processClampScreen = SET_PROPERTY_TEMPLATE(clampScreen,SNamedPropertyElement::Type::BOOLEAN,IrradianceCacheIntegrator); - auto processOverture = SET_PROPERTY_TEMPLATE(overture,SNamedPropertyElement::Type::BOOLEAN,IrradianceCacheIntegrator); - auto processQualityAdjustment = SET_PROPERTY_TEMPLATE(qualityAdjustment,SNamedPropertyElement::Type::FLOAT,IrradianceCacheIntegrator); - auto processIndirecOnly = SET_PROPERTY_TEMPLATE(indirectOnly,SNamedPropertyElement::Type::BOOLEAN,IrradianceCacheIntegrator); - auto processDebug = SET_PROPERTY_TEMPLATE(debug,SNamedPropertyElement::Type::BOOLEAN,IrradianceCacheIntegrator); + _this->field.undefined = _property; // TODO: redo + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("undefined",SPECTRUM,std::is_same,FieldExtraction) + { + _this->field.undefined = _property; // TODO: redo + return true; + } + ); + + // Now for the compound/nested integrators + // meta integrator has no members settable via properties + + // adaptive integrator + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxError,FLOAT,std::is_same,AdaptiveIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(pValue,FLOAT,std::is_same,AdaptiveIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxSampleFactor,INTEGER,std::is_same,AdaptiveIntegrator); + + // irradiance cache + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(resolution,INTEGER,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(quality,FLOAT,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(gradients,BOOLEAN,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(clampNeighbour,BOOLEAN,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(clampScreen,BOOLEAN,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(overture,BOOLEAN,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(qualityAdjustment,FLOAT,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(indirectOnly,BOOLEAN,std::is_same,IrradianceCacheIntegrator); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(debug,BOOLEAN,std::is_same,IrradianceCacheIntegrator); + + // multi channel no extra members - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - {"shadingSamples",processShadingSamples}, - {"rayLength",processRayLength}, - {"emitterSamples",processEmitterSamples}, - {"bsdfSamples",processBSDFSamples}, - {"strictNormals",processStrictNormals}, - {"hideEmitters",processHideEmitters}, - {"hideEnvironment",processHideEnvironment}, - {"maxDepth",processMaxDepth}, - {"rrDepth",processRRDepth}, - {"lightImage",processLightImage}, - {"sampleDirect",processSampleDirect}, - {"granularity",processGranularity}, - {"directSamples",processDirectSamples}, - {"glossySamples",processGlossySamples}, - {"globalPhotons",processGlobalPhotons}, - {"causticPhotons",processCausticPhotons}, - {"volumePhotons",processVolumePhotons}, - {"globalLookupRadius",processGlobalLookupRadius}, - {"causticLookupRadius",processCausticLookupRadius}, - {"lookupSize",processLookupSize}, - {"photonCount",processPhotonCount}, - {"initialRadius",processInitialRadius}, - {"alpha",processAlpha}, - {"maxPasses",processMaxPasses}, - {"luminanceSamples",processLuminanceSamples}, - {"twoStage",processTwoStage}, - {"bidirectional",processBidirectional}, - {"pLarge",processPLarge}, - {"lensPerturbation",processLensPerturbation}, - {"multiChainPerturbation",processMultiChainPerturbation}, - {"causticPerturbation",processCausticPerturbation}, - {"manifoldPerturbation",processManifoldPerturbation}, - {"lambda",processLambda}, - {"bidirectionalMutation",processBidirectionalMutation}, - {"numChains",processNumChains}, - {"maxChains",processMaxChains}, - {"chainLength",processChainLength}, - {"bruteForce",processBruteForce}, - {"shadowMap",processShadowMap}, - {"clamping",processClamping}, - {"field",processField}, - {"undefined",processUndefined}, - {"maxError",processMaxError}, - {"pValue",processPValue}, - {"maxSampleFactor",processMaxSampleFactor}, - {"resolution",processResolution}, - {"quality",processQuality}, - {"gradients",processGradients}, - {"clampNeighbour",processClampNeighbour}, - {"clampScreen",processClampScreen}, - {"overture",processOverture}, - {"qualityAdjustment",processQualityAdjustment}, - {"indirectOnly",processIndirecOnly}, - {"debug",processDebug}, - }; - - auto found = SetPropertyMap.find(_property.name); - if (found==SetPropertyMap.end()) - { - invalidXMLFileStructure(logger,"No Integrator can have such property set with name: "+_property.name); - return false; - } - - found->second(); -#endif - return !error; + return retval; } bool CElementIntegrator::onEndTag(CMitsubaMetadata* metadata, system::logger_opt_ptr logger) From 8cc46625853959fa653d4ed35a022534e0c54932 Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 22 Dec 2025 00:09:14 +0100 Subject: [PATCH 18/30] refactor CElementEmissionProfile and CElementRFilter, also spot we need as many structs as we have Types for VariantType filtering --- .../MitsubaLoader/CElementEmissionProfile.h | 3 +- include/nbl/ext/MitsubaLoader/CElementFilm.h | 13 +++- .../nbl/ext/MitsubaLoader/CElementRFilter.h | 16 ++++- .../MitsubaLoader/CElementEmissionProfile.cpp | 69 +++++++------------ src/nbl/ext/MitsubaLoader/CElementRFilter.cpp | 59 +++++----------- 5 files changed, 70 insertions(+), 90 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index 331abf2873..86368a5499 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -61,7 +61,8 @@ struct CElementEmissionProfile final : public IElement std::string filename; // TODO: test destructor runs E_NORMALIZE normalization; - float flatten; // TODO: why is this named this way? + // how much we flatten the profile towards a uniform distribution + float flatten; }; } diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index 267cd57938..8cdd607d79 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -57,6 +57,12 @@ class CElementFilm final : public IElement bool attachLog = true; }; + struct TiledHDR : HDR + { + constexpr static inline Type VariantType = Type::TILED_HDR; + + // TODO: sure we don't have more members? + }; struct LDR { constexpr static inline Type VariantType = Type::LDR_FILM; @@ -92,6 +98,7 @@ class CElementFilm final : public IElement // using variant_list_t = core::type_list< HDR, + TiledHDR, LDR, M >; @@ -195,9 +202,9 @@ class CElementFilm final : public IElement CElementRFilter rfilter; union { - HDR hdrfilm; - LDR ldrfilm; - M mfilm; + HDR hdrfilm; + LDR ldrfilm; + M mfilm; }; constexpr static inline size_t MaxPathLen = 256; diff --git a/include/nbl/ext/MitsubaLoader/CElementRFilter.h b/include/nbl/ext/MitsubaLoader/CElementRFilter.h index b3673c9e35..a84fbbbfec 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.h @@ -29,21 +29,35 @@ class CElementRFilter final : public IElement struct Gaussian { + constexpr static inline Type VariantType = Type::GAUSSIAN; + float sigma = NAN; // can't look at mitsuba source to figure out the default it uses }; struct MitchellNetravali { + constexpr static inline Type VariantType = Type::MITCHELL; + + float B = 1.f / 3.f; + float C = 1.f / 3.f; + }; + struct CatmullRom + { + constexpr static inline Type VariantType = Type::CATMULLROM; + float B = 1.f / 3.f; float C = 1.f / 3.f; }; struct LanczosSinc { + constexpr static inline Type VariantType = Type::LANCZOS; + int32_t lobes = 3; }; using variant_list_t = core::type_list< Gaussian, MitchellNetravali, + CatmullRom, LanczosSinc >; static inline core::unordered_map compStringToTypeMap() @@ -112,7 +126,7 @@ class CElementRFilter final : public IElement { Gaussian gaussian; MitchellNetravali mitchell; - MitchellNetravali catmullrom; + CatmullRom catmullrom; LanczosSinc lanczos; }; float kappa = 0.f; diff --git a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp index 0f360ccba0..4fbe7b3f4d 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp @@ -4,61 +4,40 @@ #include "nbl/ext/MitsubaLoader/CElementEmissionProfile.h" #include "nbl/ext/MitsubaLoader/ParserUtil.h" +#include "nbl/ext/MitsubaLoader/ElementMacros.h" + #include namespace nbl::ext::MitsubaLoader { -bool CElementEmissionProfile::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) +auto CElementEmissionProfile::compAddPropertyMap() -> AddPropertyMap { - 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) + using this_t = CElementEmissionProfile; + AddPropertyMap retval; + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(filename,STRING); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("normalization",STRING) { - invalidXMLFileStructure(logger,"'s `normalization` must be a string type, instead it's: "+_property.type); - return false; + const auto normalizeS = std::string(_property.svalue); + if (normalizeS == "UNIT_MAX") + _this->normalization = EN_UNIT_MAX; + else if (normalizeS == "UNIT_AVERAGE_OVER_IMPLIED_DOMAIN") + _this->normalization = EN_UNIT_AVERAGE_OVER_IMPLIED_DOMAIN; + else if (normalizeS == "UNIT_AVERAGE_OVER_FULL_DOMAIN") + _this->normalization = EN_UNIT_AVERAGE_OVER_FULL_DOMAIN; + else + { + logger.log("'s `normalization` is unrecognized: \"%s\"",system::ILogger::ELL_ERROR,normalizeS.c_str()); + _this->normalization = EN_NONE; + } + return true; } + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(flatten,FLOAT); - const auto normalizeS = std::string(_property.getProperty()); - - if (normalizeS=="UNIT_MAX") - normalization = EN_UNIT_MAX; - else if(normalizeS=="UNIT_AVERAGE_OVER_IMPLIED_DOMAIN") - normalization = EN_UNIT_AVERAGE_OVER_IMPLIED_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") - { - if (_property.type!=SPropertyElementData::Type::FLOAT) - return false; - - flatten = _property.getProperty(); - return true; - } - else - { - invalidXMLFileStructure(logger,"No emission profile can have such property set with name: "+_property.name); - return false; - } + return retval; } bool CElementEmissionProfile::processChildData(IElement* _child, const std::string& name) diff --git a/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp b/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp index de5bdf2255..ef7ebce9f8 100644 --- a/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp @@ -11,48 +11,27 @@ namespace nbl::ext::MitsubaLoader { - -bool CElementRFilter::addProperty(SNamedPropertyElement&& _property, system::logger_opt_ptr logger) + +auto CElementRFilter::compAddPropertyMap() -> AddPropertyMap { - if (_property.type == SNamedPropertyElement::Type::INTEGER) - { - if (core::strcmpi(_property.name,std::string("lobes"))) - { - invalidXMLFileStructure(logger,"\"lobes\" must be an integer property"); - return false; - } - lanczos.lobes = _property.ivalue; - return true; - } - else if (_property.type == SNamedPropertyElement::Type::FLOAT) - { - if (core::strcmpi(_property.name,std::string("b"))==0) - { - mitchell.B = _property.fvalue; - return true; - } - else if (core::strcmpi(_property.name,std::string("c"))==0) - { - mitchell.C = _property.fvalue; - return true; - } - else if (core::strcmpi(_property.name,std::string("kappa"))==0) - { - kappa = _property.fvalue; - return true; - } - else if (core::strcmpi(_property.name,std::string("Emin"))==0) - { - Emin = _property.fvalue; - return true; - } - else - invalidXMLFileStructure(logger,"unsupported rfilter property called: "+_property.name); - } - else - invalidXMLFileStructure(logger,"this reconstruction filter type does not take this parameter type for parameter: " + _property.name); + using this_t = CElementRFilter; + AddPropertyMap retval; + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(sigma,FLOAT,std::is_same,Gaussian); + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(b,FLOAT,std::is_same,MitchellNetravali); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(c,FLOAT,std::is_same,MitchellNetravali); + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(b,FLOAT,std::is_same,CatmullRom); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(c,FLOAT,std::is_same,CatmullRom); + + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lobes,INTEGER,std::is_same,LanczosSinc); + + // common + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(kappa,FLOAT); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(Emin,FLOAT); - return false; + return retval; } bool CElementRFilter::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) From 3d8358ad44e939979b81ae2aed032d43c42c3ad8 Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 22 Dec 2025 00:44:01 +0100 Subject: [PATCH 19/30] didn't notice that can't register two callbacks for same property name and type --- .../nbl/ext/MitsubaLoader/PropertyElement.h | 3 +- .../ext/MitsubaLoader/CElementIntegrator.cpp | 64 ++++++++++++++----- src/nbl/ext/MitsubaLoader/CElementRFilter.cpp | 7 +- src/nbl/ext/MitsubaLoader/ElementMacros.h | 6 +- 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/PropertyElement.h b/include/nbl/ext/MitsubaLoader/PropertyElement.h index 320e12712e..0d8450ff62 100644 --- a/include/nbl/ext/MitsubaLoader/PropertyElement.h +++ b/include/nbl/ext/MitsubaLoader/PropertyElement.h @@ -15,8 +15,7 @@ namespace nbl::ext::MitsubaLoader 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); + logger.log("Mitsuba loader error - Invalid .xml file structure: \'%s\'",system::ILogger::E_LOG_LEVEL::ELL_ERROR,errorMessage.c_str()); _NBL_DEBUG_BREAK_IF(true); } diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index c487ab3933..fa7e89759d 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -13,30 +13,60 @@ namespace nbl::ext::MitsubaLoader { +namespace impl +{ +template +struct has_strictNormals +{ + constexpr static bool value = std::is_same_v || + std::is_base_of_v; +}; +template +struct has_granularity +{ + constexpr static bool value = std::is_base_of_v || + std::is_same_v; +}; +template +struct has_directSamples +{ + constexpr static bool value = std::is_same_v || + std::is_base_of_v || + std::is_same_v; +}; +} + auto CElementIntegrator::compAddPropertyMap() -> AddPropertyMap { using this_t = CElementIntegrator; AddPropertyMap retval; + // common + // this one has really funny legacy behaviour which Mitsuba allowed contrary to its PDF docs + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("shadingSamples",INTEGER,is_any_of,AmbientOcclusion,DirectIllumination) + { + if (_this->type == Type::AO) + _this->ao.shadingSamples = _property.ivalue; + else + _this->direct.emitterSamples = _this->direct.bsdfSamples = _property.ivalue; + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(strictNormals,BOOLEAN,impl::has_strictNormals); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(granularity,INTEGER,impl::has_granularity); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(directSamples,INTEGER,impl::has_directSamples); + // ambient - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shadingSamples,INTEGER,std::is_same,AmbientOcclusion); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(rayLength,FLOAT,std::is_same,AmbientOcclusion); // emitter hideables NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(hideEmitters,BOOLEAN,derived_from,DirectIllumination); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(hideEnvironment,BOOLEAN,derived_from,DirectIllumination); - - // this one has really funny legacy behaviour which Mitsuba allowed contrary to its PDF docs - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("shadingSamples",INTEGER,std::is_same,DirectIllumination) - { - _this->direct.emitterSamples = _this->direct.bsdfSamples = _property.ivalue; - return true; - } - ); + // direct NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(emitterSamples,INTEGER,std::is_same,DirectIllumination); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(bsdfSamples,INTEGER,std::is_same,DirectIllumination); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(strictNormals,BOOLEAN,std::is_same,DirectIllumination); + // COMMON: strictNormals // monte carlo base // Not using `NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED` because members have different names than XML names @@ -54,23 +84,23 @@ auto CElementIntegrator::compAddPropertyMap() -> AddPropertyMap AddPropertyMap AddPropertyMap AddPropertyMap NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(sigma,FLOAT,std::is_same,Gaussian); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(b,FLOAT,std::is_same,MitchellNetravali); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(c,FLOAT,std::is_same,MitchellNetravali); - - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(b,FLOAT,std::is_same,CatmullRom); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(c,FLOAT,std::is_same,CatmullRom); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(b,FLOAT,is_any_of,MitchellNetravali,CatmullRom); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(c,FLOAT,is_any_of,MitchellNetravali,CatmullRom); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lobes,INTEGER,std::is_same,LanczosSinc); diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index b214882ff1..eea6e97004 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -18,14 +18,14 @@ // Similar to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` but for `this_t` which declare `variant_list_t` (list of union types) // this adds a compile-time filter against the constraint, such that only variant types matching the constraint are visited. // Useful when multiple variants derive from the same base struct, or have the same member. -#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) retval.template registerCallback( \ +#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 // This it to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED` what `NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY` is to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` // So basically you know the member is the same across the constraint filtered types -#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__) {\ +#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_OPT__(,) __VA_ARGS__) {\ _this->visit([&_property](auto& state)->void{ \ - if constexpr (CONSTRAINT,__VA_ARGS__>::value) \ + if constexpr (CONSTRAINT __VA_OPT__(,) __VA_ARGS__>::value) \ state. ## NAME = _property.getProperty(); \ }); return true;}) From 7c0325544ea4f417b32e5ade092a7de3ab9ac659 Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 22 Dec 2025 12:26:07 +0100 Subject: [PATCH 20/30] fix transform handling and realize unit test cases can be wrong too --- examples_tests | 2 +- include/nbl/ext/MitsubaLoader/CElementTransform.h | 4 ++-- include/nbl/ext/MitsubaLoader/ParserUtil.h | 1 + src/nbl/ext/MitsubaLoader/CElementTransform.cpp | 2 +- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 8 +++++--- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/examples_tests b/examples_tests index bfcff8a686..d20b9c67bf 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit bfcff8a686409dd7c0d55607bb8cb6bcc0e0b80a +Subproject commit d20b9c67bf5ef5c4d782a13709a78ce59b24e1e4 diff --git a/include/nbl/ext/MitsubaLoader/CElementTransform.h b/include/nbl/ext/MitsubaLoader/CElementTransform.h index 45612174ad..de7bcd51e7 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTransform.h +++ b/include/nbl/ext/MitsubaLoader/CElementTransform.h @@ -16,7 +16,7 @@ class CElementTransform final : public IElement public: static AddPropertyMap compAddPropertyMap(); - inline CElementTransform() : IElement(""), matrix() {} + inline CElementTransform() : IElement(""), matrix(1.f) {} inline ~CElementTransform() {} inline bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override {return true;} @@ -33,7 +33,7 @@ class CElementTransform final : public IElement } */ - hlsl::float32_t4x4 matrix; + hlsl::float32_t4x4 matrix; // TODO: HLSL diagonal(1.f) }; } diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 5c2b3efbef..1d6bd55715 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -87,6 +87,7 @@ class ParserManager final CElementRFilter, CElementSampler, /// CElementShape, + CElementTransform, /// CElementBSDF, /// CElementTexture, /// CElementEmitter, diff --git a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp index cb583c211c..3097022a1a 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTransform.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTransform.cpp @@ -15,7 +15,7 @@ auto CElementTransform::compAddPropertyMap() -> AddPropertyMapbool { - _this->matrix = _property.mvalue; + _this->matrix = mul(_property.mvalue,_this->matrix); return true; }; for (const auto& type : { diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 0fe612e2ec..ab3d82901f 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -225,7 +225,7 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts nameIt = typeMap.find(""); if (nameIt==typeMap.end()) { - session->invalidXMLFileStructure("There's no Property named (TODO) of Type (TODO) supported by ElementType (TODO)"); + session->invalidXMLFileStructure("There's no Property named \""+property.name+"\" of Type (TODO) supported by ElementType (TODO)"); return; } const auto& callback = nameIt->second; @@ -233,7 +233,7 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts 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)"); + session->invalidXMLFileStructure("There's no Property named \""+property.name+"\" of Type(TODO) not supported on ElementType(TODO) of Variant(TODO)"); return; } callback(typedElement,std::move(property),session->params->logger); @@ -246,7 +246,8 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts ); if (unsupportedElement) { - session->invalidXMLFileStructure("Current Element Type doesn't have a AddPropertyMap at all (no property adding supported)!"); + const core::string typeName; // TODO = system::to_string(element->getType()); + session->invalidXMLFileStructure("Current Element Type "+typeName+" doesn't have a AddPropertyMap at all (no property adding supported)!"); return; } return; @@ -431,6 +432,7 @@ ParserManager::ParserManager() : propertyElements({ CElementFilm::compAddPropertyMap(), CElementRFilter::compAddPropertyMap(), CElementSampler::compAddPropertyMap(), + CElementTransform::compAddPropertyMap(), CElementEmissionProfile::compAddPropertyMap() }) { } From 70eb689601a6c4a57f4a68ec3354670ef795ac16 Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 22 Dec 2025 14:14:41 +0100 Subject: [PATCH 21/30] can't believe I spent an hour on this --- include/nbl/ext/MitsubaLoader/CElementRFilter.h | 8 ++++---- src/nbl/ext/MitsubaLoader/CElementRFilter.cpp | 4 ++-- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementRFilter.h b/include/nbl/ext/MitsubaLoader/CElementRFilter.h index a84fbbbfec..4d4be06424 100644 --- a/include/nbl/ext/MitsubaLoader/CElementRFilter.h +++ b/include/nbl/ext/MitsubaLoader/CElementRFilter.h @@ -89,16 +89,16 @@ class CElementRFilter final : public IElement case Type::TENT: break; case Type::GAUSSIAN: - visit(gaussian); + visitor(gaussian); break; case Type::MITCHELL: - visit(mitchell); + visitor(mitchell); break; case Type::CATMULLROM: - visit(catmullrom); + visitor(catmullrom); break; case Type::LANCZOS: - visit(lanczos); + visitor(lanczos); break; default: break; diff --git a/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp b/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp index a4586c8309..9bd4b864df 100644 --- a/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementRFilter.cpp @@ -19,8 +19,8 @@ auto CElementRFilter::compAddPropertyMap() -> AddPropertyMap NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(sigma,FLOAT,std::is_same,Gaussian); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(b,FLOAT,is_any_of,MitchellNetravali,CatmullRom); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(c,FLOAT,is_any_of,MitchellNetravali,CatmullRom); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(B,FLOAT,is_any_of,MitchellNetravali,CatmullRom); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(C,FLOAT,is_any_of,MitchellNetravali,CatmullRom); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(lobes,INTEGER,std::is_same,LanczosSinc); diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index ab3d82901f..9646fca073 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -231,7 +231,7 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts 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()) + if (!callback.allowedVariantTypes.empty() && std::find(callback.allowedVariantTypes.begin(),callback.allowedVariantTypes.end(),typedElement->type)==callback.allowedVariantTypes.end()) { session->invalidXMLFileStructure("There's no Property named \""+property.name+"\" of Type(TODO) not supported on ElementType(TODO) of Variant(TODO)"); return; From 0e38e803546699c40eafd744e3bc49345ad7ad3f Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 22 Dec 2025 17:02:11 +0100 Subject: [PATCH 22/30] fix lookat matrices --- src/nbl/ext/MitsubaLoader/PropertyElement.cpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/nbl/ext/MitsubaLoader/PropertyElement.cpp b/src/nbl/ext/MitsubaLoader/PropertyElement.cpp index d6144b6919..1beff22eb7 100644 --- a/src/nbl/ext/MitsubaLoader/PropertyElement.cpp +++ b/src/nbl/ext/MitsubaLoader/PropertyElement.cpp @@ -202,19 +202,20 @@ std::optional CPropertyElementManager::createPropertyData invalidXMLFileStructure(logger,"Invalid element, name:\'"+result.name+"\' Axis can't be (0,0,0)"); return {}; } + // TODO: quaternion after the rework 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.mvalue = hlsl::float32_t4x4(1.f); - if (desiredAttributes[0]) + if (desiredAttributes[0]) // you either get this one attribute { const float uniformScale = atof(desiredAttributes[0]); for (auto i=0u; i<3u; i++) result.mvalue[i][i] = uniformScale; } - else + else // or x,y,z { for (auto i=0u; i<3u; i++) if (desiredAttributes[i+1u]) @@ -255,9 +256,16 @@ std::optional CPropertyElementManager::createPropertyData } up[index] = 1.f; } + // TODO: after the rm-core matrix PR we need to get rid of the tranpose (I transpose only because of GLM and HLSL mixup) + const auto lookAtGLM = reinterpret_cast(glm::lookAtLH(origin,target,up)); + const auto lookAt = hlsl::transpose(lookAtGLM); // mitsuba understands look-at and right-handed camera little bit differently than I do - const auto actualLookAt = reinterpret_cast(glm::lookAtLH(origin,target,up)); - result.mvalue = hlsl::inverse(actualLookAt); + const auto rotation = hlsl::inverse(hlsl::float32_t3x3(lookAt)); + // set the origin to avoid numerical issues + for (auto r=0; r<3; r++) + { + result.mvalue[r][3] = origin[r]; + } } break; default: @@ -291,8 +299,8 @@ hlsl::float32_t4x4 CPropertyElementManager::retrieveMatrix(const std::string_vie std::stringstream ss; ss << str; - for (auto r=0u; r<16u; r++) - for (auto c=0u; c<16u; c++) + for (auto r=0u; r<4u; r++) + for (auto c=0u; c<4u; c++) { float f = std::numeric_limits::quiet_NaN(); ss >> f; From 1a17718cb4656d04a16d59d2e7bf1fa75ca2b2d5 Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 22 Dec 2025 19:40:12 +0100 Subject: [PATCH 23/30] MAke CElementShape parse, also add logger to processChildData --- include/nbl/ext/MitsubaLoader/CElementBSDF.h | 2 +- .../MitsubaLoader/CElementEmissionProfile.h | 2 +- .../nbl/ext/MitsubaLoader/CElementEmitter.h | 2 +- include/nbl/ext/MitsubaLoader/CElementFilm.h | 8 +- .../ext/MitsubaLoader/CElementIntegrator.h | 12 +- .../nbl/ext/MitsubaLoader/CElementSensor.h | 10 +- include/nbl/ext/MitsubaLoader/CElementShape.h | 196 +++++++------- .../nbl/ext/MitsubaLoader/CElementTexture.h | 2 +- include/nbl/ext/MitsubaLoader/IElement.h | 21 +- include/nbl/ext/MitsubaLoader/ParserUtil.h | 2 +- .../MitsubaLoader/CElementEmissionProfile.cpp | 2 +- src/nbl/ext/MitsubaLoader/CElementFilm.cpp | 23 +- src/nbl/ext/MitsubaLoader/CElementShape.cpp | 253 ++++-------------- src/nbl/ext/MitsubaLoader/CMakeLists.txt | 2 +- src/nbl/ext/MitsubaLoader/ElementMacros.h | 108 -------- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 7 +- 16 files changed, 215 insertions(+), 437 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index 7f5e73c13f..0873c6e41d 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -379,7 +379,7 @@ class CElementBSDF : public IElement 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 processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override; inline bool isMeta() const { diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index 86368a5499..ecf24c9f63 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -44,7 +44,7 @@ struct CElementEmissionProfile final : public IElement inline bool onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) override {return true;} - bool processChildData(IElement* _child, const std::string& name) override; + bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override; constexpr static inline auto ElementType = IElement::Type::EMISSION_PROFILE; inline IElement::Type getType() const override { return ElementType; } diff --git a/include/nbl/ext/MitsubaLoader/CElementEmitter.h b/include/nbl/ext/MitsubaLoader/CElementEmitter.h index 5de6861d7f..04833986d1 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmitter.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmitter.h @@ -209,7 +209,7 @@ class CElementEmitter : public IElement inline IElement::Type getType() const override { return ElementType; } std::string getLogName() const override { return "emitter"; } - bool processChildData(IElement* _child, const std::string& name) override + bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override { if (!_child) return true; diff --git a/include/nbl/ext/MitsubaLoader/CElementFilm.h b/include/nbl/ext/MitsubaLoader/CElementFilm.h index 8cdd607d79..3da02a21b8 100644 --- a/include/nbl/ext/MitsubaLoader/CElementFilm.h +++ b/include/nbl/ext/MitsubaLoader/CElementFilm.h @@ -177,15 +177,21 @@ class CElementFilm final : public IElement 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 + inline bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override { if (!_child) return true; if (_child->getType() != IElement::Type::RFILTER) + { + logger.log("CElementFilm only expects type %d children, is %d instead",system::ILogger::ELL_ERROR,IElement::Type::RFILTER,_child->getType()); return false; + } auto _rfilter = static_cast(_child); if (_rfilter->type == CElementRFilter::Type::INVALID) + { + logger.log("CElementRFilter::Type::INVALID used as child in CElementFilm",system::ILogger::ELL_ERROR); return false; + } rfilter = *_rfilter; return true; } diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index 760f87fe5b..b3061ba380 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -366,7 +366,7 @@ class CElementIntegrator final : public IElement inline IElement::Type getType() const override { return ElementType; } inline std::string getLogName() const override { return "integrator"; } - inline bool processChildData(IElement* _child, const std::string& name) override + inline bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override { if (!_child) return true; @@ -377,10 +377,11 @@ class CElementIntegrator final : public IElement [[fallthrough]]; case Type::MULTI_CHANNEL: if (_child->getType() != IElement::Type::INTEGRATOR) - return false; - break; + break; + [[fallthrough]]; default: - break; + logger.log("Only IrradianceCache or MultiChannel can only have another nested inside", system::ILogger::ELL_ERROR); + return false; } switch (type) { @@ -396,7 +397,8 @@ class CElementIntegrator final : public IElement return true; } break; - default: + default: // to make compiler shut up + assert(false); break; } return false; diff --git a/include/nbl/ext/MitsubaLoader/CElementSensor.h b/include/nbl/ext/MitsubaLoader/CElementSensor.h index 4ef41e42d5..fecd248ad0 100644 --- a/include/nbl/ext/MitsubaLoader/CElementSensor.h +++ b/include/nbl/ext/MitsubaLoader/CElementSensor.h @@ -207,7 +207,7 @@ class CElementSensor final : public IElement inline IElement::Type getType() const override { return ElementType; } inline std::string getLogName() const override { return "sensor"; } - inline bool processChildData(IElement* _child, const std::string& name) override + inline bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override { if (!_child) return true; @@ -216,8 +216,11 @@ class CElementSensor final : public IElement case IElement::Type::TRANSFORM: { auto tform = static_cast(_child); - if (name!="toWorld") + if (name != "toWorld") + { + logger.log("The nested inside needs to be named \"toWorld\"",system::ILogger::ELL_ERROR); return false; + } //toWorldType = IElement::Type::TRANSFORM; transform = *tform; return true; @@ -241,7 +244,10 @@ class CElementSensor final : public IElement if (sampler.type!=CElementSampler::Type::INVALID) return true; break; + default: + break; } + logger.log("Only valid nested children inside are: VALID , , and . The is not supported yet.",system::ILogger::ELL_ERROR); return false; } diff --git a/include/nbl/ext/MitsubaLoader/CElementShape.h b/include/nbl/ext/MitsubaLoader/CElementShape.h index 23018079a1..1ce78a399b 100644 --- a/include/nbl/ext/MitsubaLoader/CElementShape.h +++ b/include/nbl/ext/MitsubaLoader/CElementShape.h @@ -18,7 +18,7 @@ namespace nbl::ext::MitsubaLoader class CElementShape final : public IElement { public: - enum Type + enum Type : uint8_t { INVALID, CUBE, @@ -34,51 +34,88 @@ class CElementShape final : public IElement //HAIR, //HEIGHTFIELD }; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"cube", CElementShape::Type::CUBE}, + {"sphere", CElementShape::Type::SPHERE}, + {"cylinder", CElementShape::Type::CYLINDER}, + {"rectangle", CElementShape::Type::RECTANGLE}, + {"disk", CElementShape::Type::DISK}, + {"obj", CElementShape::Type::OBJ}, + {"ply", CElementShape::Type::PLY}, + {"serialized", CElementShape::Type::SERIALIZED}, + {"shapegroup", CElementShape::Type::SHAPEGROUP}, + {"instance", CElementShape::Type::INSTANCE}/*, + {"hair", CElementShape::Type::HAIR}, + {"heightfield", CElementShape::Type::HEIGHTFIELD}*/ + }; + } + struct Base { bool flipNormals = false; }; + struct Cube : Base + { + constexpr static inline Type VariantType = Type::CUBE; + }; struct Sphere : Base { - core::vectorSIMDf center = core::vectorSIMDf(0,0,0); + constexpr static inline Type VariantType = Type::SPHERE; + + hlsl::float32_t3 center = {0,0,0}; float radius = 1.f; }; struct Cylinder : Base { - core::vectorSIMDf p0 = core::vectorSIMDf(0,0,0); - core::vectorSIMDf p1 = core::vectorSIMDf(0,0,1); + constexpr static inline Type VariantType = Type::CYLINDER; + + hlsl::float32_t3 p0 = {0,0,0}; + hlsl::float32_t3 p1 = {0,0,1}; float radius = 1.f; }; struct LoadedFromFileBase : Base { - SPropertyElementData filename; + constexpr static inline uint16_t MaxPathLen = 1024u; + + char filename[MaxPathLen]; //! Use face normals (any per-vertex normals will be discarded) - bool faceNormals = false; - float maxSmoothAngle = NAN; + bool faceNormals = false; + float maxSmoothAngle = NAN; }; struct Obj : LoadedFromFileBase { + constexpr static inline Type VariantType = Type::OBJ; + bool flipTexCoords = true; bool collapse = false; }; struct Ply : LoadedFromFileBase { - bool flipNormals = false; + constexpr static inline Type VariantType = Type::PLY; + bool srgb = true; }; struct Serialized : LoadedFromFileBase { + constexpr static inline Type VariantType = Type::SERIALIZED; + int32_t shapeIndex; - bool flipNormals; }; + // geometries basically struct ShapeGroup { - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxChildCount = 128u; + constexpr static inline Type VariantType = Type::SHAPEGROUP; + constexpr static inline size_t MaxChildCount = 128u; + size_t childCount = 0u; CElementShape* children[MaxChildCount] = { nullptr }; }; struct Instance { + constexpr static inline Type VariantType = Type::INSTANCE; + CElementShape* parent = nullptr; };/* struct Hair : Base @@ -88,17 +125,27 @@ class CElementShape final : public IElement float angleThreshold = 1.f; float reduction = 0.f; }; - struct HeightField + struct HeightField : Base { SPropertyElementData filename; boolean shadingNormals; - boolean flipNormals; int32_t width; int32_t height; float scale; CElementTexture* texture; };*/ + // + using variant_list_t = core::type_list< + Sphere, + Cylinder, + Obj, + Ply, + Serialized, + ShapeGroup, + Instance + >; + // static AddPropertyMap compAddPropertyMap(); inline CElementShape(const char* id) : IElement(id), type(Type::INVALID), /*toWorldType(IElement::Type::TRANSFORM),*/ transform(), bsdf(nullptr), emitter(nullptr) @@ -116,104 +163,69 @@ class CElementShape final : public IElement { } - inline CElementShape& operator=(const CElementShape& other) + template + inline void visit(Visitor&& visitor) { - IElement::operator=(other); - transform = other.transform; - type = other.type; switch (type) { - case Type::CUBE: - cube = other.cube; + case CElementShape::Type::CUBE: + visitor(cube); break; - case Type::SPHERE: - sphere = other.sphere; + case CElementShape::Type::SPHERE: + visitor(sphere); break; - case Type::CYLINDER: - cylinder = other.cylinder; + case CElementShape::Type::CYLINDER: + visitor(cylinder); break; - case Type::RECTANGLE: - rectangle = other.rectangle; + case CElementShape::Type::RECTANGLE: + visitor(rectangle); break; - case Type::DISK: - disk = other.disk; + case CElementShape::Type::DISK: + visitor(disk); break; - case Type::OBJ: - obj = other.obj; + case CElementShape::Type::OBJ: + visitor(obj); break; - case Type::PLY: - ply = other.ply; + case CElementShape::Type::PLY: + visitor(ply); break; - case Type::SERIALIZED: - serialized = other.serialized; + case CElementShape::Type::SERIALIZED: + visitor(serialized); break; - case Type::SHAPEGROUP: - shapegroup = other.shapegroup; + case CElementShape::Type::SHAPEGROUP: + visitor(shapegroup); break; - case Type::INSTANCE: - instance = other.instance; + case CElementShape::Type::INSTANCE: + visitor(instance); break;/* - case Type::HAIR: - hair = other.hair; + case CElementShape::Type::HAIR: + visitor(hair); break; - case Type::HEIGHTFIELD: - heightfield = other.heightfield; + case CElementShape::Type::HEIGHTFIELD: + visitor(heightfield); break;*/ default: break; } - bsdf = other.bsdf; - emitter = other.emitter; - return *this; } - inline CElementShape& operator=(CElementShape&& other) + template + inline void visit(Visitor&& visitor) const { - IElement::operator=(std::move(other)); - std::swap(transform,other.transform); - std::swap(type,other.type); - switch (type) - { - case Type::CUBE: - std::swap(cube,other.cube); - break; - case Type::SPHERE: - std::swap(sphere,other.sphere); - break; - case Type::CYLINDER: - std::swap(cylinder,other.cylinder); - break; - case Type::RECTANGLE: - std::swap(rectangle,other.rectangle); - break; - case Type::DISK: - std::swap(disk,other.disk); - break; - case Type::OBJ: - std::swap(obj,other.obj); - break; - case Type::PLY: - std::swap(ply,other.ply); - break; - case Type::SERIALIZED: - std::swap(serialized,other.serialized); - break; - case Type::SHAPEGROUP: - std::swap(shapegroup,other.shapegroup); - break; - case Type::INSTANCE: - std::swap(instance,other.instance); - break;/* - case Type::HAIR: - std::swap(hair,other.hair); - break; - case Type::HEIGHTFIELD: - std::swap(heightfield,other.heightfield); - break;*/ - default: - break; - } - std::swap(bsdf,other.bsdf); - std::swap(emitter,other.emitter); + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); + } + + inline CElementShape& operator=(const CElementShape& other) + { + IElement::operator=(other); + transform = other.transform; + type = other.type; + IElement::copyVariant(this,&other); + bsdf = other.bsdf; + emitter = other.emitter; return *this; } @@ -247,7 +259,7 @@ class CElementShape final : public IElement } - bool processChildData(IElement* _child, const std::string& name) override; + bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override; // Type type; @@ -261,7 +273,7 @@ class CElementShape final : public IElement };*/ union { - Base cube; + Cube cube; Sphere sphere; Cylinder cylinder; Base rectangle; diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index ece070785e..8cad6f7ce3 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -245,7 +245,7 @@ class CElementTexture : public IElement 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; + bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override; // Type type; diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index 4da3dbb848..f4b9b09ebb 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -55,8 +55,6 @@ class IElement TRANSFORM, ANIMATION }; - public: - std::string id; IElement(const char* _id) : id(_id ? _id:"") {} virtual ~IElement() = default; @@ -66,7 +64,7 @@ class IElement 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) + virtual bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) { return !_child; } @@ -198,6 +196,23 @@ class IElement std::array,SNamedPropertyElement::Type::INVALID> byPropertyType = {}; }; + + // members + std::string id; + + protected: + static inline void setLimitedString(const std::string_view memberName, std::span out, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger) + { + auto len = strlen(_property.svalue); + if (len>=out.size()) + logger.log( + "String property assigned to %s is too long, max allowed length %d, is %d, property value: \"%s\"", + system::ILogger::ELL_ERROR,memberName.data(),out.size(),len,_property.svalue + ); + len = std::min(out.size()-1,len); + memcpy(out.data(),_property.svalue,len); + out[len] = 0; + } }; namespace impl diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 1d6bd55715..3ac2c6fe4d 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -86,7 +86,7 @@ class ParserManager final CElementFilm, CElementRFilter, CElementSampler, -/// CElementShape, + CElementShape, CElementTransform, /// CElementBSDF, /// CElementTexture, diff --git a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp index 4fbe7b3f4d..8b0b34e3e4 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp @@ -40,7 +40,7 @@ auto CElementEmissionProfile::compAddPropertyMap() -> AddPropertyMap out, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger) -{ - auto len = strlen(_property.svalue); - if (len>=out.size()) - logger.log( - "String property assigned to %s is too long, max allowed length %d, is %d, property value: \"%s\"", - system::ILogger::ELL_ERROR,memberName.data(),out.size(),len,_property.svalue - ); - len = std::min(out.size()-1,len); - memcpy(out.data(),_property.svalue,len); - out[len] = 0; - return true; -} - auto CElementFilm::compAddPropertyMap() -> AddPropertyMap { using this_t = CElementFilm; @@ -118,22 +103,22 @@ auto CElementFilm::compAddPropertyMap() -> AddPropertyMap NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("variable",STRING,std::is_same,M) { - return setLimitedString("variable",_this->outputFilePath,std::move(_property),logger); + setLimitedString("variable",_this->outputFilePath,std::move(_property),logger); return true; } ); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("outputFilePath",STRING) { - return setLimitedString("outputFilePath",_this->outputFilePath,std::move(_property),logger); + setLimitedString("outputFilePath",_this->outputFilePath,std::move(_property),logger); return true; } }); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("bloomFilePath",STRING) { - return setLimitedString("bloomFilePath",_this->denoiserTonemapperArgs,std::move(_property),logger); + setLimitedString("bloomFilePath",_this->denoiserTonemapperArgs,std::move(_property),logger); return true; } }); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("tonemapper",STRING) { - return setLimitedString("tonemapper",_this->denoiserTonemapperArgs,std::move(_property),logger); + setLimitedString("tonemapper",_this->denoiserTonemapperArgs,std::move(_property),logger); return true; } }); diff --git a/src/nbl/ext/MitsubaLoader/CElementShape.cpp b/src/nbl/ext/MitsubaLoader/CElementShape.cpp index 0af5b97172..c6db773afa 100644 --- a/src/nbl/ext/MitsubaLoader/CElementShape.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementShape.cpp @@ -1,213 +1,59 @@ // 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/CElementShape.h" + +#include "nbl/ext/MitsubaLoader/ElementMacros.h" +#include "nbl/type_traits.h" // legacy stuff for `is_any_of` #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader +namespace nbl::ext::MitsubaLoader { -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +auto CElementShape::compAddPropertyMap() -> AddPropertyMap { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr,""); + using this_t = CElementShape; + AddPropertyMap retval; - static const core::unordered_map StringToType = - { - {"cube", CElementShape::Type::CUBE}, - {"sphere", CElementShape::Type::SPHERE}, - {"cylinder", CElementShape::Type::CYLINDER}, - {"rectangle", CElementShape::Type::RECTANGLE}, - {"disk", CElementShape::Type::DISK}, - {"obj", CElementShape::Type::OBJ}, - {"ply", CElementShape::Type::PLY}, - {"serialized", CElementShape::Type::SERIALIZED}, - {"shapegroup", CElementShape::Type::SHAPEGROUP}, - {"instance", CElementShape::Type::INSTANCE}/*, - {"hair", CElementShape::Type::HAIR}, - {"heightfield", CElementShape::Type::HEIGHTFIELD}*/ - }; - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } + // base + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(flipNormals,BOOLEAN,derived_from,Base); + // cube has nothing - CElementShape* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); + // sphere + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(center,POINT,std::is_same,Sphere); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(radius,FLOAT,is_any_of,Sphere,Cylinder/*,Hair*/); - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementShape::Type::CUBE: - obj->cube = CElementShape::Base(); - break; - case CElementShape::Type::SPHERE: - obj->sphere = CElementShape::Sphere(); - break; - case CElementShape::Type::CYLINDER: - obj->cylinder = CElementShape::Cylinder(); - break; - case CElementShape::Type::RECTANGLE: - obj->rectangle = CElementShape::Base(); - break; - case CElementShape::Type::DISK: - obj->disk = CElementShape::Base(); - break; - case CElementShape::Type::OBJ: - obj->obj = CElementShape::Obj(); - break; - case CElementShape::Type::PLY: - obj->ply = CElementShape::Ply(); - break; - case CElementShape::Type::SERIALIZED: - obj->serialized = CElementShape::Serialized(); - break; - case CElementShape::Type::SHAPEGROUP: - obj->shapegroup = CElementShape::ShapeGroup(); - break; - case CElementShape::Type::INSTANCE: - obj->instance = CElementShape::Instance(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} + // cylinder + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(p0,POINT,std::is_same,Cylinder); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(p1,POINT,std::is_same,Cylinder); + // COMMON: radius -bool CElementShape::addProperty(SNamedPropertyElement&& _property) -{ - bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) + // LoadedFromFileBase + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,derived_from,LoadedFromFileBase) { - case CElementShape::Type::CUBE: - func(cube); - break; - case CElementShape::Type::SPHERE: - func(sphere); - break; - case CElementShape::Type::CYLINDER: - func(cylinder); - break; - case CElementShape::Type::RECTANGLE: - func(rectangle); - break; - case CElementShape::Type::DISK: - func(disk); - break; - case CElementShape::Type::OBJ: - func(obj); - break; - case CElementShape::Type::PLY: - func(ply); - break; - case CElementShape::Type::SERIALIZED: - func(serialized); - break; - case CElementShape::Type::SHAPEGROUP: - func(shapegroup); - break; - case CElementShape::Type::INSTANCE: - func(instance); - break;/* - case CElementShape::Type::HAIR: - func(hair); - break; - case CElementShape::Type::HEIGHTFIELD: - func(heightfield); - break;*/ - default: - error = true; - break; + setLimitedString("filename",_this->serialized.filename,std::move(_property),logger); return true; } - }; + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(faceNormals,BOOLEAN,derived_from,LoadedFromFileBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxSmoothAngle,FLOAT,derived_from,LoadedFromFileBase); -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ - } \ - }); \ - } + // Obj + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(flipTexCoords,BOOLEAN,std::is_same,Obj); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(collapse,BOOLEAN,std::is_same,Obj); - auto setFlipNormals = SET_PROPERTY_TEMPLATE(flipNormals,SNamedPropertyElement::Type::BOOLEAN, Base,Sphere,Cylinder,Obj,Ply,Serialized/*,Heightfield*/); - auto setCenter = SET_PROPERTY_TEMPLATE(center,SNamedPropertyElement::Type::POINT, Sphere); - auto setRadius = SET_PROPERTY_TEMPLATE(radius,SNamedPropertyElement::Type::FLOAT, Sphere,Cylinder/*,Hair*/); - auto setP0 = SET_PROPERTY_TEMPLATE(p0,SNamedPropertyElement::Type::POINT, Cylinder); - auto setP1 = SET_PROPERTY_TEMPLATE(p1,SNamedPropertyElement::Type::POINT, Cylinder); - auto setFilename = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; + // Ply + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(srgb,BOOLEAN,std::is_same,Ply); - if constexpr (is_any_of::value) - { - state.filename = std::move(_property); - } - }); - }; - auto setFaceNormals = SET_PROPERTY_TEMPLATE(faceNormals,SNamedPropertyElement::Type::BOOLEAN, Obj,Ply,Serialized); - auto setMaxSmoothAngle = SET_PROPERTY_TEMPLATE(maxSmoothAngle,SNamedPropertyElement::Type::FLOAT, Obj,Ply,Serialized); - auto setFlipTexCoords = SET_PROPERTY_TEMPLATE(flipTexCoords,SNamedPropertyElement::Type::BOOLEAN, Obj); - auto setCollapse = SET_PROPERTY_TEMPLATE(collapse,SNamedPropertyElement::Type::BOOLEAN, Obj); - auto setSRGB = SET_PROPERTY_TEMPLATE(srgb,SNamedPropertyElement::Type::BOOLEAN, Ply); - auto setShapeIndex = SET_PROPERTY_TEMPLATE(shapeIndex,SNamedPropertyElement::Type::INTEGER, Serialized); - //auto setToWorld = SET_PROPERTY_TEMPLATE(toWorld, SNamedPropertyElement::Type::MATRIX, Instance); + // Serialized + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(shapeIndex,INTEGER,std::is_same,Serialized); - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - {"flipNormals", setFlipNormals}, - {"center", setCenter}, - {"radius", setRadius}, - {"p0", setP0}, - {"p1", setP1}, - {"filename", setFilename}, - {"faceNormals", setFaceNormals}, - {"maxSmoothAngle", setMaxSmoothAngle}, - {"flipTexCoords", setFlipTexCoords}, - {"collapse", setCollapse}, - {"srgb", setSRGB}, - {"shapeIndex", setShapeIndex}/*, - {"", set}*/ - }; - - - 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); - return false; - } - - found->second(); - return !error; + return retval; } -bool CElementShape::processChildData(IElement* _child, const std::string& name) +bool CElementShape::processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) { if (!_child) return true; @@ -217,7 +63,10 @@ bool CElementShape::processChildData(IElement* _child, const std::string& name) { auto tform = static_cast(_child); if (name!="toWorld") + { + logger.log("The nested inside needs to be named \"toWorld\"",system::ILogger::ELL_ERROR); return false; + } //toWorldType = IElement::Type::TRANSFORM; transform = *tform; return true; @@ -237,33 +86,44 @@ bool CElementShape::processChildData(IElement* _child, const std::string& name) switch (type) { case Type::SHAPEGROUP: - if (child->type==Type::INVALID || child->type==Type::SHAPEGROUP) + if (child->type == Type::INVALID || child->type == Type::SHAPEGROUP) + { + logger.log(" cannot be nested inside each other or have INVALID shapes nested inside.",system::ILogger::ELL_ERROR); return false; - if (shapegroup.childCount == ShapeGroup::MaxChildCount) + } + if (shapegroup.childCount==ShapeGroup::MaxChildCount) { - ParserLog::invalidXMLFileStructure("Maximum shape-group children exceeded."); + logger.log("The 's MaxChildCount of %d exceeded!",system::ILogger::ELL_ERROR,ShapeGroup::MaxChildCount); return false; } shapegroup.children[shapegroup.childCount++] = child; return true; - break; case Type::INSTANCE: - if (child->type != Type::SHAPEGROUP) + if (child->type!=Type::SHAPEGROUP) + { + logger.log("Only can be nested inside ",system::ILogger::ELL_ERROR); return false; - instance.parent = child; // yeah I kknow its fucked up, but its the XML child, but Abstract Syntax Tree (or Scene Tree) parent + } + if (instance.parent) + logger.log(" 's parent already set to %s, overriding",system::ILogger::ELL_WARNING,instance.parent->id.c_str()); + instance.parent = child; // yeah I know its messed up, but its the XML child, not the Abstract Syntax Tree (or Scene Tree) parent return true; - break; default: - break; + logger.log("Only and support nesting other s inside",system::ILogger::ELL_ERROR); + return false; } } break; case IElement::Type::BSDF: + if (bsdf) + logger.log("'s BSDF already set to %s, overriding",system::ILogger::ELL_WARNING,bsdf->id.c_str()); bsdf = static_cast(_child); if (bsdf->type != CElementBSDF::Type::INVALID) return true; break; case IElement::Type::EMITTER: + if (emitter) + logger.log("'s Emitter already set to %s, overriding",system::ILogger::ELL_WARNING,emitter->id.c_str()); emitter = static_cast(_child); if (emitter->type != CElementEmitter::Type::INVALID) return true; @@ -271,6 +131,7 @@ bool CElementShape::processChildData(IElement* _child, const std::string& name) default: break; } + logger.log("Invalid or unsupported child with ID %s and Name %s nested inside of ",system::ILogger::ELL_ERROR,_child->id.c_str(),name.c_str()); return false; } @@ -283,6 +144,4 @@ bool CElementShape::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_op return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index 7bedf035b8..ef3f326ad5 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -33,7 +33,7 @@ set(NBL_EXT_MITSUBA_LOADER_SRC CElementRFilter.cpp CElementSampler.cpp CElementTransform.cpp -# CElementShape.cpp + CElementShape.cpp # CElementBSDF.cpp # CElementTexture.cpp # CElementEmitter.cpp diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index eea6e97004..6db96f452f 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -37,114 +37,6 @@ 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"); \ diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 9646fca073..6f1af1e301 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -9,7 +9,7 @@ #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/CElementShape.h" #include "nbl/ext/MitsubaLoader/CElementTransform.h" //#include "nbl/ext/MitsubaLoader/CElementAnimation.h" //#include "nbl/ext/MitsubaLoader/CElementBSDF.h" @@ -308,7 +308,7 @@ void ParserManager::XMLContext::onEnd(const char* _el) if (!elements.empty()) { IElement* parent = elements.top().element; - if (parent && !parent->processChildData(element.element,element.name)) + if (parent && !parent->processChildData(element.element,element.name,session->params->logger)) { if (element.element) killParseWithError(element.element->getLogName()+" could not processChildData with name: "+element.name); @@ -417,7 +417,7 @@ ParserManager::ParserManager() : propertyElements({ {"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}}, + {"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}}, @@ -432,6 +432,7 @@ ParserManager::ParserManager() : propertyElements({ CElementFilm::compAddPropertyMap(), CElementRFilter::compAddPropertyMap(), CElementSampler::compAddPropertyMap(), + CElementShape::compAddPropertyMap(), CElementTransform::compAddPropertyMap(), CElementEmissionProfile::compAddPropertyMap() }) { } From 49ffbc62a70bc27d09d69e20a63aec5cf3c5e402 Mon Sep 17 00:00:00 2001 From: devsh Date: Tue, 23 Dec 2025 00:57:36 +0100 Subject: [PATCH 24/30] implement `CElementTexture` and `CElementEmitter`, also refactor the ElementMacros.h --- .../nbl/ext/MitsubaLoader/CElementEmitter.h | 240 ++++------- .../nbl/ext/MitsubaLoader/CElementTexture.h | 108 ++--- src/nbl/ext/MitsubaLoader/CElementEmitter.cpp | 407 +++++++----------- src/nbl/ext/MitsubaLoader/CElementTexture.cpp | 324 ++++---------- src/nbl/ext/MitsubaLoader/ElementMacros.h | 36 +- 5 files changed, 417 insertions(+), 698 deletions(-) diff --git a/include/nbl/ext/MitsubaLoader/CElementEmitter.h b/include/nbl/ext/MitsubaLoader/CElementEmitter.h index 04833986d1..8eaebcae74 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmitter.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmitter.h @@ -22,7 +22,7 @@ class CElementEmitter : public IElement INVALID, POINT, AREA, - SPOT, + //SPOT, // deprecated, use POINT with an IES profile instead! DIRECTIONAL, COLLIMATED, //SKY, @@ -31,43 +31,67 @@ class CElementEmitter : public IElement ENVMAP, CONSTANT }; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"point", CElementEmitter::Type::POINT}, + {"area", CElementEmitter::Type::AREA}, + {"directional", CElementEmitter::Type::DIRECTIONAL}, + {"collimated", CElementEmitter::Type::COLLIMATED},/* + {"sky", CElementEmitter::Type::SKY}, + {"sun", CElementEmitter::Type::SUN}, + {"sunsky", CElementEmitter::Type::SUNSKY},*/ + {"envmap", CElementEmitter::Type::ENVMAP}, + {"constant", CElementEmitter::Type::CONSTANT} + }; + } struct SampledEmitter { - SampledEmitter() : samplingWeight(1.f) {} + inline SampledEmitter() : samplingWeight(1.f) {} float samplingWeight; }; - struct Point : SampledEmitter - { - core::vectorSIMDf intensity = core::vectorSIMDf(1.f); // Watts Steradian^-1 - }; - struct Area : SampledEmitter + struct DeltaDistributionEmitter : SampledEmitter + { + // Watts + hlsl::float32_t3 intensity = {1.f,1.f,1.f}; + }; + struct SolidAngleEmitter : SampledEmitter + { + // Watts Steradian^-1 + hlsl::float32_t3 radiance = {1.f,1.f,1.f}; + }; + struct EmissionProfileEmitter + { + CElementEmissionProfile* emissionProfile = nullptr; + }; + struct Point : DeltaDistributionEmitter, EmissionProfileEmitter { - core::vectorSIMDf radiance = core::vectorSIMDf(1.f); // Watts Meter^-2 Steradian^-1 - CElementEmissionProfile* emissionProfile = nullptr; + constexpr static inline Type VariantType = Type::POINT; }; - struct Spot : SampledEmitter + struct Area : SolidAngleEmitter, EmissionProfileEmitter { - core::vectorSIMDf intensity = core::vectorSIMDf(1.f); // Watts Steradian^-1 - float cutoffAngle = 20.f; // degrees, its the cone half-angle - float beamWidth = NAN; - CElementTexture* texture = nullptr; + constexpr static inline Type VariantType = Type::AREA; }; struct Directional : SampledEmitter { - core::vectorSIMDf irradiance = core::vectorSIMDf(1.f); // Watts Meter^-2 + constexpr static inline Type VariantType = Type::DIRECTIONAL; + + hlsl::float32_t3 irradiance = {1.f,1.f,1.f}; // Watts Meter^-2 }; struct Collimated : SampledEmitter { - core::vectorSIMDf power = core::vectorSIMDf(1.f); // Watts + constexpr static inline Type VariantType = Type::COLLIMATED; + + hlsl::float32_t3 power = {1.f,1.f,1.f}; // Watts };/* struct Sky : SampledEmitter { float turbidity = 3.f; - core::vectorSIMDf albedo = core::vectorSIMDf(0.15f); - core::vectorSIMDf sunDirection = calculate default from tokyo japan at 15:00 on 10.07.2010; + hlsl::float32_t3 albedo = {0.15f,0.15f,0.15f}; + hlsl::float32_t3 sunDirection = calculate default from tokyo japan at 15:00 on 10.07.2010; float stretch = 1.f; // must be [1,2] int32_t resolution = 512; float scale = 1.f; @@ -75,7 +99,7 @@ class CElementEmitter : public IElement struct Sun : SampledEmitter { float turbidity = 3.f; - core::vectorSIMDf sunDirection = calculate default from tokyo japan at 15:00 on 10.07.2010; + hlsl::float32_t3 sunDirection = calculate default from tokyo japan at 15:00 on 10.07.2010; int32_t resolution = 512; float scale = 1.f; float sunRadiusScale = 1.f; @@ -87,16 +111,31 @@ class CElementEmitter : public IElement };*/ struct EnvMap : SampledEmitter { - SPropertyElementData filename; // TODO: make sure destructor runs - float scale = 1.f; - float gamma = NAN; + constexpr static inline Type VariantType = Type::ENVMAP; + constexpr static inline uint16_t MaxPathLen = 1024u; + + char filename[MaxPathLen]; + float scale = 1.f; + float gamma = NAN; //bool cache = false; }; - struct Constant : SampledEmitter + struct Constant : SolidAngleEmitter { - core::vectorSIMDf radiance = core::vectorSIMDf(1.f); // Watts Meter^-2 Steradian^-1 + constexpr static inline Type VariantType = Type::CONSTANT; }; + // + using variant_list_t = core::type_list< + Point, + Area, + Directional, + Collimated, +// Sky, +// Sun, +// SunSky, + EnvMap, + Constant + >; // static AddPropertyMap compAddPropertyMap(); @@ -109,97 +148,62 @@ class CElementEmitter : public IElement { operator=(other); } - inline CElementEmitter(CElementEmitter&& other) : IElement(""), transform() - { - operator=(std::move(other)); - } virtual ~CElementEmitter() { } - inline CElementEmitter& operator=(const CElementEmitter& other) + template + inline void visit(Visitor&& func) { - IElement::operator=(other); - transform = other.transform; - type = other.type; switch (type) { case Type::POINT: - point = other.point; + func(point); break; case Type::AREA: - area = other.area; - break; - case Type::SPOT: - spot = other.spot; + func(area); break; case Type::DIRECTIONAL: - directional = other.directional; + func(directional); break; case Type::COLLIMATED: - collimated = other.collimated; + func(collimated); break;/* case Type::SKY: - sky = other.sky; + func(sky); break; case Type::SUN: - sun = other.sun; + func(sun); break; case Type::SUNSKY: - sunsky = other.sunsky; + func(sunsky); break;*/ case Type::ENVMAP: - envmap = other.envmap; + func(envmap); break; case Type::CONSTANT: - constant = other.constant; + func(constant); break; default: break; } - return *this; + } + template + inline void visit(Visitor&& visitor) const + { + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); } - inline CElementEmitter& operator=(CElementEmitter&& other) + inline CElementEmitter& operator=(const CElementEmitter& other) { - IElement::operator=(std::move(other)); - std::swap(transform,other.transform); - std::swap(type,other.type); - switch (type) - { - case Type::POINT: - std::swap(point,other.point); - break; - case Type::AREA: - std::swap(area,other.area); - break; - case Type::SPOT: - std::swap(spot,other.spot); - break; - case Type::DIRECTIONAL: - std::swap(directional,other.directional); - break; - case Type::COLLIMATED: - std::swap(collimated,other.collimated); - break;/* - case Type::SKY: - sky,other.sky; - break; - case Type::SUN: - sun,other.sun; - break; - case Type::SUNSKY: - sunsky,other.sunsky; - break;*/ - case Type::ENVMAP: - std::swap(envmap,other.envmap); - break; - case Type::CONSTANT: - std::swap(constant,other.constant); - break; - default: - break; - } + IElement::operator=(other); + transform = other.transform; + type = other.type; + IElement::copyVariant(this,&other); return *this; } @@ -209,72 +213,7 @@ class CElementEmitter : public IElement inline IElement::Type getType() const override { return ElementType; } std::string getLogName() const override { return "emitter"; } - bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override - { - if (!_child) - return true; - switch (_child->getType()) - { - case IElement::Type::TRANSFORM: - { - auto tform = static_cast(_child); - if (name!="toWorld") - return false; - //toWorldType = IElement::Type::TRANSFORM; - switch (type) - { - case Type::POINT: - [[fallthrough]]; - case Type::SPOT: - [[fallthrough]]; - case Type::DIRECTIONAL: - [[fallthrough]]; - case Type::COLLIMATED: - [[fallthrough]]; - case Type::AREA: - [[fallthrough]]; - /* - case Type::SKY: - [[fallthrough]]; - case Type::SUN: - [[fallthrough]]; - case Type::SUNSKY: - [[fallthrough]];*/ - case Type::ENVMAP: - transform = *tform; - return true; - default: - break; - } - return false; - } - break;/* - case IElement::Type::ANIMATION: - auto anim = static_cast(_child); - if (anim->name!="toWorld") - return false; - toWorlType = IElement::Type::ANIMATION; - animation = anim; - return true; - break;*/ - case IElement::Type::EMISSION_PROFILE: { - if (type == Type::AREA) { - area.emissionProfile = static_cast(_child); - return true; - } - return false; - } - case IElement::Type::TEXTURE: - if (type!=SPOT || name!="texture") - return false; - spot.texture = static_cast(_child); - return true; - break; - default: - break; - } - return false; - } + bool processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) override; // Type type; @@ -290,7 +229,6 @@ class CElementEmitter : public IElement { Point point; Area area; - Spot spot; Directional directional; Collimated collimated;/* Sky sky; diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index 8cad6f7ce3..5381920a38 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -105,8 +105,19 @@ class CElementTexture : public IElement //WIREFRAME, //CURVATURE }; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"bitmap", CElementTexture::Type::BITMAP}, + {"scale", CElementTexture::Type::SCALE} + }; + } + struct Bitmap { + constexpr static inline Type VariantType = Type::BITMAP; + constexpr static inline uint16_t MaxPathLen = 1024u; + enum WRAP_MODE { REPEAT, @@ -133,18 +144,18 @@ class CElementTexture : public IElement Z*/ }; - SPropertyElementData filename; // TODO: make sure destructor runs - WRAP_MODE wrapModeU = REPEAT; - WRAP_MODE wrapModeV = REPEAT; - float gamma = NAN; + char filename[MaxPathLen]; + WRAP_MODE wrapModeU = REPEAT; + WRAP_MODE wrapModeV = REPEAT; + float gamma = NAN; FILTER_TYPE filterType = EWA; - float maxAnisotropy = 20.f; + float maxAnisotropy = 20.f; //bool cache = false; - float uoffset = 0.f; - float voffset = 0.f; - float uscale = 1.f; - float vscale = 1.f; - CHANNEL channel = INVALID; + float uoffset = 0.f; + float voffset = 0.f; + float uscale = 1.f; + float vscale = 1.f; + CHANNEL channel = INVALID; }; struct MetaTexture { @@ -152,9 +163,14 @@ class CElementTexture : public IElement }; struct Scale : MetaTexture { - float scale; + constexpr static inline Type VariantType = Type::SCALE; + + // only monochrome scaling for now! + float scale = 1.f; }; + // + using variant_list_t = core::type_list; // static AddPropertyMap compAddPropertyMap(); @@ -166,76 +182,40 @@ class CElementTexture : public IElement { operator=(other); } - inline CElementTexture(CElementTexture&& other) : CElementTexture("") - { - operator=(std::move(other)); - } inline virtual ~CElementTexture() { } - - inline CElementTexture& operator=(const CElementTexture& other) + + template + inline void visit(Visitor&& func) { - IElement::operator=(other); - type = other.type; switch (type) { case CElementTexture::Type::BITMAP: - bitmap = other.bitmap; + func(bitmap); break; - //case CElementTexture::Type::CHECKERBOARD: - //checkerboard = CheckerBoard(); - //break; - //case CElementTexture::Type::GRID: - //grid = Grid(); - //break; case CElementTexture::Type::SCALE: - scale = other.scale; + func(scale); break; - //case CElementTexture::Type::VERTEXCOLOR: - //vertexcolor = VertexColor(); - //break; - //case CElementTexture::Type::WIREFRAME: - //wireframe = Wireframe(); - //break; - //case CElementTexture::Type::CURVATURE: - //curvature = Curvature(); - //break; default: break; } - return *this; } - inline CElementTexture& operator=(CElementTexture&& other) + template + inline void visit(Visitor&& visitor) const + { + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); + } + + inline CElementTexture& operator=(const CElementTexture& other) { IElement::operator=(other); type = other.type; - switch (type) - { - case CElementTexture::Type::BITMAP: - std::swap(bitmap,other.bitmap); - break; - //case CElementTexture::Type::CHECKERBOARD: - //checkerboard = CheckerBoard(); - //break; - //case CElementTexture::Type::GRID: - //grid = Grid(); - //break; - case CElementTexture::Type::SCALE: - std::swap(scale,other.scale); - break; - //case CElementTexture::Type::VERTEXCOLOR: - //vertexcolor = VertexColor(); - //break; - //case CElementTexture::Type::WIREFRAME: - //wireframe = Wireframe(); - //break; - //case CElementTexture::Type::CURVATURE: - //curvature = Curvature(); - //break; - default: - break; - } + IElement::copyVariant(this,&other); return *this; } diff --git a/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp b/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp index 1a0389c684..c7115dfcef 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp @@ -1,287 +1,206 @@ // 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/CElementEmitter.h" + +#include "nbl/ext/MitsubaLoader/ElementMacros.h" +#include "nbl/type_traits.h" // legacy stuff for `is_any_of` #include -namespace nbl -{ -namespace ext -{ -namespace MitsubaLoader -{ +#include "nbl/builtin/hlsl/math/linalg/transform.hlsl" +#include "glm/gtc/matrix_transform.hpp" -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 = - { - {"point", CElementEmitter::Type::POINT}, - {"area", CElementEmitter::Type::AREA}, - {"spot", CElementEmitter::Type::SPOT}, - {"directional", CElementEmitter::Type::DIRECTIONAL}, - {"collimated", CElementEmitter::Type::COLLIMATED},/* - {"sky", CElementEmitter::Type::SKY}, - {"sun", CElementEmitter::Type::SUN}, - {"sunsky", CElementEmitter::Type::SUNSKY},*/ - {"envmap", CElementEmitter::Type::ENVMAP}, - {"constant", CElementEmitter::Type::CONSTANT} - }; +auto CElementEmitter::compAddPropertyMap() -> AddPropertyMap +{ + using this_t = CElementEmitter; + AddPropertyMap retval; - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); + // funky transform setting + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("position",POINT) + { + if (_this->type!=Type::POINT && _this->type!=Type::COLLIMATED) + return false; + for (auto r=0; r<3; r++) + _this->transform.matrix[r][3] = _property.vvalue[r]; + return true; + } + }); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("direction",VECTOR) + { + // for point lights direction gets concatenated with IES rotation + if (_this->type!=Type::POINT && _this->type!=Type::DIRECTIONAL && _this->type!=Type::COLLIMATED) + return false; + hlsl::float32_t3 up = {0,0,0}; + { + uint32_t index = 0u; + { + float maxDot = std::abs(_property.vvalue[0]); + for (auto i=1u; i<3u; i++) + { + float thisAbs = std::abs(_property.vvalue[i]); + if (thisAbs < maxDot) + { + maxDot = thisAbs; + index = i; + } + } + } + up[index] = hlsl::sign(_property.vvalue[index]); + } + // TODO: check if correct + const hlsl::float32_t3 target = (-_property.vvalue).xyz; + // TODO: after the rm-core matrix PR we need to get rid of the tranpose (I transpose only because of GLM and HLSL mixup) + const auto lookAtGLM = reinterpret_cast(glm::lookAtRH({},target,up)); + const auto lookAt = hlsl::transpose(lookAtGLM); + // turn lookat into a rotation matrix + const auto rotation = hlsl::inverse(hlsl::float32_t3x3(lookAt)); + _NBL_DEBUG_BREAK_IF(true); // no idea if matrix is correct + for (auto r=0; r<3; r++) + _this->transform.matrix[r].xyz = rotation[r]; + return true; + } + }); + + // spectrum setting +#define ADD_SPECTRUM(MEMBER,CONSTRAINT,...) { \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,FLOAT,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER.x = state. ## MEMBER.y = state. ## MEMBER.z = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,RGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SRGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SPECTRUM,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ } - CElementEmitter* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); + // base + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(samplingWeight,FLOAT,derived_from,SampledEmitter); - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementEmitter::Type::POINT: - obj->point = CElementEmitter::Point(); - break; - case CElementEmitter::Type::AREA: - obj->area = CElementEmitter::Area(); - break; - case CElementEmitter::Type::SPOT: - obj->spot = CElementEmitter::Spot(); - break; - case CElementEmitter::Type::DIRECTIONAL: - obj->directional = CElementEmitter::Directional(); - break; - case CElementEmitter::Type::COLLIMATED: - obj->collimated = CElementEmitter::Collimated(); - break;/* - case CElementEmitter::Type::SKY: - obj->sky = CElementEmitter::Sky(); - break; - case CElementEmitter::Type::SUN: - obj->ply = CElementEmitter::Sun(); - break; - case CElementEmitter::Type::SUNSKY: - obj->serialized = CElementEmitter::SunSky(); - break;*/ - case CElementEmitter::Type::ENVMAP: - obj->envmap = CElementEmitter::EnvMap(); - break; - case CElementEmitter::Type::CONSTANT: - obj->constant = CElementEmitter::Constant(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); -} + // delta + ADD_SPECTRUM(intensity,derived_from,DeltaDistributionEmitter); + // point covered by delta -bool CElementEmitter::addProperty(SNamedPropertyElement&& _property) -{ - bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) - { - case Type::POINT: - func(point); - break; - case Type::AREA: - func(area); - break; - case Type::SPOT: - func(spot); - break; - case Type::DIRECTIONAL: - func(directional); - break; - case Type::COLLIMATED: - func(collimated); - break;/* - case Type::SKY: - func(sky); - break; - case Type::SUN: - func(sun); - break; - case Type::SUNSKY: - func(sunsky); - break;*/ - case Type::ENVMAP: - func(envmap); - break; - case Type::CONSTANT: - func(constant); - break; - default: - error = true; - break; - } - }; + // non zero solid angle + ADD_SPECTRUM(radiance,derived_from,SolidAngleEmitter); + // area covered by solid angle -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ - } \ - }); \ - } -#define SET_SPECTRUM(MEMBER, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - switch (_property.type) { \ - case SPropertyElementData::Type::FLOAT: \ - state. ## MEMBER.x = state. ## MEMBER.y = state. ## MEMBER.z = _property.getProperty(); \ - break; \ - case SPropertyElementData::Type::RGB: \ - state. ## MEMBER = _property.getProperty(); \ - break; \ - case SPropertyElementData::Type::SRGB: \ - state. ## MEMBER = _property.getProperty(); \ - break; \ - case SPropertyElementData::Type::SPECTRUM: \ - state. ## MEMBER = _property.getProperty(); \ - break; \ - default: \ - error = true; \ - break; \ - } \ - } \ - }); \ - } + // directional + ADD_SPECTRUM(irradiance,std::is_same,Directional); - auto setSamplingWeight = SET_PROPERTY_TEMPLATE(samplingWeight, SNamedPropertyElement::Type::FLOAT, Point,Area,Spot,Directional,Collimated,/*Sky,Sun,SunSky,*/EnvMap,Constant); - auto setIntensity = SET_SPECTRUM(intensity, Point,Spot); - auto setPosition = [&]() -> void { - if (_property.type!=SNamedPropertyElement::Type::POINT || type!=Type::POINT) - { - error = true; - return; - } - transform.matrix.setTranslation(_property.vvalue); - }; - auto setRadiance = SET_SPECTRUM(radiance, Area,Constant); - auto setCutoffAngle = SET_PROPERTY_TEMPLATE(cutoffAngle, SNamedPropertyElement::Type::FLOAT, Spot); - auto setBeamWidth = SET_PROPERTY_TEMPLATE(beamWidth, SNamedPropertyElement::Type::FLOAT, Spot); - auto setDirection = [&]() -> void { - if (_property.type != SNamedPropertyElement::Type::VECTOR || type != Type::DIRECTIONAL) - { - error = true; - return; - } - core::vectorSIMDf up(0.f); - float maxDot = _property.vvalue[0]; - uint32_t index = 0u; - for (auto i=1u; i<3u; i++) - if (_property.vvalue[i] < maxDot) + // collimated + ADD_SPECTRUM(power,std::is_same,Collimated); + + // environment map + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,std::is_same,EnvMap) { - maxDot = _property.vvalue[i]; - index = i; + setLimitedString("filename",_this->envmap.filename,std::move(_property),logger); return true; } - up[index] = 1.f; - // hope it works - core::matrix3x4SIMD tmp; - core::matrix3x4SIMD::buildCameraLookAtMatrixRH(core::vectorSIMDf(),-_property.vvalue,up).getInverse(tmp); - transform.matrix = core::matrix4SIMD(tmp); - _NBL_DEBUG_BREAK_IF(true); // no idea if matrix is correct - }; - auto setPower = SET_SPECTRUM(power, Collimated); - auto setFilename = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(scale,FLOAT,std::is_same,EnvMap); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(gamma,FLOAT,std::is_same,EnvMap); - if constexpr (std::is_same::value) - { - envmap.filename = std::move(_property); - } - }); - }; - auto setScale = SET_PROPERTY_TEMPLATE(scale, SNamedPropertyElement::Type::FLOAT, EnvMap); - auto setGamma = SET_PROPERTY_TEMPLATE(gamma, SNamedPropertyElement::Type::FLOAT, EnvMap); - //auto setCache = SET_PROPERTY_TEMPLATE(cache, SNamedPropertyElement::Type::BOOLEAN, EnvMap); -#undef SET_SPECTRUM -#undef SET_PROPERTY_TEMPLATE - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - {"samplingWeight", setSamplingWeight}, - {"intensity", setIntensity}, - {"position", setPosition}, - {"radiance", setRadiance}, - {"cutoffAngle", setCutoffAngle}, - {"beamWidth", setBeamWidth}, - {"direction", setDirection}, - {"power", setPower},/* - {"turbidity", setTurbidity}, - {"", set}, - {"sunRadiusScale", setSunRadiusScale},*/ - {"filename", setFilename}, - {"scale", setScale}, - {"gamma", setGamma}//, - //{"cache", setCache}, - }; +#undef ADD_SPECTRUM + return retval; +} + +bool CElementEmitter::processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) +{ + if (!_child) + return true; - auto found = SetPropertyMap.find(_property.name); - if (found==SetPropertyMap.end()) + switch (_child->getType()) { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("No Emitter can have such property set with name: " + _property.name); - return false; + case IElement::Type::TRANSFORM: + { + auto tform = static_cast(_child); + if (name!="toWorld") + { + logger.log("The nested inside needs to be named \"toWorld\"",system::ILogger::ELL_ERROR); + return false; + } + //toWorldType = IElement::Type::TRANSFORM; + switch (type) + { + case Type::POINT: + [[fallthrough]]; + case Type::DIRECTIONAL: + [[fallthrough]]; + case Type::COLLIMATED: + [[fallthrough]]; + case Type::AREA: + [[fallthrough]]; + /* + case Type::SKY: + [[fallthrough]]; + case Type::SUN: + [[fallthrough]]; + case Type::SUNSKY: + [[fallthrough]];*/ + case Type::ENVMAP: + transform = *tform; + return true; + default: + logger.log(" does not support ",system::ILogger::ELL_ERROR,type); + return false; + } + } + break;/* + case IElement::Type::ANIMATION: + auto anim = static_cast(_child); + if (anim->name!="toWorld") + return false; + toWorlType = IElement::Type::ANIMATION; + animation = anim; + return true; + break;*/ + case IElement::Type::EMISSION_PROFILE: + if (type!=Type::AREA && type!=Type::POINT) + { + logger.log(" does not support nested emission profiles, only Point and Area lights do",system::ILogger::ELL_ERROR,type); + return false; + } + area.emissionProfile = static_cast(_child); + return true; + default: + break; } - - found->second(); - return !error; + logger.log(" does not support nested <%s> elements",system::ILogger::ELL_ERROR,type,_child->getLogName()); + return false; } -bool CElementEmitter::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* metadata) +bool CElementEmitter::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { // TODO: some more validation switch (type) { case Type::INVALID: - ParserLog::invalidXMLFileStructure(getLogName() + ": type not specified"); + logger.log("'s type not specified!",system::ILogger::ELL_ERROR); _NBL_DEBUG_BREAK_IF(true); return true; break; - case Type::SPOT: - if (std::isnan(spot.beamWidth)) - spot.beamWidth = spot.cutoffAngle * 0.75f; - default: - break; - } - - switch (type) - { case Type::AREA: break; default: - metadata->m_global.m_emitters.push_back(*this); + // TODO: slap into the scene instead! +// globalMetadata->m_global.m_emitters.push_back(*this); break; } - return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementTexture.cpp b/src/nbl/ext/MitsubaLoader/CElementTexture.cpp index 410ab8508f..0add6ac3ca 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTexture.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTexture.cpp @@ -2,255 +2,118 @@ // 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/CElementTexture.h" + +#include "nbl/ext/MitsubaLoader/ElementMacros.h" #include namespace nbl::ext::MitsubaLoader { - - -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +inline CElementTexture::Bitmap::WRAP_MODE getWrapMode(const SPropertyElementData& _property) { - 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 = + using mode_e = CElementTexture::Bitmap::WRAP_MODE; + static const core::unordered_map StringToWrap = { - {"bitmap", CElementTexture::Type::BITMAP}, - {"scale", CElementTexture::Type::SCALE} + {"repeat", mode_e::REPEAT}, + {"mirror", mode_e::MIRROR}, + {"clamp", mode_e::CLAMP}, + {"zero", mode_e::ZERO}, + {"one", mode_e::ONE} }; - - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr,""); - } - - CElementTexture* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr,""); - - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementTexture::Type::BITMAP: - obj->bitmap = CElementTexture::Bitmap(); - break; - case CElementTexture::Type::SCALE: - obj->scale = CElementTexture::Scale(); - break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); + assert(_property.type==SPropertyElementData::Type::STRING); + auto found = StringToWrap.find(_property.getProperty()); + if (found != StringToWrap.end()) + return found->second; + return mode_e::REPEAT; } -bool CElementTexture::addProperty(SNamedPropertyElement&& _property) +auto CElementTexture::compAddPropertyMap() -> AddPropertyMap { - if (type==CElementTexture::Type::SCALE) - { - if (_property.type!=SPropertyElementData::Type::FLOAT) - return false; - scale.scale = _property.fvalue; - return true; - } - + using this_t = CElementTexture; + AddPropertyMap retval; - bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) + // bitmap + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,std::is_same,Bitmap) { - case CElementTexture::Type::BITMAP: - func(bitmap); - break; - case CElementTexture::Type::SCALE: - func(scale); - break; - default: - error = true; - break; + setLimitedString("filename",_this->bitmap.filename,std::move(_property),logger); return true; } - }; - -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ - } \ - }); \ - } - - auto processFilename = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - bitmap.filename = std::move(_property); - } - }); - }; - auto getWrapMode = [&]() -> Bitmap::WRAP_MODE { - static const core::unordered_map StringToWrap = + ); + // special + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("wrapMode",STRING,std::is_same,Bitmap) { - {"repeat", Bitmap::WRAP_MODE::REPEAT}, - {"mirror", Bitmap::WRAP_MODE::MIRROR}, - {"clamp", Bitmap::WRAP_MODE::CLAMP}, - {"zero", Bitmap::WRAP_MODE::ZERO}, - {"one", Bitmap::WRAP_MODE::ONE} - }; - auto found = StringToWrap.end(); - if (_property.type == SPropertyElementData::Type::STRING) - found = StringToWrap.find(_property.getProperty()); - if (found != StringToWrap.end()) - return found->second; - return Bitmap::WRAP_MODE::REPEAT; - }; - auto processWrapMode = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - auto value = getWrapMode(); - state.wrapModeU = value; - state.wrapModeV = value; - } - }); - }; - auto processWrapModeU = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - state.wrapModeU = getWrapMode(); - } - }); - }; - auto processWrapModeV = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - state.wrapModeV = getWrapMode(); - } - }); - }; - auto processGamma = SET_PROPERTY_TEMPLATE(gamma,SPropertyElementData::Type::FLOAT,Bitmap); - auto processFilterType = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) + _this->bitmap.wrapModeV = _this->bitmap.wrapModeU = getWrapMode(_property); + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("wrapModeU",STRING,std::is_same,Bitmap) + { + _this->bitmap.wrapModeU = getWrapMode(_property); + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("wrapModeV",STRING,std::is_same,Bitmap) + { + _this->bitmap.wrapModeV = getWrapMode(_property); + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(gamma,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filterType",STRING,std::is_same,Bitmap) + { + static const core::unordered_map StringToType = { - static const core::unordered_map StringToType = - { - {"ewa", Bitmap::FILTER_TYPE::EWA}, - {"trilinear", Bitmap::FILTER_TYPE::TRILINEAR}, - {"nearest", Bitmap::FILTER_TYPE::NEAREST} - }; - auto found = StringToType.end(); - if (_property.type==SPropertyElementData::Type::STRING) - found = StringToType.find(_property.getProperty()); - if (found==StringToType.end()) - { - error = true; - return; - } - state.filterType = found->second; - } - }); - }; - auto processMaxAnisotropy = SET_PROPERTY_TEMPLATE(maxAnisotropy,SPropertyElementData::Type::FLOAT,Bitmap); - auto processCache = []() -> void {}; // silently drop - auto processUoffset = SET_PROPERTY_TEMPLATE(uoffset,SPropertyElementData::Type::FLOAT,Bitmap); - auto processVoffset = SET_PROPERTY_TEMPLATE(voffset,SPropertyElementData::Type::FLOAT,Bitmap); - auto processUscale = SET_PROPERTY_TEMPLATE(uscale,SPropertyElementData::Type::FLOAT,Bitmap); - auto processVscale = SET_PROPERTY_TEMPLATE(vscale,SPropertyElementData::Type::FLOAT,Bitmap); - auto processChannel = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) + {"ewa", Bitmap::FILTER_TYPE::EWA}, + {"trilinear", Bitmap::FILTER_TYPE::TRILINEAR}, + {"nearest", Bitmap::FILTER_TYPE::NEAREST} + }; + auto found = StringToType.find(_property.getProperty()); + if (found==StringToType.end()) + return false; + _this->bitmap.filterType = found->second; + return true; + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(maxAnisotropy,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("cache",BOOLEAN,std::is_same,Bitmap) + { + return true; // silently drop + } + ); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(uoffset,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(voffset,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(uscale,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(vscale,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(vscale,FLOAT,std::is_same,Bitmap); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,std::is_same,Bitmap) + { + static const core::unordered_map StringToType = { - static const core::unordered_map StringToType = - { - {"r", Bitmap::CHANNEL::R}, - {"g", Bitmap::CHANNEL::G}, - {"b", Bitmap::CHANNEL::B}, - {"a", Bitmap::CHANNEL::A}/*, - {"x", Bitmap::CHANNEL::X}, - {"y", Bitmap::CHANNEL::Y}, - {"z", Bitmap::CHANNEL::Z}*/ - }; - auto found = StringToType.end(); - if (_property.type == SPropertyElementData::Type::STRING) - found = StringToType.find(_property.getProperty()); - if (found == StringToType.end()) - { - error = true; - return; - } - state.channel = found->second; - } - }); - }; - + {"r", Bitmap::CHANNEL::R}, + {"g", Bitmap::CHANNEL::G}, + {"b", Bitmap::CHANNEL::B}, + {"a", Bitmap::CHANNEL::A}/*, + {"x", Bitmap::CHANNEL::X}, + {"y", Bitmap::CHANNEL::Y}, + {"z", Bitmap::CHANNEL::Z}*/ + }; + auto found = StringToType.find(_property.getProperty()); + if (found==StringToType.end()) + return false; + _this->bitmap.channel = found->second; + return true; + } + ); - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - {"filename", processFilename}, - {"wrapMode", processWrapMode}, - {"wrapModeU", processWrapModeU}, - {"wrapModeV", processWrapModeV}, - {"gamma", processGamma}, - {"filterType", processFilterType}, - {"maxAnisotropy", processMaxAnisotropy}, - {"cache", processCache}, - {"uoffset", processUoffset}, - {"voffset", processVoffset}, - {"uscale", processUscale}, - {"vscale", processVscale}, - {"channel", processChannel} - }; - - auto found = SetPropertyMap.find(_property.name); - if (found==SetPropertyMap.end()) - { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("No BSDF can have such property set with name: "+_property.name); - return false; - } + // scale + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(scale,FLOAT,std::is_same,Scale); - found->second(); - return !error; + return retval; } -bool CElementTexture::processChildData(IElement* _child, const std::string& name) +bool CElementTexture::processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) { if (!_child) return true; @@ -267,17 +130,16 @@ bool CElementTexture::processChildData(IElement* _child, const std::string& name break; default: _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("No supported texture can have a texture as child element, except for \"scale\""); + logger.log("Only can have nested elements",system::ILogger::ELL_ERROR); return false; - break; } } - break; + return true; default: - return false; break; } - return true; + logger.log(" does not support nested <%s> elements",system::ILogger::ELL_ERROR,type,_child->getLogName()); + return false; } bool CElementTexture::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index 6db96f452f..ab88a11cb4 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -11,9 +11,13 @@ .func=[](this_t* _this, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger)->bool // when you know that there's a member of `this_t` with identifier equal to NAME -#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_SIMPLE_ADD_PROPERTY(NAME,PROP_TYPE) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(#NAME,PROP_TYPE) \ + {\ + _this->NAME = _property.getProperty(); \ + return true; \ + } \ + } \ +) // Similar to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` but for `this_t` which declare `variant_list_t` (list of union types) // this adds a compile-time filter against the constraint, such that only variant types matching the constraint are visited. @@ -21,13 +25,29 @@ #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 +// TODO: docs +#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED(#NAME,PROP_TYPE,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + {\ + bool success = false; \ + _this->visit([&_property,&success](auto& state)->void \ + { \ + if constexpr (CONSTRAINT __VA_OPT__(,) __VA_ARGS__>::value) \ + { + +#define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END \ + } \ + } \ + ); \ + return success; \ + } \ +) + // This it to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED` what `NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY` is to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` // So basically you know the member is the same across the constraint filtered types -#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_OPT__(,) __VA_ARGS__) {\ - _this->visit([&_property](auto& state)->void{ \ - if constexpr (CONSTRAINT __VA_OPT__(,) __VA_ARGS__>::value) \ - state. ## NAME = _property.getProperty(); \ - }); return true;}) +#define NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## NAME = _property.getProperty(); \ + success = true; \ +NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END // just to reverse `is_base_of` From 4fc80d8c148833a662dac22eb8284309a5c2fc24 Mon Sep 17 00:00:00 2001 From: devsh Date: Tue, 23 Dec 2025 17:54:00 +0100 Subject: [PATCH 25/30] CElementBSDF is done! also fix typos in CElementTexture --- include/nbl/core/string/stringutil.h | 4 +- include/nbl/ext/MitsubaLoader/CElementBSDF.h | 274 ++++-- .../ext/MitsubaLoader/CElementIntegrator.h | 3 +- .../nbl/ext/MitsubaLoader/CElementTexture.h | 61 +- include/nbl/ext/MitsubaLoader/IElement.h | 17 +- include/nbl/ext/MitsubaLoader/ParserUtil.h | 6 +- src/nbl/ext/MitsubaLoader/CElementBSDF.cpp | 919 +++++------------- .../MitsubaLoader/CElementEmissionProfile.cpp | 7 +- src/nbl/ext/MitsubaLoader/CElementEmitter.cpp | 52 +- src/nbl/ext/MitsubaLoader/CElementFilm.cpp | 8 +- .../ext/MitsubaLoader/CElementIntegrator.cpp | 5 +- src/nbl/ext/MitsubaLoader/CElementShape.cpp | 2 +- src/nbl/ext/MitsubaLoader/CElementTexture.cpp | 5 +- src/nbl/ext/MitsubaLoader/CMakeLists.txt | 6 +- src/nbl/ext/MitsubaLoader/ElementMacros.h | 4 +- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 13 +- 16 files changed, 571 insertions(+), 815 deletions(-) diff --git a/include/nbl/core/string/stringutil.h b/include/nbl/core/string/stringutil.h index 3183ef149b..0eb9628250 100644 --- a/include/nbl/core/string/stringutil.h +++ b/include/nbl/core/string/stringutil.h @@ -180,7 +180,7 @@ namespace core //! DOCUMENTATION TODO struct CaseInsensitiveHash { - inline std::size_t operator()(const std::string& val) const + inline std::size_t operator()(const std::string_view val) const { std::size_t seed = 0; for (auto it = val.begin(); it != val.end(); it++) @@ -192,7 +192,7 @@ namespace core }; struct CaseInsensitiveEquals { - inline bool operator()(const std::string& A, const std::string& B) const + inline bool operator()(const std::string_view A, const std::string_view B) const { return core::strcmpi(A, B)==0; } diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index 0873c6e41d..432064b847 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -29,6 +29,7 @@ class CElementBSDF : public IElement COATING, ROUGHCOATING, BUMPMAP, + NORMALMAP, PHONG, WARD, MIXTURE_BSDF, @@ -39,9 +40,39 @@ class CElementBSDF : public IElement //HANRAHAN_KRUEGER, //IRAWAN_MARSCHNER }; + static inline core::unordered_map compStringToTypeMap() + { + return { + {"diffuse", CElementBSDF::Type::DIFFUSE}, + {"roughdiffuse", CElementBSDF::Type::ROUGHDIFFUSE}, + {"dielectric", CElementBSDF::Type::DIELECTRIC}, + {"thindielectric", CElementBSDF::Type::THINDIELECTRIC}, + {"roughdielectric", CElementBSDF::Type::ROUGHDIELECTRIC}, + {"conductor", CElementBSDF::Type::CONDUCTOR}, + {"roughconductor", CElementBSDF::Type::ROUGHCONDUCTOR}, + {"plastic", CElementBSDF::Type::PLASTIC}, + {"roughplastic", CElementBSDF::Type::ROUGHPLASTIC}, + {"coating", CElementBSDF::Type::COATING}, + {"roughcoating", CElementBSDF::Type::ROUGHCOATING}, + {"bumpmap", CElementBSDF::Type::BUMPMAP}, + {"normalmap", CElementBSDF::Type::NORMALMAP}, + {"phong", CElementBSDF::Type::PHONG}, + {"ward", CElementBSDF::Type::WARD}, + {"mixturebsdf", CElementBSDF::Type::MIXTURE_BSDF}, + {"blendbsdf", CElementBSDF::Type::BLEND_BSDF}, + {"mask", CElementBSDF::Type::MASK}, + {"twosided", CElementBSDF::Type::TWO_SIDED}, + {"difftrans", CElementBSDF::Type::DIFFUSE_TRANSMITTER}//, + //{"hk", CElementBSDF::Type::HANRAHAN_KRUEGER}, + //{"irawan", CElementBSDF::Type::IRAWAN_MARSCHNER} + }; + } + struct DiffuseTransmitter { - DiffuseTransmitter() : transmittance(0.5f) {} + constexpr static inline Type VariantType = Type::DIFFUSE_TRANSMITTER; + + inline DiffuseTransmitter() : transmittance(0.5f) {} inline DiffuseTransmitter& operator=(const DiffuseTransmitter& other) { @@ -53,8 +84,8 @@ class CElementBSDF : public IElement }; struct AllDiffuse { - AllDiffuse() : reflectance(0.5f), alpha(0.2f), useFastApprox(false) {} - ~AllDiffuse() {} + inline AllDiffuse() : reflectance(0.5f), alpha(0.2f), useFastApprox(false) {} + inline ~AllDiffuse() {} inline AllDiffuse& operator=(const AllDiffuse& other) { @@ -72,6 +103,14 @@ class CElementBSDF : public IElement CElementTexture::FloatOrTexture alpha; // not the parameter from Oren-Nayar bool useFastApprox; }; + struct Diffuse : AllDiffuse + { + constexpr static inline Type VariantType = Type::DIFFUSE; + }; + struct RoughDiffuse : AllDiffuse + { + constexpr static inline Type VariantType = Type::ROUGHDIFFUSE; + }; struct RoughSpecularBase { enum NormalDistributionFunction : uint32_t @@ -82,13 +121,13 @@ class CElementBSDF : public IElement ASHIKHMIN_SHIRLEY }; - RoughSpecularBase(float defaultAlpha) : distribution(GGX), specularReflectance(1.f), + inline RoughSpecularBase(float defaultAlpha) : distribution(GGX), specularReflectance(1.f), // union ignores ctors, and ctors are important to not try to free garbage strings alphaU(core::nan()), alphaV(core::nan()) { alpha = defaultAlpha; } - virtual ~RoughSpecularBase() {} + virtual inline ~RoughSpecularBase() {} inline RoughSpecularBase& operator=(const RoughSpecularBase& other) { @@ -119,12 +158,40 @@ class CElementBSDF : public IElement }; CElementTexture::SpectrumOrTexture specularReflectance; }; + struct AllConductor : RoughSpecularBase + { + inline AllConductor() : AllConductor("cu",nullptr) {} + inline AllConductor(const std::string_view material, system::logger_opt_ptr logger); + inline AllConductor(SPropertyElementData&& _eta, SPropertyElementData&& _k, system::logger_opt_ptr logger) : + RoughSpecularBase(0.1f), eta(_eta), k(_k), extEta(TransmissiveBase::findIOR("air",logger)) {} + + inline AllConductor& operator=(const AllConductor& other) + { + RoughSpecularBase::operator=(other); + eta = other.eta; + k = other.k; + extEta = other.extEta; + return *this; + } + + SPropertyElementData eta,k; + float extEta; + }; + struct Conductor : AllConductor + { + constexpr static inline Type VariantType = Type::CONDUCTOR; + }; + struct RoughConductor : AllConductor + { + constexpr static inline Type VariantType = Type::ROUGHCONDUCTOR; + }; struct TransmissiveBase { - static float findIOR(const std::string& name); + static float findIOR(const std::string_view name, system::logger_opt_ptr logger); - TransmissiveBase(float _intIOR, float _extIOR) : intIOR(_intIOR), extIOR(_extIOR), specularTransmittance(1.f) {} - TransmissiveBase(const std::string& _intIOR, const std::string& _extIOR) : TransmissiveBase(findIOR(_intIOR), findIOR(_extIOR)) {} + inline TransmissiveBase(float _intIOR, float _extIOR) : intIOR(_intIOR), extIOR(_extIOR), specularTransmittance(1.f) {} + inline TransmissiveBase(const std::string_view _intIOR, const std::string_view _extIOR, system::logger_opt_ptr logger) : + TransmissiveBase(findIOR(_intIOR,logger), findIOR(_extIOR,logger)) {} inline TransmissiveBase& operator=(const TransmissiveBase& other) { @@ -140,9 +207,10 @@ class CElementBSDF : public IElement }; struct AllDielectric : RoughSpecularBase, TransmissiveBase { - AllDielectric() : RoughSpecularBase(0.1f), TransmissiveBase("bk7","air") {} - AllDielectric(float intIOR, float extIOR) : RoughSpecularBase(0.1f), TransmissiveBase(intIOR,extIOR) {} - AllDielectric(const std::string& intIOR, const std::string& extIOR) : RoughSpecularBase(0.1f), TransmissiveBase(intIOR,extIOR) {} + inline AllDielectric() : RoughSpecularBase(0.1f), TransmissiveBase("bk7","air",nullptr) {} + inline AllDielectric(float intIOR, float extIOR) : RoughSpecularBase(0.1f), TransmissiveBase(intIOR,extIOR) {} + inline AllDielectric(const std::string_view intIOR, const std::string_view extIOR, system::logger_opt_ptr logger) : + RoughSpecularBase(0.1f), TransmissiveBase(intIOR,extIOR,logger) {} inline AllDielectric& operator=(const AllDielectric& other) { @@ -151,29 +219,25 @@ class CElementBSDF : public IElement return *this; } }; - struct AllConductor : RoughSpecularBase + struct Dielectric : AllDielectric { - AllConductor() : AllConductor("cu") {} - AllConductor(const std::string& material); - AllConductor(SPropertyElementData&& _eta, SPropertyElementData&& _k) : RoughSpecularBase(0.1f), eta(_eta), k(_k), extEta(TransmissiveBase::findIOR("air")) {} - - inline AllConductor& operator=(const AllConductor& other) - { - RoughSpecularBase::operator=(other); - eta = other.eta; - k = other.k; - extEta = other.extEta; - return *this; - } - - SPropertyElementData eta,k; - float extEta; + constexpr static inline Type VariantType = Type::DIELECTRIC; + }; + struct ThinDielectric : AllDielectric + { + constexpr static inline Type VariantType = Type::THINDIELECTRIC; + }; + struct RoughDielectric : AllDielectric + { + constexpr static inline Type VariantType = Type::ROUGHDIELECTRIC; }; struct AllPlastic : RoughSpecularBase, TransmissiveBase { - AllPlastic() : RoughSpecularBase(0.1f), TransmissiveBase("polypropylene", "air"), nonlinear(false) {} - AllPlastic(float intIOR, float extIOR) : RoughSpecularBase(0.1f), TransmissiveBase(intIOR, extIOR), nonlinear(false) {} - AllPlastic(const std::string& intIOR, const std::string& extIOR) : RoughSpecularBase(0.1f), TransmissiveBase(intIOR, extIOR), nonlinear(false) {} + inline AllPlastic() : RoughSpecularBase(0.1f), TransmissiveBase("polypropylene","air",nullptr), nonlinear(false) {} + inline AllPlastic(float intIOR, float extIOR) : + RoughSpecularBase(0.1f), TransmissiveBase(intIOR,extIOR), nonlinear(false) {} + inline AllPlastic(const std::string_view intIOR, const std::string_view extIOR, system::logger_opt_ptr logger) : + RoughSpecularBase(0.1f), TransmissiveBase(intIOR,extIOR,logger), nonlinear(false) {} inline AllPlastic& operator=(const AllPlastic& other) { @@ -186,13 +250,21 @@ class CElementBSDF : public IElement bool nonlinear; CElementTexture::SpectrumOrTexture diffuseReflectance = 0.5f; + }; + struct Plastic : AllPlastic + { + constexpr static inline Type VariantType = Type::PLASTIC; + }; + struct RoughPlastic : AllPlastic + { + constexpr static inline Type VariantType = Type::ROUGHPLASTIC; };/* struct HanrahanKrueger { class CPhaseElement { }; - HanrahanKrueger(const std::string& material); + HanrahanKrueger(const std::string_view material); HanrahanKrueger() : HanrahanKrueger("skin1") {} bool tNOTs = false; @@ -214,15 +286,16 @@ class CElementBSDF : public IElement };*/ struct MetaBSDF { - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxChildCount = 32u; + constexpr static inline size_t MaxChildCount = 32u; size_t childCount = 0u; CElementBSDF* bsdf[MaxChildCount] = { nullptr }; }; struct AllCoating : MetaBSDF, RoughSpecularBase, TransmissiveBase { - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxChildCount = 1u; + constexpr static inline size_t MaxChildCount = 1u; - AllCoating() : MetaBSDF(), RoughSpecularBase(0.1f), TransmissiveBase("bk7","air"), thickness(1.f), sigmaA(0.f) {} + inline AllCoating() final : MetaBSDF(), RoughSpecularBase(0.1f), + TransmissiveBase("bk7","air",nullptr), thickness(1.f), sigmaA(0.f) {} inline AllCoating& operator=(const AllCoating& other) { @@ -237,45 +310,69 @@ class CElementBSDF : public IElement float thickness; CElementTexture::SpectrumOrTexture sigmaA; }; - struct BumpMap : MetaBSDF + struct Coating final : AllCoating + { + constexpr static inline Type VariantType = Type::COATING; + }; + struct RoughCoating final : AllCoating + { + constexpr static inline Type VariantType = Type::ROUGHCOATING; + }; + struct BumpMap final : MetaBSDF { - CElementTexture* texture; - bool wasNormal; + constexpr static inline Type VariantType = Type::BUMPMAP; + + CElementTexture* texture = nullptr; + }; + struct NormalMap final : MetaBSDF + { + constexpr static inline Type VariantType = Type::NORMALMAP; + + CElementTexture* texture = nullptr; }; - struct MixtureBSDF : MetaBSDF + struct MixtureBSDF final : MetaBSDF { + constexpr static inline Type VariantType = Type::MIXTURE_BSDF; + uint32_t weightCount = 0u; float weights[MetaBSDF::MaxChildCount] = { 1.f }; }; - struct BlendBSDF : MetaBSDF + struct BlendBSDF final : MetaBSDF { - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxChildCount = 2u; + constexpr static inline Type VariantType = Type::BLEND_BSDF; + constexpr static inline size_t MaxChildCount = 2u; - BlendBSDF() : weight(0.5f) {} + inline BlendBSDF() : weight(0.5f) {} CElementTexture::SpectrumOrTexture weight; }; - struct Mask : MetaBSDF + struct Mask final : MetaBSDF { - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxChildCount = 1u; + constexpr static inline Type VariantType = Type::MASK; + constexpr static inline size_t MaxChildCount = 1u; - Mask() : opacity(0.5f) {} + inline Mask() : opacity(0.5f) {} CElementTexture::SpectrumOrTexture opacity; }; - struct TwoSided : MetaBSDF + struct TwoSided final : MetaBSDF { - _NBL_STATIC_INLINE_CONSTEXPR size_t MaxChildCount = 1u; + constexpr static inline Type VariantType = Type::TWO_SIDED; + constexpr static inline size_t MaxChildCount = 1u; }; // legacy and evil struct Phong { + constexpr static inline Type VariantType = Type::PHONG; + CElementTexture::FloatOrTexture exponent = 30.f; CElementTexture::SpectrumOrTexture specularReflectance = 0.2f; CElementTexture::SpectrumOrTexture diffuseReflectance = 0.5f; }; struct Ward { + constexpr static inline Type VariantType = Type::WARD; + enum Type : uint32_t { WARD, @@ -288,7 +385,32 @@ class CElementBSDF : public IElement CElementTexture::SpectrumOrTexture specularReflectance = 0.2f; CElementTexture::SpectrumOrTexture diffuseReflectance = 0.5f; }; - + + // + using variant_list_t = core::type_list< + Diffuse, + RoughDiffuse, + Dielectric, + ThinDielectric, + RoughDielectric, + Conductor, + RoughConductor, + Plastic, + RoughPlastic, + Coating, + RoughCoating, + BumpMap, + NormalMap, + Phong, + Ward, + MixtureBSDF, + BlendBSDF, + Mask, + TwoSided, + DiffuseTransmitter/*, + HanrahanKrueger, + IrawanMarschner*/ + >; // static AddPropertyMap compAddPropertyMap(); @@ -304,72 +426,90 @@ class CElementBSDF : public IElement { } - inline CElementBSDF& operator=(const CElementBSDF& other) + template + inline void visit(Visitor&& func) { - IElement::operator=(other); - type = other.type; switch (type) { case CElementBSDF::Type::DIFFUSE: [[fallthrough]]; case CElementBSDF::Type::ROUGHDIFFUSE: - diffuse = other.diffuse; + func(diffuse); break; case CElementBSDF::Type::DIELECTRIC: [[fallthrough]]; case CElementBSDF::Type::THINDIELECTRIC: [[fallthrough]]; case CElementBSDF::Type::ROUGHDIELECTRIC: - dielectric = other.dielectric; + func(dielectric); break; case CElementBSDF::Type::CONDUCTOR: [[fallthrough]]; case CElementBSDF::Type::ROUGHCONDUCTOR: - conductor = other.conductor; + func(conductor); break; case CElementBSDF::Type::PLASTIC: [[fallthrough]]; case CElementBSDF::Type::ROUGHPLASTIC: - plastic = other.plastic; + func(plastic); break; case CElementBSDF::Type::COATING: [[fallthrough]]; case CElementBSDF::Type::ROUGHCOATING: - coating = other.coating; + func(coating); break; case CElementBSDF::Type::BUMPMAP: - bumpmap = other.bumpmap; + func(bumpmap); + break; + case CElementBSDF::Type::NORMALMAP: + func(normalmap); break; case CElementBSDF::Type::PHONG: - phong = other.phong; + func(phong); break; case CElementBSDF::Type::WARD: - ward = other.ward; + func(ward); break; case CElementBSDF::Type::MIXTURE_BSDF: - mixturebsdf = other.mixturebsdf; + func(mixturebsdf); break; case CElementBSDF::Type::BLEND_BSDF: - blendbsdf = other.blendbsdf; + func(blendbsdf); break; case CElementBSDF::Type::MASK: - mask = other.mask; + func(mask); break; case CElementBSDF::Type::TWO_SIDED: - twosided = other.twosided; + func(twosided); break; case CElementBSDF::Type::DIFFUSE_TRANSMITTER: - difftrans = other.difftrans; + func(difftrans); break; //case CElementBSDF::Type::HANRAHAN_KRUEGER: - //hk = HanrahanKrueger(); + //func(hk); //break; //case CElementBSDF::Type::IRAWAN_MARSCHNER: - //irawan = IrawanMarschner(); + //func(irwan); //break; default: break; } + } + template + inline void visit(Visitor&& visitor) const + { + const_cast(this)->visit([&](T& var)->void + { + visitor(const_cast(var)); + } + ); + } + + inline CElementBSDF& operator=(const CElementBSDF& other) + { + IElement::operator=(other); + type = other.type; + IElement::copyVariant(this,&other); return *this; } @@ -391,7 +531,8 @@ class CElementBSDF : public IElement case MASK: [[fallthrough]]; case BLEND_BSDF: [[fallthrough]]; case MIXTURE_BSDF: [[fallthrough]]; - case BUMPMAP: + case BUMPMAP: [[fallthrough]]; + case NORMALMAP: return true; default: return false; @@ -409,6 +550,7 @@ class CElementBSDF : public IElement AllPlastic plastic; AllCoating coating; BumpMap bumpmap; + NormalMap normalmap; Phong phong; Ward ward; MixtureBSDF mixturebsdf; diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index b3061ba380..875bb08378 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -212,7 +212,8 @@ class CElementIntegrator final : public IElement } Type field; - SPropertyElementData undefined; // TODO: test destructor runs + // TODO: Specral properties really need a redo + SPropertyElementData undefined; }; struct MetaIntegrator { diff --git a/include/nbl/ext/MitsubaLoader/CElementTexture.h b/include/nbl/ext/MitsubaLoader/CElementTexture.h index 5381920a38..bf986f4ddb 100644 --- a/include/nbl/ext/MitsubaLoader/CElementTexture.h +++ b/include/nbl/ext/MitsubaLoader/CElementTexture.h @@ -17,59 +17,40 @@ class CElementTexture : public IElement public: struct FloatOrTexture { - FloatOrTexture(CElementTexture* _tex) + inline FloatOrTexture(CElementTexture* _tex) { - value.type = SPropertyElementData::Type::INVALID; + value = std::numeric_limits::quiet_NaN(); texture = _tex; } - FloatOrTexture(float _value) + inline FloatOrTexture(const float _value) { - value.type = SPropertyElementData::Type::FLOAT; - value.fvalue = _value; + value = _value; texture = nullptr; } - FloatOrTexture(const SPropertyElementData& _other) : FloatOrTexture(nullptr) - { - operator=(_other); - } - FloatOrTexture(SPropertyElementData&& _other) : FloatOrTexture(nullptr) - { - operator=(std::move(_other)); - } - inline FloatOrTexture& operator=(const SPropertyElementData& _other) - { - return operator=(SPropertyElementData(_other)); - } - inline FloatOrTexture& operator=(SPropertyElementData&& _other) - { - switch (_other.type) - { - case SPropertyElementData::Type::INVALID: - case SPropertyElementData::Type::FLOAT: - value = std::move(_other); - break; - default: - _NBL_DEBUG_BREAK_IF(true); - break; - } - return *this; - } + inline FloatOrTexture(const FloatOrTexture&) = default; - SPropertyElementData value = {}; - CElementTexture* texture = nullptr; // only used if value.type==INVALID + inline FloatOrTexture& operator=(const FloatOrTexture&) = default; + + float value = 0.f; + CElementTexture* texture = nullptr; }; - struct SpectrumOrTexture : FloatOrTexture + struct SpectrumOrTexture { - SpectrumOrTexture(CElementTexture* _tex) : FloatOrTexture(_tex) {} - SpectrumOrTexture(float _value) : FloatOrTexture(_value) {} - SpectrumOrTexture(const SPropertyElementData& _other) : SpectrumOrTexture(nullptr) + inline SpectrumOrTexture(CElementTexture* _tex) + { + value.type = SPropertyElementData::Type::INVALID; + texture = _tex; + } + inline SpectrumOrTexture(const SPropertyElementData& _other) : SpectrumOrTexture(nullptr) { operator=(_other); } - SpectrumOrTexture(SPropertyElementData&& _other) : SpectrumOrTexture(nullptr) + inline SpectrumOrTexture(SPropertyElementData&& _other) : SpectrumOrTexture(nullptr) { operator=(std::move(_other)); } + inline SpectrumOrTexture(const float _value) : SpectrumOrTexture(SPropertyElementData{_value}) {} + inline SpectrumOrTexture& operator=(const SPropertyElementData& _other) { return operator=(SPropertyElementData(_other)); @@ -90,8 +71,12 @@ class CElementTexture : public IElement _NBL_DEBUG_BREAK_IF(true); break; } + texture = nullptr; return *this; } + + SPropertyElementData value = {}; + CElementTexture* texture = nullptr; }; enum Type diff --git a/include/nbl/ext/MitsubaLoader/IElement.h b/include/nbl/ext/MitsubaLoader/IElement.h index f4b9b09ebb..a09761e87f 100644 --- a/include/nbl/ext/MitsubaLoader/IElement.h +++ b/include/nbl/ext/MitsubaLoader/IElement.h @@ -196,12 +196,27 @@ class IElement std::array,SNamedPropertyElement::Type::INVALID> byPropertyType = {}; }; + // + template + struct ProcessChildCallback + { + using element_t = Derived; + // TODO: list or map of supported variants (if `visit` is present) + using func_t = bool(*)(Derived*,IElement* _child,const system::logger_opt_ptr); + + inline bool operator()(Derived* d, IElement* _child, const system::logger_opt_ptr l) const {return func(d,_child,l);} + + func_t func; + // TODO: allowed IElement types + }; + template + using ProcessChildCallbackMap = core::unordered_map,core::CaseInsensitiveHash,core::CaseInsensitiveEquals>; // members std::string id; protected: - static inline void setLimitedString(const std::string_view memberName, std::span out, SNamedPropertyElement&& _property, const system::logger_opt_ptr logger) + static inline void setLimitedString(const std::string_view memberName, std::span out, const SNamedPropertyElement& _property, const system::logger_opt_ptr logger) { auto len = strlen(_property.svalue); if (len>=out.size()) diff --git a/include/nbl/ext/MitsubaLoader/ParserUtil.h b/include/nbl/ext/MitsubaLoader/ParserUtil.h index 3ac2c6fe4d..787c1a534a 100644 --- a/include/nbl/ext/MitsubaLoader/ParserUtil.h +++ b/include/nbl/ext/MitsubaLoader/ParserUtil.h @@ -88,9 +88,9 @@ class ParserManager final CElementSampler, CElementShape, CElementTransform, -/// CElementBSDF, -/// CElementTexture, -/// CElementEmitter, + CElementBSDF, + CElementTexture, + CElementEmitter, CElementEmissionProfile >; diff --git a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp index 93187d723f..3790e89748 100644 --- a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp @@ -1,140 +1,197 @@ // 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/CElementBSDF.h" + +#include "nbl/ext/MitsubaLoader/ElementMacros.h" -#include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" +#include "nbl/builtin/hlsl/complex.hlsl" +#include "nbl/type_traits.h" // legacy stuff for `is_any_of` #include -namespace nbl + +namespace nbl::ext::MitsubaLoader { -namespace ext +namespace impl { -namespace MitsubaLoader +template +struct has_alpha { + constexpr static bool value = std::is_base_of_v || std::is_base_of_v; +}; +template +struct has_diffuseReflectance +{ + constexpr static bool value = std::is_base_of_v || std::is_base_of_v || + std::is_same_v || std::is_same_v; +}; +template +struct can_have_isotropicNDF +{ + constexpr static bool value = std::is_base_of_v || std::is_same_v; +}; +template +struct has_specularReflectance +{ + constexpr static bool value = std::is_base_of_v || std::is_same_v || + std::is_same_v; +}; +} - -template<> -CElementFactory::return_type CElementFactory::createElement(const char** _atts, ParserManager* _util) +auto CElementBSDF::compAddPropertyMap() -> AddPropertyMap { - const char* type; - const char* id; - std::string name; - if (!IElement::getTypeIDAndNameStrings(type, id, name, _atts)) - return CElementFactory::return_type(nullptr, ""); + using this_t = CElementBSDF; + AddPropertyMap retval; + +// spectrum setting +#define ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(MEMBER,CONSTRAINT,...) { \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,FLOAT,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = std::move(_property); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,RGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = std::move(_property); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SRGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = std::move(_property); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SPECTRUM,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = std::move(_property); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ +} - static const core::unordered_map StringToType = - { - {"diffuse", CElementBSDF::Type::DIFFUSE}, - {"roughdiffuse", CElementBSDF::Type::ROUGHDIFFUSE}, - {"dielectric", CElementBSDF::Type::DIELECTRIC}, - {"thindielectric", CElementBSDF::Type::THINDIELECTRIC}, - {"roughdielectric", CElementBSDF::Type::ROUGHDIELECTRIC}, - {"conductor", CElementBSDF::Type::CONDUCTOR}, - {"roughconductor", CElementBSDF::Type::ROUGHCONDUCTOR}, - {"plastic", CElementBSDF::Type::PLASTIC}, - {"roughplastic", CElementBSDF::Type::ROUGHPLASTIC}, - {"coating", CElementBSDF::Type::COATING}, - {"roughcoating", CElementBSDF::Type::ROUGHCOATING}, - {"bumpmap", CElementBSDF::Type::BUMPMAP}, - {"normalmap", CElementBSDF::Type::BUMPMAP}, - {"phong", CElementBSDF::Type::PHONG}, - {"ward", CElementBSDF::Type::WARD}, - {"mixturebsdf", CElementBSDF::Type::MIXTURE_BSDF}, - {"blendbsdf", CElementBSDF::Type::BLEND_BSDF}, - {"mask", CElementBSDF::Type::MASK}, - {"twosided", CElementBSDF::Type::TWO_SIDED}, - {"difftrans", CElementBSDF::Type::DIFFUSE_TRANSMITTER}//, - //{"hk", CElementBSDF::Type::HANRAHAN_KRUEGER}, - //{"irawan", CElementBSDF::Type::IRAWAN_MARSCHNER} - }; + // diff trans + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(transmittance,std::is_same,DiffuseTransmitter); - auto found = StringToType.find(type); - if (found==StringToType.end()) - { - ParserLog::invalidXMLFileStructure("unknown type"); - _NBL_DEBUG_BREAK_IF(false); - return CElementFactory::return_type(nullptr, ""); - } + // diffuse + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(reflectance,derived_from,AllDiffuse); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(diffuseReflectance,impl::has_diffuseReflectance); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(alpha,FLOAT,impl::has_alpha); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(useFastApprox,BOOLEAN,derived_from,AllDiffuse); - CElementBSDF* obj = _util->objects.construct(id); - if (!obj) - return CElementFactory::return_type(nullptr, ""); + // specular base + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(distribution,STRING,derived_from,RoughSpecularBase) + using ndf_e = RoughSpecularBase::NormalDistributionFunction; + static const core::unordered_map StringToType = + { + {"beckmann",ndf_e::BECKMANN}, + {"ggx", ndf_e::GGX}, + {"phong", ndf_e::PHONG}, + {"as", ndf_e::ASHIKHMIN_SHIRLEY} + }; + auto found = StringToType.find(_property.getProperty()); + if (found==StringToType.end()) + return; + state.distribution = found->second; + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; + // COMMON: alpha + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(alphaU,FLOAT,impl::can_have_isotropicNDF); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(alphaV,FLOAT,impl::can_have_isotropicNDF); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(specularReflectance,impl::has_specularReflectance); + + // conductor + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(eta,derived_from,AllConductor); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(k,derived_from,AllConductor); + // adding twice cause two property types are allowed + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(extEta,FLOAT,derived_from,AllConductor) + state.extEta = TransmissiveBase::findIOR(_property.getProperty(),logger); + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; + // special + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(material,STRING,derived_from,AllConductor) + state = AllConductor(_property.getProperty(),logger); + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; + + // transmissive base + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(intIOR,FLOAT,derived_from,TransmissiveBase); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(extIOR,FLOAT,derived_from,TransmissiveBase); + // adding twice cause two property types are allowed + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(intIOR,STRING,derived_from,TransmissiveBase) + state.intIOR = TransmissiveBase::findIOR(_property.getProperty(),logger); + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(extIOR,STRING,derived_from,TransmissiveBase) + state.extIOR = TransmissiveBase::findIOR(_property.getProperty(),logger); + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(specularTransmittance,derived_from,TransmissiveBase); + + // plastic + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(nonlinear,BOOLEAN,derived_from,AllPlastic); + // COMMON: diffuseReflectance + + // coating + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(thickness,FLOAT,derived_from,AllCoating); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(sigmaA,derived_from,AllCoating); + + // bumpmap + // normalmap + + // mixture + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(weights,STRING,std::is_same,MixtureBSDF) + std::istringstream sstr(_property.svalue); + std::string token; + while (std::getline(sstr,token,',')) + { + if (state.weightCount) + { + logger.log(" MaxChildCount of %d exceeded!",system::ILogger::ELL_ERROR,MetaBSDF::MaxChildCount); + break; + } + state.weights[state.weightCount++] = std::stof(token); + } + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; - obj->type = found->second; - // defaults - switch (obj->type) - { - case CElementBSDF::Type::DIFFUSE: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHDIFFUSE: - obj->diffuse = CElementBSDF::AllDiffuse(); - break; - case CElementBSDF::Type::DIELECTRIC: - [[fallthrough]]; - case CElementBSDF::Type::THINDIELECTRIC: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHDIELECTRIC: - obj->dielectric = CElementBSDF::AllDielectric(); - break; - case CElementBSDF::Type::CONDUCTOR: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHCONDUCTOR: - obj->conductor = CElementBSDF::AllConductor(); - break; - case CElementBSDF::Type::PLASTIC: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHPLASTIC: - obj->plastic = CElementBSDF::AllPlastic(); - break; - case CElementBSDF::Type::COATING: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHCOATING: - obj->coating = CElementBSDF::AllCoating(); - break; - case CElementBSDF::Type::BUMPMAP: - obj->bumpmap = CElementBSDF::BumpMap(); - obj->bumpmap.wasNormal = strcmp(type,"bumpmap")!=0; - break; - case CElementBSDF::Type::PHONG: - obj->phong = CElementBSDF::Phong(); - break; - case CElementBSDF::Type::WARD: - obj->ward = CElementBSDF::Ward(); - break; - case CElementBSDF::Type::MIXTURE_BSDF: - obj->mixturebsdf = CElementBSDF::MixtureBSDF(); - break; - case CElementBSDF::Type::BLEND_BSDF: - obj->blendbsdf = CElementBSDF::BlendBSDF(); - break; - case CElementBSDF::Type::MASK: - obj->mask = CElementBSDF::Mask(); - break; - case CElementBSDF::Type::TWO_SIDED: - obj->twosided = CElementBSDF::TwoSided(); - break; - case CElementBSDF::Type::DIFFUSE_TRANSMITTER: - obj->difftrans = CElementBSDF::DiffuseTransmitter(); - break; - //case CElementBSDF::Type::HANRAHAN_KRUEGER: - //hk = CElementBSDF::HanrahanKrueger(); - //break; - //case CElementBSDF::Type::IRAWAN_MARSCHNER: - //irawan = CElementBSDF::IrawanMarschner(); - //break; - default: - break; - } - return CElementFactory::return_type(obj, std::move(name)); + // blend + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(weight,FLOAT,std::is_same,BlendBSDF); + + // mask + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(opacity,std::is_same,Mask); + + // twosided + + // phong + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(exponent,FLOAT,std::is_same,Phong); + // COMMON: specularReflectance + // COMMON: diffuseReflectance + + // ward + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(variant,STRING,std::is_same,Ward) + static const core::unordered_map StringToType = + { + {"ward", Ward::Type::WARD}, + {"ward-duer", Ward::Type::WARD_DUER}, + {"balanced", Ward::Type::BALANCED} + }; + auto found = StringToType.find(_property.getProperty()); + if (found==StringToType.end()) + return; + state.variant = found->second; + success = true; + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; + // COMMON: alphaU + // COMMON: alphaV + // COMMON: specularReflectance + // COMMON: diffuseReflectance + + // TODO: set HK and IRAWAN parameters, sigmaS, sigmaT, albedo, filename, repeatU, repeatV + +#undef ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED + + return retval; } -float CElementBSDF::TransmissiveBase::findIOR(const std::string& name) +float CElementBSDF::TransmissiveBase::findIOR(const std::string_view name, system::logger_opt_ptr logger) { - static const core::unordered_map NamedIndicesOfRefraction = + static const core::unordered_map NamedIndicesOfRefraction = { {"vacuum", 1.f}, {"helium", 1.00004f}, @@ -167,13 +224,13 @@ float CElementBSDF::TransmissiveBase::findIOR(const std::string& name) } -CElementBSDF::AllConductor::AllConductor(const std::string& material) : RoughSpecularBase(0.1) +CElementBSDF::AllConductor::AllConductor(const std::string_view material, system::logger_opt_ptr logger) : RoughSpecularBase(0.1) { // TODO fill this out with values from http://www.luxpop.com/HU_v173.cgi?OpCode=73 and https://github.com/mmp/pbrt-v3/blob/master/src/materials/metal.cpp or https://refractiveindex.info/?shelf=main&book=Cu&page=Johnson // we use Rec 709 for the Color primaries of this table, so Red ~= 615nm, Green ~= 535nm, Blue ~= 465nm - static const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> NamedConductors = + static const core::unordered_map,3>,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> NamedConductors = { -#define SPECTRUM_MACRO(R,G,B,X,Y,Z) {SPropertyElementData(SPropertyElementData::Type::RGB,core::vectorSIMDf(R,G,B)),SPropertyElementData(SPropertyElementData::Type::RGB,core::vectorSIMDf(X,Y,Z))} +#define SPECTRUM_MACRO(R,G,B,X,Y,Z) {{R,X},{G,Y},{B,Z}} {"a-C", SPECTRUM_MACRO(1.6855f, 1.065f, 1.727f, 0.0f, 0.009f, 0.0263f)}, // there is no "a-C", but "a-C:H; data from palik" {"Ag", SPECTRUM_MACRO(0.059481f, 0.055090f, 0.046878f, 4.1367f, 3.4574f, 2.8028f)}, {"Al", SPECTRUM_MACRO(1.3404f, 0.95151f, 0.68603f, 7.3509f, 6.4542f, 5.6351f)}, @@ -238,574 +295,122 @@ CElementBSDF::AllConductor::AllConductor(const std::string& material) : RoughSpe }; auto found = NamedConductors.find(material); - if (found == NamedConductors.end()) + if (found==NamedConductors.end()) { _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("IoR Table lookup not implemented for material preset: " + material); + logger.log("Named material %s in failed to be found, defaulting to \"none\"",system::ILogger::ELL_ERROR,material.data()); found = NamedConductors.find("none"); assert(found != NamedConductors.end()); } - eta = found->second.first; - k = found->second.second; - extEta = TransmissiveBase::findIOR("air"); + const auto etaK = found->second; + eta = SPropertyElementData(SPropertyElementData::Type::RGB,float32_t4{etaK.r.real(),etaK.g.real(),etaK.b.real(),0.f}); + k = SPropertyElementData(SPropertyElementData::Type::RGB,float32_t4{etaK.r.real(),etaK.g.real(),etaK.b.real(),0.f}); + extEta = TransmissiveBase::findIOR("air",logger); } -bool CElementBSDF::addProperty(SNamedPropertyElement&& _property) + +bool CElementBSDF::processChildData(IElement* _child, const std::string& name, system::logger_opt_ptr logger) { - bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) - { - case CElementBSDF::Type::DIFFUSE: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHDIFFUSE: - func(diffuse); - break; - case CElementBSDF::Type::DIELECTRIC: - [[fallthrough]]; - case CElementBSDF::Type::THINDIELECTRIC: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHDIELECTRIC: - func(dielectric); - break; - case CElementBSDF::Type::CONDUCTOR: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHCONDUCTOR: - func(conductor); - break; - case CElementBSDF::Type::PLASTIC: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHPLASTIC: - func(plastic); - break; - case CElementBSDF::Type::COATING: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHCOATING: - func(coating); - break; - case CElementBSDF::Type::BUMPMAP: - func(bumpmap); - break; - case CElementBSDF::Type::PHONG: - func(phong); - break; - case CElementBSDF::Type::WARD: - func(ward); - break; - case CElementBSDF::Type::MIXTURE_BSDF: - func(mixturebsdf); - break; - case CElementBSDF::Type::BLEND_BSDF: - func(blendbsdf); - break; - case CElementBSDF::Type::MASK: - func(mask); - break; - case CElementBSDF::Type::TWO_SIDED: - func(twosided); - break; - case CElementBSDF::Type::DIFFUSE_TRANSMITTER: - func(difftrans); - break; - //case CElementBSDF::Type::HANRAHAN_KRUEGER: - //func(hk); - //break; - //case CElementBSDF::Type::IRAWAN_MARSCHNER: - //func(irwan); - //break; - default: - error = true; - break; - } - }; + if (!_child) + return true; -#define SET_FLOAT(MEMBER, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - switch (_property.type) { \ - case SPropertyElementData::Type::FLOAT: \ - state. ## MEMBER = SPropertyElementData(_property); \ - break; \ - default: \ - error = true; \ - break; \ - } \ - } \ - }); \ - } -#define SET_SPECTRUM(MEMBER, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - switch (_property.type) { \ - case SPropertyElementData::Type::FLOAT: \ - case SPropertyElementData::Type::RGB: \ - case SPropertyElementData::Type::SRGB: \ - case SPropertyElementData::Type::SPECTRUM: \ - state. ## MEMBER = SPropertyElementData(_property); \ - break; \ - default: \ - error = true; \ - break; \ - } \ - } \ - }); \ - } -#define SET_PROPERTY_TEMPLATE(MEMBER,PROPERTY_TYPE, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ + using this_t = CElementBSDF; + +#define SET_TEXTURE_CONSTRAINED(MEMBER,CONSTRAINT,... ) {#MEMBER,{.func = [](this_t* _this, IElement* _child, const system::logger_opt_ptr logger)->bool \ + { \ + bool success = false; \ + auto _texture = static_cast(_child); \ + _this->visit([&_texture,logger,&success](auto& state)->void \ { \ - if (_property.type!=PROPERTY_TYPE) { \ - error = true; \ - return; \ - } \ - state. ## MEMBER = _property.getProperty(); \ + if constexpr (CONSTRAINT __VA_OPT__(,) __VA_ARGS__>::value) \ + { +#define SET_TEXTURE_CONSTRAINED_END } \ } \ - }); \ - } - - auto processReflectance = SET_SPECTRUM(reflectance,AllDiffuse); - auto processDistribution = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_base_of::value) - { - static const core::unordered_map StringToType = - { - {"beckmann",RoughSpecularBase::NormalDistributionFunction::BECKMANN}, - {"ggx", RoughSpecularBase::NormalDistributionFunction::GGX}, - {"phong", RoughSpecularBase::NormalDistributionFunction::PHONG}, - {"as", RoughSpecularBase::NormalDistributionFunction::ASHIKHMIN_SHIRLEY} - }; - - auto found = StringToType.end(); - if (_property.type==SPropertyElementData::Type::STRING) - found = StringToType.find(_property.getProperty()); - if (found==StringToType.end()) - { - error = true; - return; - } - state.distribution = found->second; - } - }); - }; -#define TRANSMISSIVE_TYPES AllDielectric,AllPlastic,AllCoating -#define SPECULAR_TYPES TRANSMISSIVE_TYPES,AllConductor - auto processAlpha = SET_FLOAT(alpha, AllDiffuse,SPECULAR_TYPES); - auto processAlphaU = SET_FLOAT(alphaU, SPECULAR_TYPES); - auto processAlphaV = SET_FLOAT(alphaV, SPECULAR_TYPES); - auto processUseFastApprox = SET_PROPERTY_TEMPLATE(useFastApprox,SPropertyElementData::Type::BOOLEAN,AllDiffuse); - auto processIntIOR = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (is_any_of::value) - { - if (_property.type==SPropertyElementData::Type::FLOAT) - state.intIOR = _property.getProperty(); - else if (_property.type==SPropertyElementData::Type::STRING) - state.intIOR = TransmissiveBase::findIOR(_property.getProperty()); - else - error = true; - } - }); + ); \ + return success; \ + } \ +}} +#define SET_TEXTURE_CONSTRAINED_SIMPLE(MEMBER,CONSTRAINT,... ) SET_TEXTURE_CONSTRAINED(MEMBER,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _texture; \ + success = true; \ +SET_TEXTURE_CONSTRAINED_END + + // TODO: store this somewhere outside a global + static const ProcessChildCallbackMap TextureCallbacks = + { + SET_TEXTURE_CONSTRAINED_SIMPLE(transmittance,std::is_same,DiffuseTransmitter), + SET_TEXTURE_CONSTRAINED_SIMPLE(reflectance,derived_from,AllDiffuse), + SET_TEXTURE_CONSTRAINED_SIMPLE(diffuseReflectance,impl::has_diffuseReflectance), + SET_TEXTURE_CONSTRAINED_SIMPLE(alpha,impl::has_alpha), + SET_TEXTURE_CONSTRAINED_SIMPLE(alphaU,impl::can_have_isotropicNDF), + SET_TEXTURE_CONSTRAINED_SIMPLE(alphaV,impl::can_have_isotropicNDF), + SET_TEXTURE_CONSTRAINED_SIMPLE(specularReflectance,impl::has_specularReflectance), + SET_TEXTURE_CONSTRAINED_SIMPLE(specularTransmittance,derived_from,TransmissiveBase), + SET_TEXTURE_CONSTRAINED_SIMPLE(sigmaA,derived_from,AllCoating), + SET_TEXTURE_CONSTRAINED("",is_any_of,BumpMap,NormalMap) + state.texture = _texture; + success = true; + SET_TEXTURE_CONSTRAINED_END, + SET_TEXTURE_CONSTRAINED_SIMPLE(weight,std::is_same,BlendBSDF), + SET_TEXTURE_CONSTRAINED_SIMPLE(opacity,std::is_same,Mask), + SET_TEXTURE_CONSTRAINED_SIMPLE(exponent,std::is_same,Phong) }; - auto processExtIOR = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; +#undef SET_TEXTURE_CONSTRAINED +#undef SET_TEXTURE_CONSTRAINED_SIMPLE - if constexpr (is_any_of::value) - { - if (_property.type==SPropertyElementData::Type::FLOAT) - state.extIOR = _property.getProperty(); - else if (_property.type==SPropertyElementData::Type::STRING) - state.extIOR = TransmissiveBase::findIOR(_property.getProperty()); - else - error = true; - } - }); - }; - auto processSpecularReflectance = SET_SPECTRUM(specularReflectance, SPECULAR_TYPES,Phong,Ward); - auto processDiffuseReflectance = SET_SPECTRUM(diffuseReflectance, AllDiffuse,AllPlastic,Phong,Ward); - auto processSpecularTransmittance = SET_SPECTRUM(specularTransmittance, TRANSMISSIVE_TYPES); -#undef SPECULAR_TYPES -#undef TRANSMISSIVE_TYPES - auto processMaterial = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - if (_property.type == SPropertyElementData::Type::STRING) - conductor = AllConductor(_property.getProperty()); - else - error = true; - }/* - else - { - if constexpr (std::is_same::value) - { - } - }*/ - }); - }; - auto processEta = SET_SPECTRUM(eta, AllConductor); - auto processK = SET_SPECTRUM(k, AllConductor); - auto processExtEta = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) - { - if (_property.type==SPropertyElementData::Type::FLOAT) - state.extEta = _property.getProperty(); - else if (_property.type==SPropertyElementData::Type::STRING) - state.extEta = TransmissiveBase::findIOR(_property.getProperty()); - else - error = true; - } - }); - }; - auto processNonlinear = SET_PROPERTY_TEMPLATE(nonlinear, SPropertyElementData::Type::BOOLEAN, AllPlastic); - auto processThickness = SET_PROPERTY_TEMPLATE(thickness, SPropertyElementData::Type::FLOAT, AllCoating); - auto processSigmaA = SET_SPECTRUM(sigmaA, AllCoating); - auto processExponent = SET_FLOAT(exponent, Phong); - auto processVariant = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) + switch (_child->getType()) + { + case IElement::Type::TEXTURE: + { + auto found = TextureCallbacks.find(name); + if (found==TextureCallbacks.end()) + found = TextureCallbacks.find(""); + if (found==TextureCallbacks.end()) { - static const core::unordered_map StringToType = - { - {"ward", Ward::Type::WARD}, - {"ward-duer", Ward::Type::WARD_DUER}, - {"balanced", Ward::Type::BALANCED} - }; - auto found = StringToType.end(); - if (_property.type==SPropertyElementData::Type::STRING) - found = StringToType.find(_property.getProperty()); - if (found==StringToType.end()) - { - error = true; - return; - } - state.variant = found->second; + logger.log("No can have nested inside it with name \"%s\"!",system::ILogger::ELL_ERROR,name.c_str()); + return false; } - }); - }; - auto processWeights = [&]() -> void - { - dispatch([&](auto& state) -> void { - using state_type = std::remove_reference::type; - - if constexpr (std::is_same::value) + if (found->second(this,_child,logger)) { - if (_property.type!=SPropertyElementData::Type::STRING) - { - error = true; - return; - } - - std::istringstream sstr(_property.getProperty()); - std::string token; - while (std::getline(sstr, token, ',')) - state.weights[state.weightCount++] = std::stof(token); + logger.log( + "Failed to parse with name \"%s\" nested inside of type %d!", + system::ILogger::ELL_ERROR,name.c_str(),type + ); + return true; } - }); - }; - auto processWeight = SET_SPECTRUM(weight, BlendBSDF); - auto processOpacity = SET_SPECTRUM(opacity, Mask); - auto processTransmittance = SET_SPECTRUM(transmittance, DiffuseTransmitter); - // TODO: set HK and IRAWAN parameters - /* - auto processField = [&]() -> void - { - dispatch([&](auto& state) -> void + return true; + } + case IElement::Type::BSDF: { - using state_type = std::remove_reference::type; - if constexpr (std::is_same::value) + size_t maxChildCount = 0; { - if (_property.type != SPropertyElementData::Type::STRING) - { - error = true; - return; - } - auto found = StringToType.find(_property.svalue); - if (found!=StringToType.end()) - state.field = found->second; - else - state.field = FieldExtraction::Type::INVALID; - } - }); - }; - */ -#undef SET_FLOAT -#undef SET_SPECTRUM -#undef SET_PROPERTY_TEMPLATE - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetPropertyMap = - { - {"reflectance", processReflectance}, - {"distribution", processDistribution}, - {"alpha", processAlpha}, - {"alphaU", processAlphaU}, - {"alphaV", processAlphaV}, - {"useFastApprox", processUseFastApprox}, - {"intIOR", processIntIOR}, - {"extIOR", processExtIOR}, - {"specularReflectance", processSpecularReflectance}, - {"diffuseReflectance", processDiffuseReflectance}, - {"specularTransmittance", processSpecularTransmittance}, - {"material", processMaterial}, - {"eta", processEta}, - {"k", processK}, - {"extEta", processExtEta}, - {"nonlinear", processNonlinear}, - {"thickness", processThickness}, - {"sigmaA", processSigmaA}, - {"exponent", processExponent}, - {"variant", processVariant}, - {"weights", processWeights}, - {"weight", processWeight}, - {"opacity", processOpacity}, - {"transmittance", processTransmittance}//, - //{"sigmaS", processSigmaS}, - //{"sigmaT", processSigmaT}, - //{"albedo", processAlbedo}, - //{"filename", processFilename}, - //{"repeatU", processRepeatU}, - //{"repeatV", processRepeatV} - }; - - auto found = SetPropertyMap.find(_property.name); - if (found==SetPropertyMap.end()) - { - ParserLog::invalidXMLFileStructure("No BSDF can have such property set with name: "+_property.name); - return false; - } - - found->second(); - return !error; -} - - -bool CElementBSDF::processChildData(IElement* _child, const std::string& name) -{ - if (!_child) - return true; - - switch (_child->getType()) - { - case IElement::Type::TEXTURE: - { - auto _texture = static_cast(_child); - - bool error = false; - auto dispatch = [&](auto func) -> void - { - switch (type) + const auto* _this = this; + visit([&maxChildCount,_this](const auto& state)->void { - case CElementBSDF::Type::DIFFUSE: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHDIFFUSE: - func(diffuse); - break; - case CElementBSDF::Type::DIELECTRIC: - [[fallthrough]]; - case CElementBSDF::Type::THINDIELECTRIC: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHDIELECTRIC: - func(dielectric); - break; - case CElementBSDF::Type::CONDUCTOR: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHCONDUCTOR: - func(conductor); - break; - case CElementBSDF::Type::PLASTIC: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHPLASTIC: - func(plastic); - break; - case CElementBSDF::Type::COATING: - [[fallthrough]]; - case CElementBSDF::Type::ROUGHCOATING: - func(coating); - break; - case CElementBSDF::Type::BUMPMAP: - func(bumpmap); - break; - case CElementBSDF::Type::PHONG: - func(phong); - break; - case CElementBSDF::Type::WARD: - func(ward); - break; - case CElementBSDF::Type::MIXTURE_BSDF: - func(mixturebsdf); - break; - case CElementBSDF::Type::BLEND_BSDF: - func(blendbsdf); - break; - case CElementBSDF::Type::MASK: - func(mask); - break; - case CElementBSDF::Type::TWO_SIDED: - func(twosided); - break; - case CElementBSDF::Type::DIFFUSE_TRANSMITTER: - func(difftrans); - break; - //case CElementBSDF::Type::HANRAHAN_KRUEGER: - //func(hk); - //break; - //case CElementBSDF::Type::IRAWAN_MARSCHNER: - //func(irwan); - //break; - default: - error = true; - break; + using state_t = std::remove_reference_t; + if constexpr (std::is_base_of_v) + maxChildCount = state_t::MaxChildCount; } - }; -#define SET_TEXTURE(MEMBER, ... ) [&]() -> void { \ - dispatch([&](auto& state) -> void { \ - if constexpr (is_any_of::type,__VA_ARGS__>::value) \ - { \ - state. ## MEMBER.value.type = SPropertyElementData::Type::INVALID; \ - state. ## MEMBER.texture = _texture; \ - } \ - }); \ - } - - auto processReflectance = SET_TEXTURE(reflectance, AllDiffuse); -#define TRANSMISSIVE_TYPES AllDielectric,AllPlastic,AllCoating -#define SPECULAR_TYPES TRANSMISSIVE_TYPES,AllConductor - auto processAlpha = SET_TEXTURE(alpha, AllDiffuse,SPECULAR_TYPES); - auto processAlphaU = SET_TEXTURE(alphaU, SPECULAR_TYPES); - auto processAlphaV = SET_TEXTURE(alphaV, SPECULAR_TYPES); - auto processSpecularReflectance = SET_TEXTURE(specularReflectance, SPECULAR_TYPES,Phong,Ward); - auto processDiffuseReflectance = SET_TEXTURE(diffuseReflectance, AllDiffuse,AllPlastic,Phong,Ward); - auto processSpecularTransmittance = SET_TEXTURE(specularTransmittance, TRANSMISSIVE_TYPES); - auto processSigmaA = SET_TEXTURE(sigmaA, AllCoating); - auto processExponent = SET_TEXTURE(exponent, Phong); - auto processWeight = SET_TEXTURE(weight, BlendBSDF); - auto processOpacity = SET_TEXTURE(opacity, Mask); - auto processTransmittance = SET_TEXTURE(transmittance, DiffuseTransmitter); -#undef TRANSMISSIVE_TYPES -#undef SPECULAR_TYPES -#undef SET_TEXTURE - - const core::unordered_map, core::CaseInsensitiveHash, core::CaseInsensitiveEquals> SetChildMap = - { - {"reflectance", processReflectance}, - {"alpha", processAlpha}, - {"alphaU", processAlphaU}, - {"alphaV", processAlphaV}, - {"specularReflectance", processSpecularReflectance}, - {"diffuseReflectance", processDiffuseReflectance}, - {"specularTransmittance", processSpecularTransmittance}, - {"sigmaA", processSigmaA}, - {"exponent", processExponent}, - {"weight", processWeight}, - {"opacity", processOpacity}, - {"transmittance", processTransmittance}//, - //{"sigmaS", processSigmaS}, - //{"sigmaT", processSigmaT}, - //{"albedo", processAlbedo} - }; - - switch (type) - { - case Type::BUMPMAP: - bumpmap.texture = _texture; - break; - default: - { - auto found = SetChildMap.find(name); - if (found!=SetChildMap.end()) - found->second(); - else - { - _NBL_DEBUG_BREAK_IF(true); - ParserLog::invalidXMLFileStructure("No BSDF can have such property set with name: " + name); - return false; - } - } - break; - } - - if (error) - return false; + ); } - break; - case IElement::Type::BSDF: + if (meta_common.childCount(_child); - switch (type) - { - case Type::COATING: - [[fallthrough]]; - case Type::ROUGHCOATING: - if (coating.childCount < AllCoating::MaxChildCount) - coating.bsdf[coating.childCount++] = _bsdf; - else - return false; - break; - case Type::BUMPMAP: - if (bumpmap.childCount < BumpMap::MaxChildCount) - bumpmap.bsdf[bumpmap.childCount++] = _bsdf; - else - return false; - break; - case Type::MIXTURE_BSDF: - if (mixturebsdf.childCount < MixtureBSDF::MaxChildCount) - mixturebsdf.bsdf[mixturebsdf.childCount++] = _bsdf; - else - return false; - break; - case Type::BLEND_BSDF: - if (blendbsdf.childCount < BlendBSDF::MaxChildCount) - blendbsdf.bsdf[blendbsdf.childCount++] = _bsdf; - else - return false; - break; - case Type::MASK: - if (mask.childCount < Mask::MaxChildCount) - mask.bsdf[mask.childCount++] = _bsdf; - else - return false; - break; - case Type::TWO_SIDED: - if (twosided.childCount < TwoSided::MaxChildCount) - twosided.bsdf[twosided.childCount++] = _bsdf; - else - return false; - break; - default: - return false; - break; - } + twosided.bsdf[twosided.childCount++] = _bsdf; + return true; } - break; + logger.log(" cannot have more than %d other s nested inside it!",system::ILogger::ELL_ERROR,type,maxChildCount); + return false; + } default: + logger.log("Unsupported <%s> nested inside only and are allowed!",system::ILogger::ELL_ERROR,_child->getLogName()); return false; - break; } return true; } -bool CElementBSDF::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override, CMitsubaMetadata* metadata) +bool CElementBSDF::onEndTag(CMitsubaMetadata* globalMetadata, system::logger_opt_ptr logger) { NBL_EXT_MITSUBA_LOADER_ELEMENT_INVALID_TYPE_CHECK(true); @@ -816,6 +421,4 @@ bool CElementBSDF::onEndTag(asset::IAssetLoader::IAssetLoaderOverride* _override return true; } -} -} } \ No newline at end of file diff --git a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp index 8b0b34e3e4..89ca3c00e2 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmissionProfile.cpp @@ -17,7 +17,12 @@ auto CElementEmissionProfile::compAddPropertyMap() -> AddPropertyMap retval; - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(filename,STRING); + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("filename",STRING) + { + setLimitedString("filename",_this->filename,_property,logger); + return true; + } + }); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("normalization",STRING) { const auto normalizeS = std::string(_property.svalue); diff --git a/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp b/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp index c7115dfcef..eb9aa154dd 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp @@ -67,47 +67,49 @@ auto CElementEmitter::compAddPropertyMap() -> AddPropertyMap } }); - // spectrum setting -#define ADD_SPECTRUM(MEMBER,CONSTRAINT,...) { \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,FLOAT,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ - state. ## MEMBER.x = state. ## MEMBER.y = state. ## MEMBER.z = _property.getProperty(); \ - success = true; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,RGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ - state. ## MEMBER = _property.getProperty(); \ - success = true; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SRGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ - state. ## MEMBER = _property.getProperty(); \ - success = true; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SPECTRUM,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ - state. ## MEMBER = _property.getProperty(); \ - success = true; \ - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ - } - // base NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(samplingWeight,FLOAT,derived_from,SampledEmitter); +// spectrum setting +#define ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(MEMBER,CONSTRAINT,...) { \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,FLOAT,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER.x = state. ## MEMBER.y = state. ## MEMBER.z = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,RGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SRGB,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(MEMBER,SPECTRUM,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + state. ## MEMBER = _property.getProperty(); \ + success = true; \ + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; \ +} + // delta - ADD_SPECTRUM(intensity,derived_from,DeltaDistributionEmitter); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(intensity,derived_from,DeltaDistributionEmitter); // point covered by delta // non zero solid angle - ADD_SPECTRUM(radiance,derived_from,SolidAngleEmitter); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(radiance,derived_from,SolidAngleEmitter); // area covered by solid angle // directional - ADD_SPECTRUM(irradiance,std::is_same,Directional); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(irradiance,std::is_same,Directional); // collimated - ADD_SPECTRUM(power,std::is_same,Collimated); + ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(power,std::is_same,Collimated); + +#undef ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED // environment map NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,std::is_same,EnvMap) { - setLimitedString("filename",_this->envmap.filename,std::move(_property),logger); return true; + setLimitedString("filename",_this->envmap.filename,_property,logger); return true; } ); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(scale,FLOAT,std::is_same,EnvMap); diff --git a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp index d558975998..fec400829f 100644 --- a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp @@ -103,22 +103,22 @@ auto CElementFilm::compAddPropertyMap() -> AddPropertyMap NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("variable",STRING,std::is_same,M) { - setLimitedString("variable",_this->outputFilePath,std::move(_property),logger); return true; + setLimitedString("variable",_this->outputFilePath,_property,logger); return true; } ); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("outputFilePath",STRING) { - setLimitedString("outputFilePath",_this->outputFilePath,std::move(_property),logger); return true; + setLimitedString("outputFilePath",_this->outputFilePath,_property,logger); return true; } }); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("bloomFilePath",STRING) { - setLimitedString("bloomFilePath",_this->denoiserTonemapperArgs,std::move(_property),logger); return true; + setLimitedString("bloomFilePath",_this->denoiserTonemapperArgs,_property,logger); return true; } }); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY("tonemapper",STRING) { - setLimitedString("tonemapper",_this->denoiserTonemapperArgs,std::move(_property),logger); return true; + setLimitedString("tonemapper",_this->denoiserTonemapperArgs,_property,logger); return true; } }); diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index fa7e89759d..9854912fc7 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -166,16 +166,15 @@ auto CElementIntegrator::compAddPropertyMap() -> AddPropertyMapfield.undefined = _property; // TODO: redo + _this->field.undefined = _property; return true; } ); NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("undefined",SPECTRUM,std::is_same,FieldExtraction) { - _this->field.undefined = _property; // TODO: redo + _this->field.undefined = _property; return true; } ); diff --git a/src/nbl/ext/MitsubaLoader/CElementShape.cpp b/src/nbl/ext/MitsubaLoader/CElementShape.cpp index c6db773afa..03b50f3f7c 100644 --- a/src/nbl/ext/MitsubaLoader/CElementShape.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementShape.cpp @@ -34,7 +34,7 @@ auto CElementShape::compAddPropertyMap() -> AddPropertyMap // LoadedFromFileBase NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,derived_from,LoadedFromFileBase) { - setLimitedString("filename",_this->serialized.filename,std::move(_property),logger); return true; + setLimitedString("filename",_this->serialized.filename,_property,logger); return true; } ); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(faceNormals,BOOLEAN,derived_from,LoadedFromFileBase); diff --git a/src/nbl/ext/MitsubaLoader/CElementTexture.cpp b/src/nbl/ext/MitsubaLoader/CElementTexture.cpp index 0add6ac3ca..213a52cba3 100644 --- a/src/nbl/ext/MitsubaLoader/CElementTexture.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementTexture.cpp @@ -37,7 +37,7 @@ auto CElementTexture::compAddPropertyMap() -> AddPropertyMap // bitmap NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,std::is_same,Bitmap) { - setLimitedString("filename",_this->bitmap.filename,std::move(_property),logger); return true; + setLimitedString("filename",_this->bitmap.filename,_property,logger); return true; } ); // special @@ -85,8 +85,7 @@ auto CElementTexture::compAddPropertyMap() -> AddPropertyMap NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(voffset,FLOAT,std::is_same,Bitmap); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(uscale,FLOAT,std::is_same,Bitmap); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(vscale,FLOAT,std::is_same,Bitmap); - NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(vscale,FLOAT,std::is_same,Bitmap); - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("filename",STRING,std::is_same,Bitmap) + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED("channel",STRING,std::is_same,Bitmap) { static const core::unordered_map StringToType = { diff --git a/src/nbl/ext/MitsubaLoader/CMakeLists.txt b/src/nbl/ext/MitsubaLoader/CMakeLists.txt index ef3f326ad5..0ec8ba0685 100644 --- a/src/nbl/ext/MitsubaLoader/CMakeLists.txt +++ b/src/nbl/ext/MitsubaLoader/CMakeLists.txt @@ -34,9 +34,9 @@ set(NBL_EXT_MITSUBA_LOADER_SRC CElementSampler.cpp CElementTransform.cpp CElementShape.cpp -# CElementBSDF.cpp -# CElementTexture.cpp -# CElementEmitter.cpp + CElementBSDF.cpp + CElementTexture.cpp + CElementEmitter.cpp CElementEmissionProfile.cpp ParserUtil.cpp CSerializedLoader.cpp diff --git a/src/nbl/ext/MitsubaLoader/ElementMacros.h b/src/nbl/ext/MitsubaLoader/ElementMacros.h index ab88a11cb4..3bbb997e6e 100644 --- a/src/nbl/ext/MitsubaLoader/ElementMacros.h +++ b/src/nbl/ext/MitsubaLoader/ElementMacros.h @@ -13,6 +13,7 @@ // when you know that there's a member of `this_t` with identifier equal to NAME #define NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(NAME,PROP_TYPE) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY(#NAME,PROP_TYPE) \ {\ + static_assert(SNamedPropertyElement::Type::PROP_TYPE!=SNamedPropertyElement::Type::STRING); \ _this->NAME = _property.getProperty(); \ return true; \ } \ @@ -29,7 +30,7 @@ #define NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED(#NAME,PROP_TYPE,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ {\ bool success = false; \ - _this->visit([&_property,&success](auto& state)->void \ + _this->visit([&_property,logger,&success](auto& state)->void \ { \ if constexpr (CONSTRAINT __VA_OPT__(,) __VA_ARGS__>::value) \ { @@ -45,6 +46,7 @@ // This it to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY_CONSTRAINED` what `NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY` is to `NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_PROPERTY` // So basically you know the member is the same across the constraint filtered types #define NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT,...) NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(NAME,PROP_TYPE,CONSTRAINT __VA_OPT__(,) __VA_ARGS__) \ + static_assert(SNamedPropertyElement::Type::PROP_TYPE!=SNamedPropertyElement::Type::STRING); \ state. ## NAME = _property.getProperty(); \ success = true; \ NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 6f1af1e301..6b7a3f5f66 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -12,9 +12,9 @@ #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/CElementBSDF.h" //#include "nbl/ext/MitsubaLoader/CElementTexture.h" -//#include "nbl/ext/MitsubaLoader/CElementEmitter.h" +#include "nbl/ext/MitsubaLoader/CElementEmitter.h" #include "nbl/ext/MitsubaLoader/CElementEmissionProfile.h" #include "expat/lib/expat.h" @@ -420,9 +420,9 @@ ParserManager::ParserManager() : propertyElements({ {"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}}, + {"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}} @@ -434,6 +434,9 @@ ParserManager::ParserManager() : propertyElements({ CElementSampler::compAddPropertyMap(), CElementShape::compAddPropertyMap(), CElementTransform::compAddPropertyMap(), + CElementBSDF::compAddPropertyMap(), + CElementTexture::compAddPropertyMap(), + CElementEmitter::compAddPropertyMap(), CElementEmissionProfile::compAddPropertyMap() }) { } From ab505fe13b194f808127da444877431adf5bf58d Mon Sep 17 00:00:00 2001 From: devsh Date: Tue, 23 Dec 2025 23:01:09 +0100 Subject: [PATCH 26/30] fix bugs (most importantly handling) --- src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp | 4 ++-- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index 9854912fc7..c26b07889d 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -60,8 +60,8 @@ auto CElementIntegrator::compAddPropertyMap() -> AddPropertyMapsecond.retvalGoesOnStack) return; - if (created.element && created.name.size()) - session->handles[created.name] = created.element; + if (created.element && created.element->id.size()) + session->handles[created.element->id] = created.element; session->elements.push(std::move(created)); } From 078899fcdb32e1e2de16ba6c98649740f6d25482 Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 24 Dec 2025 01:24:06 +0100 Subject: [PATCH 27/30] fix all MitsubaLoader bugs which came up during parsing tests --- examples_tests | 2 +- include/nbl/ext/MitsubaLoader/CElementBSDF.h | 2 +- .../MitsubaLoader/CElementEmissionProfile.h | 17 ++++------------- .../nbl/ext/MitsubaLoader/CElementIntegrator.h | 14 ++++++++------ src/nbl/ext/MitsubaLoader/CElementBSDF.cpp | 11 ++++++----- src/nbl/ext/MitsubaLoader/CElementEmitter.cpp | 2 +- src/nbl/ext/MitsubaLoader/CElementFilm.cpp | 3 +++ .../ext/MitsubaLoader/CElementIntegrator.cpp | 5 +++-- src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp | 6 +++--- src/nbl/ext/MitsubaLoader/ParserUtil.cpp | 18 ++++++++++++------ 10 files changed, 42 insertions(+), 38 deletions(-) diff --git a/examples_tests b/examples_tests index d20b9c67bf..8333763f44 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit d20b9c67bf5ef5c4d782a13709a78ce59b24e1e4 +Subproject commit 8333763f44407f45dfc47d5ae4b1bed3f6d8fb9e diff --git a/include/nbl/ext/MitsubaLoader/CElementBSDF.h b/include/nbl/ext/MitsubaLoader/CElementBSDF.h index 432064b847..4729c36dc5 100644 --- a/include/nbl/ext/MitsubaLoader/CElementBSDF.h +++ b/include/nbl/ext/MitsubaLoader/CElementBSDF.h @@ -127,7 +127,7 @@ class CElementBSDF : public IElement { alpha = defaultAlpha; } - virtual inline ~RoughSpecularBase() {} + inline ~RoughSpecularBase() {} inline RoughSpecularBase& operator=(const RoughSpecularBase& other) { diff --git a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h index ecf24c9f63..84927497df 100644 --- a/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h +++ b/include/nbl/ext/MitsubaLoader/CElementEmissionProfile.h @@ -14,6 +14,8 @@ namespace nbl::ext::MitsubaLoader struct CElementEmissionProfile final : public IElement { + constexpr static inline uint16_t MaxPathLen = 1024u; + static AddPropertyMap compAddPropertyMap(); inline CElementEmissionProfile(const char* id) : IElement(id), normalization(EN_NONE), flatten(0.0) /*no blending by default*/ {} @@ -22,23 +24,12 @@ struct CElementEmissionProfile final : public IElement { operator=(other); } - inline CElementEmissionProfile(CElementEmissionProfile&& other) : IElement("") - { - operator=(std::move(other)); - } inline ~CElementEmissionProfile() {} inline CElementEmissionProfile& operator=(const CElementEmissionProfile& other) { IElement::operator=(other); - filename = other.filename; - return *this; - } - - inline CElementEmissionProfile& operator=(CElementEmissionProfile&& other) - { - IElement::operator=(std::move(other)); - std::swap(filename, other.filename); + memcpy(filename,other.filename,MaxPathLen); return *this; } @@ -59,7 +50,7 @@ struct CElementEmissionProfile final : public IElement }; - std::string filename; // TODO: test destructor runs + char filename[MaxPathLen]; E_NORMALIZE normalization; // how much we flatten the profile towards a uniform distribution float flatten; diff --git a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h index 875bb08378..7ed5f0cbb4 100644 --- a/include/nbl/ext/MitsubaLoader/CElementIntegrator.h +++ b/include/nbl/ext/MitsubaLoader/CElementIntegrator.h @@ -88,10 +88,12 @@ class CElementIntegrator final : public IElement }; struct PathTracing : MonteCarloTracingBase,EmitterHideableBase { - constexpr static inline Type VariantType = Type::PATH; - bool strictNormals = false; }; + struct UniDirectionalPathTracing final : PathTracing + { + constexpr static inline Type VariantType = Type::PATH; + }; struct SimpleVolumetricPathTracing : PathTracing { constexpr static inline Type VariantType = Type::VOL_PATH_SIMPLE; @@ -100,7 +102,7 @@ class CElementIntegrator final : public IElement { constexpr static inline Type VariantType = Type::VOL_PATH; }; - struct BiDirectionalPathTracing final : MonteCarloTracingBase + struct BiDirectionalPathTracing final : PathTracing { constexpr static inline Type VariantType = Type::BDPT; @@ -252,9 +254,9 @@ class CElementIntegrator final : public IElement using variant_list_t = core::type_list< AmbientOcclusion, DirectIllumination, + UniDirectionalPathTracing, SimpleVolumetricPathTracing, ExtendedVolumetricPathTracing, - PathTracing, BiDirectionalPathTracing, PhotonMapping, ProgressivePhotonMapping, @@ -377,7 +379,7 @@ class CElementIntegrator final : public IElement case Type::IRR_CACHE: [[fallthrough]]; case Type::MULTI_CHANNEL: - if (_child->getType() != IElement::Type::INTEGRATOR) + if (_child->getType() == IElement::Type::INTEGRATOR) break; [[fallthrough]]; default: @@ -411,9 +413,9 @@ class CElementIntegrator final : public IElement { AmbientOcclusion ao; DirectIllumination direct; + PathTracing path; SimpleVolumetricPathTracing volpath_simple; ExtendedVolumetricPathTracing volpath; - PathTracing path; BiDirectionalPathTracing bdpt; PhotonMapping photonmapper; ProgressivePhotonMapping ppm; diff --git a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp index 3790e89748..6c91e4dded 100644 --- a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp @@ -98,8 +98,9 @@ auto CElementBSDF::compAddPropertyMap() -> AddPropertyMap // conductor ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(eta,derived_from,AllConductor); ADD_VARIANT_SPECTRUM_PROPERTY_CONSTRAINED(k,derived_from,AllConductor); + NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_VARIANT_PROPERTY_CONSTRAINED(extEta,FLOAT,derived_from,AllConductor); // adding twice cause two property types are allowed - NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(extEta,FLOAT,derived_from,AllConductor) + NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED(extEta,STRING,derived_from,AllConductor) state.extEta = TransmissiveBase::findIOR(_property.getProperty(),logger); success = true; NBL_EXT_MITSUBA_LOADER_REGISTER_ADD_VARIANT_PROPERTY_CONSTRAINED_END; @@ -348,7 +349,7 @@ SET_TEXTURE_CONSTRAINED_END SET_TEXTURE_CONSTRAINED_SIMPLE(specularReflectance,impl::has_specularReflectance), SET_TEXTURE_CONSTRAINED_SIMPLE(specularTransmittance,derived_from,TransmissiveBase), SET_TEXTURE_CONSTRAINED_SIMPLE(sigmaA,derived_from,AllCoating), - SET_TEXTURE_CONSTRAINED("",is_any_of,BumpMap,NormalMap) + SET_TEXTURE_CONSTRAINED(,is_any_of,BumpMap,NormalMap) state.texture = _texture; success = true; SET_TEXTURE_CONSTRAINED_END, @@ -371,13 +372,13 @@ SET_TEXTURE_CONSTRAINED_END logger.log("No can have nested inside it with name \"%s\"!",system::ILogger::ELL_ERROR,name.c_str()); return false; } - if (found->second(this,_child,logger)) + if (!found->second(this,_child,logger)) { logger.log( "Failed to parse with name \"%s\" nested inside of type %d!", system::ILogger::ELL_ERROR,name.c_str(),type ); - return true; + return false; } return true; } @@ -397,7 +398,7 @@ SET_TEXTURE_CONSTRAINED_END if (meta_common.childCount(_child); - twosided.bsdf[twosided.childCount++] = _bsdf; + meta_common.bsdf[meta_common.childCount++] = _bsdf; return true; } logger.log(" cannot have more than %d other s nested inside it!",system::ILogger::ELL_ERROR,type,maxChildCount); diff --git a/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp b/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp index eb9aa154dd..831de4506e 100644 --- a/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementEmitter.cpp @@ -60,7 +60,7 @@ auto CElementEmitter::compAddPropertyMap() -> AddPropertyMap const auto lookAt = hlsl::transpose(lookAtGLM); // turn lookat into a rotation matrix const auto rotation = hlsl::inverse(hlsl::float32_t3x3(lookAt)); - _NBL_DEBUG_BREAK_IF(true); // no idea if matrix is correct + //_NBL_DEBUG_BREAK_IF(true); // no idea if matrix is correct, looks okay for (auto r=0; r<3; r++) _this->transform.matrix[r].xyz = rotation[r]; return true; diff --git a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp index fec400829f..c85aa2082d 100644 --- a/src/nbl/ext/MitsubaLoader/CElementFilm.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementFilm.cpp @@ -126,8 +126,11 @@ auto CElementFilm::compAddPropertyMap() -> AddPropertyMap NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cascadeLuminanceBase,FLOAT); NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(cascadeLuminanceStart,FLOAT); + const auto floatPropType = SNamedPropertyElement::Type::FLOAT; NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(denoiserBloomScale,FLOAT); + retval.byPropertyType[floatPropType]["bloomScale"] = retval.byPropertyType[floatPropType]["denoiserBloomScale"]; // alias NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(denoiserBloomIntensity,FLOAT); + retval.byPropertyType[floatPropType]["bloomIntensity"] = retval.byPropertyType[floatPropType]["denoiserBloomIntensity"]; // alias NBL_EXT_MITSUBA_LOADER_REGISTER_SIMPLE_ADD_PROPERTY(envmapRegularizationFactor,FLOAT); diff --git a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp index c26b07889d..f99b4487f9 100644 --- a/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementIntegrator.cpp @@ -212,11 +212,12 @@ bool CElementIntegrator::onEndTag(CMitsubaMetadata* metadata, system::logger_opt { } - if (metadata->m_global.m_integrator.type!=Type::INVALID) + /* Nested integrators rely on closing branch to post-order visit here to set the root one as the main one in the metadata + if (metadata->m_global.m_integrator.type!=Type::INVALID) // D { invalidXMLFileStructure(logger,"already specified an integrator, NOT overwriting."); return true; - } + }*/ metadata->m_global.m_integrator = *this; return true; diff --git a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp index df9d8c776e..a852978d75 100644 --- a/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp +++ b/src/nbl/ext/MitsubaLoader/CMitsubaLoader.cpp @@ -261,11 +261,11 @@ bool CMitsubaLoader::isALoadableFileFormat(system::IFile* _file, const system::l if (fileSizeread(success,tempBuff,0,pos); + _file->read(success,tempBuff,pos,3); if (!success) return false; if (tempBuff[0] == 0xEFu && tempBuff[1] == 0xBBu && tempBuff[2] == 0xBFu) diff --git a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp index 934fd82506..fb54fab0ef 100644 --- a/src/nbl/ext/MitsubaLoader/ParserUtil.cpp +++ b/src/nbl/ext/MitsubaLoader/ParserUtil.cpp @@ -66,7 +66,8 @@ bool ParserManager::SessionContext::parse(IFile* _file) XML_SetUserData(parser,&ctx); const size_t size = _file->getSize(); - const char* buff = reinterpret_cast(const_cast(_file)->getMappedPointer()); + const void* const origPtr = const_cast(_file)->getMappedPointer(); + const char* buff = reinterpret_cast(origPtr); if (!buff) { buff = reinterpret_cast(_NBL_ALIGNED_MALLOC(size,4096u)); @@ -79,7 +80,7 @@ bool ParserManager::SessionContext::parse(IFile* _file) } } XML_Status parseStatus = XML_Parse(parser,buff,size,0); - if (_file->getMappedPointer()!=buff) + if (origPtr!=buff) _NBL_ALIGNED_FREE(const_cast(buff)); XML_ParserFree(parser); @@ -225,7 +226,9 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts nameIt = typeMap.find(""); if (nameIt==typeMap.end()) { - session->invalidXMLFileStructure("There's no Property named \""+property.name+"\" of Type (TODO) supported by ElementType (TODO)"); + core::string msg = "There's no Property named \""+property.name+"\" of Type "; + msg += property.type+" supported by <"+element->getLogName()+">"; + session->invalidXMLFileStructure(msg); return; } const auto& callback = nameIt->second; @@ -233,7 +236,10 @@ void ParserManager::XMLContext::parseElement(const char* _el, const char** _atts if constexpr (!std::is_same_v) if (!callback.allowedVariantTypes.empty() && std::find(callback.allowedVariantTypes.begin(),callback.allowedVariantTypes.end(),typedElement->type)==callback.allowedVariantTypes.end()) { - session->invalidXMLFileStructure("There's no Property named \""+property.name+"\" of Type(TODO) not supported on ElementType(TODO) of Variant(TODO)"); + core::string msg = "There's no Property named \""+property.name+"\" of Type "; + msg += property.type+" supported by <"+element->getLogName()+"> of Variant "; + msg += std::to_string(typedElement->type); + session->invalidXMLFileStructure(msg); return; } callback(typedElement,std::move(property),session->params->logger); @@ -311,7 +317,7 @@ void ParserManager::XMLContext::onEnd(const char* _el) if (parent && !parent->processChildData(element.element,element.name,session->params->logger)) { if (element.element) - killParseWithError(element.element->getLogName()+" could not processChildData with name: "+element.name); + killParseWithError("<"+parent->getLogName()+ "> could not processChildData of <"+element.element->getLogName()+"> with name: "+element.name); else killParseWithError("Failed to add a nullptr child with name: "+element.name); } @@ -384,7 +390,7 @@ struct ParserManager::CreateElement auto found = StringToTypeMap.find(type); if (found==StringToTypeMap.end()) { - ctx->invalidXMLFileStructure("unknown type"); + ctx->invalidXMLFileStructure(core::string("unknown type in <")+std::to_string((uint8_t)Element::ElementType)+" type=\""+type+"\">"); return {}; } From 846a38311936409fa73b12b55de9e6cc1870dd3b Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 24 Dec 2025 02:01:58 +0100 Subject: [PATCH 28/30] oopsie pushed a dangling submodule pointer last commit --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 8333763f44..513c5a7365 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 8333763f44407f45dfc47d5ae4b1bed3f6d8fb9e +Subproject commit 513c5a736539086c97227643c62c4fbcf2eafa1a From aad78bba1aa58fb403ce57a9546dc5b2060ec8e6 Mon Sep 17 00:00:00 2001 From: devsh Date: Wed, 24 Dec 2025 02:13:43 +0100 Subject: [PATCH 29/30] fix a small typo in CElementBSDF::MixtureBSDF --- examples_tests | 2 +- src/nbl/ext/MitsubaLoader/CElementBSDF.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples_tests b/examples_tests index 513c5a7365..3db6e3cef4 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 513c5a736539086c97227643c62c4fbcf2eafa1a +Subproject commit 3db6e3cef42467eb3fda53f59b78264e43c31ba8 diff --git a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp index 6c91e4dded..4117ca5f3a 100644 --- a/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp +++ b/src/nbl/ext/MitsubaLoader/CElementBSDF.cpp @@ -141,7 +141,7 @@ auto CElementBSDF::compAddPropertyMap() -> AddPropertyMap std::string token; while (std::getline(sstr,token,',')) { - if (state.weightCount) + if (state.weightCount>=MixtureBSDF::MaxChildCount) { logger.log(" MaxChildCount of %d exceeded!",system::ILogger::ELL_ERROR,MetaBSDF::MaxChildCount); break; From 3d61b44b72d4c408ceaa50311c601215b21c0525 Mon Sep 17 00:00:00 2001 From: devsh Date: Mon, 29 Dec 2025 15:40:11 +0100 Subject: [PATCH 30/30] pre-merge `examples_tests` submodule pointer update --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index c5e28aaeaa..5df217517f 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit c5e28aaeaae107d8b0baa2b28355f8d445b7cd7a +Subproject commit 5df217517fd5af0964b6d170afb68d5194daf60d