0029902: Data Exchange, XCAF - provide extended Material definition for visualization...
[occt.git] / src / XCAFDoc / XCAFDoc_VisMaterial.cxx
CommitLineData
a4815d55 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
22IMPLEMENT_STANDARD_RTTIEXT(XCAFDoc_VisMaterial, TDF_Attribute)
23
24//=======================================================================
25//function : GetID
26//purpose :
27//=======================================================================
28const 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//=======================================================================
38XCAFDoc_VisMaterial::XCAFDoc_VisMaterial()
39: myAlphaMode (Graphic3d_AlphaMode_BlendAuto),
40 myAlphaCutOff (0.5f),
41 myIsDoubleSided (Standard_True)
42{
43 //
44}
45
46//=======================================================================
47//function : SetMetalRougnessMaterial
48//purpose :
49//=======================================================================
50void XCAFDoc_VisMaterial::SetPbrMaterial (const XCAFDoc_VisMaterialPBR& theMaterial)
51{
52 Backup();
53 myPbrMat = theMaterial;
54}
55
56//=======================================================================
57//function : SetCommonMaterial
58//purpose :
59//=======================================================================
60void XCAFDoc_VisMaterial::SetCommonMaterial (const XCAFDoc_VisMaterialCommon& theMaterial)
61{
62 Backup();
63 myCommonMat = theMaterial;
64}
65
66//=======================================================================
67//function : SetAlphaMode
68//purpose :
69//=======================================================================
70void XCAFDoc_VisMaterial::SetAlphaMode (Graphic3d_AlphaMode theMode,
71 Standard_ShortReal theCutOff)
72{
73 Backup();
74 myAlphaMode = theMode;
75 myAlphaCutOff = theCutOff;
76}
77
78//=======================================================================
79//function : SetDoubleSided
80//purpose :
81//=======================================================================
82void XCAFDoc_VisMaterial::SetDoubleSided (Standard_Boolean theIsDoubleSided)
83{
84 Backup();
85 myIsDoubleSided = theIsDoubleSided;
86}
87
88//=======================================================================
89//function : Restore
90//purpose :
91//=======================================================================
92void 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 myIsDoubleSided = anOther->myIsDoubleSided;
100}
101
102//=======================================================================
103//function : NewEmpty
104//purpose :
105//=======================================================================
106Handle(TDF_Attribute) XCAFDoc_VisMaterial::NewEmpty() const
107{
108 return new XCAFDoc_VisMaterial();
109}
110
111//=======================================================================
112//function : Paste
113//purpose :
114//=======================================================================
115void 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->myIsDoubleSided = myIsDoubleSided;
125}
126
127// =======================================================================
128// function : BaseColor
129// purpose :
130// =======================================================================
131Quantity_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//=======================================================================
148XCAFDoc_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.DiffuseColor = myPbrMat.BaseColor.GetRGB();
163 aComMat.SpecularColor = Quantity_Color (Graphic3d_Vec3 (myPbrMat.Metallic));
164 aComMat.Transparency = 1.0f - myPbrMat.BaseColor.Alpha();
165 aComMat.Shininess = 1.0f - myPbrMat.Roughness;
166 return aComMat;
167}
168
169//! Compute material roughness from common material.
170static Standard_ShortReal roughnessFromCommon (const XCAFDoc_VisMaterialCommon& theMat)
171{
172 Standard_Real aRoughnessFactor = 1.0 - theMat.Shininess;
173 //Standard_Real aSpecIntens = theMat.SpecularColor.Light() * theMat.SpecularColor;
174 const Standard_Real aSpecIntens = theMat.SpecularColor.Red() * 0.2125
175 + theMat.SpecularColor.Green() * 0.7154
176 + theMat.SpecularColor.Blue() * 0.0721;
177 if (aSpecIntens < 0.1)
178 {
179 // low specular intensity should produce a rough material even if shininess is high
180 aRoughnessFactor *= (1.0 - aSpecIntens);
181 }
182 return (Standard_ShortReal )aRoughnessFactor;
183}
184
185//=======================================================================
186//function : ConvertToPbrMaterial
187//purpose :
188//=======================================================================
189XCAFDoc_VisMaterialPBR XCAFDoc_VisMaterial::ConvertToPbrMaterial()
190{
191 if (myPbrMat.IsDefined)
192 {
193 return myPbrMat;
194 }
195 else if (!myCommonMat.IsDefined)
196 {
197 return XCAFDoc_VisMaterialPBR();
198 }
199
200 XCAFDoc_VisMaterialPBR aPbrMat;
201 aPbrMat.IsDefined = true;
202 aPbrMat.BaseColor.SetRGB (myCommonMat.DiffuseColor);
203 aPbrMat.BaseColor.SetAlpha (1.0f - myCommonMat.Transparency);
204 // we allow to save any number in range [0, 1] but logically metallicity can be either 0 or 1
205 aPbrMat.Metallic = ((Graphic3d_Vec3 )myCommonMat.SpecularColor).maxComp(); // > 0.1f ? 1.0 : 0.0;
206 aPbrMat.Roughness = roughnessFromCommon (myCommonMat);
207 return aPbrMat;
208}
209
210//=======================================================================
211//function : FillMaterialAspect
212//purpose :
213//=======================================================================
214void XCAFDoc_VisMaterial::FillMaterialAspect (Graphic3d_MaterialAspect& theAspect) const
215{
216 if (myCommonMat.IsDefined)
217 {
218 theAspect = Graphic3d_MaterialAspect (Graphic3d_NOM_UserDefined);
219 theAspect.SetAmbientColor (myCommonMat.AmbientColor);
220 theAspect.SetDiffuseColor (myCommonMat.DiffuseColor);
221 theAspect.SetSpecularColor(myCommonMat.SpecularColor);
222 theAspect.SetEmissiveColor(myCommonMat.EmissiveColor);
223 theAspect.SetTransparency (myCommonMat.Transparency);
224 theAspect.SetShininess (myCommonMat.Shininess);
225
226 // convert common into metal-roughness
227 if (!myPbrMat.IsDefined)
228 {
229 #ifdef _Graphic3d_PBRMaterial_HeaderFile
230 Graphic3d_PBRMaterial aPbr;
231 aPbr.SetColor (myCommonMat.DiffuseColor);
232 aPbr.SetMetallic (((Graphic3d_Vec3 )myCommonMat.SpecularColor).maxComp());
233 aPbr.SetRoughness (roughnessFromCommon (myCommonMat));
234 theAspect.SetPBRMaterial (aPbr);
235 #endif
236 }
237 }
238
239 if (myPbrMat.IsDefined)
240 {
241 if (!myCommonMat.IsDefined)
242 {
243 // convert metal-roughness into common
244 theAspect = Graphic3d_MaterialAspect (Graphic3d_NOM_UserDefined);
245 theAspect.SetDiffuseColor (myPbrMat.BaseColor.GetRGB());
246 theAspect.SetAlpha (myPbrMat.BaseColor.Alpha());
247 theAspect.SetSpecularColor(Quantity_Color (Graphic3d_Vec3 (myPbrMat.Metallic)));
248 theAspect.SetShininess (1.0f - myPbrMat.Roughness);
249 }
250
251 #ifdef _Graphic3d_PBRMaterial_HeaderFile
252 Graphic3d_PBRMaterial aPbr;
253 aPbr.SetColor (myPbrMat.BaseColor);
254 aPbr.SetMetallic (myPbrMat.Metallic);
255 aPbr.SetRoughness(myPbrMat.Roughness);
256 aPbr.SetEmission (myPbrMat.EmissiveFactor);
257 theAspect.SetPBRMaterial (aPbr);
258 #endif
259 }
260}
261
262//=======================================================================
263//function : FillAspect
264//purpose :
265//=======================================================================
266void XCAFDoc_VisMaterial::FillAspect (const Handle(Graphic3d_Aspects)& theAspect) const
267{
268 if (IsEmpty())
269 {
270 return;
271 }
272
273 Graphic3d_MaterialAspect aMaterial;
274 FillMaterialAspect (aMaterial);
275 theAspect->SetFrontMaterial (aMaterial);
276 theAspect->SetAlphaMode (myAlphaMode , myAlphaCutOff);
277 theAspect->SetSuppressBackFaces (!myIsDoubleSided);
278
279 Handle(Image_Texture) aColorTexture, aNormTexture;
280 if (!myCommonMat.DiffuseTexture.IsNull())
281 {
282 aColorTexture = myCommonMat.DiffuseTexture;
283 }
284 else if (!myPbrMat.BaseColorTexture.IsNull())
285 {
286 aColorTexture = myPbrMat.BaseColorTexture;
287 }
288
289 if (!myPbrMat.NormalTexture.IsNull())
290 {
291 aNormTexture = myPbrMat.NormalTexture;
292 }
293
294 Standard_Integer aNbTextures = 0;
295 if (!aColorTexture.IsNull())
296 {
297 ++aNbTextures;
298 }
299 if (!aNormTexture.IsNull())
300 {
301 //++aNbTextures;
302 }
303 if (aNbTextures != 0)
304 {
305 Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (aNbTextures);
306 Standard_Integer aTextureIndex = 0;
307 if (!aColorTexture.IsNull())
308 {
309 aTextureSet->SetValue (aTextureIndex++, new XCAFPrs_Texture (*aColorTexture, Graphic3d_TextureUnit_BaseColor));
310 }
311 if (!aNormTexture.IsNull())
312 {
313 //aTextureSet->SetValue (aTextureIndex++, new XCAFPrs_Texture (*aColorTexture, Graphic3d_TextureUnit_Normal));
314 }
315 theAspect->SetTextureSet (aTextureSet);
316 theAspect->SetTextureMapOn (true);
317 }
318}