From fe4600c03a8d658776ed7f54f11baa942c4b9fd9 Mon Sep 17 00:00:00 2001 From: devsh Date: Sat, 27 Sep 2025 15:19:20 +0200 Subject: [PATCH 01/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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)");