From ca5ac0b5324773a9b4074fdf9fc676cafd0cf566 Mon Sep 17 00:00:00 2001 From: Leo Terziman Date: Thu, 1 Jun 2017 09:47:50 +0200 Subject: [PATCH] Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the complete model --- code/IFCLoader.cpp | 57 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 24c5452b2..463803ab3 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -882,6 +882,7 @@ void ProcessSpatialStructures(ConversionData& conv) } } + std::vector nodes; for(const STEP::LazyObject* lz : *range) { const IfcSpatialStructureElement* const prod = lz->ToPtr(); @@ -890,20 +891,19 @@ void ProcessSpatialStructures(ConversionData& conv) } IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():"")); - // the primary site is referenced by an IFCRELAGGREGATES element which assigns it to the IFCPRODUCT + // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT const STEP::DB::RefMap& refs = conv.db.GetRefs(); - STEP::DB::RefMapRange range = refs.equal_range(conv.proj.GetID()); - for(;range.first != range.second; ++range.first) { - if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr()) { + STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID()); + for(; ref_range.first != ref_range.second; ++ref_range.first) { + if(const IfcRelAggregates* const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr()) { for(const IfcObjectDefinition& def : aggr->RelatedObjects) { // comparing pointer values is not sufficient, we would need to cast them to the same type first // as there is multiple inheritance in the game. if (def.GetID() == prod->GetID()) { IFCImporter::LogDebug("selecting this spatial structure as root structure"); - // got it, this is the primary site. - conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL); - return; + // got it, this is one primary site. + nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); } } @@ -911,19 +911,42 @@ void ProcessSpatialStructures(ConversionData& conv) } } + size_t nb_nodes = nodes.size(); - IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite"); - for(const STEP::LazyObject* lz : *range) { - const IfcSpatialStructureElement* const prod = lz->ToPtr(); - if(!prod) { - continue; - } + if (nb_nodes == 0) { + IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite"); + for (const STEP::LazyObject* lz : *range) { + const IfcSpatialStructureElement* const prod = lz->ToPtr(); + if (!prod) { + continue; + } - conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL); - return; - } + nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); + } - IFCImporter::ThrowException("failed to determine primary site element"); + nb_nodes = nodes.size(); + } + + if (nb_nodes == 1) { + conv.out->mRootNode = nodes[0]; + } + else if (nb_nodes > 1) { + conv.out->mRootNode = new aiNode("Root"); + conv.out->mRootNode->mParent = NULL; + conv.out->mRootNode->mNumChildren = static_cast(nb_nodes); + conv.out->mRootNode->mChildren = new aiNode*[conv.out->mRootNode->mNumChildren]; + + for (size_t i = 0; i < nb_nodes; ++i) { + aiNode* node = nodes[i]; + + node->mParent = conv.out->mRootNode; + + conv.out->mRootNode->mChildren[i] = node; + } + } + else { + IFCImporter::ThrowException("failed to determine primary site element"); + } } // ------------------------------------------------------------------------------------------------