0031284: Visualization - XCAFDoc_VisMaterialPBR lacks Index of Refraction
[occt.git] / src / BinMXCAFDoc / BinMXCAFDoc_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 <BinMXCAFDoc_VisMaterialDriver.hxx>
15
16 #include <BinObjMgt_Persistent.hxx>
17 #include <Message_Messenger.hxx>
18 #include <XCAFDoc_VisMaterial.hxx>
19
20 IMPLEMENT_STANDARD_RTTIEXT(BinMXCAFDoc_VisMaterialDriver, BinMDF_ADriver)
21
22 //! Encode alpha mode into character.
23 static Standard_Byte alphaModeToChar (Graphic3d_AlphaMode theMode)
24 {
25   switch (theMode)
26   {
27     case Graphic3d_AlphaMode_Opaque:    return 'O';
28     case Graphic3d_AlphaMode_Mask:      return 'M';
29     case Graphic3d_AlphaMode_Blend:     return 'B';
30     case Graphic3d_AlphaMode_BlendAuto: return 'A';
31   }
32   return 'A';
33 }
34
35 //! Decode alpha mode from character.
36 static Graphic3d_AlphaMode alphaModeFromChar (Standard_Byte theMode)
37 {
38   switch (theMode)
39   {
40     case 'O': return Graphic3d_AlphaMode_Opaque;
41     case 'M': return Graphic3d_AlphaMode_Mask;
42     case 'B': return Graphic3d_AlphaMode_Blend;
43     case 'A': return Graphic3d_AlphaMode_BlendAuto;
44   }
45   return Graphic3d_AlphaMode_BlendAuto;
46 }
47
48 //! Encode vec3.
49 static void writeVec3 (BinObjMgt_Persistent& theTarget,
50                        const Graphic3d_Vec3& theVec3)
51 {
52   theTarget.PutShortReal (theVec3[0]);
53   theTarget.PutShortReal (theVec3[1]);
54   theTarget.PutShortReal (theVec3[2]);
55 }
56
57 //! Encode vec4.
58 static void writeVec4 (BinObjMgt_Persistent& theTarget,
59                        const Graphic3d_Vec4& theVec4)
60 {
61   theTarget.PutShortReal (theVec4[0]);
62   theTarget.PutShortReal (theVec4[1]);
63   theTarget.PutShortReal (theVec4[2]);
64   theTarget.PutShortReal (theVec4[3]);
65 }
66
67 //! Decode vec3.
68 static void readVec3 (const BinObjMgt_Persistent& theSource,
69                       Graphic3d_Vec3& theVec3)
70 {
71   theSource.GetShortReal (theVec3[0]);
72   theSource.GetShortReal (theVec3[1]);
73   theSource.GetShortReal (theVec3[2]);
74 }
75
76 //! Decode vec3.
77 static void readColor (const BinObjMgt_Persistent& theSource,
78                        Quantity_Color& theColor)
79 {
80   Graphic3d_Vec3 aVec3;
81   readVec3 (theSource, aVec3);
82   theColor = Quantity_Color (aVec3);
83 }
84
85 //! Decode vec4.
86 static void readColor (const BinObjMgt_Persistent& theSource,
87                        Quantity_ColorRGBA& theColor)
88 {
89   Graphic3d_Vec4 aVec4;
90   theSource.GetShortReal (aVec4[0]);
91   theSource.GetShortReal (aVec4[1]);
92   theSource.GetShortReal (aVec4[2]);
93   theSource.GetShortReal (aVec4[3]);
94   theColor = Quantity_ColorRGBA (aVec4);
95 }
96
97 //! Encode texture path.
98 static void writeTexture (BinObjMgt_Persistent& theTarget,
99                           const Handle(Image_Texture)& theImage)
100 {
101   theTarget.PutAsciiString (!theImage.IsNull()
102                          && !theImage->FilePath().IsEmpty()
103                          &&  theImage->FileOffset() == -1
104                           ? theImage->FilePath()
105                           : "");
106 }
107
108 //! Decode texture path.
109 static void readTexture (const BinObjMgt_Persistent& theSource,
110                          Handle(Image_Texture)& theTexture)
111 {
112   TCollection_AsciiString aPath;
113   theSource.GetAsciiString (aPath);
114   if (!aPath.IsEmpty())
115   {
116     theTexture = new Image_Texture (aPath);
117   }
118 }
119
120 //=======================================================================
121 //function : Constructor
122 //purpose  :
123 //=======================================================================
124 BinMXCAFDoc_VisMaterialDriver::BinMXCAFDoc_VisMaterialDriver (const Handle(Message_Messenger)& theMsgDriver)
125 : BinMDF_ADriver(theMsgDriver, STANDARD_TYPE(XCAFDoc_VisMaterial)->Name())
126 {
127 }
128
129 //=======================================================================
130 //function : NewEmpty
131 //purpose  :
132 //=======================================================================
133 Handle(TDF_Attribute) BinMXCAFDoc_VisMaterialDriver::NewEmpty() const
134 {
135   return new XCAFDoc_VisMaterial();
136 }
137
138 //=======================================================================
139 //function : Paste
140 //purpose  :
141 //=======================================================================
142 Standard_Boolean BinMXCAFDoc_VisMaterialDriver::Paste (const BinObjMgt_Persistent&  theSource,
143                                                        const Handle(TDF_Attribute)& theTarget,
144                                                        BinObjMgt_RRelocationTable& /*theRelocTable*/) const
145 {
146   Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theTarget);
147   Standard_Byte aVerMaj = 0, aVerMin = 0;
148   theSource.GetByte (aVerMaj);
149   theSource.GetByte (aVerMin);
150   if (aVerMaj < 1 || aVerMaj > MaterialVersionMajor)
151   {
152     myMessageDriver->Send (TCollection_AsciiString ("Skipping XCAFDoc_VisMaterial of unknown version ")
153                          + Standard_Integer(aVerMaj) + "." + Standard_Integer(aVerMin)
154                          + " (supported version: " + Standard_Integer(MaterialVersionMajor) + "." + Standard_Integer(MaterialVersionMinor) + ")");
155     return false;
156   }
157
158   Standard_Byte isDoubleSided = 0, anAlphaMode = 0;
159   Standard_ShortReal anAlphaCutOff = 0.5f;
160   theSource.GetByte (isDoubleSided);
161   theSource.GetByte (anAlphaMode);
162   theSource.GetShortReal (anAlphaCutOff);
163   aMat->SetDoubleSided (isDoubleSided == '1');
164   aMat->SetAlphaMode (alphaModeFromChar (anAlphaMode), anAlphaCutOff);
165
166   XCAFDoc_VisMaterialPBR aPbrMat;
167   theSource.GetBoolean (aPbrMat.IsDefined);
168   if (aPbrMat.IsDefined)
169   {
170     readColor (theSource, aPbrMat.BaseColor);
171     readVec3  (theSource, aPbrMat.EmissiveFactor);
172     theSource.GetShortReal (aPbrMat.Metallic);
173     theSource.GetShortReal (aPbrMat.Roughness);
174     readTexture (theSource, aPbrMat.BaseColorTexture);
175     readTexture (theSource, aPbrMat.MetallicRoughnessTexture);
176     readTexture (theSource, aPbrMat.EmissiveTexture);
177     readTexture (theSource, aPbrMat.OcclusionTexture);
178     readTexture (theSource, aPbrMat.NormalTexture);
179     aMat->SetPbrMaterial (aPbrMat);
180   }
181
182   bool hasComMat = false;
183   theSource.GetBoolean (hasComMat);
184   if (hasComMat)
185   {
186     XCAFDoc_VisMaterialCommon aComMat;
187     aComMat.IsDefined = true;
188     readColor (theSource, aComMat.AmbientColor);
189     readColor (theSource, aComMat.DiffuseColor);
190     readColor (theSource, aComMat.SpecularColor);
191     readColor (theSource, aComMat.EmissiveColor);
192     theSource.GetShortReal (aComMat.Shininess);
193     theSource.GetShortReal (aComMat.Transparency);
194     readTexture (theSource, aComMat.DiffuseTexture);
195     aMat->SetCommonMaterial (aComMat);
196   }
197
198   if (aVerMaj > MaterialVersionMajor_1
199     || (aVerMaj == MaterialVersionMajor_1
200      && aVerMin >= MaterialVersionMinor_1))
201   {
202     if (aPbrMat.IsDefined)
203     {
204       theSource.GetShortReal (aPbrMat.RefractionIndex);
205     }
206   }
207
208   if (aPbrMat.IsDefined)
209   {
210     aMat->SetPbrMaterial (aPbrMat);
211   }
212
213   return Standard_True;
214 }
215
216 //=======================================================================
217 //function : Paste
218 //purpose  :
219 //=======================================================================
220 void BinMXCAFDoc_VisMaterialDriver::Paste (const Handle(TDF_Attribute)& theSource,
221                                            BinObjMgt_Persistent& theTarget,
222                                            BinObjMgt_SRelocationTable& ) const
223 {
224   Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theSource);
225   theTarget.PutByte (MaterialVersionMajor);
226   theTarget.PutByte (MaterialVersionMinor);
227
228   theTarget.PutByte (aMat->IsDoubleSided() ? '1' : '0');
229   theTarget.PutByte (alphaModeToChar (aMat->AlphaMode()));
230   theTarget.PutShortReal (aMat->AlphaCutOff());
231
232   theTarget.PutBoolean (aMat->HasPbrMaterial());
233   if (aMat->HasPbrMaterial())
234   {
235     const XCAFDoc_VisMaterialPBR& aPbrMat = aMat->PbrMaterial();
236     writeVec4 (theTarget, aPbrMat.BaseColor);
237     writeVec3 (theTarget, aPbrMat.EmissiveFactor);
238     theTarget.PutShortReal (aPbrMat.Metallic);
239     theTarget.PutShortReal (aPbrMat.Roughness);
240     writeTexture (theTarget, aPbrMat.BaseColorTexture);
241     writeTexture (theTarget, aPbrMat.MetallicRoughnessTexture);
242     writeTexture (theTarget, aPbrMat.EmissiveTexture);
243     writeTexture (theTarget, aPbrMat.OcclusionTexture);
244     writeTexture (theTarget, aPbrMat.NormalTexture);
245   }
246
247   theTarget.PutBoolean (aMat->HasCommonMaterial());
248   if (aMat->HasCommonMaterial())
249   {
250     const XCAFDoc_VisMaterialCommon& aComMat = aMat->CommonMaterial();
251     writeVec3 (theTarget, aComMat.AmbientColor);
252     writeVec3 (theTarget, aComMat.DiffuseColor);
253     writeVec3 (theTarget, aComMat.SpecularColor);
254     writeVec3 (theTarget, aComMat.EmissiveColor);
255     theTarget.PutShortReal (aComMat.Shininess);
256     theTarget.PutShortReal (aComMat.Transparency);
257     writeTexture (theTarget, aComMat.DiffuseTexture);
258   }
259
260   if (aMat->HasPbrMaterial())
261   {
262     theTarget.PutShortReal (aMat->PbrMaterial().RefractionIndex);
263   }
264 }