22// This file is part of the "Nabla Engine".
33// For conditions of distribution and use, see copyright notice in nabla.h
44
5+
56#include " nbl/builtin/hlsl/math/linalg/basic.hlsl"
67#include " nbl/builtin/hlsl/math/linalg/fast_affine.hlsl"
78
89#include " nbl/ext/MitsubaLoader/CMitsubaLoader.h"
910#include " nbl/ext/MitsubaLoader/ParserUtil.h"
11+ #include " nbl/ext/MitsubaLoader/CMitsubaSerializedMetadata.h"
1012
1113#include < cwchar>
1214
13- #if 0
14- #include "nbl/asset/utils/CDerivativeMapCreator.h"
15+ // #include "nbl/asset/utils/CDerivativeMapCreator.h"
1516
16- #include "nbl/ext/MitsubaLoader/CMitsubaSerializedMetadata.h"
17- #endif
1817
1918
2019#if defined(_NBL_DEBUG) || defined(_NBL_RELWITHDEBINFO)
@@ -220,6 +219,10 @@ SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _file, const IAssetLoader:
220219 _override,
221220 result.metadata .get ()
222221 );
222+ ctx.interm_getAssetInHierarchy = [&](const char * filename, const uint16_t hierarchyOffset)->SAssetBundle
223+ {
224+ return this ->interm_getAssetInHierarchy (filename,ctx.inner .params ,_hierarchyLevel+hierarchyOffset,ctx.override_ );
225+ };
223226 //
224227 ctx.scene ->m_ambientLight = result.ambient ;
225228
@@ -289,14 +292,14 @@ SAssetBundle CMitsubaLoader::loadAsset(system::IFile* _file, const IAssetLoader:
289292 continue ;
290293
291294 if (shapedef->type !=CElementShape::Type::INSTANCE)
292- addToScene (shapedef,ctx.loadBasicShape (_hierarchyLevel, shapedef));
295+ addToScene (shapedef,ctx.loadBasicShape (shapedef));
293296 else // mitsuba is weird and lists instances under a shapegroup instead of having instances reference the shapegroup
294297 {
295298 // get group reference
296299 const CElementShape* parent = shapedef->instance .parent ;
297300 if (!parent) // we should probably assert this
298301 continue ;
299- addToScene (shapedef,ctx.loadShapeGroup (_hierarchyLevel, parent));
302+ addToScene (shapedef,ctx.loadShapeGroup (parent));
300303 }
301304 }
302305 result.shapegroups .clear ();
@@ -625,7 +628,7 @@ SContext::SContext(
625628 frontIR = material_compiler3::CFrontendIR::create ();
626629}
627630
628- auto SContext::loadShapeGroup (const uint32_t hierarchyLevel, const CElementShape* shape) -> SContext::shape_ass_type
631+ auto SContext::loadShapeGroup (const CElementShape* shape) -> SContext::shape_ass_type
629632{
630633 assert (shape->type ==CElementShape::Type::SHAPEGROUP);
631634 const auto * const shapegroup = &shape->shapegroup ;
@@ -650,9 +653,9 @@ auto SContext::loadShapeGroup(const uint32_t hierarchyLevel, const CElementShape
650653
651654 shape_ass_type nestedCollection;
652655 if (child->type !=CElementShape::Type::SHAPEGROUP)
653- nestedCollection = loadBasicShape (hierarchyLevel, child);
656+ nestedCollection = loadBasicShape (child);
654657 else
655- nestedCollection = loadShapeGroup (hierarchyLevel, child);
658+ nestedCollection = loadShapeGroup (child);
656659 if (!nestedCollection)
657660 continue ;
658661
@@ -673,7 +676,7 @@ auto SContext::loadShapeGroup(const uint32_t hierarchyLevel, const CElementShape
673676 return collection;
674677}
675678
676- auto SContext::loadBasicShape (const uint32_t hierarchyLevel, const CElementShape* shape) -> SContext::shape_ass_type
679+ auto SContext::loadBasicShape (const CElementShape* shape) -> SContext::shape_ass_type
677680{
678681 auto found = shapeCache.find (shape);
679682 if (found!=shapeCache.end ())
@@ -697,69 +700,97 @@ auto SContext::loadBasicShape(const uint32_t hierarchyLevel, const CElementShape
697700
698701 auto loadModel = [&](const char * filename, int64_t index=-1 ) -> void
699702 {
700- # if 0
701- auto retval = interm_getAssetInHierarchy(filename,inner.params,hierarchyLevel+/*ICPUScene::GEOMETRY_COLLECTION_HIERARCHY_LEVELS_BELOW*/1,override_ );
702- if (retval.getContents() .empty())
703+ auto retval = interm_getAssetInHierarchy (filename, /* ICPUScene::GEOMETRY_COLLECTION_HIERARCHY_LEVELS_BELOW */ 1 );
704+ auto contentRange = retval. getContents ( );
705+ if (contentRange .empty ())
703706 {
704- os::Printer:: log(std::string("[ERROR] Could Not Find Mesh: ") + filename.svalue, ELL_ERROR );
707+ inner. params . logger . log (" Could Not Load Shape : %s " ,LoggerError,filename );
705708 return ;
706709 }
710+
711+ // we used to load with the IAssetLoader::ELPF_RIGHT_HANDED_MESHES flag, this means flipping the mesh x-axis
712+ auto transform = math::linalg::diagonal<float32_t3x4>(1 .f );
713+ transform[0 ][0 ] = -1 .f ;
714+
715+ //
716+ auto addCollectionGeometries = [&](const ICPUGeometryCollection* col)->void
717+ {
718+ if (col)
719+ for (auto ref : col->getGeometries ())
720+ {
721+ if (ref.hasTransform ())
722+ ref.transform = math::linalg::promoted_mul (ref.transform ,transform);
723+ else
724+ ref.transform = transform;
725+ addGeometry (std::move (ref));
726+ }
727+ };
728+
729+ // take first target and replace the collection
730+ auto addFirstTargetGeometries = [&](const ICPUMorphTargets* morph)->void
731+ {
732+ if (const auto & targets=morph->getTargets (); !targets.empty ())
733+ addCollectionGeometries (targets.front ().geoCollection .get ());
734+ };
707735
708- uint32_t actualIndex = 0;
709736 switch (retval.getAssetType ())
710737 {
711738 case IAsset::ET_GEOMETRY:
712739 {
713- auto contentRange = retval.getContents();
740+ // only add one geometry, if we meant to add a whole collection, the file would load a collection
741+ const IGeometry<ICPUBuffer>* geo = nullptr ;
714742 auto serializedMeta = retval.getMetadata ()->selfCast <CMitsubaSerializedMetadata>();
715- //
716- if (index>=0ll && serializedMeta)
717743 for (auto it=contentRange.begin (); it!=contentRange.end (); it++)
718744 {
719- auto meshMeta = static_cast<const CMitsubaSerializedMetadata::CMesh*>(serializedMeta->getAssetSpecificMetadata(IAsset::castDown<ICPUMesh>(*it).get()));
720- if (meshMeta->m_id!=static_cast<uint32_t>(index))
721- continue;
722- actualIndex = it-contentRange.begin();
723- break;
724- }
725- //
726- if (contentRange.begin()+actualIndex < contentRange.end())
727- {
728- auto asset = contentRange.begin()[actualIndex];
729- if (!asset)
730- {
731- return;
732- }
733- addGeometry(asset);
745+ geo = IAsset::castDown<const ICPUPolygonGeometry>(*it).get ();
746+ assert (geo);
747+ if (!serializedMeta || index<0ll || index>numeric_limits<uint32_t >::max) // not Misuba serialized or shape index not specialized
748+ break ;
749+ auto * const meta = serializedMeta->getAssetSpecificMetadata (static_cast <const ICPUPolygonGeometry*>(geo));
750+ assert (meta);
751+ auto * const polygonMeta = static_cast <const CMitsubaSerializedMetadata::CPolygonGeometry*>(meta);
752+ if (polygonMeta->m_id ==static_cast <uint32_t >(index))
753+ break ;
734754 }
755+ if (auto * const mg=const_cast <IGeometry<ICPUBuffer>*>(geo); mg)
756+ addGeometry ({.transform =transform,.geometry =core::smart_refctd_ptr<IGeometry<ICPUBuffer>>(mg)});
757+ break ;
735758 }
736759 case IAsset::ET_GEOMETRY_COLLECTION:
737760 {
738- // TODO: replace the collection
761+ // only add the first collection's geometries
762+ addCollectionGeometries (IAsset::castDown<const ICPUGeometryCollection>(contentRange[0 ]).get ());
739763 break ;
740764 }
741765 case IAsset::ET_MORPH_TARGETS:
742766 {
743- // TODO: take first target and replace the collection
744- _NBL_DEBUG_BREAK_IF(true); // we have no such loaders right now
767+ addFirstTargetGeometries (IAsset::castDown<const ICPUMorphTargets>(contentRange[0 ]).get ());
745768 break ;
746769 }
747770 case IAsset::ET_SCENE:
748771 {
749- // TODO: flatten the scene into a single instance, this is path for OBJ loading
750- // NOTE: also need to preserve/forward the materials somehow (need to chape the `shape_ass_type` to have a default Material Binding Table)
772+ // flatten the scene into a single instance, this is path for OBJ loading
773+ const auto & instances = IAsset::castDown<const ICPUScene>(contentRange[0 ])->getInstances ();
774+ const auto instanceTforms = instances.getInitialTransforms ();
775+ for (auto i=0u ; i<instances.size (); i++)
776+ {
777+ auto * const targets = instances.getMorphTargets ()[i].get ();
778+ const auto oldGeoBegin = pGeometries->size ();
779+ addFirstTargetGeometries (targets);
780+ if (!instanceTforms.empty ())
781+ for (auto geoIx=oldGeoBegin; geoIx<pGeometries->size (); geoIx++)
782+ {
783+ auto & ref = pGeometries->operator [](geoIx);
784+ ref.transform = math::linalg::promoted_mul (instanceTforms[i],ref.transform );
785+ }
786+ // NOTE: also need to preserve/forward the materials somehow (need to chape the `shape_ass_type` to have a default Material Binding Table)
787+ }
788+ break ;
751789 }
752790 default :
753- os::Printer:: log("[ERROR] Loaded an Asset but it wasn 't a mesh , was E_ASSET_TYPE " + std ::to_string(retval.getAssetType()), ELL_ERROR );
791+ inner. params . logger . log (" Loaded an Asset but it didn 't contain any geometry , was %s " ,LoggerError, system ::to_string (retval.getAssetType ()));
754792 break ;
755793 }
756- #endif
757- // we used to load with the IAssetLoader::ELPF_RIGHT_HANDED_MESHES flag, this means flipping the mesh x-axis
758- for (auto & ref : *pGeometries)
759- {
760- ref.transform = math::linalg::diagonal<float32_t3x4>(1 .f );
761- ref.transform [0 ][0 ] = -1 .f ;
762- }
763794 };
764795
765796 bool flipNormals = false ;
0 commit comments