0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / RWGltf / RWGltf_GltfMaterialMap.cxx
1 // Copyright (c) 2017-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 <RWGltf_GltfMaterialMap.hxx>
15
16 #include <RWGltf_GltfRootElement.hxx>
17
18 #ifdef HAVE_RAPIDJSON
19   #include <RWGltf_GltfOStreamWriter.hxx>
20 #endif
21
22 // =======================================================================
23 // function : baseColorTexture
24 // purpose  :
25 // =======================================================================
26 const Handle(Image_Texture)& RWGltf_GltfMaterialMap::baseColorTexture (const Handle(XCAFDoc_VisMaterial)& theMat)
27 {
28   static const Handle(Image_Texture) THE_NULL_TEXTURE;
29   if (theMat.IsNull())
30   {
31     return THE_NULL_TEXTURE;
32   }
33   else if (theMat->HasPbrMaterial()
34        && !theMat->PbrMaterial().BaseColorTexture.IsNull())
35   {
36     return theMat->PbrMaterial().BaseColorTexture;
37   }
38   else if (theMat->HasCommonMaterial()
39        && !theMat->CommonMaterial().DiffuseTexture.IsNull())
40   {
41     return theMat->CommonMaterial().DiffuseTexture;
42   }
43   return THE_NULL_TEXTURE;
44 }
45
46 // =======================================================================
47 // function : RWGltf_GltfMaterialMap
48 // purpose  :
49 // =======================================================================
50 RWGltf_GltfMaterialMap::RWGltf_GltfMaterialMap (const TCollection_AsciiString& theFile,
51                                                 const Standard_Integer theDefSamplerId)
52 : RWMesh_MaterialMap (theFile),
53   myWriter (NULL),
54   myDefSamplerId (theDefSamplerId),
55   myNbImages (0)
56 {
57   myMatNameAsKey = false;
58 }
59
60 // =======================================================================
61 // function : ~RWGltf_GltfMaterialMap
62 // purpose  :
63 // =======================================================================
64 RWGltf_GltfMaterialMap::~RWGltf_GltfMaterialMap()
65 {
66   //
67 }
68
69 // =======================================================================
70 // function : AddImages
71 // purpose  :
72 // =======================================================================
73 void RWGltf_GltfMaterialMap::AddImages (RWGltf_GltfOStreamWriter* theWriter,
74                                         const XCAFPrs_Style& theStyle,
75                                         Standard_Boolean& theIsStarted)
76 {
77   if (theWriter == NULL
78    || theStyle.Material().IsNull()
79    || theStyle.Material()->IsEmpty())
80   {
81     return;
82   }
83
84   addImage (theWriter, baseColorTexture (theStyle.Material()), theIsStarted);
85   addImage (theWriter, theStyle.Material()->PbrMaterial().MetallicRoughnessTexture, theIsStarted);
86   addImage (theWriter, theStyle.Material()->PbrMaterial().NormalTexture,    theIsStarted);
87   addImage (theWriter, theStyle.Material()->PbrMaterial().EmissiveTexture,  theIsStarted);
88   addImage (theWriter, theStyle.Material()->PbrMaterial().OcclusionTexture, theIsStarted);
89 }
90
91 // =======================================================================
92 // function : addImage
93 // purpose  :
94 // =======================================================================
95 void RWGltf_GltfMaterialMap::addImage (RWGltf_GltfOStreamWriter* theWriter,
96                                        const Handle(Image_Texture)& theTexture,
97                                        Standard_Boolean& theIsStarted)
98 {
99 #ifdef HAVE_RAPIDJSON
100   if (theTexture.IsNull()
101    || myImageMap.IsBound1 (theTexture)
102    || myImageFailMap.Contains (theTexture))
103   {
104     return;
105   }
106
107   TCollection_AsciiString aGltfImgKey = myNbImages;
108   ++myNbImages;
109   for (; myImageMap.IsBound2 (aGltfImgKey); ++myNbImages)
110   {
111     aGltfImgKey = myNbImages;
112   }
113
114   TCollection_AsciiString aTextureUri;
115   if (!CopyTexture (aTextureUri, theTexture, aGltfImgKey))
116   {
117     myImageFailMap.Add (theTexture);
118     return;
119   }
120
121   myImageMap.Bind (theTexture, aGltfImgKey);
122
123   if (!theIsStarted)
124   {
125     theWriter->Key (RWGltf_GltfRootElementName (RWGltf_GltfRootElement_Images));
126     theWriter->StartArray();
127     theIsStarted = true;
128   }
129
130   theWriter->StartObject();
131   {
132     theWriter->Key ("uri");
133     theWriter->String (aTextureUri.ToCString());
134   }
135   theWriter->EndObject();
136 #else
137   (void )theWriter;
138   (void )theTexture;
139   (void )theIsStarted;
140 #endif
141 }
142
143 // =======================================================================
144 // function : AddMaterial
145 // purpose  :
146 // =======================================================================
147 void RWGltf_GltfMaterialMap::AddMaterial (RWGltf_GltfOStreamWriter* theWriter,
148                                           const XCAFPrs_Style& theStyle,
149                                           Standard_Boolean& theIsStarted)
150 {
151 #ifdef HAVE_RAPIDJSON
152   if (theWriter == NULL
153    || ((theStyle.Material().IsNull() || theStyle.Material()->IsEmpty())
154     && !theStyle.IsSetColorSurf()))
155   {
156     return;
157   }
158
159   if (!theIsStarted)
160   {
161     theWriter->Key (RWGltf_GltfRootElementName (RWGltf_GltfRootElement_Materials));
162     theWriter->StartArray();
163     theIsStarted = true;
164   }
165   myWriter = theWriter;
166   AddMaterial (theStyle);
167   myWriter = NULL;
168 #else
169   (void )theWriter;
170   (void )theStyle;
171   (void )theIsStarted;
172 #endif
173 }
174
175 // =======================================================================
176 // function : AddTextures
177 // purpose  :
178 // =======================================================================
179 void RWGltf_GltfMaterialMap::AddTextures (RWGltf_GltfOStreamWriter* theWriter,
180                                           const XCAFPrs_Style& theStyle,
181                                           Standard_Boolean& theIsStarted)
182 {
183   if (theWriter == NULL
184    || theStyle.Material().IsNull()
185    || theStyle.Material()->IsEmpty())
186   {
187     return;
188   }
189
190   addTexture (theWriter, baseColorTexture (theStyle.Material()), theIsStarted);
191   addTexture (theWriter, theStyle.Material()->PbrMaterial().MetallicRoughnessTexture, theIsStarted);
192   addTexture (theWriter, theStyle.Material()->PbrMaterial().NormalTexture,    theIsStarted);
193   addTexture (theWriter, theStyle.Material()->PbrMaterial().EmissiveTexture,  theIsStarted);
194   addTexture (theWriter, theStyle.Material()->PbrMaterial().OcclusionTexture, theIsStarted);
195 }
196
197 // =======================================================================
198 // function : addTexture
199 // purpose  :
200 // =======================================================================
201 void RWGltf_GltfMaterialMap::addTexture (RWGltf_GltfOStreamWriter* theWriter,
202                                          const Handle(Image_Texture)& theTexture,
203                                          Standard_Boolean& theIsStarted)
204 {
205 #ifdef HAVE_RAPIDJSON
206   if (theTexture.IsNull()
207   ||  myTextureMap.Contains (theTexture)
208   || !myImageMap  .IsBound1 (theTexture))
209   {
210     return;
211   }
212
213   const TCollection_AsciiString anImgKey = myImageMap.Find1 (theTexture);
214   myTextureMap.Add (theTexture);
215   if (anImgKey.IsEmpty())
216   {
217     return;
218   }
219
220   if (!theIsStarted)
221   {
222     theWriter->Key (RWGltf_GltfRootElementName (RWGltf_GltfRootElement_Textures));
223     theWriter->StartArray();
224     theIsStarted = true;
225   }
226
227   theWriter->StartObject();
228   {
229     theWriter->Key ("sampler");
230     theWriter->Int (myDefSamplerId); // mandatory field by specs
231     theWriter->Key ("source");
232     theWriter->Int (anImgKey.IntegerValue());
233   }
234   theWriter->EndObject();
235 #else
236   (void )theWriter;
237   (void )theTexture;
238   (void )theIsStarted;
239 #endif
240 }
241
242 // =======================================================================
243 // function : AddMaterial
244 // purpose  :
245 // =======================================================================
246 TCollection_AsciiString RWGltf_GltfMaterialMap::AddMaterial (const XCAFPrs_Style& theStyle)
247 {
248   return RWMesh_MaterialMap::AddMaterial (theStyle);
249 }
250
251 // =======================================================================
252 // function : DefineMaterial
253 // purpose  :
254 // =======================================================================
255 void RWGltf_GltfMaterialMap::DefineMaterial (const XCAFPrs_Style& theStyle,
256                                              const TCollection_AsciiString& /*theKey*/,
257                                              const TCollection_AsciiString& theName)
258 {
259 #ifdef HAVE_RAPIDJSON
260   if (myWriter == NULL)
261   {
262     Standard_ProgramError::Raise ("RWGltf_GltfMaterialMap::DefineMaterial() should be called with JSON Writer");
263     return;
264   }
265
266   XCAFDoc_VisMaterialPBR aPbrMat;
267   const bool hasMaterial = !theStyle.Material().IsNull()
268                         && !theStyle.Material()->IsEmpty();
269   if (hasMaterial)
270   {
271     aPbrMat = theStyle.Material()->ConvertToPbrMaterial();
272   }
273   else if (!myDefaultStyle.Material().IsNull()
274          && myDefaultStyle.Material()->HasPbrMaterial())
275   {
276     aPbrMat = myDefaultStyle.Material()->PbrMaterial();
277   }
278   if (theStyle.IsSetColorSurf())
279   {
280     aPbrMat.BaseColor.SetRGB (theStyle.GetColorSurf());
281     if (theStyle.GetColorSurfRGBA().Alpha() < 1.0f)
282     {
283       aPbrMat.BaseColor.SetAlpha (theStyle.GetColorSurfRGBA().Alpha());
284     }
285   }
286   myWriter->StartObject();
287   {
288     myWriter->Key ("name");
289     myWriter->String (theName.ToCString());
290
291     myWriter->Key ("pbrMetallicRoughness");
292     myWriter->StartObject();
293     {
294       myWriter->Key ("baseColorFactor");
295       myWriter->StartArray();
296       {
297         myWriter->Double (aPbrMat.BaseColor.GetRGB().Red());
298         myWriter->Double (aPbrMat.BaseColor.GetRGB().Green());
299         myWriter->Double (aPbrMat.BaseColor.GetRGB().Blue());
300         myWriter->Double (aPbrMat.BaseColor.Alpha());
301       }
302       myWriter->EndArray();
303
304       if (const Handle(Image_Texture)& aBaseTexture = baseColorTexture (theStyle.Material()))
305       {
306         if (myImageMap.IsBound1 (aBaseTexture))
307         {
308           myWriter->Key ("baseColorTexture");
309           myWriter->StartObject();
310           {
311             myWriter->Key ("index");
312             const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aBaseTexture);
313             if (!anImageIdx.IsEmpty())
314             {
315               myWriter->Int (anImageIdx.IntegerValue());
316             }
317           }
318           myWriter->EndObject();
319         }
320       }
321
322       if (hasMaterial
323        || aPbrMat.Metallic != 1.0f)
324       {
325         myWriter->Key ("metallicFactor");
326         myWriter->Double (aPbrMat.Metallic);
327       }
328
329       if (!aPbrMat.MetallicRoughnessTexture.IsNull()
330         && myImageMap.IsBound1 (aPbrMat.MetallicRoughnessTexture))
331       {
332         myWriter->Key ("metallicRoughnessTexture");
333         myWriter->StartObject();
334         {
335           myWriter->Key ("index");
336           const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.MetallicRoughnessTexture);
337           if (!anImageIdx.IsEmpty())
338           {
339             myWriter->Int (anImageIdx.IntegerValue());
340           }
341         }
342         myWriter->EndObject();
343       }
344
345       if (hasMaterial
346        || aPbrMat.Roughness != 1.0f)
347       {
348         myWriter->Key ("roughnessFactor");
349         myWriter->Double (aPbrMat.Roughness);
350       }
351     }
352     myWriter->EndObject();
353
354     if (theStyle.Material().IsNull()
355      || theStyle.Material()->IsDoubleSided())
356     {
357       myWriter->Key ("doubleSided");
358       myWriter->Bool (true);
359     }
360
361     const Graphic3d_AlphaMode anAlphaMode = !theStyle.Material().IsNull() ? theStyle.Material()->AlphaMode() : Graphic3d_AlphaMode_BlendAuto;
362     switch (anAlphaMode)
363     {
364       case Graphic3d_AlphaMode_BlendAuto:
365       {
366         if (aPbrMat.BaseColor.Alpha() < 1.0f)
367         {
368           myWriter->Key ("alphaMode");
369           myWriter->String ("BLEND");
370         }
371         break;
372       }
373       case Graphic3d_AlphaMode_Opaque:
374       {
375         break;
376       }
377       case Graphic3d_AlphaMode_Mask:
378       {
379         myWriter->Key ("alphaMode");
380         myWriter->String ("MASK");
381         break;
382       }
383       case Graphic3d_AlphaMode_Blend:
384       {
385         myWriter->Key ("alphaMode");
386         myWriter->String ("BLEND");
387         break;
388       }
389     }
390     if (!theStyle.Material().IsNull()
391       && theStyle.Material()->AlphaCutOff() != 0.5f)
392     {
393       myWriter->Key ("alphaCutoff");
394       myWriter->Double (theStyle.Material()->AlphaCutOff());
395     }
396
397     if (aPbrMat.EmissiveFactor != Graphic3d_Vec3 (0.0f, 0.0f, 0.0f))
398     {
399       myWriter->Key ("emissiveFactor");
400       myWriter->StartArray();
401       {
402         myWriter->Double (aPbrMat.EmissiveFactor.r());
403         myWriter->Double (aPbrMat.EmissiveFactor.g());
404         myWriter->Double (aPbrMat.EmissiveFactor.b());
405       }
406       myWriter->EndArray();
407     }
408     if (!aPbrMat.EmissiveTexture.IsNull()
409       && myImageMap.IsBound1 (aPbrMat.EmissiveTexture))
410     {
411       myWriter->Key ("emissiveTexture");
412       myWriter->StartObject();
413       {
414         myWriter->Key ("index");
415         const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.EmissiveTexture);
416         if (!anImageIdx.IsEmpty())
417         {
418           myWriter->Int (anImageIdx.IntegerValue());
419         }
420       }
421       myWriter->EndObject();
422     }
423
424     if (!aPbrMat.NormalTexture.IsNull()
425       && myImageMap.IsBound1 (aPbrMat.NormalTexture))
426     {
427       myWriter->Key ("normalTexture");
428       myWriter->StartObject();
429       {
430         myWriter->Key ("index");
431         const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.NormalTexture);
432         if (!anImageIdx.IsEmpty())
433         {
434           myWriter->Int (anImageIdx.IntegerValue());
435         }
436       }
437       myWriter->EndObject();
438     }
439
440     if (!aPbrMat.OcclusionTexture.IsNull()
441       && myImageMap.IsBound1 (aPbrMat.OcclusionTexture))
442     {
443       myWriter->Key ("occlusionTexture");
444       myWriter->StartObject();
445       {
446         myWriter->Key ("index");
447         const TCollection_AsciiString& anImageIdx = myImageMap.Find1 (aPbrMat.OcclusionTexture);
448         if (!anImageIdx.IsEmpty())
449         {
450           myWriter->Int (anImageIdx.IntegerValue());
451         }
452       }
453       myWriter->EndObject();
454     }
455   }
456   myWriter->EndObject();
457 #else
458   (void )theStyle;
459   (void )theName;
460 #endif
461 }