1 // Created on: 2012-04-09
2 // Created by: Sergey ANIKIN
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 #include <ViewerTest.hxx>
17 
18 #include <AIS_InteractiveContext.hxx>
19 #include <Draw.hxx>
20 #include <Draw_Interpretor.hxx>
21 #include <Image_AlienPixMap.hxx>
22 #include <Message.hxx>
23 #include <OSD_File.hxx>
24 #include <OSD_FileSystem.hxx>
25 #include <V3d_View.hxx>
26 #include <V3d_Viewer.hxx>
27 
28 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
29 
30 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
31 
32 //==============================================================================
33 //function : VImmediateFront
34 //purpose  :
35 //==============================================================================
36 
VImmediateFront(Draw_Interpretor &,Standard_Integer theArgNb,const char ** theArgVec)37 static int VImmediateFront (Draw_Interpretor& ,
38                             Standard_Integer  theArgNb,
39                             const char**      theArgVec)
40 {
41   // get the context
42   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
43   if (aContextAIS.IsNull())
44   {
45     Message::SendFail ("Error: no active viewer");
46     return 1;
47   }
48 
49   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
50   if (aDriver.IsNull())
51   {
52     Message::SendFail ("Error: graphic driver not available.");
53     return 1;
54   }
55 
56   if (theArgNb < 2)
57   {
58     Message::SendFail ("Syntax error: wrong number of arguments.");
59     return 1;
60   }
61 
62   ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0);
63 
64   return 0;
65 }
66 
67 //! Search the info from the key.
searchInfo(const TColStd_IndexedDataMapOfStringString & theDict,const TCollection_AsciiString & theKey)68 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
69                                            const TCollection_AsciiString& theKey)
70 {
71   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
72   {
73     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
74     {
75       return anIter.Value();
76     }
77   }
78   return TCollection_AsciiString();
79 }
80 
81 //==============================================================================
82 //function : VGlInfo
83 //purpose  :
84 //==============================================================================
85 
VGlInfo(Draw_Interpretor & theDI,Standard_Integer theArgNb,const char ** theArgVec)86 static int VGlInfo (Draw_Interpretor& theDI,
87                     Standard_Integer  theArgNb,
88                     const char**      theArgVec)
89 {
90   // get the active view
91   Handle(V3d_View) aView = ViewerTest::CurrentView();
92   if (aView.IsNull())
93   {
94     Message::SendFail ("No active viewer");
95     return 1;
96   }
97 
98   Graphic3d_DiagnosticInfo anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
99   Standard_Integer aLineWidth = 80;
100   NCollection_Sequence<TCollection_AsciiString> aKeys;
101   TColStd_IndexedDataMapOfStringString aDict;
102   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
103   {
104     TCollection_AsciiString aName (theArgVec[anArgIter]);
105     aName.LowerCase();
106     TCollection_AsciiString aValue;
107     if (aName == "-short")
108     {
109       anInfoLevel = Graphic3d_DiagnosticInfo_Short;
110     }
111     else if (aName == "-basic")
112     {
113       anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
114     }
115     else if (aName == "-complete"
116           || aName == "-full")
117     {
118       anInfoLevel = Graphic3d_DiagnosticInfo_Complete;
119     }
120     else if (anArgIter + 1 < theArgNb
121           && (aName == "-maxwidth"
122            || aName == "-maxlinewidth"
123            || aName == "-linewidth"))
124     {
125       aLineWidth = Draw::Atoi (theArgVec[++anArgIter]);
126       if (aLineWidth < 0)
127       {
128         aLineWidth = IntegerLast();
129       }
130     }
131     else if (aName.Search ("vendor") != -1)
132     {
133       aKeys.Append ("GLvendor");
134     }
135     else if (aName.Search ("renderer") != -1)
136     {
137       aKeys.Append ("GLdevice");
138     }
139     else if (aName.Search ("shading_language_version") != -1
140           || aName.Search ("glsl") != -1)
141     {
142       aKeys.Append ("GLSLversion");
143     }
144     else if (aName.Search ("version") != -1)
145     {
146       aKeys.Append ("GLversion");
147     }
148     else if (aName.Search ("extensions") != -1)
149     {
150       aKeys.Append ("GLextensions");
151     }
152     else if (aName.Search ("extensions") != -1)
153     {
154       aKeys.Append ("GLextensions");
155     }
156     else
157     {
158       Message::SendFail() << "Syntax error: unknown key '" << aName << "'";
159       return 1;
160     }
161   }
162 
163   if (aKeys.IsEmpty())
164   {
165     aView->DiagnosticInformation (aDict, anInfoLevel);
166     TCollection_AsciiString aText;
167     for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aDict); aValueIter.More(); aValueIter.Next())
168     {
169       if (!aText.IsEmpty())
170       {
171         aText += "\n";
172       }
173       if ((aValueIter.Key().Length() + aValueIter.Value().Length() + 4) <= aLineWidth)
174       {
175         aText += TCollection_AsciiString("  ") + aValueIter.Key() + ": " + aValueIter.Value();
176         continue;
177       }
178 
179       // split into lines
180       aText += TCollection_AsciiString("  ") + aValueIter.Key() + ":";
181       TCollection_AsciiString aSubList;
182       for (Standard_Integer aTokenIter = 1;; ++aTokenIter)
183       {
184         TCollection_AsciiString aToken = aValueIter.Value().Token (" ", aTokenIter);
185         if (aToken.IsEmpty())
186         {
187           break;
188         }
189 
190         if (!aSubList.IsEmpty()
191          && (aSubList.Length() + aToken.Length() + 5) > aLineWidth)
192         {
193           aText += TCollection_AsciiString("\n    ") + aSubList;
194           aSubList = aToken;
195         }
196         else
197         {
198           if (!aSubList.IsEmpty())
199           {
200             aSubList += " ";
201           }
202           aSubList += aToken;
203         }
204       }
205       if (!aSubList.IsEmpty())
206       {
207         aText += TCollection_AsciiString("\n    ") + aSubList;
208       }
209     }
210 
211     theDI << "OpenGL info:\n"
212           << aText;
213     return 0;
214   }
215 
216   aView->DiagnosticInformation (aDict, Graphic3d_DiagnosticInfo_Complete);
217   for (NCollection_Sequence<TCollection_AsciiString>::Iterator aKeyIter (aKeys); aKeyIter.More(); aKeyIter.Next())
218   {
219     TCollection_AsciiString aValue = searchInfo (aDict, aKeyIter.Value());
220     if (aKeys.Length() > 1)
221     {
222       theDI << "{" << aValue << "} ";
223     }
224     else
225     {
226       theDI << aValue;
227     }
228   }
229 
230   return 0;
231 }
232 
233 
234 //! Parse shader type argument.
parseShaderTypeArg(Graphic3d_TypeOfShaderObject & theType,const TCollection_AsciiString & theArg)235 static bool parseShaderTypeArg (Graphic3d_TypeOfShaderObject& theType,
236                                 const TCollection_AsciiString& theArg)
237 {
238   if (theArg == "-vertex"
239    || theArg == "-vert")
240   {
241     theType = Graphic3d_TOS_VERTEX;
242   }
243   else if (theArg == "-tessevaluation"
244         || theArg == "-tesseval"
245         || theArg == "-evaluation"
246         || theArg == "-eval")
247   {
248     theType = Graphic3d_TOS_TESS_EVALUATION;
249   }
250   else if (theArg == "-tesscontrol"
251         || theArg == "-tessctrl"
252         || theArg == "-control"
253         || theArg == "-ctrl")
254   {
255     theType = Graphic3d_TOS_TESS_CONTROL;
256   }
257   else if (theArg == "-geometry"
258         || theArg == "-geom")
259   {
260     theType = Graphic3d_TOS_GEOMETRY;
261   }
262   else if (theArg == "-fragment"
263         || theArg == "-frag")
264   {
265     theType = Graphic3d_TOS_FRAGMENT;
266   }
267   else if (theArg == "-compute"
268         || theArg == "-comp")
269   {
270     theType = Graphic3d_TOS_COMPUTE;
271   }
272   else
273   {
274     return false;
275   }
276   return true;
277 }
278 
279 //==============================================================================
280 //function : VShaderProg
281 //purpose  : Sets the pair of vertex and fragment shaders for the object
282 //==============================================================================
VShaderProg(Draw_Interpretor &,Standard_Integer theArgNb,const char ** theArgVec)283 static Standard_Integer VShaderProg (Draw_Interpretor& ,
284                                      Standard_Integer  theArgNb,
285                                      const char**      theArgVec)
286 {
287   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
288   if (aCtx.IsNull())
289   {
290     Message::SendFail ("Error: no active viewer");
291     return 1;
292   }
293   else if (theArgNb < 2)
294   {
295     Message::SendFail ("Syntax error: lack of arguments");
296     return 1;
297   }
298 
299   bool isExplicitShaderType = false;
300   Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram();
301   NCollection_Sequence<Handle(AIS_InteractiveObject)> aPrsList;
302   Graphic3d_GroupAspect aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
303   bool isSetGroupAspect = false;
304   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
305   {
306     TCollection_AsciiString anArg (theArgVec[anArgIter]);
307     anArg.LowerCase();
308     Graphic3d_TypeOfShaderObject aShaderTypeArg = Graphic3d_TypeOfShaderObject(-1);
309     if (!aProgram.IsNull()
310       && anArg == "-uniform"
311       && anArgIter + 2 < theArgNb)
312     {
313       TCollection_AsciiString aName = theArgVec[++anArgIter];
314       aProgram->PushVariableFloat (aName, float (Draw::Atof (theArgVec[++anArgIter])));
315     }
316     else if (!aProgram.IsNull()
317           &&  aProgram->ShaderObjects().IsEmpty()
318           && (anArg == "-off"
319            || anArg ==  "off"))
320     {
321       aProgram.Nullify();
322     }
323     else if (!aProgram.IsNull()
324           &&  aProgram->ShaderObjects().IsEmpty()
325           && (anArg == "-phong"
326            || anArg ==  "phong"))
327     {
328       const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder();
329       if (aShadersRoot.IsEmpty())
330       {
331         Message::SendFail("Error: both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
332                           "At least one should be defined to load Phong program.");
333         return 1;
334       }
335 
336       const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs";
337       const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs";
338       if (!aSrcVert.IsEmpty()
339        && !OSD_File (aSrcVert).Exists())
340       {
341         Message::SendFail ("Error: PhongShading.vs is not found");
342         return 1;
343       }
344       if (!aSrcFrag.IsEmpty()
345        && !OSD_File (aSrcFrag).Exists())
346       {
347         Message::SendFail ("Error: PhongShading.fs is not found");
348         return 1;
349       }
350 
351       aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX,   aSrcVert));
352       aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
353     }
354     else if (aPrsList.IsEmpty()
355           && anArg == "*")
356     {
357       //
358     }
359     else if (!isSetGroupAspect
360           &&  anArgIter + 1 < theArgNb
361           && (anArg == "-primtype"
362            || anArg == "-primitivetype"
363            || anArg == "-groupaspect"
364            || anArg == "-aspecttype"
365            || anArg == "-aspect"))
366     {
367       isSetGroupAspect = true;
368       TCollection_AsciiString aPrimTypeStr (theArgVec[++anArgIter]);
369       aPrimTypeStr.LowerCase();
370       if (aPrimTypeStr == "line")
371       {
372         aGroupAspect = Graphic3d_ASPECT_LINE;
373       }
374       else if (aPrimTypeStr == "tris"
375             || aPrimTypeStr == "triangles"
376             || aPrimTypeStr == "fill"
377             || aPrimTypeStr == "fillarea"
378             || aPrimTypeStr == "shading"
379             || aPrimTypeStr == "shade")
380       {
381         aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
382       }
383       else if (aPrimTypeStr == "text")
384       {
385         aGroupAspect = Graphic3d_ASPECT_TEXT;
386       }
387       else if (aPrimTypeStr == "marker"
388             || aPrimTypeStr == "point"
389             || aPrimTypeStr == "pnt")
390       {
391         aGroupAspect = Graphic3d_ASPECT_MARKER;
392       }
393       else
394       {
395         Message::SendFail() << "Syntax error at '" << aPrimTypeStr << "'";
396         return 1;
397       }
398     }
399     else if (anArgIter + 1 < theArgNb
400          && !aProgram.IsNull()
401          &&  aProgram->Header().IsEmpty()
402          &&  (anArg == "-version"
403            || anArg == "-glslversion"
404            || anArg == "-header"
405            || anArg == "-glslheader"))
406     {
407       TCollection_AsciiString aHeader (theArgVec[++anArgIter]);
408       if (aHeader.IsIntegerValue())
409       {
410         aHeader = TCollection_AsciiString ("#version ") + aHeader;
411       }
412       aProgram->SetHeader (aHeader);
413     }
414     else if (!anArg.StartsWith ("-")
415           && GetMapOfAIS().IsBound2 (theArgVec[anArgIter]))
416     {
417       Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (theArgVec[anArgIter]);
418       if (anIO.IsNull())
419       {
420         Message::SendFail() << "Syntax error: " << theArgVec[anArgIter] << " is not an AIS object";
421         return 1;
422       }
423       aPrsList.Append (anIO);
424     }
425     else if (!aProgram.IsNull()
426            && ((anArgIter + 1 < theArgNb && parseShaderTypeArg (aShaderTypeArg, anArg))
427             || (!isExplicitShaderType && aProgram->ShaderObjects().Size() < 2)))
428     {
429       TCollection_AsciiString aShaderPath (theArgVec[anArgIter]);
430       if (aShaderTypeArg != Graphic3d_TypeOfShaderObject(-1))
431       {
432         aShaderPath = (theArgVec[++anArgIter]);
433         isExplicitShaderType = true;
434       }
435 
436       const bool isSrcFile = OSD_File (aShaderPath).Exists();
437       Handle(Graphic3d_ShaderObject) aShader = isSrcFile
438                                              ? Graphic3d_ShaderObject::CreateFromFile  (Graphic3d_TOS_VERTEX, aShaderPath)
439                                              : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_VERTEX, aShaderPath);
440       const TCollection_AsciiString& aShaderSrc = aShader->Source();
441 
442       const bool hasVertPos   = aShaderSrc.Search ("gl_Position")  != -1;
443       const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1
444                              || aShaderSrc.Search ("occFragColor") != -1
445                              || aShaderSrc.Search ("gl_FragColor") != -1
446                              || aShaderSrc.Search ("gl_FragData")  != -1;
447       Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg;
448       if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
449       {
450         if (hasVertPos
451         && !hasFragColor)
452         {
453           aShaderType = Graphic3d_TOS_VERTEX;
454         }
455         if (hasFragColor
456         && !hasVertPos)
457         {
458           aShaderType = Graphic3d_TOS_FRAGMENT;
459         }
460       }
461       if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
462       {
463         Message::SendFail() << "Error: non-existing or invalid shader source";
464         return 1;
465       }
466 
467       aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aShaderType, aShaderSrc));
468     }
469     else
470     {
471       Message::SendFail() << "Syntax error at '" << anArg << "'";
472       return 1;
473     }
474   }
475 
476   if (!aProgram.IsNull()
477     && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
478   {
479     aProgram->SetNbFragmentOutputs (2);
480     aProgram->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
481   }
482 
483   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
484   NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (aPrsList);
485   const bool isGlobalList = aPrsList.IsEmpty();
486   for (;;)
487   {
488     Handle(AIS_InteractiveObject) anIO;
489     if (isGlobalList)
490     {
491       if (!aGlobalPrsIter.More())
492       {
493         break;
494       }
495       anIO = aGlobalPrsIter.Key1();
496       aGlobalPrsIter.Next();
497       if (anIO.IsNull())
498       {
499         continue;
500       }
501     }
502     else
503     {
504       if (!aPrsIter.More())
505       {
506         break;
507       }
508       anIO = aPrsIter.Value();
509       aPrsIter.Next();
510     }
511 
512     if (anIO->Attributes()->SetShaderProgram (aProgram, aGroupAspect, true))
513     {
514       aCtx->Redisplay (anIO, Standard_False);
515     }
516     else
517     {
518       anIO->SynchronizeAspects();
519     }
520   }
521 
522   aCtx->UpdateCurrentViewer();
523   return 0;
524 }
525 
526 //! Print triplet of values.
operator <<(S & theStream,const NCollection_Vec3<T> & theVec)527 template<class S, class T> static S& operator<< (S& theStream, const NCollection_Vec3<T>& theVec)
528 {
529   theStream << theVec[0] << " " << theVec[1] << " " << theVec[2];
530   return theStream;
531 }
532 
533 //! Print 4 values.
operator <<(S & theStream,const NCollection_Vec4<T> & theVec)534 template<class S, class T> static S& operator<< (S& theStream, const NCollection_Vec4<T>& theVec)
535 {
536   theStream << theVec[0] << " " << theVec[1] << " " << theVec[2] << " " << theVec[3];
537   return theStream;
538 }
539 
540 //! Print fresnel model.
fresnelModelString(const Graphic3d_FresnelModel theModel)541 static const char* fresnelModelString (const Graphic3d_FresnelModel theModel)
542 {
543   switch (theModel)
544   {
545     case Graphic3d_FM_SCHLICK:    return "SCHLICK";
546     case Graphic3d_FM_CONSTANT:   return "CONSTANT";
547     case Graphic3d_FM_CONDUCTOR:  return "CONDUCTOR";
548     case Graphic3d_FM_DIELECTRIC: return "DIELECTRIC";
549   }
550   return "N/A";
551 }
552 
553 //! Create a colored rectangle SVG element.
formatSvgColoredRect(const Quantity_Color & theColor)554 static TCollection_AsciiString formatSvgColoredRect (const Quantity_Color& theColor)
555 {
556   return TCollection_AsciiString()
557        + "<svg width='20px' height='20px'><rect width='20px' height='20px' fill='" + Quantity_Color::ColorToHex (theColor) + "' /></svg>";
558 }
559 
560 //==============================================================================
561 //function : VListMaterials
562 //purpose  :
563 //==============================================================================
VListMaterials(Draw_Interpretor & theDI,Standard_Integer theArgNb,const char ** theArgVec)564 static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
565                                         Standard_Integer  theArgNb,
566                                         const char**      theArgVec)
567 {
568   TCollection_AsciiString aDumpFile;
569   NCollection_Sequence<Graphic3d_NameOfMaterial> aMatList;
570   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
571   {
572     TCollection_AsciiString anArg (theArgVec[anArgIter]);
573     anArg.LowerCase();
574     Graphic3d_NameOfMaterial aMat = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter]);
575     if (aMat != Graphic3d_NameOfMaterial_DEFAULT)
576     {
577       aMatList.Append (aMat);
578     }
579     else if (anArg == "*")
580     {
581       for (Standard_Integer aMatIter = 0; aMatIter < (Standard_Integer )Graphic3d_NameOfMaterial_DEFAULT; ++aMatIter)
582       {
583         aMatList.Append ((Graphic3d_NameOfMaterial )aMatIter);
584       }
585     }
586     else if (aDumpFile.IsEmpty()
587           && (anArg.EndsWith (".obj")
588            || anArg.EndsWith (".mtl")
589            || anArg.EndsWith (".htm")
590            || anArg.EndsWith (".html")))
591     {
592       aDumpFile = theArgVec[anArgIter];
593     }
594     else
595     {
596       Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
597       return 1;
598     }
599   }
600   if (aMatList.IsEmpty())
601   {
602     if (aDumpFile.IsEmpty())
603     {
604       for (Standard_Integer aMatIter = 1; aMatIter <= Graphic3d_MaterialAspect::NumberOfMaterials(); ++aMatIter)
605       {
606         theDI << Graphic3d_MaterialAspect::MaterialName (aMatIter) << " ";
607       }
608       return 0;
609     }
610 
611     for (Standard_Integer aMatIter = 0; aMatIter < (Standard_Integer )Graphic3d_NameOfMaterial_DEFAULT; ++aMatIter)
612     {
613       aMatList.Append ((Graphic3d_NameOfMaterial )aMatIter);
614     }
615   }
616 
617   // geometry for dumping
618   const Graphic3d_Vec3 aBoxVerts[8] =
619   {
620     Graphic3d_Vec3( 1, -1, -1),
621     Graphic3d_Vec3( 1, -1,  1),
622     Graphic3d_Vec3(-1, -1,  1),
623     Graphic3d_Vec3(-1, -1, -1),
624     Graphic3d_Vec3( 1,  1, -1),
625     Graphic3d_Vec3( 1,  1,  1),
626     Graphic3d_Vec3(-1,  1,  1),
627     Graphic3d_Vec3(-1,  1, -1)
628   };
629 
630   const Graphic3d_Vec4i aBoxQuads[6] =
631   {
632     Graphic3d_Vec4i (1, 2, 3, 4),
633     Graphic3d_Vec4i (5, 8, 7, 6),
634     Graphic3d_Vec4i (1, 5, 6, 2),
635     Graphic3d_Vec4i (2, 6, 7, 3),
636     Graphic3d_Vec4i (3, 7, 8, 4),
637     Graphic3d_Vec4i (5, 1, 4, 8)
638   };
639 
640   const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
641   opencascade::std::shared_ptr<std::ostream> aMatFile, anObjFile, aHtmlFile;
642   if (aDumpFile.EndsWith (".obj")
643    || aDumpFile.EndsWith (".mtl"))
644   {
645     const TCollection_AsciiString aMatFilePath  = aDumpFile.SubString (1, aDumpFile.Length() - 3) + "mtl";
646     const TCollection_AsciiString anObjFilePath = aDumpFile.SubString (1, aDumpFile.Length() - 3) + "obj";
647 
648     aMatFile = aFileSystem->OpenOStream (aMatFilePath, std::ios::out | std::ios::binary);
649     if (aMatFile.get() == NULL)
650     {
651       Message::SendFail ("Error: unable creating material file");
652       return 0;
653     }
654     if (!aDumpFile.EndsWith (".mtl"))
655     {
656       anObjFile = aFileSystem->OpenOStream (anObjFilePath, std::ios::out | std::ios::binary);
657       if (anObjFile.get() == NULL)
658       {
659         Message::SendFail ("Error: unable creating OBJ file");
660         return 0;
661       }
662 
663       TCollection_AsciiString anMtlName, aFolder;
664       OSD_Path::FolderAndFileFromPath (aMatFilePath, aFolder, anMtlName);
665       *anObjFile << "mtllib " << anMtlName << "\n";
666     }
667   }
668   else if (aDumpFile.EndsWith (".htm")
669         || aDumpFile.EndsWith (".html"))
670   {
671     aHtmlFile = aFileSystem->OpenOStream (aDumpFile, std::ios::out | std::ios::binary);
672     if (aHtmlFile.get() == NULL)
673     {
674       Message::SendFail ("Error: unable creating HTML file");
675       return 0;
676     }
677     *aHtmlFile << "<html>\n"
678                   "<head><title>OCCT Material table</title></head>\n"
679                   "<body>\n"
680                   "<table border='1'><tbody>\n"
681                   "<tr>\n"
682                   "<th rowspan='2'><div title='Material name.\n"
683                                               "See also Graphic3d_NameOfMaterial enumeration'>"
684                                    "Name</div></th>\n"
685                   "<th rowspan='2'><div title='Material type: PHYSIC or ASPECT.\n"
686                                               "ASPECT material does not define final colors, it is taken from Internal Color instead.\n"
687                                               "See also Graphic3d_TypeOfMaterial enumeration'>"
688                                    "Type</div></th>\n"
689                   "<th rowspan='2'>Transparency</th>\n"
690                   "<th colspan='5'><div title='PBR Metallic-Roughness'>"
691                                    "PBR Metallic-Roughness</div></th>\n"
692                   "<th colspan='5'><div title='Common material definition for Phong shading model'>"
693                                    "Common (Blinn-Phong)</div></th>\n"
694                   "<th colspan='10'><div title='BSDF (Bidirectional Scattering Distribution Function).\n"
695                                               "Used for physically-based rendering (in path tracing engine).\n"
696                                               "BSDF is represented as weighted mixture of basic BRDFs/BTDFs (Bidirectional Reflectance (Transmittance) Distribution Functions).\n"
697                                               "See also Graphic3d_BSDF structure.'>"
698                                    "BSDF (Bidirectional Scattering Distribution Function)</div></th>\n"
699                   "</tr>\n"
700                   "<tr>\n"
701                   "<th>Color</th>\n"
702                   "<th>Metallic</th>\n"
703                   "<th>Roughness</th>\n"
704                   "<th>Emission</th>\n"
705                   "<th><div title='Index of refraction'>"
706                        "IOR</div></th>\n"
707                   "<th>Ambient</th>\n"
708                   "<th>Diffuse</th>\n"
709                   "<th>Specular</th>\n"
710                   "<th>Emissive</th>\n"
711                   "<th>Shiness</th>\n"
712                   "<th><div title='Weight of coat specular/glossy BRDF'>"
713                        "Kc</div></th>\n"
714                   "<th><div title='Weight of base diffuse BRDF'>"
715                        "Kd</div></th>\n"
716                   "<th><div title='Weight of base specular/glossy BRDF'>"
717                        "Ks</div></th>\n"
718                   "<th><div title='Weight of base specular/glossy BTDF'>"
719                        "Kt</div></th>\n"
720                   "<th><div title='Radiance emitted by the surface'>"
721                        "Le</div></th>\n"
722                   "<th><div title='Volume scattering color/density'>"
723                        "Absorption</div></th>\n"
724                   "<th><div title='Parameters of Fresnel reflectance of coat layer'>"
725                        "FresnelCoat</div></th>\n"
726                   "<th><div title='Parameters of Fresnel reflectance of base layer'>"
727                        "FresnelBase</div></th>\n"
728                   "<th>Refraction Index</th>\n"
729                   "</tr>\n";
730   }
731   else if (!aDumpFile.IsEmpty())
732   {
733     Message::SendFail ("Syntax error: unknown output file format");
734     return 1;
735   }
736 
737   Standard_Integer aMatIndex = 0, anX = 0, anY = 0;
738   for (NCollection_Sequence<Graphic3d_NameOfMaterial>::Iterator aMatIter (aMatList); aMatIter.More(); aMatIter.Next(), ++aMatIndex)
739   {
740     Graphic3d_MaterialAspect aMat (aMatIter.Value());
741     const TCollection_AsciiString aMatName = aMat.StringName();
742     const Graphic3d_Vec3 anAmbient  = (Graphic3d_Vec3 )aMat.AmbientColor();
743     const Graphic3d_Vec3 aDiffuse   = (Graphic3d_Vec3 )aMat.DiffuseColor();
744     const Graphic3d_Vec3 aSpecular  = (Graphic3d_Vec3 )aMat.SpecularColor();
745     const Graphic3d_Vec3 anEmission = (Graphic3d_Vec3 )aMat.EmissiveColor();
746     const Standard_Real  aShiness  = aMat.Shininess() * 1000.0;
747     if (aMatFile.get() != NULL)
748     {
749       *aMatFile << "newmtl " << aMatName << "\n";
750       *aMatFile << "Ka " << Quantity_Color::Convert_LinearRGB_To_sRGB (anAmbient) << "\n";
751       *aMatFile << "Kd " << Quantity_Color::Convert_LinearRGB_To_sRGB (aDiffuse)  << "\n";
752       *aMatFile << "Ks " << Quantity_Color::Convert_LinearRGB_To_sRGB (aSpecular) << "\n";
753       *aMatFile << "Ns " << aShiness  << "\n";
754       if (aMat.Transparency() >= 0.0001)
755       {
756         *aMatFile << "Tr " << aMat.Transparency() << "\n";
757       }
758       *aMatFile << "\n";
759     }
760     else if (aHtmlFile.get() != NULL)
761     {
762       *aHtmlFile << "<tr>\n";
763       *aHtmlFile << "<td>" << aMat.StringName() << "</td>\n";
764       *aHtmlFile << "<td>" << (aMat.MaterialType() == Graphic3d_MATERIAL_PHYSIC ? "PHYSIC" : "ASPECT")  << "</td>\n";
765       *aHtmlFile << "<td>" << aMat.Transparency() << "</td>\n";
766       *aHtmlFile << "<td>" << formatSvgColoredRect (aMat.PBRMaterial().Color().GetRGB()) << (Graphic3d_Vec3 )aMat.PBRMaterial().Color().GetRGB() << "</td>\n";
767       *aHtmlFile << "<td>" << aMat.PBRMaterial().Metallic() << "</td>\n";
768       *aHtmlFile << "<td>" << aMat.PBRMaterial().NormalizedRoughness() << "</td>\n";
769       *aHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aMat.PBRMaterial().Emission())) << aMat.PBRMaterial().Emission() << "</td>\n";
770       *aHtmlFile << "<td>" << aMat.PBRMaterial().IOR() << "</td>\n";
771       *aHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (anAmbient))  << anAmbient  << "</td>\n";
772       *aHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aDiffuse))   << aDiffuse   << "</td>\n";
773       *aHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aSpecular))  << aSpecular  << "</td>\n";
774       *aHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (anEmission)) << anEmission << "</td>\n";
775       *aHtmlFile << "<td>" << aMat.Shininess() << "</td>\n";
776       *aHtmlFile << "<td>" << aMat.BSDF().Kc << "</td>\n";
777       *aHtmlFile << "<td>" << aMat.BSDF().Kd << "</td>\n";
778       *aHtmlFile << "<td>" << aMat.BSDF().Ks << "</td>\n";
779       *aHtmlFile << "<td>" << aMat.BSDF().Kt << "</td>\n";
780       *aHtmlFile << "<td>" << aMat.BSDF().Le << "</td>\n";
781       *aHtmlFile << "<td>" << aMat.BSDF().Absorption << "</td>\n";
782       *aHtmlFile << "<td>" << fresnelModelString (aMat.BSDF().FresnelCoat.FresnelType()) << "</td>\n";
783       *aHtmlFile << "<td>" << fresnelModelString (aMat.BSDF().FresnelBase.FresnelType()) << "</td>\n";
784       *aHtmlFile << "<td>" << aMat.RefractionIndex() << "</td>\n";
785       *aHtmlFile << "</tr>\n";
786     }
787     else
788     {
789       theDI << aMat.StringName() << "\n";
790       theDI << "  Transparency:           " << aMat.Transparency() << "\n";
791       theDI << "  PBR.BaseColor:          " << (Graphic3d_Vec3 )aMat.PBRMaterial().Color().GetRGB() << "\n";
792       theDI << "  PBR.Metallic:           " << aMat.PBRMaterial().Metallic() << "\n";
793       theDI << "  PBR.Roughness:          " << aMat.PBRMaterial().NormalizedRoughness() << "\n";
794       theDI << "  PBR.Emission:           " << aMat.PBRMaterial().Emission() << "\n";
795       theDI << "  PBR.IOR:                " << aMat.PBRMaterial().IOR() << "\n";
796       theDI << "  Common.Ambient:         " << anAmbient << "\n";
797       theDI << "  Common.Diffuse:         " << aDiffuse  << "\n";
798       theDI << "  Common.Specular:        " << aSpecular << "\n";
799       theDI << "  Common.Emissive:        " << anEmission << "\n";
800       theDI << "  Common.Shiness:         " << aMat.Shininess() << "\n";
801       theDI << "  BSDF.Kc:                " << aMat.BSDF().Kc << "\n";
802       theDI << "  BSDF.Kd:                " << aMat.BSDF().Kd << "\n";
803       theDI << "  BSDF.Ks:                " << aMat.BSDF().Ks << "\n";
804       theDI << "  BSDF.Kt:                " << aMat.BSDF().Kt << "\n";
805       theDI << "  BSDF.Le:                " << aMat.BSDF().Le << "\n";
806       theDI << "  BSDF.Absorption:        " << aMat.BSDF().Absorption << "\n";
807       theDI << "  BSDF.FresnelCoat:       " << fresnelModelString (aMat.BSDF().FresnelCoat.FresnelType()) << "\n";
808       theDI << "  BSDF.FresnelBase:       " << fresnelModelString (aMat.BSDF().FresnelBase.FresnelType()) << "\n";
809       theDI << "  RefractionIndex:        " << aMat.RefractionIndex() << "\n";
810     }
811 
812     if (anObjFile.get() != NULL)
813     {
814       *anObjFile << "g " << aMatName << "\n";
815       *anObjFile << "usemtl " << aMatName << "\n";
816       for (Standard_Integer aVertIter = 0; aVertIter < 8; ++aVertIter)
817       {
818         *anObjFile << "v " << (aBoxVerts[aVertIter] + Graphic3d_Vec3 (3.0f * anX, -3.0f * anY, 0.0f)) << "\n";
819       }
820       *anObjFile << "s off\n";
821       for (Standard_Integer aFaceIter = 0; aFaceIter < 6; ++aFaceIter)
822       {
823         *anObjFile << "f " << (aBoxQuads[aFaceIter] + Graphic3d_Vec4i (8 * aMatIndex)) << "\n";
824       }
825       *anObjFile << "\n";
826       if (++anX > 5)
827       {
828         anX = 0;
829         ++anY;
830       }
831     }
832   }
833 
834   if (aHtmlFile.get() != NULL)
835   {
836     *aHtmlFile << "</tbody></table>\n</body>\n</html>\n";
837   }
838   return 0;
839 }
840 
841 //==============================================================================
842 //function : VListColors
843 //purpose  :
844 //==============================================================================
VListColors(Draw_Interpretor & theDI,Standard_Integer theArgNb,const char ** theArgVec)845 static Standard_Integer VListColors (Draw_Interpretor& theDI,
846                                      Standard_Integer  theArgNb,
847                                      const char**      theArgVec)
848 {
849   TCollection_AsciiString aDumpFile;
850   NCollection_Sequence<Quantity_NameOfColor> aColList;
851   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
852   {
853     TCollection_AsciiString anArg (theArgVec[anArgIter]);
854     anArg.LowerCase();
855     Quantity_NameOfColor aName;
856     if (Quantity_Color::ColorFromName (theArgVec[anArgIter], aName))
857     {
858       aColList.Append (aName);
859     }
860     else if (anArg == "*")
861     {
862       for (Standard_Integer aColIter = 0; aColIter <= (Standard_Integer )Quantity_NOC_WHITE; ++aColIter)
863       {
864         aColList.Append ((Quantity_NameOfColor )aColIter);
865       }
866     }
867     else if (aDumpFile.IsEmpty()
868           && (anArg.EndsWith (".htm")
869            || anArg.EndsWith (".html")))
870     {
871       aDumpFile = theArgVec[anArgIter];
872     }
873     else
874     {
875       Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
876       return 1;
877     }
878   }
879   if (aColList.IsEmpty())
880   {
881     if (aDumpFile.IsEmpty())
882     {
883       for (Standard_Integer aColIter = 0; aColIter <= (Standard_Integer )Quantity_NOC_WHITE; ++aColIter)
884       {
885         theDI << Quantity_Color::StringName (Quantity_NameOfColor (aColIter)) << " ";
886       }
887       return 0;
888     }
889 
890     for (Standard_Integer aColIter = 0; aColIter <= (Standard_Integer )Quantity_NOC_WHITE; ++aColIter)
891     {
892       aColList.Append ((Quantity_NameOfColor )aColIter);
893     }
894   }
895 
896   const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
897   opencascade::std::shared_ptr<std::ostream> aHtmlFile;
898   TCollection_AsciiString aFileNameBase, aFolder;
899   if (aDumpFile.EndsWith (".htm")
900    || aDumpFile.EndsWith (".html"))
901   {
902     OSD_Path::FolderAndFileFromPath (aDumpFile, aFolder, aFileNameBase);
903     aFileNameBase = aFileNameBase.SubString (1, aFileNameBase.Length() -  (aDumpFile.EndsWith (".htm") ? 4 : 5));
904   }
905   else if (!aDumpFile.IsEmpty())
906   {
907     Message::SendFail ("Syntax error: unknown output file format");
908     return 1;
909   }
910 
911   Standard_Integer aMaxNameLen = 1;
912   for (NCollection_Sequence<Quantity_NameOfColor>::Iterator aColIter (aColList); aColIter.More(); aColIter.Next())
913   {
914     aMaxNameLen = Max (aMaxNameLen, TCollection_AsciiString (Quantity_Color::StringName (aColIter.Value())).Length());
915   }
916 
917   V3d_ImageDumpOptions anImgParams;
918   anImgParams.Width  = 60;
919   anImgParams.Height = 30;
920   anImgParams.BufferType = Graphic3d_BT_RGB;
921   anImgParams.StereoOptions  = V3d_SDO_MONO;
922   anImgParams.ToAdjustAspect = Standard_True;
923   Handle(V3d_View) aView;
924   if (!aDumpFile.IsEmpty())
925   {
926     ViewerTest::ViewerInit (0, 0, anImgParams.Width, anImgParams.Height, "TmpDriver/TmpViewer/TmpView");
927     aView = ViewerTest::CurrentView();
928     aView->SetImmediateUpdate (false);
929     aView->SetBgGradientStyle (Aspect_GradientFillMethod_None, false);
930   }
931 
932   if (!aDumpFile.IsEmpty())
933   {
934     aHtmlFile = aFileSystem->OpenOStream (aDumpFile, std::ios::out | std::ios::binary);
935     if (aHtmlFile.get() == NULL)
936     {
937       Message::SendFail ("Error: unable creating HTML file");
938       return 0;
939     }
940     *aHtmlFile << "<html>\n"
941                << "<head><title>OCCT Color table</title></head>\n"
942                << "<body>\n"
943                << "<table border='1'><tbody>\n"
944                << "<tr>\n"
945                << "<th>HTML</th>\n"
946                << "<th>OCCT</th>\n"
947                << "<th>Color name</th>\n"
948                << "<th>sRGB hex</th>\n"
949                << "<th>sRGB dec</th>\n"
950                << "<th>RGB linear</th>\n"
951                << "</tr>\n";
952   }
953 
954   Image_AlienPixMap anImg;
955   Standard_Integer aColIndex = 0;
956   for (NCollection_Sequence<Quantity_NameOfColor>::Iterator aColIter (aColList); aColIter.More(); aColIter.Next(), ++aColIndex)
957   {
958     Quantity_Color aCol (aColIter.Value());
959     const TCollection_AsciiString aColName  = Quantity_Color::StringName (aColIter.Value());
960     const TCollection_AsciiString anSRgbHex = Quantity_Color::ColorToHex (aCol);
961     const Graphic3d_Vec3i anSRgbInt ((Graphic3d_Vec3 )aCol * 255.0f);
962     if (aHtmlFile.get() != NULL)
963     {
964       const TCollection_AsciiString anImgPath = aFileNameBase + "_" + aColName + ".png";
965       if (!aView.IsNull())
966       {
967         aView->SetImmediateUpdate (false);
968         aView->SetBackgroundColor (aCol);
969         if (!aView->ToPixMap (anImg, anImgParams)
970          || !anImg.Save (aFolder + anImgPath))
971         {
972           theDI << "Error: image dump failed\n";
973           return 0;
974         }
975       }
976 
977       *aHtmlFile << "<tr>\n";
978       *aHtmlFile << "<td style='background-color:" << anSRgbHex << "'><pre>       </pre></td>\n";
979       *aHtmlFile << "<td><img src='" << (!aView.IsNull() ? anImgPath : "") << "'></img></td>\n";
980       *aHtmlFile << "<td style='text-align:left'>" << aColName << "</td>\n";
981       *aHtmlFile << "<td style='text-align:left'><pre>" << anSRgbHex << "</pre></td>\n";
982       *aHtmlFile << "<td style='text-align:left'>(" << anSRgbInt.r() << " " << anSRgbInt.g() << " " << anSRgbInt.b() << ")</td>\n";
983       *aHtmlFile << "<td style='text-align:left'>(" << aCol.Red() << " " << aCol.Green() << " " << aCol.Blue() << ")</td>\n";
984       *aHtmlFile << "</tr>\n";
985     }
986     else
987     {
988       TCollection_AsciiString aColNameLong (aColName);
989       aColNameLong.RightJustify (aMaxNameLen, ' ');
990       theDI << aColNameLong << " [" << anSRgbHex << "]: " << aCol.Red() << " " << aCol.Green() << " " << aCol.Blue() << "\n";
991     }
992   }
993 
994   if (!aView.IsNull())
995   {
996     ViewerTest::RemoveView (aView);
997   }
998 
999   if (aHtmlFile.get() != NULL)
1000   {
1001     *aHtmlFile << "</tbody></table>\n</body>\n</html>\n";
1002   }
1003   return 0;
1004 }
1005 
1006 //==============================================================================
1007 //function : envlutWriteToFile
1008 //purpose  :
1009 //==============================================================================
envLutWriteToFile(Standard_ShortReal theValue)1010 static std::string envLutWriteToFile (Standard_ShortReal theValue)
1011 {
1012   std::stringstream aStream;
1013   aStream << theValue;
1014   if (aStream.str().length() == 1)
1015   {
1016     aStream << '.';
1017   }
1018   aStream << 'f';
1019   return aStream.str();
1020 }
1021 
1022 //==============================================================================
1023 //function : VGenEnvLUT
1024 //purpose  :
1025 //==============================================================================
VGenEnvLUT(Draw_Interpretor &,Standard_Integer theArgNb,const char ** theArgVec)1026 static Standard_Integer VGenEnvLUT (Draw_Interpretor&,
1027                                     Standard_Integer  theArgNb,
1028                                     const char**      theArgVec)
1029 {
1030   Standard_Integer aTableSize = -1;
1031   Standard_Integer aNbSamples = -1;
1032   TCollection_AsciiString aFilePath = Graphic3d_TextureRoot::TexturesFolder() + "/Textures_EnvLUT.pxx";
1033 
1034   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1035   {
1036     TCollection_AsciiString anArg(theArgVec[anArgIter]);
1037     anArg.LowerCase();
1038 
1039     if (anArg == "-size"
1040      || anArg == "-s")
1041     {
1042       if (anArgIter + 1 >= theArgNb)
1043       {
1044         Message::SendFail ("Syntax error: size of PBR environment look up table is undefined");
1045         return 1;
1046       }
1047 
1048       aTableSize = Draw::Atoi(theArgVec[++anArgIter]);
1049 
1050       if (aTableSize < 16)
1051       {
1052         Message::SendFail ("Error: size of PBR environment look up table must be greater or equal 16");
1053         return 1;
1054       }
1055     }
1056     else if (anArg == "-nbsamples"
1057           || anArg == "-samples")
1058     {
1059       if (anArgIter + 1 >= theArgNb)
1060       {
1061         Message::SendFail ("Syntax error: number of samples to generate PBR environment look up table is undefined");
1062         return 1;
1063       }
1064 
1065       aNbSamples = Draw::Atoi(theArgVec[++anArgIter]);
1066 
1067       if (aNbSamples < 1)
1068       {
1069         Message::SendFail ("Syntax error: number of samples to generate PBR environment look up table must be greater than 1");
1070         return 1;
1071       }
1072     }
1073     else
1074     {
1075       Message::SendFail() << "Syntax error: unknown argument " << anArg;
1076       return 1;
1077     }
1078   }
1079 
1080   if (aTableSize < 0)
1081   {
1082     aTableSize = 128;
1083   }
1084 
1085   if (aNbSamples < 0)
1086   {
1087     aNbSamples = 1024;
1088   }
1089 
1090   const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
1091   opencascade::std::shared_ptr<std::ostream> aFile = aFileSystem->OpenOStream (aFilePath, std::ios::out | std::ios::trunc);
1092 
1093   if (aFile.get() == NULL || !aFile->good())
1094   {
1095     Message::SendFail() << "Error: unable to write to " << aFilePath;
1096     return 1;
1097   }
1098 
1099   *aFile << "//this file has been generated by vgenenvlut draw command\n";
1100   *aFile << "static unsigned int Textures_EnvLUTSize = " << aTableSize << ";\n\n";
1101   *aFile << "static float Textures_EnvLUT[] =\n";
1102   *aFile << "{\n";
1103 
1104   Handle(Image_PixMap) aPixMap = new Image_PixMap();
1105   aPixMap->InitZero (Image_Format_RGF, aTableSize, aTableSize);
1106   Graphic3d_PBRMaterial::GenerateEnvLUT (aPixMap, aNbSamples);
1107 
1108   const Standard_Integer aNumbersInRow = 5;
1109   Standard_Integer aCounter = 0;
1110 
1111   for (int y = 0; y < aTableSize - 1; ++y)
1112   {
1113     aCounter = 0;
1114     for (int x = 0; x < aTableSize; ++x)
1115     {
1116       *aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(aTableSize - 1 - y, x).x()) << ",";
1117       *aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(aTableSize - 1 - y, x).y()) << ",";
1118       if (++aCounter % aNumbersInRow == 0)
1119       {
1120         *aFile << "\n";
1121       }
1122       else if (x != aTableSize - 1)
1123       {
1124         *aFile << " ";
1125       }
1126     }
1127     *aFile << "\n";
1128     if (aTableSize % aNumbersInRow != 0)
1129     {
1130       *aFile << "\n";
1131     }
1132   }
1133 
1134   aCounter = 0;
1135   for (int x = 0; x < aTableSize - 1; ++x)
1136   {
1137     *aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, x).x()) << ",";
1138     *aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, x).y()) << ",";
1139     if (++aCounter % aNumbersInRow == 0)
1140     {
1141       *aFile << "\n";
1142     }
1143     else
1144     {
1145       *aFile << " ";
1146     }
1147   }
1148 
1149   *aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, aTableSize - 1).x()) << ",";
1150   *aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, aTableSize - 1).y()) << "\n";
1151 
1152   *aFile << "};";
1153 
1154   return 0;
1155 }
1156 
1157 //=======================================================================
1158 //function : OpenGlCommands
1159 //purpose  :
1160 //=======================================================================
1161 
OpenGlCommands(Draw_Interpretor & theCommands)1162 void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
1163 {
1164   const char* aGroup ="Commands for low-level TKOpenGl features";
1165 
1166   theCommands.Add("vimmediatefront",
1167     "vimmediatefront : render immediate mode to front buffer or to back buffer",
1168     __FILE__, VImmediateFront, aGroup);
1169   theCommands.Add("vglinfo",
1170                 "vglinfo [-short|-basic|-complete] [-lineWidth Value=80]"
1171         "\n\t\t:         [GL_VENDOR] [GL_RENDERER] [GL_VERSION]"
1172         "\n\t\t:         [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
1173         "\n\t\t: print OpenGL info."
1174         "\n\t\t:  -lineWidth split values longer than specified value into multiple lines;"
1175         "\n\t\t:             -1 disables splitting.",
1176     __FILE__, VGlInfo, aGroup);
1177   theCommands.Add("vshader",
1178                   "vshader name -vert VertexShader -frag FragmentShader [-geom GeometryShader]"
1179                   "\n\t\t:   [-off] [-phong] [-aspect {shading|line|point|text}=shading]"
1180                   "\n\t\t:   [-header VersionHeader]"
1181                   "\n\t\t:   [-tessControl TessControlShader -tesseval TessEvaluationShader]"
1182                   "\n\t\t:   [-uniform Name FloatValue]"
1183                   "\n\t\t: Assign custom GLSL program to presentation aspects.",
1184     __FILE__, VShaderProg, aGroup);
1185   theCommands.Add("vshaderprog", "Alias for vshader", __FILE__, VShaderProg, aGroup);
1186   theCommands.Add("vlistmaterials",
1187                   "vlistmaterials [*] [MaterialName1 [MaterialName2 [...]]] [dump.obj|dump.html]"
1188                   "\n\t\t: Without arguments, command prints the list of standard materials."
1189                   "\n\t\t: Otherwise, properties of specified materials will be printed"
1190                   "\n\t\t: or dumped into specified file."
1191                   "\n\t\t: * can be used to refer to complete list of standard materials.",
1192                   __FILE__, VListMaterials, aGroup);
1193   theCommands.Add("vlistcolors",
1194                   "vlistcolors [*] [ColorName1 [ColorName2 [...]]] [dump.html]"
1195                   "\n\t\t: Without arguments, command prints the list of standard colors."
1196                   "\n\t\t: Otherwise, properties of specified colors will be printed"
1197                   "\n\t\t: or dumped into specified file."
1198                   "\n\t\t: * can be used to refer to complete list of standard colors.",
1199                   __FILE__, VListColors, aGroup);
1200   theCommands.Add("vgenenvlut",
1201                   "vgenenvlut [-size size = 128] [-nbsamples nbsamples = 1024]"
1202                   "\n\t\t: Generates PBR environment look up table."
1203                   "\n\t\t: Saves it as C++ source file which is expected to be included in code."
1204                   "\n\t\t: The path where result will be located is 'Graphic3d_TextureRoot::TexturesFolder()'."
1205                   "\n\t\t:  -size size of one side of resulted square table"
1206                   "\n\t\t:  -nbsamples number of samples used in Monte-Carlo integration",
1207                   __FILE__, VGenEnvLUT, aGroup);
1208 }
1209