diff --git a/src/Mod/Import/App/ExportOCAF.cpp b/src/Mod/Import/App/ExportOCAF.cpp index 2baa95e2f4..3a76769b42 100644 --- a/src/Mod/Import/App/ExportOCAF.cpp +++ b/src/Mod/Import/App/ExportOCAF.cpp @@ -58,7 +58,7 @@ # include # include # include -# include +# include # include # include # include @@ -95,6 +95,17 @@ #include #include +#if OCC_VERSION_HEX >= 0x070500 +// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware +# define OCC_COLOR_SPACE Quantity_TOC_sRGB +#else +# define OCC_COLOR_SPACE Quantity_TOC_RGB +#endif + +static inline Quantity_ColorRGBA convertColor(const App::Color &c) +{ + return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), 1.0 - c.a); +} using namespace Import; @@ -284,7 +295,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co */ // Add color information - Quantity_Color col; + Quantity_ColorRGBA col; std::set face_index; TopTools_IndexedMapOfShape faces; @@ -317,11 +328,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co if (!faceLabel.IsNull()) { const App::Color& color = colors[index-1]; - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col = convertColor(color); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } @@ -330,11 +337,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector& co } else if (!colors.empty()) { App::Color color = colors.front(); - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col = convertColor(color); aColorTool->SetColor(shapeLabel, col, XCAFDoc_ColorGen); } @@ -400,7 +403,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch TopoDS_Shape baseShape = part->Shape.getValue(); // Add color information - Quantity_Color col; + Quantity_ColorRGBA col; std::set face_index; TopTools_IndexedMapOfShape faces; @@ -433,11 +436,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch if (!faceLabel.IsNull()) { const App::Color& color = colors[index-1]; - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col = convertColor(color); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } @@ -447,11 +446,7 @@ void ExportOCAF::reallocateFreeShape(std::vector hierarch } else if (!colors.empty()) { App::Color color = colors.front(); - Standard_Real mat[3]; - mat[0] = color.r; - mat[1] = color.g; - mat[2] = color.b; - col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); + col = convertColor(color); aColorTool->SetColor(label, col, XCAFDoc_ColorGen); } } diff --git a/src/Mod/Import/App/ImportOCAF.cpp b/src/Mod/Import/App/ImportOCAF.cpp index 17cc74f906..a6c392f0b7 100644 --- a/src/Mod/Import/App/ImportOCAF.cpp +++ b/src/Mod/Import/App/ImportOCAF.cpp @@ -60,7 +60,7 @@ # include # include # include -# include +# include # include # include # include @@ -108,6 +108,23 @@ using namespace Import; +#if OCC_VERSION_HEX >= 0x070500 +// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware +# define OCC_COLOR_SPACE Quantity_TOC_sRGB +#else +# define OCC_COLOR_SPACE Quantity_TOC_RGB +#endif + +static inline App::Color convertColor(const Quantity_ColorRGBA &c) +{ + Standard_Real r, g, b; + c.GetRGB().Values(r, g, b, OCC_COLOR_SPACE); + return App::Color(static_cast(r), + static_cast(g), + static_cast(b), + 1.0f - static_cast(c.Alpha())); +} + #define OCAF_KEEP_PLACEMENT ImportOCAF::ImportOCAF(Handle(TDocStd_Document) h, App::Document* d, const std::string& name) @@ -439,14 +456,12 @@ void ImportOCAF::createShape(const TopoDS_Shape& aShape, const TopLoc_Location& void ImportOCAF::loadColors(Part::Feature* part, const TopoDS_Shape& aShape) { - Quantity_Color aColor; + Quantity_ColorRGBA aColor; App::Color color(0.8f,0.8f,0.8f); if (aColorTool->GetColor(aShape, XCAFDoc_ColorGen, aColor) || aColorTool->GetColor(aShape, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(aShape, XCAFDoc_ColorCurv, aColor)) { - color.r = (float)aColor.Red(); - color.g = (float)aColor.Green(); - color.b = (float)aColor.Blue(); + color = convertColor(aColor); std::vector colors; colors.push_back(color); applyColors(part, colors); @@ -468,9 +483,7 @@ void ImportOCAF::loadColors(Part::Feature* part, const TopoDS_Shape& aShape) aColorTool->GetColor(xp.Current(), XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(xp.Current(), XCAFDoc_ColorCurv, aColor)) { int index = faces.FindIndex(xp.Current()); - color.r = (float)aColor.Red(); - color.g = (float)aColor.Green(); - color.b = (float)aColor.Blue(); + color = convertColor(aColor); faceColors[index-1] = color; found_face_color = true; } @@ -551,7 +564,7 @@ void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setna part = static_cast(doc->addObject("Part::Feature", default_name.c_str())); part->Label.setValue(default_name); part->Shape.setValue(shape); - std::map::const_iterator jt; + std::map::const_iterator jt; jt = myColorMap.find(shape.HashCode(INT_MAX)); App::Color partColor(0.8f,0.8f,0.8f); @@ -596,11 +609,7 @@ void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setna jt = myColorMap.find(xp.Current().HashCode(INT_MAX)); if (jt != myColorMap.end()) { int index = faces.FindIndex(xp.Current()); - App::Color color; - color.r = (float)jt->second.Red(); - color.g = (float)jt->second.Green(); - color.b = (float)jt->second.Blue(); - faceColors[index-1] = color; + faceColors[index-1] = convertColor(jt->second); found_face_color = true; } xp.Next(); @@ -653,7 +662,7 @@ void ImportXCAF::loadShapes(const TDF_Label& label) } // getting color - Quantity_Color col; + Quantity_ColorRGBA col; if (hColors->GetColor(label, XCAFDoc_ColorGen, col) || hColors->GetColor(label, XCAFDoc_ColorSurf, col) || hColors->GetColor(label, XCAFDoc_ColorCurv, col)) { diff --git a/src/Mod/Import/App/ImportOCAF.h b/src/Mod/Import/App/ImportOCAF.h index 8c4d609265..4f30d921a9 100644 --- a/src/Mod/Import/App/ImportOCAF.h +++ b/src/Mod/Import/App/ImportOCAF.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -117,7 +117,7 @@ private: std::map myShells; std::map myCompds; std::map myShapes; - std::map myColorMap; + std::map myColorMap; std::map myNameMap; }; diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index 4de3b10adb..1c803be05c 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -41,7 +41,7 @@ # include # include # include -# include +# include # include # include # include @@ -50,6 +50,7 @@ #include +#include #include #include #include @@ -71,12 +72,40 @@ #include #include +#if OCC_VERSION_HEX >= 0x070500 +// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware +# define OCC_COLOR_SPACE Quantity_TOC_sRGB +#else +# define OCC_COLOR_SPACE Quantity_TOC_RGB +#endif + FC_LOG_LEVEL_INIT("Import",true,true) using namespace Import; ///////////////////////////////////////////////////////////////////// +static inline App::Color convertColor(const Quantity_ColorRGBA &c) +{ + Standard_Real r, g, b; + c.GetRGB().Values(r, g, b, OCC_COLOR_SPACE); + return App::Color(static_cast(r), + static_cast(g), + static_cast(b), + 1.0f - static_cast(c.Alpha())); +} + +static inline Quantity_ColorRGBA convertColor(const App::Color &c) +{ + return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), 1.0f - c.a); +} + +static inline std::ostream& operator<<(std::ostream& os, const Quantity_ColorRGBA &c) { + App::Color color = convertColor(c); + auto toHex = [](float v) {return boost::format("%02X") % static_cast(v*255);}; + return os << "#" << toHex(color.r) << toHex(color.g) << toHex(color.b) << toHex(color.a); +} + static std::string labelName(TDF_Label label) { std::string txt; Handle(TDataStd_Name) name; @@ -116,13 +145,13 @@ static void printLabel(TDF_Label label, Handle(XCAFDoc_ShapeTool) aShapeTool, ss << ", " << Part::TopoShape::shapeName(shape.ShapeType(),true); } if(aShapeTool->IsShape(label)) { - Quantity_Color c; + Quantity_ColorRGBA c; if(aColorTool->GetColor(label,XCAFDoc_ColorGen,c)) - ss << ", gc: " << c.StringName(c.Name()); + ss << ", gc: " << c; if(aColorTool->GetColor(label,XCAFDoc_ColorSurf,c)) - ss << ", sc: " << c.StringName(c.Name()); + ss << ", sc: " << c; if(aColorTool->GetColor(label,XCAFDoc_ColorCurv,c)) - ss << ", cc: " << c.StringName(c.Name()); + ss << ", cc: " << c; } ss << std::endl; @@ -229,12 +258,11 @@ void ImportOCAF2::setObjectName(Info &info, TDF_Label label) { } } - bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bool noDefault) { bool ret = false; - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if(aColorTool->GetColor(shape, XCAFDoc_ColorSurf, aColor)) { - App::Color c(aColor.Red(),aColor.Green(),aColor.Blue()); + App::Color c = convertColor(aColor); if(!check || info.faceColor!=c) { info.faceColor = c; info.hasFaceColor = true; @@ -242,7 +270,7 @@ bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bo } } if(!noDefault && !info.hasFaceColor && aColorTool->GetColor(shape, XCAFDoc_ColorGen, aColor)) { - App::Color c(aColor.Red(),aColor.Green(),aColor.Blue()); + App::Color c = convertColor(aColor); if(!check || info.faceColor!=c) { info.faceColor = c; info.hasFaceColor = true; @@ -250,7 +278,7 @@ bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bo } } if(aColorTool->GetColor(shape, XCAFDoc_ColorCurv, aColor)) { - App::Color c(aColor.Red(),aColor.Green(),aColor.Blue()); + App::Color c = convertColor(aColor); // Some STEP include a curve color with the same value of the face // color. And this will look weird in FC. So for shape with face // we'll ignore the curve color, if it is the same as the face color. @@ -365,15 +393,15 @@ bool ImportOCAF2::createObject(App::Document *doc, TDF_Label label, bool foundFaceColor=false,foundEdgeColor=false; App::Color faceColor,edgeColor; - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if(aColorTool->GetColor(l, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(l, XCAFDoc_ColorGen, aColor)) { - faceColor = App::Color(aColor.Red(),aColor.Green(),aColor.Blue()); + faceColor = convertColor(aColor); foundFaceColor = true; } if(aColorTool->GetColor(l, XCAFDoc_ColorCurv, aColor)) { - edgeColor = App::Color(aColor.Red(),aColor.Green(),aColor.Blue()); + edgeColor = convertColor(aColor); foundEdgeColor = true; if(j==0 && foundFaceColor && faceColors.size() && edgeColor==faceColor) { // Do not set edge the same color as face @@ -648,11 +676,11 @@ void ImportOCAF2::getSHUOColors(TDF_Label label, subname += App::DocumentObject::hiddenMarker(); colors.emplace(subname,App::Color()); } else { - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if(aColorTool->GetColor(slabel, XCAFDoc_ColorSurf, aColor) || aColorTool->GetColor(slabel, XCAFDoc_ColorGen, aColor)) { - colors.emplace(subname,App::Color(aColor.Red(),aColor.Green(),aColor.Blue())); + colors.emplace(subname,convertColor(aColor)); } } } @@ -782,12 +810,9 @@ bool ImportOCAF2::createAssembly(App::Document *_doc, childInfo.vis.push_back(vis); childInfo.labels.push_back(childLabel); childInfo.plas.emplace_back(Part::TopoShape::convert(childShape.Location().Transformation())); - Quantity_Color aColor; + Quantity_ColorRGBA aColor; if (aColorTool->GetColor(childShape, XCAFDoc_ColorSurf, aColor)) { - auto &color = childInfo.colors[childInfo.plas.size()-1]; - color.r = (float)aColor.Red(); - color.g = (float)aColor.Green(); - color.b = (float)aColor.Blue(); + childInfo.colors[childInfo.plas.size()-1] = convertColor(aColor); } } assert(visibilities.size() == children.size()); @@ -1036,7 +1061,7 @@ void ExportOCAF2::setupObject(TDF_Label label, App::DocumentObject *obj, continue; } const App::Color& c = vv.second; - Quantity_Color color(c.r,c.g,c.b,Quantity_TOC_RGB); + Quantity_ColorRGBA color = convertColor(c); auto colorType = vv.first[0]=='F'?XCAFDoc_ColorSurf:XCAFDoc_ColorCurv; if(vv.first=="Face" || vv.first=="Edge") { aColorTool->SetColor(nodeLabel, color, colorType); @@ -1219,8 +1244,17 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, // not call setupObject() on a non-located baseshape like above, // because OCCT does not respect shape style sharing when not // exporting assembly - if(!keepPlacement) + if(!keepPlacement || shape.getPlacement() == Base::Placement()) shape.setShape(shape.getShape().Located(TopLoc_Location())); + else { + Base::Matrix4D mat = shape.getTransform(); + shape.setShape(shape.getShape().Located(TopLoc_Location())); + // Transform with copy to conceal the transformation + shape.transformShape(mat, true); + // Even if the shape has no transformation, TopoShape still sets + // a TopLoc_Location, so we need to clear it again. + shape.setShape(shape.getShape().Located(TopLoc_Location())); + } label = aShapeTool->AddShape(shape.getShape(),Standard_False, Standard_False); auto o = name?parentObj:obj; if(o!=linked) @@ -1277,7 +1311,7 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, // Work around OCCT bug. If no color setting here, it will crash. // The culprit is at STEPCAFControl_Writer::1093 as shown below // - // surfColor = Styles.EncodeColor(Quantity_Color(1,1,1,Quantity_TOC_RGB),DPDCs,ColRGBs); + // surfColor = Styles.EncodeColor(Quantity_Color(1,1,1,OCC_COLOR_SPACE),DPDCs,ColRGBs); // PSA = Styles.MakeColorPSA ( item, surfColor, curvColor, isComponent ); // if ( isComponent ) // setDefaultInstanceColor( override, PSA); @@ -1287,13 +1321,13 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj, // setDefaultInstanceColor( override, PSA); // auto childShape = aShapeTool->GetShape(childLabel); - Quantity_Color col; + Quantity_ColorRGBA col; if(!aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorGen,col) && !aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorSurf,col) && !aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorCurv,col)) { auto &c = defaultColor; - aColorTool->SetColor(childLabel, Quantity_Color(c.r,c.g,c.b,Quantity_TOC_RGB), XCAFDoc_ColorGen); + aColorTool->SetColor(childLabel, convertColor(c), XCAFDoc_ColorGen); FC_WARN(labelName(childLabel) << " set default color"); } aColorTool->SetVisibility(childLabel,Standard_False); diff --git a/src/Mod/Import/Gui/AppImportGuiPy.cpp b/src/Mod/Import/Gui/AppImportGuiPy.cpp index 6601973cc2..72e5de3417 100644 --- a/src/Mod/Import/Gui/AppImportGuiPy.cpp +++ b/src/Mod/Import/Gui/AppImportGuiPy.cpp @@ -322,9 +322,10 @@ private: return; } // vp->MapFaceColor.setValue(false); - if(colors.size() == 1) + if(colors.size() == 1) { vp->ShapeColor.setValue(colors.front()); - else + vp->Transparency.setValue(100 * colors.front().a); + } else vp->DiffuseColor.setValues(colors); } virtual void applyEdgeColors(Part::Feature* part, const std::vector& colors) override { diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 8a52f1701b..daf355e909 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -356,24 +356,19 @@ void ViewProviderPartExt::onChanged(const App::Property* prop) else if (prop == &ShapeMaterial || prop == &ShapeColor) { pcFaceBind->value = SoMaterialBinding::OVERALL; ViewProviderGeometryObject::onChanged(prop); - DiffuseColor.setValue(ShapeColor.getValue()); + App::Color c = ShapeColor.getValue(); + c.a = Transparency.getValue()/100.0f; + DiffuseColor.setValue(c); } else if (prop == &Transparency) { const App::Material& Mat = ShapeMaterial.getValue(); long value = (long)(100*Mat.transparency); if (value != Transparency.getValue()) { float trans = Transparency.getValue()/100.0f; - if (pcFaceBind->value.getValue() == SoMaterialBinding::PER_PART) { - int cnt = pcShapeMaterial->diffuseColor.getNum(); - pcShapeMaterial->transparency.setNum(cnt); - float *t = pcShapeMaterial->transparency.startEditing(); - for (int i=0; itransparency.finishEditing(); - } - else { - pcShapeMaterial->transparency = trans; - } + auto colors = DiffuseColor.getValues(); + for (auto &c : colors) + c.a = trans; + DiffuseColor.setValues(colors); App::PropertyContainer* parent = ShapeMaterial.getContainer(); ShapeMaterial.setContainer(0); @@ -642,7 +637,7 @@ void ViewProviderPartExt::setHighlightedFaces(const std::vector& col else if (colors.size() == 1) { pcFaceBind->value = SoMaterialBinding::OVERALL; pcShapeMaterial->diffuseColor.setValue(colors[0].r, colors[0].g, colors[0].b); - //pcShapeMaterial->transparency = colors[0].a; do not get transparency from DiffuseColor in this case + pcShapeMaterial->transparency = Transparency.getValue()/100.f; } } @@ -708,6 +703,7 @@ std::map ViewProviderPartExt::getElementColors(const cha } if(size && singleColor) { color = DiffuseColor[0]; + color.a = Transparency.getValue()/100.0f; ret.clear(); } ret["Face"] = color;