1 // Copyright (c) 2019 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <XmlMXCAFDoc_VisMaterialDriver.hxx>
16 #include <Message.hxx>
17 #include <Message_Messenger.hxx>
18 #include <XCAFDoc_VisMaterial.hxx>
19 #include <XmlObjMgt.hxx>
20 #include <XmlObjMgt_Document.hxx>
21 #include <XmlObjMgt_Persistent.hxx>
23 IMPLEMENT_STANDARD_RTTIEXT(XmlMXCAFDoc_VisMaterialDriver, XmlMDF_ADriver)
25 IMPLEMENT_DOMSTRING(IsDoubleSided, "isdoublesided")
26 IMPLEMENT_DOMSTRING(AlphaMode, "alpha_mode")
27 IMPLEMENT_DOMSTRING(AlphaCutOff, "alpha_cutoff")
29 IMPLEMENT_DOMSTRING(BaseColor, "base_color")
30 IMPLEMENT_DOMSTRING(RefractionIndex, "ior")
31 IMPLEMENT_DOMSTRING(EmissiveFactor, "emissive_factor")
32 IMPLEMENT_DOMSTRING(Metallic, "metallic")
33 IMPLEMENT_DOMSTRING(Roughness, "roughness")
34 IMPLEMENT_DOMSTRING(BaseColorTexture, "base_color_texture")
35 IMPLEMENT_DOMSTRING(MetallicRoughnessTexture, "metallic_roughness_texture")
36 IMPLEMENT_DOMSTRING(EmissiveTexture, "emissive_texture")
37 IMPLEMENT_DOMSTRING(OcclusionTexture, "occlusion_texture")
38 IMPLEMENT_DOMSTRING(NormalTexture, "normal_texture")
40 IMPLEMENT_DOMSTRING(AmbientColor, "ambient_color")
41 IMPLEMENT_DOMSTRING(DiffuseColor, "diffuse_color")
42 IMPLEMENT_DOMSTRING(SpecularColor, "specular_color")
43 IMPLEMENT_DOMSTRING(EmissiveColor, "emissive_color")
44 IMPLEMENT_DOMSTRING(Shininess, "shininess")
45 IMPLEMENT_DOMSTRING(Transparency, "transparency")
46 IMPLEMENT_DOMSTRING(DiffuseTexture, "diffuse_texture")
47 IMPLEMENT_DOMSTRING(FilePath, "file_path")
48 IMPLEMENT_DOMSTRING(TextureId, "texture_id")
49 IMPLEMENT_DOMSTRING(Offset, "offset")
50 IMPLEMENT_DOMSTRING(Length, "length")
52 //! Encode alpha mode into character.
53 static const char* alphaModeToString (Graphic3d_AlphaMode theMode)
57 case Graphic3d_AlphaMode_Opaque: return "Opaque";
58 case Graphic3d_AlphaMode_Mask: return "Mask";
59 case Graphic3d_AlphaMode_Blend: return "Blend";
60 case Graphic3d_AlphaMode_MaskBlend: return "MaskBlend";
61 case Graphic3d_AlphaMode_BlendAuto: return "Auto";
66 //! Decode alpha mode from string.
67 static Graphic3d_AlphaMode alphaModeFromString (const char* theMode)
69 if (strcasecmp (theMode, "Opaque") == 0)
71 return Graphic3d_AlphaMode_Opaque;
73 else if (strcasecmp (theMode, "Mask") == 0)
75 return Graphic3d_AlphaMode_Mask;
77 else if (strcasecmp (theMode, "Blend") == 0)
79 return Graphic3d_AlphaMode_Blend;
81 else if (strcasecmp (theMode, "MaskBlend") == 0)
83 return Graphic3d_AlphaMode_MaskBlend;
85 else if (strcasecmp (theMode, "Auto") == 0)
87 return Graphic3d_AlphaMode_BlendAuto;
89 return Graphic3d_AlphaMode_BlendAuto;
92 //! Encode short real value.
93 static void writeReal (XmlObjMgt_Persistent& theTarget,
94 const XmlObjMgt_DOMString& theName,
95 const Standard_ShortReal theValue)
97 theTarget.Element().setAttribute (theName, TCollection_AsciiString(theValue).ToCString());
100 //! Encode short real value.
101 static bool readReal (const XmlObjMgt_Element& theElement,
102 const XmlObjMgt_DOMString& theName,
103 Standard_ShortReal& theValue)
105 Standard_Real aValue = 0.0;
106 if (XmlObjMgt::GetReal (theElement.getAttribute (theName), aValue))
108 theValue = (Standard_ShortReal )aValue;
115 static void writeVec3 (XmlObjMgt_Persistent& theTarget,
116 const XmlObjMgt_DOMString& theName,
117 const Graphic3d_Vec3& theVec3)
119 TCollection_AsciiString aString = TCollection_AsciiString() + theVec3[0] + " " + theVec3[1] + " " + theVec3[2];
120 theTarget.Element().setAttribute (theName, aString.ToCString());
124 static bool readVec3 (const XmlObjMgt_Element& theElement,
125 const XmlObjMgt_DOMString& theName,
126 Graphic3d_Vec3& theVec3)
128 Graphic3d_Vec3 aVec3;
129 LDOMString aString = theElement.getAttribute (theName);
130 const char* aPos = aString.GetString();
132 aVec3[0] = (float )Strtod (aPos, &aNext);
134 aVec3[1] = (float )Strtod (aPos, &aNext);
136 aVec3[2] = (float )Strtod (aPos, &aNext);
146 static bool readColor (const XmlObjMgt_Element& theElement,
147 const XmlObjMgt_DOMString& theName,
148 Quantity_Color& theColor)
150 Graphic3d_Vec3 aVec3;
151 if (readVec3 (theElement, theName, aVec3))
153 theColor = Quantity_Color (aVec3);
160 static void writeVec4 (XmlObjMgt_Persistent& theTarget,
161 const XmlObjMgt_DOMString& theName,
162 const Graphic3d_Vec4& theVec4)
164 TCollection_AsciiString aString = TCollection_AsciiString() + theVec4[0] + " " + theVec4[1] + " " + theVec4[2] + " " + theVec4[3];
165 theTarget.Element().setAttribute (theName, aString.ToCString());
169 static bool readVec4 (const XmlObjMgt_Element& theElement,
170 const XmlObjMgt_DOMString& theName,
171 Graphic3d_Vec4& theVec4)
173 Graphic3d_Vec4 aVec4;
174 LDOMString aString = theElement.getAttribute (theName);
175 const char* aPos = aString.GetString();
177 aVec4[0] = (float )Strtod (aPos, &aNext);
179 aVec4[1] = (float )Strtod (aPos, &aNext);
181 aVec4[2] = (float )Strtod (aPos, &aNext);
183 aVec4[3] = (float )Strtod (aPos, &aNext);
193 static bool readColor (const XmlObjMgt_Element& theElement,
194 const XmlObjMgt_DOMString& theName,
195 Quantity_ColorRGBA& theColor)
197 Graphic3d_Vec4 aVec4;
198 if (readVec4 (theElement, theName, aVec4))
200 theColor = Quantity_ColorRGBA (aVec4);
206 //! Encode texture path.
207 static void writeTexture (XmlObjMgt_Persistent& theTarget,
208 const XmlObjMgt_DOMString& theName,
209 const Handle(Image_Texture)& theImage)
211 if (theImage.IsNull())
215 XmlObjMgt_Document aDoc(theTarget.Element().getOwnerDocument());
216 XmlObjMgt_Element aCurTarget = aDoc.createElement(theName);
217 theTarget.Element().appendChild(aCurTarget);
218 if (theImage->DataBuffer().IsNull())
220 aCurTarget.setAttribute(::FilePath(), theImage->FilePath().ToCString());
221 if (theImage->FileOffset() == -1 || theImage->FileLength() == -1)
225 aCurTarget.setAttribute(::Offset(), static_cast<int>(theImage->FileOffset()));
226 aCurTarget.setAttribute(::Length(), static_cast<int>(theImage->FileLength()));
230 Message::SendWarning() << "Warning: XmlMXCAFDoc_VisMaterialDriver : Can't write a texture to buffer.";
234 //! Decode texture path.
235 static void readTexture (const XmlObjMgt_Element& theElement,
236 const XmlObjMgt_DOMString& theName,
237 Handle(Image_Texture)& theImage)
239 TCollection_AsciiString aStr(theElement.getAttribute(theName).GetString());
242 theImage = new Image_Texture(aStr);
245 LDOM_Element anElement = theElement.GetChildByTagName(theName);
246 if (anElement.isNull())
250 TCollection_AsciiString aFilePath(anElement.getAttribute(::FilePath()).GetString());
251 TCollection_AsciiString anId(anElement.getAttribute(::TextureId()).GetString());
252 Standard_Integer anOffset = -1, aLength = -1;
253 if (!aFilePath.IsEmpty())
255 anElement.getAttribute(::Offset()).GetInteger(anOffset);
256 anElement.getAttribute(::Length()).GetInteger(aLength);
257 if (anOffset == -1 || aLength == -1)
259 theImage = new Image_Texture(aFilePath);
262 theImage = new Image_Texture(aFilePath, anOffset, aLength);
264 else if (!anId.IsEmpty())
266 Message::SendWarning() << "Warning: XmlMXCAFDoc_VisMaterialDriver : Can't write a texture to buffer.";
270 //=======================================================================
271 //function : XmlMXCAFDoc_VisMaterialDriver
273 //=======================================================================
274 XmlMXCAFDoc_VisMaterialDriver::XmlMXCAFDoc_VisMaterialDriver (const Handle(Message_Messenger)& theMsgDriver)
275 : XmlMDF_ADriver (theMsgDriver, "xcaf", "VisMaterial")
280 //=======================================================================
281 //function : NewEmpty
283 //=======================================================================
284 Handle(TDF_Attribute) XmlMXCAFDoc_VisMaterialDriver::NewEmpty() const
286 return new XCAFDoc_VisMaterial();
289 //=======================================================================
291 //purpose : persistent -> transient (retrieve)
292 //=======================================================================
293 Standard_Boolean XmlMXCAFDoc_VisMaterialDriver::Paste (const XmlObjMgt_Persistent& theSource,
294 const Handle(TDF_Attribute)& theTarget,
295 XmlObjMgt_RRelocationTable& ) const
297 Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theTarget);
299 const XmlObjMgt_DOMString aDoubleSidedStr = theSource.Element().getAttribute (::IsDoubleSided());
300 Standard_Integer aDoubleSidedInt = 1;
301 aDoubleSidedStr.GetInteger (aDoubleSidedInt);
302 Standard_ShortReal anAlphaCutOff = 0.5f;
303 readReal (theSource, ::AlphaCutOff(), anAlphaCutOff);
304 switch (aDoubleSidedInt)
306 case 1: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_DoubleSided); break;
307 case 2: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled); break;
308 case 3: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_FrontCulled); break;
310 default: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_Auto); break;
312 aMat->SetAlphaMode (alphaModeFromString (theSource.Element().getAttribute (::AlphaMode()).GetString()), anAlphaCutOff);
314 Quantity_ColorRGBA aBaseColor;
315 if (readColor (theSource, ::BaseColor(), aBaseColor))
317 XCAFDoc_VisMaterialPBR aPbrMat;
318 aPbrMat.IsDefined = true;
319 aPbrMat.BaseColor = aBaseColor;
320 readVec3 (theSource, ::EmissiveFactor(), aPbrMat.EmissiveFactor);
321 readReal (theSource, ::Metallic(), aPbrMat.Metallic);
322 readReal (theSource, ::Roughness(), aPbrMat.Roughness);
323 readReal (theSource, ::RefractionIndex(), aPbrMat.RefractionIndex);
324 readTexture (theSource, ::BaseColorTexture(), aPbrMat.BaseColorTexture);
325 readTexture (theSource, ::MetallicRoughnessTexture(), aPbrMat.MetallicRoughnessTexture);
326 readTexture (theSource, ::EmissiveTexture(), aPbrMat.EmissiveTexture);
327 readTexture (theSource, ::OcclusionTexture(), aPbrMat.OcclusionTexture);
328 readTexture (theSource, ::NormalTexture(), aPbrMat.NormalTexture);
329 aMat->SetPbrMaterial (aPbrMat);
332 Quantity_Color aDiffColor;
333 if (readColor (theSource, ::DiffuseColor(), aDiffColor))
335 XCAFDoc_VisMaterialCommon aComMat;
336 aComMat.IsDefined = true;
337 aComMat.DiffuseColor = aDiffColor;
338 readColor (theSource, ::AmbientColor(), aComMat.AmbientColor);
339 readColor (theSource, ::SpecularColor(), aComMat.SpecularColor);
340 readColor (theSource, ::EmissiveColor(), aComMat.EmissiveColor);
341 readReal (theSource, ::Shininess(), aComMat.Shininess);
342 readReal (theSource, ::Transparency(), aComMat.Transparency);
343 readTexture (theSource, ::DiffuseTexture(), aComMat.DiffuseTexture);
344 aMat->SetCommonMaterial (aComMat);
346 return Standard_True;
349 //=======================================================================
351 //purpose : transient -> persistent (store)
352 //=======================================================================
353 void XmlMXCAFDoc_VisMaterialDriver::Paste (const Handle(TDF_Attribute)& theSource,
354 XmlObjMgt_Persistent& theTarget,
355 XmlObjMgt_SRelocationTable& ) const
357 Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theSource);
358 Standard_Integer aDoubleSidedInt = 0;
359 switch (aMat->FaceCulling())
361 case Graphic3d_TypeOfBackfacingModel_DoubleSided: aDoubleSidedInt = 1; break;
362 case Graphic3d_TypeOfBackfacingModel_BackCulled: aDoubleSidedInt = 2; break;
363 case Graphic3d_TypeOfBackfacingModel_FrontCulled: aDoubleSidedInt = 3; break;
364 case Graphic3d_TypeOfBackfacingModel_Auto: aDoubleSidedInt = 0; break;
366 theTarget.Element().setAttribute (::IsDoubleSided(), aDoubleSidedInt);
367 theTarget.Element().setAttribute (::AlphaMode(), alphaModeToString (aMat->AlphaMode()));
368 writeReal (theTarget, ::AlphaCutOff(), aMat->AlphaCutOff());
369 if (aMat->HasPbrMaterial())
371 const XCAFDoc_VisMaterialPBR& aPbrMat = aMat->PbrMaterial();
372 writeVec4 (theTarget, ::BaseColor(), aPbrMat.BaseColor);
373 writeVec3 (theTarget, ::EmissiveFactor(), aPbrMat.EmissiveFactor);
374 writeReal (theTarget, ::Metallic(), aPbrMat.Metallic);
375 writeReal (theTarget, ::Roughness(), aPbrMat.Roughness);
376 writeReal (theTarget, ::RefractionIndex(), aPbrMat.RefractionIndex);
377 writeTexture (theTarget, ::BaseColorTexture(), aPbrMat.BaseColorTexture);
378 writeTexture (theTarget, ::MetallicRoughnessTexture(), aPbrMat.MetallicRoughnessTexture);
379 writeTexture (theTarget, ::EmissiveTexture(), aPbrMat.EmissiveTexture);
380 writeTexture (theTarget, ::OcclusionTexture(), aPbrMat.OcclusionTexture);
381 writeTexture (theTarget, ::NormalTexture(), aPbrMat.NormalTexture);
384 if (aMat->HasCommonMaterial())
386 const XCAFDoc_VisMaterialCommon& aComMat = aMat->CommonMaterial();
387 writeVec3 (theTarget, ::AmbientColor(), aComMat.AmbientColor);
388 writeVec3 (theTarget, ::DiffuseColor(), aComMat.DiffuseColor);
389 writeVec3 (theTarget, ::SpecularColor(), aComMat.SpecularColor);
390 writeVec3 (theTarget, ::EmissiveColor(), aComMat.EmissiveColor);
391 writeReal (theTarget, ::Shininess(), aComMat.Shininess);
392 writeReal (theTarget, ::Transparency(), aComMat.Transparency);
393 writeTexture (theTarget, ::DiffuseTexture(), aComMat.DiffuseTexture);