From b1a641fa688c8d1d8651672d34e92f9a9da18fad Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Sat, 11 Jul 2026 07:21:38 +0300 Subject: [PATCH] Use NEGATIVE-side IfcSurfaceStyle as a fallback instead of dropping it (#5618) The surface-style picker skipped every IfcSurfaceStyle whose Side was NEGATIVE outright, so an item styled only with a NEGATIVE-side style was left completely unstyled and fell back to the gray DefaultMaterial. Keep preferring a POSITIVE or BOTH style for the visible front face (returned immediately, unchanged), but remember a NEGATIVE-side style and its shading and use it as a fallback when no POSITIVE/BOTH style supplies the requested presentation type. A styled item is then no longer rendered unstyled. Verified on OCC 7.9.2 with a two-box IFC4 fixture (one box styled red on the NEGATIVE side, one green on the POSITIVE side): - before: NEG box -> DefaultMaterial (Kd 0.7 0.7 0.7), POS box -> green - after: NEG box -> its red (Kd 1 0 0), POS box -> green (unchanged) Co-Authored-By: Claude Opus 4.8 --- src/ifcgeom/mapping/mapping.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/ifcgeom/mapping/mapping.cpp b/src/ifcgeom/mapping/mapping.cpp index 56df064c49..2fb209fd3b 100644 --- a/src/ifcgeom/mapping/mapping.cpp +++ b/src/ifcgeom/mapping/mapping.cpp @@ -488,20 +488,41 @@ namespace { #endif IfcSchema::IfcSurfaceStyle *surface_style_ = nullptr; + // A surface style with Side == NEGATIVE targets the back (negative) face. + // When a POSITIVE or BOTH style is also present it is preferred for the + // visible front face, but a NEGATIVE style must still be used as a + // fallback so a styled item is not left completely unstyled (see #5618). + IfcSchema::IfcSurfaceStyle *negative_surface_style_ = nullptr; + std::pair negative_fallback{nullptr, nullptr}; for (auto& style : prs_styles) { if (auto surface_style = style->as()) { - if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) { + const bool is_negative = surface_style->Side() == IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE; + if (is_negative) { + if (negative_surface_style_ == nullptr) { + negative_surface_style_ = surface_style; + } + } else { surface_style_ = surface_style; - auto styles_elements = surface_style->Styles(); - for (auto mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) { - if ((*mt)->template as()) { + } + auto styles_elements = surface_style->Styles(); + for (auto mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) { + if ((*mt)->template as()) { + if (!is_negative) { return std::make_pair(surface_style, (*mt)->as()); + } else if (negative_fallback.first == nullptr) { + negative_fallback = std::make_pair(surface_style, (*mt)->as()); } } } } } - return std::make_pair(surface_style_, nullptr); + if (negative_fallback.first != nullptr) { + return negative_fallback; + } + if (surface_style_ != nullptr) { + return std::make_pair(surface_style_, nullptr); + } + return std::make_pair(negative_surface_style_, nullptr); } bool process_colour(IfcSchema::IfcColourRgb* colour, double* rgb) {