0029902: Data Exchange, XCAF - provide extended Material definition for visualization...
[occt.git] / src / XmlMXCAFDoc / XmlMXCAFDoc_VisMaterialDriver.cxx
1 // Copyright (c) 2019 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
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.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <XmlMXCAFDoc_VisMaterialDriver.hxx>
15
16 #include <Message_Messenger.hxx>
17 #include <XCAFDoc_VisMaterial.hxx>
18 #include <XmlObjMgt.hxx>
19 #include <XmlObjMgt_Persistent.hxx>
20
21 IMPLEMENT_STANDARD_RTTIEXT(XmlMXCAFDoc_VisMaterialDriver, XmlMDF_ADriver)
22
23 IMPLEMENT_DOMSTRING(IsDoubleSided,     "isdoublesided")
24 IMPLEMENT_DOMSTRING(AlphaMode,         "alpha_mode")
25 IMPLEMENT_DOMSTRING(AlphaCutOff,       "alpha_cutoff")
26 //
27 IMPLEMENT_DOMSTRING(BaseColor,         "base_color")
28 IMPLEMENT_DOMSTRING(EmissiveFactor,    "emissive_factor")
29 IMPLEMENT_DOMSTRING(Metallic,          "metallic")
30 IMPLEMENT_DOMSTRING(Roughness,         "roughness")
31 IMPLEMENT_DOMSTRING(BaseColorTexture,  "base_color_texture")
32 IMPLEMENT_DOMSTRING(MetallicRoughnessTexture,   "metallic_roughness_texture")
33 IMPLEMENT_DOMSTRING(EmissiveTexture,   "emissive_texture")
34 IMPLEMENT_DOMSTRING(OcclusionTexture,  "occlusion_texture")
35 IMPLEMENT_DOMSTRING(NormalTexture,     "normal_texture")
36 //
37 IMPLEMENT_DOMSTRING(AmbientColor,      "ambient_color")
38 IMPLEMENT_DOMSTRING(DiffuseColor,      "diffuse_color")
39 IMPLEMENT_DOMSTRING(SpecularColor,     "specular_color")
40 IMPLEMENT_DOMSTRING(EmissiveColor,     "emissive_color")
41 IMPLEMENT_DOMSTRING(Shininess,         "shininess")
42 IMPLEMENT_DOMSTRING(Transparency,      "transparency")
43 IMPLEMENT_DOMSTRING(DiffuseTexture,    "diffuse_texture")
44
45 //! Encode alpha mode into character.
46 static const char* alphaModeToString (Graphic3d_AlphaMode theMode)
47 {
48   switch (theMode)
49   {
50     case Graphic3d_AlphaMode_Opaque:    return "Opaque";
51     case Graphic3d_AlphaMode_Mask:      return "Mask";
52     case Graphic3d_AlphaMode_Blend:     return "Blend";
53     case Graphic3d_AlphaMode_BlendAuto: return "Auto";
54   }
55   return "Auto";
56 }
57
58 //! Decode alpha mode from string.
59 static Graphic3d_AlphaMode alphaModeFromString (const char* theMode)
60 {
61   switch (*theMode)
62   {
63     case 'O': return Graphic3d_AlphaMode_Opaque;
64     case 'M': return Graphic3d_AlphaMode_Mask;
65     case 'B': return Graphic3d_AlphaMode_Blend;
66     case 'A': return Graphic3d_AlphaMode_BlendAuto;
67   }
68   return Graphic3d_AlphaMode_BlendAuto;
69 }
70
71 //! Encode short real value.
72 static void writeReal (XmlObjMgt_Persistent& theTarget,
73                        const XmlObjMgt_DOMString& theName,
74                        const Standard_ShortReal theValue)
75 {
76   theTarget.Element().setAttribute (theName, TCollection_AsciiString(theValue).ToCString());
77 }
78
79 //! Encode short real value.
80 static bool readReal (const XmlObjMgt_Element& theElement,
81                       const XmlObjMgt_DOMString& theName,
82                       Standard_ShortReal& theValue)
83 {
84   Standard_Real aValue = 0.0;
85   if (XmlObjMgt::GetReal (theElement.getAttribute (theName), aValue))
86   {
87     theValue = (Standard_ShortReal )aValue;
88     return true;
89   }
90   return false;
91 }
92
93 //! Encode vec3.
94 static void writeVec3 (XmlObjMgt_Persistent& theTarget,
95                        const XmlObjMgt_DOMString& theName,
96                        const Graphic3d_Vec3& theVec3)
97 {
98   TCollection_AsciiString aString = TCollection_AsciiString() + theVec3[0] + " " + theVec3[1] + " " + theVec3[2];
99   theTarget.Element().setAttribute (theName, aString.ToCString());
100 }
101
102 //! Decode vec3.
103 static bool readVec3 (const XmlObjMgt_Element& theElement,
104                       const XmlObjMgt_DOMString& theName,
105                       Graphic3d_Vec3& theVec3)
106 {
107   Graphic3d_Vec3 aVec3;
108   LDOMString aString = theElement.getAttribute (theName);
109   const char* aPos = aString.GetString();
110   char* aNext = NULL;
111   aVec3[0] = (float )Strtod (aPos, &aNext);
112   aPos = aNext;
113   aVec3[1] = (float )Strtod (aPos, &aNext);
114   aPos = aNext;
115   aVec3[2] = (float )Strtod (aPos, &aNext);
116   if (aPos != aNext)
117   {
118     theVec3 = aVec3;
119     return true;
120   }
121   return false;
122 }
123
124 //! Decode vec3.
125 static bool readColor (const XmlObjMgt_Element& theElement,
126                        const XmlObjMgt_DOMString& theName,
127                        Quantity_Color& theColor)
128 {
129   Graphic3d_Vec3 aVec3;
130   if (readVec3 (theElement, theName, aVec3))
131   {
132     theColor = Quantity_Color (aVec3);
133     return true;
134   }
135   return false;
136 }
137
138 //! Encode vec4.
139 static void writeVec4 (XmlObjMgt_Persistent& theTarget,
140                        const XmlObjMgt_DOMString& theName,
141                        const Graphic3d_Vec4& theVec4)
142 {
143   TCollection_AsciiString aString = TCollection_AsciiString() + theVec4[0] + " " + theVec4[1] + " " + theVec4[2] + " " + theVec4[3];
144   theTarget.Element().setAttribute (theName, aString.ToCString());
145 }
146
147 //! Decode vec34
148 static bool readVec4 (const XmlObjMgt_Element& theElement,
149                       const XmlObjMgt_DOMString& theName,
150                       Graphic3d_Vec4& theVec4)
151 {
152   Graphic3d_Vec4 aVec4;
153   LDOMString aString = theElement.getAttribute (theName);
154   const char* aPos = aString.GetString();
155   char* aNext = NULL;
156   aVec4[0] = (float )Strtod (aPos, &aNext);
157   aPos = aNext;
158   aVec4[1] = (float )Strtod (aPos, &aNext);
159   aPos = aNext;
160   aVec4[2] = (float )Strtod (aPos, &aNext);
161   aPos = aNext;
162   aVec4[3] = (float )Strtod (aPos, &aNext);
163   if (aPos != aNext)
164   {
165     theVec4 = aVec4;
166     return true;
167   }
168   return false;
169 }
170
171 //! Decode vec4.
172 static bool readColor (const XmlObjMgt_Element& theElement,
173                        const XmlObjMgt_DOMString& theName,
174                        Quantity_ColorRGBA& theColor)
175 {
176   Graphic3d_Vec4 aVec4;
177   if (readVec4 (theElement, theName, aVec4))
178   {
179     theColor = Quantity_ColorRGBA (aVec4);
180     return true;
181   }
182   return false;
183 }
184
185 //! Encode texture path.
186 static void writeTexture (XmlObjMgt_Persistent& theTarget,
187                           const XmlObjMgt_DOMString& theName,
188                           const Handle(Image_Texture)& theImage)
189 {
190   if (!theImage.IsNull()
191    && !theImage->FilePath().IsEmpty()
192    &&  theImage->FileOffset() == -1)
193   {
194     theTarget.Element().setAttribute (theName, theImage->FilePath().ToCString());
195   }
196 }
197
198 //! Decode texture path.
199 static void readTexture (const XmlObjMgt_Element& theElement,
200                          const XmlObjMgt_DOMString& theName,
201                          Handle(Image_Texture)& theImage)
202 {
203   TCollection_AsciiString aPath (theElement.getAttribute (theName).GetString());
204   if (!aPath.IsEmpty())
205   {
206     theImage = new Image_Texture (aPath);
207   }
208 }
209
210 //=======================================================================
211 //function : XmlMXCAFDoc_VisMaterialDriver
212 //purpose  :
213 //=======================================================================
214 XmlMXCAFDoc_VisMaterialDriver::XmlMXCAFDoc_VisMaterialDriver (const Handle(Message_Messenger)& theMsgDriver)
215 : XmlMDF_ADriver (theMsgDriver, "xcaf", "VisMaterial")
216 {
217   //
218 }
219
220 //=======================================================================
221 //function : NewEmpty
222 //purpose  :
223 //=======================================================================
224 Handle(TDF_Attribute) XmlMXCAFDoc_VisMaterialDriver::NewEmpty() const
225 {
226   return new XCAFDoc_VisMaterial();
227 }
228
229 //=======================================================================
230 //function : Paste
231 //purpose  : persistent -> transient (retrieve)
232 //=======================================================================
233 Standard_Boolean XmlMXCAFDoc_VisMaterialDriver::Paste (const XmlObjMgt_Persistent&  theSource,
234                                                        const Handle(TDF_Attribute)& theTarget,
235                                                        XmlObjMgt_RRelocationTable&  ) const
236 {
237   Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theTarget);
238
239   const XmlObjMgt_DOMString aDoubleSidedStr = theSource.Element().getAttribute (::IsDoubleSided());
240   Standard_Integer isDoubleSided = 1;
241   aDoubleSidedStr.GetInteger (isDoubleSided);
242   Standard_ShortReal anAlphaCutOff = 0.5f;
243   readReal (theSource, ::AlphaCutOff(), anAlphaCutOff);
244   aMat->SetDoubleSided (isDoubleSided != 0);
245   aMat->SetAlphaMode (alphaModeFromString (theSource.Element().getAttribute (::AlphaMode()).GetString()), anAlphaCutOff);
246
247   Quantity_ColorRGBA aBaseColor;
248   if (readColor (theSource, ::BaseColor(), aBaseColor))
249   {
250     XCAFDoc_VisMaterialPBR aPbrMat;
251     aPbrMat.IsDefined = true;
252     aPbrMat.BaseColor = aBaseColor;
253     readVec3    (theSource, ::EmissiveFactor(),   aPbrMat.EmissiveFactor);
254     readReal    (theSource, ::Metallic(),         aPbrMat.Metallic);
255     readReal    (theSource, ::Roughness(),        aPbrMat.Roughness);
256     readTexture (theSource, ::BaseColorTexture(), aPbrMat.BaseColorTexture);
257     readTexture (theSource, ::MetallicRoughnessTexture(), aPbrMat.MetallicRoughnessTexture);
258     readTexture (theSource, ::EmissiveTexture(),  aPbrMat.EmissiveTexture);
259     readTexture (theSource, ::OcclusionTexture(), aPbrMat.OcclusionTexture);
260     readTexture (theSource, ::NormalTexture(),    aPbrMat.NormalTexture);
261     aMat->SetPbrMaterial (aPbrMat);
262   }
263
264   Quantity_Color aDiffColor;
265   if (readColor (theSource, ::DiffuseColor(), aDiffColor))
266   {
267     XCAFDoc_VisMaterialCommon aComMat;
268     aComMat.IsDefined = true;
269     aComMat.DiffuseColor = aDiffColor;
270     readColor   (theSource, ::AmbientColor(),    aComMat.AmbientColor);
271     readColor   (theSource, ::SpecularColor(),   aComMat.SpecularColor);
272     readColor   (theSource, ::EmissiveColor(),   aComMat.EmissiveColor);
273     readReal    (theSource, ::Shininess(),       aComMat.Shininess);
274     readReal    (theSource, ::Transparency(),    aComMat.Transparency);
275     readTexture (theSource, ::DiffuseTexture(),  aComMat.DiffuseTexture);
276     aMat->SetCommonMaterial (aComMat);
277   }
278   return Standard_True;
279 }
280
281 //=======================================================================
282 //function : Paste
283 //purpose  : transient -> persistent (store)
284 //=======================================================================
285 void XmlMXCAFDoc_VisMaterialDriver::Paste (const Handle(TDF_Attribute)& theSource,
286                                            XmlObjMgt_Persistent&        theTarget,
287                                            XmlObjMgt_SRelocationTable&  ) const
288 {
289   Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theSource);
290
291   theTarget.Element().setAttribute (::IsDoubleSided(), aMat->IsDoubleSided() ? 1 : 0);
292   theTarget.Element().setAttribute (::AlphaMode(),     alphaModeToString (aMat->AlphaMode()));
293   writeReal (theTarget, ::AlphaCutOff(), aMat->AlphaCutOff());
294   if (aMat->HasPbrMaterial())
295   {
296     const XCAFDoc_VisMaterialPBR& aPbrMat = aMat->PbrMaterial();
297     writeVec4    (theTarget, ::BaseColor(),        aPbrMat.BaseColor);
298     writeVec3    (theTarget, ::EmissiveFactor(),   aPbrMat.EmissiveFactor);
299     writeReal    (theTarget, ::Metallic(),         aPbrMat.Metallic);
300     writeReal    (theTarget, ::Roughness(),        aPbrMat.Roughness);
301     writeTexture (theTarget, ::BaseColorTexture(), aPbrMat.BaseColorTexture);
302     writeTexture (theTarget, ::MetallicRoughnessTexture(), aPbrMat.MetallicRoughnessTexture);
303     writeTexture (theTarget, ::EmissiveTexture(),  aPbrMat.EmissiveTexture);
304     writeTexture (theTarget, ::OcclusionTexture(), aPbrMat.OcclusionTexture);
305     writeTexture (theTarget, ::NormalTexture(),    aPbrMat.NormalTexture);
306   }
307
308   if (aMat->HasCommonMaterial())
309   {
310     const XCAFDoc_VisMaterialCommon& aComMat = aMat->CommonMaterial();
311     writeVec3    (theTarget, ::AmbientColor(),    aComMat.AmbientColor);
312     writeVec3    (theTarget, ::DiffuseColor(),    aComMat.DiffuseColor);
313     writeVec3    (theTarget, ::SpecularColor(),   aComMat.SpecularColor);
314     writeVec3    (theTarget, ::EmissiveColor(),   aComMat.EmissiveColor);
315     writeReal    (theTarget, ::Shininess(),       aComMat.Shininess);
316     writeReal    (theTarget, ::Transparency(),    aComMat.Transparency);
317     writeTexture (theTarget, ::DiffuseTexture(),  aComMat.DiffuseTexture);
318   }
319 }