01b2f506 |
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 | } |