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