0032188: Visualization, Graphic3d_Aspects - define backface culling using Graphic3d_T...
[occt.git] / src / XCAFDoc / XCAFDoc_VisMaterial.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 <XCAFDoc_VisMaterial.hxx>
15
16 #include <Graphic3d_Aspects.hxx>
17 #include <Graphic3d_MaterialAspect.hxx>
18 #include <Standard_GUID.hxx>
19 #include <TDF_Label.hxx>
20 #include <XCAFPrs_Texture.hxx>
21
22 IMPLEMENT_STANDARD_RTTIEXT(XCAFDoc_VisMaterial, TDF_Attribute)
23
24 //=======================================================================
25 //function : GetID
26 //purpose  :
27 //=======================================================================
28 const Standard_GUID& XCAFDoc_VisMaterial::GetID()
29 {
30   static Standard_GUID THE_VIS_MAT_ID ("EBB00255-03A0-4845-BD3B-A70EEDEEFA78");
31   return THE_VIS_MAT_ID;
32 }
33
34 //=======================================================================
35 //function : Constructor
36 //purpose  :
37 //=======================================================================
38 XCAFDoc_VisMaterial::XCAFDoc_VisMaterial()
39 : myAlphaMode (Graphic3d_AlphaMode_BlendAuto),
40   myAlphaCutOff (0.5f),
41   myFaceCulling (Graphic3d_TypeOfBackfacingModel_Auto)
42 {
43   //
44 }
45
46 //=======================================================================
47 //function : SetMetalRougnessMaterial
48 //purpose  :
49 //=======================================================================
50 void XCAFDoc_VisMaterial::SetPbrMaterial (const XCAFDoc_VisMaterialPBR& theMaterial)
51 {
52   Backup();
53   myPbrMat = theMaterial;
54 }
55
56 //=======================================================================
57 //function : SetCommonMaterial
58 //purpose  :
59 //=======================================================================
60 void XCAFDoc_VisMaterial::SetCommonMaterial (const XCAFDoc_VisMaterialCommon& theMaterial)
61 {
62   Backup();
63   myCommonMat = theMaterial;
64 }
65
66 //=======================================================================
67 //function : SetAlphaMode
68 //purpose  :
69 //=======================================================================
70 void XCAFDoc_VisMaterial::SetAlphaMode (Graphic3d_AlphaMode theMode,
71                                         Standard_ShortReal  theCutOff)
72 {
73   Backup();
74   myAlphaMode   = theMode;
75   myAlphaCutOff = theCutOff;
76 }
77
78 //=======================================================================
79 //function : SetFaceCulling
80 //purpose  :
81 //=======================================================================
82 void XCAFDoc_VisMaterial::SetFaceCulling (Graphic3d_TypeOfBackfacingModel theFaceCulling)
83 {
84   Backup();
85   myFaceCulling = theFaceCulling;
86 }
87
88 //=======================================================================
89 //function : Restore
90 //purpose  :
91 //=======================================================================
92 void XCAFDoc_VisMaterial::Restore (const Handle(TDF_Attribute)& theWith)
93 {
94   XCAFDoc_VisMaterial* anOther = dynamic_cast<XCAFDoc_VisMaterial* >(theWith.get());
95   myPbrMat        = anOther->myPbrMat;
96   myCommonMat     = anOther->myCommonMat;
97   myAlphaMode     = anOther->myAlphaMode;
98   myAlphaCutOff   = anOther->myAlphaCutOff;
99   myFaceCulling   = anOther->myFaceCulling;
100 }
101
102 //=======================================================================
103 //function : NewEmpty
104 //purpose  :
105 //=======================================================================
106 Handle(TDF_Attribute) XCAFDoc_VisMaterial::NewEmpty() const
107 {
108   return new XCAFDoc_VisMaterial();
109 }
110
111 //=======================================================================
112 //function : Paste
113 //purpose  :
114 //=======================================================================
115 void XCAFDoc_VisMaterial::Paste (const Handle(TDF_Attribute)& theInto,
116                                  const Handle(TDF_RelocationTable)& ) const
117 {
118   XCAFDoc_VisMaterial* anOther = dynamic_cast<XCAFDoc_VisMaterial* >(theInto.get());
119   anOther->Backup();
120   anOther->myPbrMat        = myPbrMat;
121   anOther->myCommonMat     = myCommonMat;
122   anOther->myAlphaMode     = myAlphaMode;
123   anOther->myAlphaCutOff   = myAlphaCutOff;
124   anOther->myFaceCulling   = myFaceCulling;
125 }
126
127 // =======================================================================
128 // function : BaseColor
129 // purpose  :
130 // =======================================================================
131 Quantity_ColorRGBA XCAFDoc_VisMaterial::BaseColor() const
132 {
133   if (myPbrMat.IsDefined)
134   {
135     return myPbrMat.BaseColor;
136   }
137   else if (myCommonMat.IsDefined)
138   {
139     return Quantity_ColorRGBA (myCommonMat.DiffuseColor, 1.0f - myCommonMat.Transparency);
140   }
141   return Quantity_ColorRGBA (Quantity_NOC_WHITE);
142 }
143
144 //=======================================================================
145 //function : ConvertToCommonMaterial
146 //purpose  :
147 //=======================================================================
148 XCAFDoc_VisMaterialCommon XCAFDoc_VisMaterial::ConvertToCommonMaterial()
149 {
150   if (myCommonMat.IsDefined)
151   {
152     return myCommonMat;
153   }
154   else if (!myPbrMat.IsDefined)
155   {
156     return XCAFDoc_VisMaterialCommon();
157   }
158
159   // convert metal-roughness into common
160   XCAFDoc_VisMaterialCommon aComMat;
161   aComMat.IsDefined = true;
162   aComMat.DiffuseTexture = myPbrMat.BaseColorTexture;
163   aComMat.DiffuseColor  = myPbrMat.BaseColor.GetRGB();
164   aComMat.SpecularColor = Quantity_Color (Graphic3d_Vec3 (myPbrMat.Metallic));
165   aComMat.Transparency = 1.0f - myPbrMat.BaseColor.Alpha();
166   aComMat.Shininess    = 1.0f - myPbrMat.Roughness;
167   return aComMat;
168 }
169
170 //=======================================================================
171 //function : ConvertToPbrMaterial
172 //purpose  :
173 //=======================================================================
174 XCAFDoc_VisMaterialPBR XCAFDoc_VisMaterial::ConvertToPbrMaterial()
175 {
176   if (myPbrMat.IsDefined)
177   {
178     return myPbrMat;
179   }
180   else if (!myCommonMat.IsDefined)
181   {
182     return XCAFDoc_VisMaterialPBR();
183   }
184
185   XCAFDoc_VisMaterialPBR aPbrMat;
186   aPbrMat.IsDefined = true;
187   aPbrMat.BaseColorTexture = myCommonMat.DiffuseTexture;
188   aPbrMat.BaseColor.SetRGB (myCommonMat.DiffuseColor);
189   aPbrMat.BaseColor.SetAlpha (1.0f - myCommonMat.Transparency);
190   aPbrMat.Metallic  = Graphic3d_PBRMaterial::MetallicFromSpecular (myCommonMat.SpecularColor);
191   aPbrMat.Roughness = Graphic3d_PBRMaterial::RoughnessFromSpecular (myCommonMat.SpecularColor, myCommonMat.Shininess);
192   return aPbrMat;
193 }
194
195 //=======================================================================
196 //function : FillMaterialAspect
197 //purpose  :
198 //=======================================================================
199 void XCAFDoc_VisMaterial::FillMaterialAspect (Graphic3d_MaterialAspect& theAspect) const
200 {
201   if (myCommonMat.IsDefined)
202   {
203     theAspect = Graphic3d_MaterialAspect (Graphic3d_NameOfMaterial_UserDefined);
204     theAspect.SetAmbientColor (myCommonMat.AmbientColor);
205     theAspect.SetDiffuseColor (myCommonMat.DiffuseColor);
206     theAspect.SetSpecularColor(myCommonMat.SpecularColor);
207     theAspect.SetEmissiveColor(myCommonMat.EmissiveColor);
208     theAspect.SetTransparency (myCommonMat.Transparency);
209     theAspect.SetShininess    (myCommonMat.Shininess);
210
211     // convert common into metal-roughness
212     if (!myPbrMat.IsDefined)
213     {
214       Graphic3d_PBRMaterial aPbr;
215       aPbr.SetColor (myCommonMat.DiffuseColor);
216       aPbr.SetMetallic (Graphic3d_PBRMaterial::MetallicFromSpecular (myCommonMat.SpecularColor));
217       aPbr.SetRoughness (Graphic3d_PBRMaterial::RoughnessFromSpecular (myCommonMat.SpecularColor, myCommonMat.Shininess));
218       theAspect.SetPBRMaterial (aPbr);
219       theAspect.SetBSDF (Graphic3d_BSDF::CreateMetallicRoughness (aPbr));
220     }
221   }
222
223   if (myPbrMat.IsDefined)
224   {
225     if (!myCommonMat.IsDefined)
226     {
227       // convert metal-roughness into common
228       theAspect = Graphic3d_MaterialAspect (Graphic3d_NameOfMaterial_UserDefined);
229       theAspect.SetDiffuseColor (myPbrMat.BaseColor.GetRGB());
230       theAspect.SetAlpha        (myPbrMat.BaseColor.Alpha());
231       theAspect.SetSpecularColor(Quantity_Color (Graphic3d_Vec3 (myPbrMat.Metallic)));
232       theAspect.SetShininess    (1.0f - myPbrMat.Roughness);
233     }
234
235     Graphic3d_PBRMaterial aPbr;
236     aPbr.SetColor    (myPbrMat.BaseColor);
237     aPbr.SetMetallic (myPbrMat.Metallic);
238     aPbr.SetRoughness(myPbrMat.Roughness);
239     aPbr.SetEmission (myPbrMat.EmissiveFactor);
240     aPbr.SetIOR      (myPbrMat.RefractionIndex);
241     theAspect.SetRefractionIndex (myPbrMat.RefractionIndex);
242     theAspect.SetPBRMaterial (aPbr);
243     theAspect.SetBSDF (Graphic3d_BSDF::CreateMetallicRoughness (aPbr));
244   }
245 }
246
247 //=======================================================================
248 //function : FillAspect
249 //purpose  :
250 //=======================================================================
251 void XCAFDoc_VisMaterial::FillAspect (const Handle(Graphic3d_Aspects)& theAspect) const
252 {
253   if (IsEmpty())
254   {
255     return;
256   }
257
258   Graphic3d_MaterialAspect aMaterial;
259   FillMaterialAspect (aMaterial);
260   theAspect->SetFrontMaterial (aMaterial);
261   theAspect->SetAlphaMode (myAlphaMode , myAlphaCutOff);
262   theAspect->SetFaceCulling (myFaceCulling);
263
264   const Handle(Image_Texture)& aColorTexture = !myPbrMat.BaseColorTexture.IsNull() ? myPbrMat.BaseColorTexture : myCommonMat.DiffuseTexture;
265   Standard_Integer aNbTexUnits = 0;
266   if (!aColorTexture.IsNull())             { ++aNbTexUnits; }
267   if (!myPbrMat.EmissiveTexture.IsNull())  { ++aNbTexUnits; }
268   if (!myPbrMat.NormalTexture.IsNull())    { ++aNbTexUnits; }
269   if (!myPbrMat.OcclusionTexture.IsNull()) { ++aNbTexUnits; }
270   if (!myPbrMat.MetallicRoughnessTexture.IsNull()) { ++aNbTexUnits; }
271   if (aNbTexUnits == 0)
272   {
273     return;
274   }
275
276   Standard_Integer aTexIter = 0;
277   Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (aNbTexUnits);
278   if (!aColorTexture.IsNull())
279   {
280     aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*aColorTexture, Graphic3d_TextureUnit_BaseColor));
281   }
282   if (!myPbrMat.EmissiveTexture.IsNull())
283   {
284     aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.EmissiveTexture, Graphic3d_TextureUnit_Emissive));
285   }
286   if (!myPbrMat.OcclusionTexture.IsNull())
287   {
288     aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.OcclusionTexture, Graphic3d_TextureUnit_Occlusion));
289   }
290   if (!myPbrMat.NormalTexture.IsNull())
291   {
292     aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.NormalTexture, Graphic3d_TextureUnit_Normal));
293   }
294   if (!myPbrMat.MetallicRoughnessTexture.IsNull())
295   {
296     aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.MetallicRoughnessTexture, Graphic3d_TextureUnit_MetallicRoughness));
297   }
298
299   theAspect->SetTextureSet (aTextureSet);
300   theAspect->SetTextureMapOn (true);
301 }
302
303 //=======================================================================
304 //function : DumpJson
305 //purpose  : 
306 //=======================================================================
307 void XCAFDoc_VisMaterial::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
308 {
309   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
310
311   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, TDF_Attribute)
312
313   OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myRawName.get())
314
315   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPbrMat)
316   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCommonMat)
317
318   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlphaMode)
319   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlphaCutOff)
320   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myFaceCulling)
321 }