0029902: Data Exchange, XCAF - provide extended Material definition for visualization...
[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   bool hasPbrMat = false;
167   theSource.GetBoolean (hasPbrMat);
168   if (hasPbrMat)
169   {
170     XCAFDoc_VisMaterialPBR aPbrMat;
171     aPbrMat.IsDefined = true;
172     readColor (theSource, aPbrMat.BaseColor);
173     readVec3  (theSource, aPbrMat.EmissiveFactor);
174     theSource.GetShortReal (aPbrMat.Metallic);
175     theSource.GetShortReal (aPbrMat.Roughness);
176     readTexture (theSource, aPbrMat.BaseColorTexture);
177     readTexture (theSource, aPbrMat.MetallicRoughnessTexture);
178     readTexture (theSource, aPbrMat.EmissiveTexture);
179     readTexture (theSource, aPbrMat.OcclusionTexture);
180     readTexture (theSource, aPbrMat.NormalTexture);
181     aMat->SetPbrMaterial (aPbrMat);
182   }
183
184   bool hasComMat = false;
185   theSource.GetBoolean (hasComMat);
186   if (hasComMat)
187   {
188     XCAFDoc_VisMaterialCommon aComMat;
189     aComMat.IsDefined = true;
190     readColor (theSource, aComMat.AmbientColor);
191     readColor (theSource, aComMat.DiffuseColor);
192     readColor (theSource, aComMat.SpecularColor);
193     readColor (theSource, aComMat.EmissiveColor);
194     theSource.GetShortReal (aComMat.Shininess);
195     theSource.GetShortReal (aComMat.Transparency);
196     readTexture (theSource, aComMat.DiffuseTexture);
197     aMat->SetCommonMaterial (aComMat);
198   }
199   return Standard_True;
200 }
201
202 //=======================================================================
203 //function : Paste
204 //purpose  :
205 //=======================================================================
206 void BinMXCAFDoc_VisMaterialDriver::Paste (const Handle(TDF_Attribute)& theSource,
207                                            BinObjMgt_Persistent& theTarget,
208                                            BinObjMgt_SRelocationTable& ) const
209 {
210   Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theSource);
211   theTarget.PutByte (MaterialVersionMajor);
212   theTarget.PutByte (MaterialVersionMinor);
213
214   theTarget.PutByte (aMat->IsDoubleSided() ? '1' : '0');
215   theTarget.PutByte (alphaModeToChar (aMat->AlphaMode()));
216   theTarget.PutShortReal (aMat->AlphaCutOff());
217
218   theTarget.PutBoolean (aMat->HasPbrMaterial());
219   if (aMat->HasPbrMaterial())
220   {
221     const XCAFDoc_VisMaterialPBR& aPbrMat = aMat->PbrMaterial();
222     writeVec4 (theTarget, aPbrMat.BaseColor);
223     writeVec3 (theTarget, aPbrMat.EmissiveFactor);
224     theTarget.PutShortReal (aPbrMat.Metallic);
225     theTarget.PutShortReal (aPbrMat.Roughness);
226     writeTexture (theTarget, aPbrMat.BaseColorTexture);
227     writeTexture (theTarget, aPbrMat.MetallicRoughnessTexture);
228     writeTexture (theTarget, aPbrMat.EmissiveTexture);
229     writeTexture (theTarget, aPbrMat.OcclusionTexture);
230     writeTexture (theTarget, aPbrMat.NormalTexture);
231   }
232
233   theTarget.PutBoolean (aMat->HasCommonMaterial());
234   if (aMat->HasCommonMaterial())
235   {
236     const XCAFDoc_VisMaterialCommon& aComMat = aMat->CommonMaterial();
237     writeVec3 (theTarget, aComMat.AmbientColor);
238     writeVec3 (theTarget, aComMat.DiffuseColor);
239     writeVec3 (theTarget, aComMat.SpecularColor);
240     writeVec3 (theTarget, aComMat.EmissiveColor);
241     theTarget.PutShortReal (aComMat.Shininess);
242     theTarget.PutShortReal (aComMat.Transparency);
243     writeTexture (theTarget, aComMat.DiffuseTexture);
244   }
245 }