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 <noreply@anthropic.com>
This commit is contained in:
Petru Conduraru
2026-07-11 07:21:38 +03:00
parent ade03b171a
commit b1a641fa68
+26 -5
View File
@@ -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<IfcSchema::IfcSurfaceStyle*, T*> negative_fallback{nullptr, nullptr};
for (auto& style : prs_styles) {
if (auto surface_style = style->as<IfcSchema::IfcSurfaceStyle>()) {
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<T>()) {
}
auto styles_elements = surface_style->Styles();
for (auto mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) {
if ((*mt)->template as<T>()) {
if (!is_negative) {
return std::make_pair(surface_style, (*mt)->as<T>());
} else if (negative_fallback.first == nullptr) {
negative_fallback = std::make_pair(surface_style, (*mt)->as<T>());
}
}
}
}
}
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) {