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