0032154: Tests - include vglinfo into Tests Summary
[occt.git] / src / ViewerTest / ViewerTest_OpenGlCommands.cxx
CommitLineData
6aca4d39 1// Created on: 2012-04-09
3946774d 2// Created by: Sergey ANIKIN
6aca4d39 3// Copyright (c) 2012-2014 OPEN CASCADE SAS
3946774d 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
3946774d 6//
d5f74e42 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
973c2be1 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.
3946774d 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
3946774d 15
3946774d 16#include <ViewerTest.hxx>
17
5e27df78 18#include <AIS_InteractiveContext.hxx>
3946774d 19#include <AIS_InteractiveObject.hxx>
20#include <Draw.hxx>
21#include <Draw_Interpretor.hxx>
22#include <Graphic3d_Group.hxx>
392ac980 23#include <Graphic3d_ShaderObject.hxx>
24#include <Graphic3d_ShaderProgram.hxx>
59ee34ef 25#include <Image_AlienPixMap.hxx>
bf5f0ca2 26#include <OpenGl_Aspects.hxx>
3946774d 27#include <OpenGl_Context.hxx>
28#include <OpenGl_Element.hxx>
3946774d 29#include <OpenGl_GlCore20.hxx>
5e27df78 30#include <OpenGl_GraphicDriver.hxx>
8613985b 31#include <OpenGl_ShaderManager.hxx>
3946774d 32#include <OpenGl_Workspace.hxx>
392ac980 33#include <OSD_Environment.hxx>
34#include <OSD_File.hxx>
67312b79 35#include <OSD_OpenFile.hxx>
6262338c 36#include <Prs3d_Drawer.hxx>
3946774d 37#include <Prs3d_Presentation.hxx>
2831708b 38#include <Prs3d_LineAspect.hxx>
392ac980 39#include <Prs3d_ShadingAspect.hxx>
3946774d 40#include <Select3D_SensitiveCurve.hxx>
41#include <SelectMgr_EntityOwner.hxx>
42#include <SelectMgr_Selection.hxx>
43#include <TCollection_AsciiString.hxx>
3c4153af 44#include <V3d_View.hxx>
392ac980 45#include <V3d_Viewer.hxx>
392ac980 46#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
47#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
92efcf78 48#include <OpenGl_Group.hxx>
59ee34ef 49#include <OSD_OpenFile.hxx>
3946774d 50
51extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
52 const Handle(AIS_InteractiveObject)& theAISObj,
53 Standard_Boolean theReplaceIfExists = Standard_True);
392ac980 54extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
3946774d 55
c04c30b3 56namespace {
57
3946774d 58//=======================================================================
59//function : VUserDraw
60//purpose : Checks availability and operation of UserDraw feature
61//=======================================================================
3946774d 62
63class VUserDrawObj : public AIS_InteractiveObject
64{
65public:
66 // CASCADE RTTI
92efcf78 67 DEFINE_STANDARD_RTTI_INLINE(VUserDrawObj,AIS_InteractiveObject);
3946774d 68
69 VUserDrawObj()
70 {
71 myCoords[0] = -10.;
72 myCoords[1] = -20.;
73 myCoords[2] = -30.;
74 myCoords[3] = 10.;
75 myCoords[4] = 20.;
76 myCoords[5] = 30.;
77 }
78
79public:
80 class Element : public OpenGl_Element
81 {
82 private:
83 Handle(VUserDrawObj) myIObj;
84
85 public:
a521d90d 86 Element (const Handle(VUserDrawObj)& theIObj) : myIObj (theIObj) {}
3946774d 87
a521d90d 88 virtual ~Element() {}
3946774d 89
90 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
91 {
92 if (!myIObj.IsNull())
93 myIObj->Render(theWorkspace);
94 }
95
10b9c7df 96 virtual void Release (OpenGl_Context*)
5e27df78 97 {
98 //
99 }
100
3946774d 101 public:
102 DEFINE_STANDARD_ALLOC
103 };
104
105private:
106 // Virtual methods implementation
107 void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
108 const Handle(Prs3d_Presentation)& thePresentation,
79104795 109 const Standard_Integer theMode) Standard_OVERRIDE;
3946774d 110
111 void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
79104795 112 const Standard_Integer theMode) Standard_OVERRIDE;
3946774d 113
114 // Called by VUserDrawElement
115 void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
3946774d 116
a521d90d 117private:
3946774d 118 GLfloat myCoords[6];
3946774d 119 friend class Element;
120};
ec357c5c 121
a521d90d 122void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
123 const Handle(Prs3d_Presentation)& thePrs,
35e08fe8 124 const Standard_Integer /*theMode*/)
3946774d 125{
a521d90d 126 thePrs->Clear();
127
128 Graphic3d_Vec4 aBndMin (myCoords[0], myCoords[1], myCoords[2], 1.0f);
129 Graphic3d_Vec4 aBndMax (myCoords[3], myCoords[4], myCoords[5], 1.0f);
130 Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast (thePrs->NewGroup());
131 aGroup->SetMinMaxValues (aBndMin.x(), aBndMin.y(), aBndMin.z(),
132 aBndMax.x(), aBndMax.y(), aBndMax.z());
2831708b 133 aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
a521d90d 134 VUserDrawObj::Element* anElem = new VUserDrawObj::Element (this);
135 aGroup->AddElement(anElem);
136
137 // invalidate bounding box of the scene
cfece3ef 138 thePrsMgr->StructureManager()->Update();
3946774d 139}
140
141void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
35e08fe8 142 const Standard_Integer /*theMode*/)
3946774d 143{
144 Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
145 Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5);
146 aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
147 aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2]));
148 aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5]));
149 aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5]));
150 aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
151 Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts);
152 theSelection->Add(aSensitive);
153}
154
3946774d 155void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
156{
1136702b 157 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
a521d90d 158
3946774d 159 // To test linking against OpenGl_Workspace and all aspect classes
bf5f0ca2 160 const OpenGl_Aspects* aMA = theWorkspace->Aspects();
161 aMA->Aspect()->MarkerType();
162 OpenGl_Vec4 aColor = theWorkspace->InteriorColor();
3946774d 163
c40eb6b9 164 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID,
165 Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false,
166 Handle(OpenGl_ShaderProgram)());
1136702b 167 aCtx->SetColor4fv (aColor);
168
169 const OpenGl_Vec3 aVertArray[4] =
170 {
171 OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[2]),
172 OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[2]),
173 OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[5]),
174 OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[5]),
175 };
176 Handle(OpenGl_VertexBuffer) aVertBuffer = new OpenGl_VertexBuffer();
177 aVertBuffer->Init (aCtx, 3, 4, aVertArray[0].GetData());
178
3946774d 179 // Finally draw something to make sure UserDraw really works
1136702b 180 aVertBuffer->BindAttribute (aCtx, Graphic3d_TOA_POS);
181 glDrawArrays(GL_LINE_LOOP, 0, aVertBuffer->GetElemsNb());
182 aVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS);
183 aVertBuffer->Release (aCtx.get());
3946774d 184}
185
c04c30b3 186} // end of anonymous namespace
187
23fe70ec 188static Standard_Integer VUserDraw (Draw_Interpretor& ,
3946774d 189 Standard_Integer argc,
190 const char ** argv)
191{
192 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
193 if (aContext.IsNull())
194 {
23fe70ec 195 Message::SendFail ("Error: no active viewer");
3946774d 196 return 1;
197 }
198
dc3fe572 199 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5e27df78 200 if (aDriver.IsNull())
201 {
23fe70ec 202 Message::SendFail ("Error: Graphic driver not available.");
5e27df78 203 return 1;
204 }
205
3946774d 206 if (argc > 2)
207 {
23fe70ec 208 Message::SendFail ("Syntax error: wrong number of arguments");
3946774d 209 return 1;
210 }
211
212 TCollection_AsciiString aName (argv[1]);
213 VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
214
3946774d 215 Handle(VUserDrawObj) anIObj = new VUserDrawObj();
216 VDisplayAISObject(aName, anIObj);
217
218 return 0;
219}
220
1981cb22 221//==============================================================================
222//function : VImmediateFront
223//purpose :
224//==============================================================================
225
35e08fe8 226static int VImmediateFront (Draw_Interpretor& /*theDI*/,
1981cb22 227 Standard_Integer theArgNb,
228 const char** theArgVec)
229{
230 // get the context
231 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
232 if (aContextAIS.IsNull())
233 {
23fe70ec 234 Message::SendFail ("Error: no active viewer");
1981cb22 235 return 1;
236 }
237
dc3fe572 238 Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
1981cb22 239 if (aDriver.IsNull())
240 {
23fe70ec 241 Message::SendFail ("Error: graphic driver not available.");
1981cb22 242 return 1;
243 }
244
245 if (theArgNb < 2)
246 {
23fe70ec 247 Message::SendFail ("Syntax error: wrong number of arguments.");
1981cb22 248 return 1;
249 }
250
c357e426 251 ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0);
252
1981cb22 253 return 0;
254}
255
26d9c835 256//! Search the info from the key.
257inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
258 const TCollection_AsciiString& theKey)
259{
260 for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
261 {
262 if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
263 {
264 return anIter.Value();
265 }
266 }
267 return TCollection_AsciiString();
268}
269
dac04bfa 270//==============================================================================
271//function : VGlInfo
272//purpose :
273//==============================================================================
274
275static int VGlInfo (Draw_Interpretor& theDI,
276 Standard_Integer theArgNb,
277 const char** theArgVec)
278{
279 // get the active view
280 Handle(V3d_View) aView = ViewerTest::CurrentView();
281 if (aView.IsNull())
282 {
23fe70ec 283 Message::SendFail ("No active viewer");
dac04bfa 284 return 1;
285 }
286
26d9c835 287 Graphic3d_DiagnosticInfo anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
72ed0644 288 Standard_Integer aLineWidth = 80;
289 NCollection_Sequence<TCollection_AsciiString> aKeys;
290 TColStd_IndexedDataMapOfStringString aDict;
291 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
dac04bfa 292 {
72ed0644 293 TCollection_AsciiString aName (theArgVec[anArgIter]);
26d9c835 294 aName.LowerCase();
72ed0644 295 TCollection_AsciiString aValue;
26d9c835 296 if (aName == "-short")
4e1523ef 297 {
26d9c835 298 anInfoLevel = Graphic3d_DiagnosticInfo_Short;
299 }
300 else if (aName == "-basic")
301 {
26d9c835 302 anInfoLevel = Graphic3d_DiagnosticInfo_Basic;
4e1523ef 303 }
26d9c835 304 else if (aName == "-complete"
305 || aName == "-full")
306 {
26d9c835 307 anInfoLevel = Graphic3d_DiagnosticInfo_Complete;
308 }
72ed0644 309 else if (anArgIter + 1 < theArgNb
310 && (aName == "-maxwidth"
311 || aName == "-maxlinewidth"
312 || aName == "-linewidth"))
313 {
314 aLineWidth = Draw::Atoi (theArgVec[++anArgIter]);
315 if (aLineWidth < 0)
316 {
317 aLineWidth = IntegerLast();
318 }
319 }
320 else if (aName.Search ("vendor") != -1)
321 {
322 aKeys.Append ("GLvendor");
323 }
324 else if (aName.Search ("renderer") != -1)
325 {
326 aKeys.Append ("GLdevice");
327 }
328 else if (aName.Search ("shading_language_version") != -1
329 || aName.Search ("glsl") != -1)
330 {
331 aKeys.Append ("GLSLversion");
332 }
333 else if (aName.Search ("version") != -1)
334 {
335 aKeys.Append ("GLversion");
336 }
337 else if (aName.Search ("extensions") != -1)
338 {
339 aKeys.Append ("GLextensions");
340 }
341 else if (aName.Search ("extensions") != -1)
342 {
343 aKeys.Append ("GLextensions");
344 }
345 else
346 {
347 Message::SendFail() << "Syntax error: unknown key '" << aName << "'";
348 return 1;
349 }
26d9c835 350 }
351
72ed0644 352 if (aKeys.IsEmpty())
26d9c835 353 {
354 aView->DiagnosticInformation (aDict, anInfoLevel);
355 TCollection_AsciiString aText;
356 for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aDict); aValueIter.More(); aValueIter.Next())
357 {
358 if (!aText.IsEmpty())
359 {
360 aText += "\n";
361 }
72ed0644 362 if ((aValueIter.Key().Length() + aValueIter.Value().Length() + 4) <= aLineWidth)
363 {
364 aText += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value();
365 continue;
366 }
367
368 // split into lines
369 aText += TCollection_AsciiString(" ") + aValueIter.Key() + ":";
370 TCollection_AsciiString aSubList;
371 for (Standard_Integer aTokenIter = 1;; ++aTokenIter)
372 {
373 TCollection_AsciiString aToken = aValueIter.Value().Token (" ", aTokenIter);
374 if (aToken.IsEmpty())
375 {
376 break;
377 }
378
379 if (!aSubList.IsEmpty()
380 && (aSubList.Length() + aToken.Length() + 5) > aLineWidth)
381 {
382 aText += TCollection_AsciiString("\n ") + aSubList;
383 aSubList = aToken;
384 }
385 else
386 {
387 if (!aSubList.IsEmpty())
388 {
389 aSubList += " ";
390 }
391 aSubList += aToken;
392 }
393 }
394 if (!aSubList.IsEmpty())
395 {
396 aText += TCollection_AsciiString("\n ") + aSubList;
397 }
26d9c835 398 }
399
dac04bfa 400 theDI << "OpenGL info:\n"
26d9c835 401 << aText;
dac04bfa 402 return 0;
403 }
404
26d9c835 405 aView->DiagnosticInformation (aDict, Graphic3d_DiagnosticInfo_Complete);
72ed0644 406 for (NCollection_Sequence<TCollection_AsciiString>::Iterator aKeyIter (aKeys); aKeyIter.More(); aKeyIter.Next())
dac04bfa 407 {
72ed0644 408 TCollection_AsciiString aValue = searchInfo (aDict, aKeyIter.Value());
409 if (aKeys.Length() > 1)
dac04bfa 410 {
411 theDI << "{" << aValue << "} ";
412 }
413 else
414 {
415 theDI << aValue;
416 }
417 }
418
419 return 0;
420}
421
8e0a2b19 422//! Parse shader type argument.
423static bool parseShaderTypeArg (Graphic3d_TypeOfShaderObject& theType,
424 const TCollection_AsciiString& theArg)
425{
426 if (theArg == "-vertex"
427 || theArg == "-vert")
428 {
429 theType = Graphic3d_TOS_VERTEX;
430 }
431 else if (theArg == "-tessevaluation"
432 || theArg == "-tesseval"
433 || theArg == "-evaluation"
434 || theArg == "-eval")
435 {
436 theType = Graphic3d_TOS_TESS_EVALUATION;
437 }
438 else if (theArg == "-tesscontrol"
439 || theArg == "-tessctrl"
440 || theArg == "-control"
441 || theArg == "-ctrl")
442 {
443 theType = Graphic3d_TOS_TESS_CONTROL;
444 }
445 else if (theArg == "-geometry"
446 || theArg == "-geom")
447 {
448 theType = Graphic3d_TOS_GEOMETRY;
449 }
450 else if (theArg == "-fragment"
451 || theArg == "-frag")
452 {
453 theType = Graphic3d_TOS_FRAGMENT;
454 }
455 else if (theArg == "-compute"
456 || theArg == "-comp")
457 {
458 theType = Graphic3d_TOS_COMPUTE;
459 }
460 else
461 {
462 return false;
463 }
464 return true;
465}
392ac980 466
467//==============================================================================
468//function : VShaderProg
469//purpose : Sets the pair of vertex and fragment shaders for the object
470//==============================================================================
d95f5ce1 471static Standard_Integer VShaderProg (Draw_Interpretor& theDI,
392ac980 472 Standard_Integer theArgNb,
473 const char** theArgVec)
474{
475 Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
476 if (aCtx.IsNull())
477 {
23fe70ec 478 Message::SendFail ("Error: no active viewer");
392ac980 479 return 1;
480 }
481 else if (theArgNb < 2)
482 {
23fe70ec 483 Message::SendFail ("Syntax error: lack of arguments");
392ac980 484 return 1;
485 }
486
8e0a2b19 487 bool isExplicitShaderType = false;
488 Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram();
489 NCollection_Sequence<Handle(AIS_InteractiveObject)> aPrsList;
490 Graphic3d_GroupAspect aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
491 bool isSetGroupAspect = false;
492 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
392ac980 493 {
8e0a2b19 494 TCollection_AsciiString anArg (theArgVec[anArgIter]);
495 anArg.LowerCase();
496 Graphic3d_TypeOfShaderObject aShaderTypeArg = Graphic3d_TypeOfShaderObject(-1);
0dab5817 497 if (!aProgram.IsNull()
498 && anArg == "-uniform"
499 && anArgIter + 2 < theArgNb)
500 {
501 TCollection_AsciiString aName = theArgVec[++anArgIter];
502 aProgram->PushVariableFloat (aName, float (Draw::Atof (theArgVec[++anArgIter])));
503 }
504 else if (anArg == "-list"
505 || ((anArg == "-update"
506 || anArg == "-dump"
507 || anArg == "-debug"
508 || anArg == "-reload"
509 || anArg == "-load")
510 && anArgIter + 1 < theArgNb))
d95f5ce1 511 {
512 Handle(OpenGl_Context) aGlCtx;
513 if (Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aCtx->CurrentViewer()->Driver()))
514 {
515 aGlCtx = aDriver->GetSharedContext();
516 }
517 if (aGlCtx.IsNull())
518 {
23fe70ec 519 Message::SendFail ("Error: no OpenGl_Context");
d95f5ce1 520 return 1;
521 }
522
523 if (anArg == "-list")
524 {
525 for (OpenGl_Context::OpenGl_ResourcesMap::Iterator aResIter (aGlCtx->SharedResources()); aResIter.More(); aResIter.Next())
526 {
527 if (Handle(OpenGl_ShaderProgram) aResProg = Handle(OpenGl_ShaderProgram)::DownCast (aResIter.Value()))
528 {
529 theDI << aResProg->ResourceId() << " ";
530 }
531 }
532 }
533 else
534 {
535 TCollection_AsciiString aShaderName = theArgVec[++anArgIter];
536 Handle(OpenGl_ShaderProgram) aResProg;
537 if (!aGlCtx->GetResource (aShaderName, aResProg))
538 {
23fe70ec 539 Message::SendFail() << "Syntax error: shader resource '" << aShaderName << "' is not found";
d95f5ce1 540 return 1;
541 }
542 if (aResProg->UpdateDebugDump (aGlCtx, "", false, anArg == "-dump"))
543 {
544 aCtx->UpdateCurrentViewer();
545 }
546 }
547 if (anArgIter + 1 < theArgNb)
548 {
23fe70ec 549 Message::SendFail ("Syntax error: wrong number of arguments");
d95f5ce1 550 return 1;
551 }
552 return 0;
553 }
554 else if (!aProgram.IsNull()
555 && aProgram->ShaderObjects().IsEmpty()
556 && (anArg == "-off"
557 || anArg == "off"))
8e0a2b19 558 {
559 aProgram.Nullify();
560 }
561 else if (!aProgram.IsNull()
562 && aProgram->ShaderObjects().IsEmpty()
563 && (anArg == "-phong"
564 || anArg == "phong"))
565 {
566 const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder();
567 if (aShadersRoot.IsEmpty())
568 {
23fe70ec 569 Message::SendFail("Error: both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
570 "At least one should be defined to load Phong program.");
8e0a2b19 571 return 1;
572 }
ee5befae 573
8e0a2b19 574 const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs";
575 const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs";
576 if (!aSrcVert.IsEmpty()
577 && !OSD_File (aSrcVert).Exists())
578 {
23fe70ec 579 Message::SendFail ("Error: PhongShading.vs is not found");
8e0a2b19 580 return 1;
581 }
582 if (!aSrcFrag.IsEmpty()
583 && !OSD_File (aSrcFrag).Exists())
584 {
23fe70ec 585 Message::SendFail ("Error: PhongShading.fs is not found");
8e0a2b19 586 return 1;
587 }
ee5befae 588
8e0a2b19 589 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
590 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
ee5befae 591 }
8e0a2b19 592 else if (aPrsList.IsEmpty()
593 && anArg == "*")
ee5befae 594 {
8e0a2b19 595 //
392ac980 596 }
8e0a2b19 597 else if (!isSetGroupAspect
598 && anArgIter + 1 < theArgNb
599 && (anArg == "-primtype"
600 || anArg == "-primitivetype"
601 || anArg == "-groupaspect"
602 || anArg == "-aspecttype"
603 || anArg == "-aspect"))
604 {
605 isSetGroupAspect = true;
606 TCollection_AsciiString aPrimTypeStr (theArgVec[++anArgIter]);
607 aPrimTypeStr.LowerCase();
608 if (aPrimTypeStr == "line")
609 {
610 aGroupAspect = Graphic3d_ASPECT_LINE;
611 }
612 else if (aPrimTypeStr == "tris"
613 || aPrimTypeStr == "triangles"
614 || aPrimTypeStr == "fill"
615 || aPrimTypeStr == "fillarea"
616 || aPrimTypeStr == "shading"
617 || aPrimTypeStr == "shade")
618 {
619 aGroupAspect = Graphic3d_ASPECT_FILL_AREA;
620 }
621 else if (aPrimTypeStr == "text")
622 {
623 aGroupAspect = Graphic3d_ASPECT_TEXT;
624 }
625 else if (aPrimTypeStr == "marker"
626 || aPrimTypeStr == "point"
627 || aPrimTypeStr == "pnt")
628 {
629 aGroupAspect = Graphic3d_ASPECT_MARKER;
630 }
631 else
632 {
23fe70ec 633 Message::SendFail() << "Syntax error at '" << aPrimTypeStr << "'";
8e0a2b19 634 return 1;
635 }
392ac980 636 }
8e0a2b19 637 else if (anArgIter + 1 < theArgNb
638 && !aProgram.IsNull()
639 && aProgram->Header().IsEmpty()
640 && (anArg == "-version"
641 || anArg == "-glslversion"
642 || anArg == "-header"
643 || anArg == "-glslheader"))
392ac980 644 {
8e0a2b19 645 TCollection_AsciiString aHeader (theArgVec[++anArgIter]);
646 if (aHeader.IsIntegerValue())
647 {
648 aHeader = TCollection_AsciiString ("#version ") + aHeader;
649 }
650 aProgram->SetHeader (aHeader);
cc8cbabe 651 }
8e0a2b19 652 else if (!anArg.StartsWith ("-")
653 && GetMapOfAIS().IsBound2 (theArgVec[anArgIter]))
cc8cbabe 654 {
8f521168 655 Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (theArgVec[anArgIter]);
8e0a2b19 656 if (anIO.IsNull())
657 {
23fe70ec 658 Message::SendFail() << "Syntax error: " << theArgVec[anArgIter] << " is not an AIS object";
8e0a2b19 659 return 1;
660 }
661 aPrsList.Append (anIO);
392ac980 662 }
8e0a2b19 663 else if (!aProgram.IsNull()
664 && ((anArgIter + 1 < theArgNb && parseShaderTypeArg (aShaderTypeArg, anArg))
665 || (!isExplicitShaderType && aProgram->ShaderObjects().Size() < 2)))
392ac980 666 {
8e0a2b19 667 TCollection_AsciiString aShaderPath (theArgVec[anArgIter]);
668 if (aShaderTypeArg != Graphic3d_TypeOfShaderObject(-1))
392ac980 669 {
8e0a2b19 670 aShaderPath = (theArgVec[++anArgIter]);
671 isExplicitShaderType = true;
fb66bb28 672 }
673
8e0a2b19 674 const bool isSrcFile = OSD_File (aShaderPath).Exists();
675 Handle(Graphic3d_ShaderObject) aShader = isSrcFile
676 ? Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aShaderPath)
677 : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_VERTEX, aShaderPath);
678 const TCollection_AsciiString& aShaderSrc = aShader->Source();
679
680 const bool hasVertPos = aShaderSrc.Search ("gl_Position") != -1;
b17e5bae 681 const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1
682 || aShaderSrc.Search ("occFragColor") != -1
8e0a2b19 683 || aShaderSrc.Search ("gl_FragColor") != -1
684 || aShaderSrc.Search ("gl_FragData") != -1;
685 Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg;
686 if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
fb66bb28 687 {
8e0a2b19 688 if (hasVertPos
689 && !hasFragColor)
690 {
691 aShaderType = Graphic3d_TOS_VERTEX;
692 }
693 if (hasFragColor
694 && !hasVertPos)
695 {
696 aShaderType = Graphic3d_TOS_FRAGMENT;
697 }
392ac980 698 }
8e0a2b19 699 if (aShaderType == Graphic3d_TypeOfShaderObject(-1))
fb66bb28 700 {
23fe70ec 701 Message::SendFail() << "Error: non-existing or invalid shader source";
8e0a2b19 702 return 1;
fb66bb28 703 }
8e0a2b19 704
705 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aShaderType, aShaderSrc));
706 }
707 else
708 {
23fe70ec 709 Message::SendFail() << "Syntax error at '" << anArg << "'";
8e0a2b19 710 return 1;
392ac980 711 }
392ac980 712 }
713
b17e5bae 714 if (!aProgram.IsNull()
715 && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
716 {
717 aProgram->SetNbFragmentOutputs (2);
78c4e836 718 aProgram->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
b17e5bae 719 }
720
8e0a2b19 721 ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
722 NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (aPrsList);
723 const bool isGlobalList = aPrsList.IsEmpty();
724 for (;;)
392ac980 725 {
8e0a2b19 726 Handle(AIS_InteractiveObject) anIO;
727 if (isGlobalList)
392ac980 728 {
8e0a2b19 729 if (!aGlobalPrsIter.More())
730 {
731 break;
732 }
8f521168 733 anIO = aGlobalPrsIter.Key1();
8e0a2b19 734 aGlobalPrsIter.Next();
735 if (anIO.IsNull())
736 {
737 continue;
738 }
392ac980 739 }
8e0a2b19 740 else
392ac980 741 {
8e0a2b19 742 if (!aPrsIter.More())
743 {
744 break;
745 }
746 anIO = aPrsIter.Value();
747 aPrsIter.Next();
392ac980 748 }
fb66bb28 749
8e0a2b19 750 if (anIO->Attributes()->SetShaderProgram (aProgram, aGroupAspect, true))
fb66bb28 751 {
fb66bb28 752 aCtx->Redisplay (anIO, Standard_False);
753 }
754 else
755 {
fb66bb28 756 anIO->SynchronizeAspects();
757 }
392ac980 758 }
759
760 aCtx->UpdateCurrentViewer();
761 return 0;
762}
763
59ee34ef 764//! Print triplet of values.
765template<class S, class T> static S& operator<< (S& theStream, const NCollection_Vec3<T>& theVec)
766{
767 theStream << theVec[0] << " " << theVec[1] << " " << theVec[2];
768 return theStream;
769}
770
771//! Print 4 values.
772template<class S, class T> static S& operator<< (S& theStream, const NCollection_Vec4<T>& theVec)
773{
774 theStream << theVec[0] << " " << theVec[1] << " " << theVec[2] << " " << theVec[3];
775 return theStream;
776}
777
778//! Print fresnel model.
779static const char* fresnelModelString (const Graphic3d_FresnelModel theModel)
780{
781 switch (theModel)
782 {
783 case Graphic3d_FM_SCHLICK: return "SCHLICK";
784 case Graphic3d_FM_CONSTANT: return "CONSTANT";
785 case Graphic3d_FM_CONDUCTOR: return "CONDUCTOR";
786 case Graphic3d_FM_DIELECTRIC: return "DIELECTRIC";
787 }
788 return "N/A";
789}
790
791//! Create a colored rectangle SVG element.
792static TCollection_AsciiString formatSvgColoredRect (const Quantity_Color& theColor)
793{
794 return TCollection_AsciiString()
795 + "<svg width='20px' height='20px'><rect width='20px' height='20px' fill='" + Quantity_Color::ColorToHex (theColor) + "' /></svg>";
796}
797
798//==============================================================================
799//function : VListMaterials
800//purpose :
801//==============================================================================
802static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
803 Standard_Integer theArgNb,
804 const char** theArgVec)
805{
806 TCollection_AsciiString aDumpFile;
807 NCollection_Sequence<Graphic3d_NameOfMaterial> aMatList;
808 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
809 {
810 TCollection_AsciiString anArg (theArgVec[anArgIter]);
811 anArg.LowerCase();
812 Graphic3d_NameOfMaterial aMat = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter]);
a966542b 813 if (aMat != Graphic3d_NameOfMaterial_DEFAULT)
59ee34ef 814 {
815 aMatList.Append (aMat);
816 }
817 else if (anArg == "*")
818 {
a966542b 819 for (Standard_Integer aMatIter = 0; aMatIter < (Standard_Integer )Graphic3d_NameOfMaterial_DEFAULT; ++aMatIter)
59ee34ef 820 {
821 aMatList.Append ((Graphic3d_NameOfMaterial )aMatIter);
822 }
823 }
824 else if (aDumpFile.IsEmpty()
825 && (anArg.EndsWith (".obj")
826 || anArg.EndsWith (".mtl")
827 || anArg.EndsWith (".htm")
828 || anArg.EndsWith (".html")))
829 {
830 aDumpFile = theArgVec[anArgIter];
831 }
832 else
833 {
23fe70ec 834 Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
59ee34ef 835 return 1;
836 }
837 }
838 if (aMatList.IsEmpty())
839 {
840 if (aDumpFile.IsEmpty())
841 {
842 for (Standard_Integer aMatIter = 1; aMatIter <= Graphic3d_MaterialAspect::NumberOfMaterials(); ++aMatIter)
843 {
844 theDI << Graphic3d_MaterialAspect::MaterialName (aMatIter) << " ";
845 }
846 return 0;
847 }
848
a966542b 849 for (Standard_Integer aMatIter = 0; aMatIter < (Standard_Integer )Graphic3d_NameOfMaterial_DEFAULT; ++aMatIter)
59ee34ef 850 {
851 aMatList.Append ((Graphic3d_NameOfMaterial )aMatIter);
852 }
853 }
854
855 // geometry for dumping
856 const Graphic3d_Vec3 aBoxVerts[8] =
857 {
858 Graphic3d_Vec3( 1, -1, -1),
859 Graphic3d_Vec3( 1, -1, 1),
860 Graphic3d_Vec3(-1, -1, 1),
861 Graphic3d_Vec3(-1, -1, -1),
862 Graphic3d_Vec3( 1, 1, -1),
863 Graphic3d_Vec3( 1, 1, 1),
864 Graphic3d_Vec3(-1, 1, 1),
865 Graphic3d_Vec3(-1, 1, -1)
866 };
867
868 const Graphic3d_Vec4i aBoxQuads[6] =
869 {
870 Graphic3d_Vec4i (1, 2, 3, 4),
871 Graphic3d_Vec4i (5, 8, 7, 6),
872 Graphic3d_Vec4i (1, 5, 6, 2),
873 Graphic3d_Vec4i (2, 6, 7, 3),
874 Graphic3d_Vec4i (3, 7, 8, 4),
875 Graphic3d_Vec4i (5, 1, 4, 8)
876 };
877
878 std::ofstream aMatFile, anObjFile, anHtmlFile;
879 if (aDumpFile.EndsWith (".obj")
880 || aDumpFile.EndsWith (".mtl"))
881 {
882 const TCollection_AsciiString aMatFilePath = aDumpFile.SubString (1, aDumpFile.Length() - 3) + "mtl";
883 const TCollection_AsciiString anObjFilePath = aDumpFile.SubString (1, aDumpFile.Length() - 3) + "obj";
884
885 OSD_OpenStream (aMatFile, aMatFilePath.ToCString(), std::ios::out | std::ios::binary);
886 if (!aMatFile.is_open())
887 {
23fe70ec 888 Message::SendFail ("Error: unable creating material file");
59ee34ef 889 return 0;
890 }
891 if (!aDumpFile.EndsWith (".mtl"))
892 {
893 OSD_OpenStream (anObjFile, anObjFilePath.ToCString(), std::ios::out | std::ios::binary);
894 if (!anObjFile.is_open())
895 {
23fe70ec 896 Message::SendFail ("Error: unable creating OBJ file");
59ee34ef 897 return 0;
898 }
899
900 TCollection_AsciiString anMtlName, aFolder;
901 OSD_Path::FolderAndFileFromPath (aMatFilePath, aFolder, anMtlName);
902 anObjFile << "mtllib " << anMtlName << "\n";
903 }
904 }
905 else if (aDumpFile.EndsWith (".htm")
906 || aDumpFile.EndsWith (".html"))
907 {
908 OSD_OpenStream (anHtmlFile, aDumpFile.ToCString(), std::ios::out | std::ios::binary);
909 if (!anHtmlFile.is_open())
910 {
23fe70ec 911 Message::SendFail ("Error: unable creating HTML file");
59ee34ef 912 return 0;
913 }
914 anHtmlFile << "<html>\n"
915 "<head><title>OCCT Material table</title></head>\n"
916 "<body>\n"
917 "<table border='1'><tbody>\n"
918 "<tr>\n"
919 "<th rowspan='2'><div title='Material name.\n"
920 "See also Graphic3d_NameOfMaterial enumeration'>"
921 "Name</div></th>\n"
922 "<th rowspan='2'><div title='Material type: PHYSIC or ASPECT.\n"
923 "ASPECT material does not define final colors, it is taken from Internal Color instead.\n"
924 "See also Graphic3d_TypeOfMaterial enumeration'>"
925 "Type</div></th>\n"
59ee34ef 926 "<th rowspan='2'>Transparency</th>\n"
67312b79 927 "<th colspan='5'><div title='PBR Metallic-Roughness'>"
928 "PBR Metallic-Roughness</div></th>\n"
929 "<th colspan='5'><div title='Common material definition for Phong shading model'>"
930 "Common (Blinn-Phong)</div></th>\n"
931 "<th colspan='10'><div title='BSDF (Bidirectional Scattering Distribution Function).\n"
59ee34ef 932 "Used for physically-based rendering (in path tracing engine).\n"
933 "BSDF is represented as weighted mixture of basic BRDFs/BTDFs (Bidirectional Reflectance (Transmittance) Distribution Functions).\n"
934 "See also Graphic3d_BSDF structure.'>"
67312b79 935 "BSDF (Bidirectional Scattering Distribution Function)</div></th>\n"
59ee34ef 936 "</tr>\n"
937 "<tr>\n"
67312b79 938 "<th>Color</th>\n"
939 "<th>Metallic</th>\n"
940 "<th>Roughness</th>\n"
941 "<th>Emission</th>\n"
942 "<th><div title='Index of refraction'>"
943 "IOR</div></th>\n"
59ee34ef 944 "<th>Ambient</th>\n"
945 "<th>Diffuse</th>\n"
946 "<th>Specular</th>\n"
947 "<th>Emissive</th>\n"
948 "<th>Shiness</th>\n"
949 "<th><div title='Weight of coat specular/glossy BRDF'>"
950 "Kc</div></th>\n"
951 "<th><div title='Weight of base diffuse BRDF'>"
952 "Kd</div></th>\n"
953 "<th><div title='Weight of base specular/glossy BRDF'>"
954 "Ks</div></th>\n"
955 "<th><div title='Weight of base specular/glossy BTDF'>"
956 "Kt</div></th>\n"
957 "<th><div title='Radiance emitted by the surface'>"
958 "Le</div></th>\n"
959 "<th><div title='Volume scattering color/density'>"
960 "Absorption</div></th>\n"
961 "<th><div title='Parameters of Fresnel reflectance of coat layer'>"
962 "FresnelCoat</div></th>\n"
963 "<th><div title='Parameters of Fresnel reflectance of base layer'>"
964 "FresnelBase</div></th>\n"
67312b79 965 "<th>Refraction Index</th>\n"
59ee34ef 966 "</tr>\n";
967 }
968 else if (!aDumpFile.IsEmpty())
969 {
23fe70ec 970 Message::SendFail ("Syntax error: unknown output file format");
59ee34ef 971 return 1;
972 }
973
974 Standard_Integer aMatIndex = 0, anX = 0, anY = 0;
975 for (NCollection_Sequence<Graphic3d_NameOfMaterial>::Iterator aMatIter (aMatList); aMatIter.More(); aMatIter.Next(), ++aMatIndex)
976 {
977 Graphic3d_MaterialAspect aMat (aMatIter.Value());
978 const TCollection_AsciiString aMatName = aMat.StringName();
61168418 979 const Graphic3d_Vec3 anAmbient = (Graphic3d_Vec3 )aMat.AmbientColor();
980 const Graphic3d_Vec3 aDiffuse = (Graphic3d_Vec3 )aMat.DiffuseColor();
981 const Graphic3d_Vec3 aSpecular = (Graphic3d_Vec3 )aMat.SpecularColor();
982 const Graphic3d_Vec3 anEmission = (Graphic3d_Vec3 )aMat.EmissiveColor();
59ee34ef 983 const Standard_Real aShiness = aMat.Shininess() * 1000.0;
984 if (aMatFile.is_open())
985 {
986 aMatFile << "newmtl " << aMatName << "\n";
ba00aab7 987 aMatFile << "Ka " << Quantity_Color::Convert_LinearRGB_To_sRGB (anAmbient) << "\n";
988 aMatFile << "Kd " << Quantity_Color::Convert_LinearRGB_To_sRGB (aDiffuse) << "\n";
989 aMatFile << "Ks " << Quantity_Color::Convert_LinearRGB_To_sRGB (aSpecular) << "\n";
59ee34ef 990 aMatFile << "Ns " << aShiness << "\n";
991 if (aMat.Transparency() >= 0.0001)
992 {
993 aMatFile << "Tr " << aMat.Transparency() << "\n";
994 }
995 aMatFile << "\n";
996 }
997 else if (anHtmlFile.is_open())
998 {
999 anHtmlFile << "<tr>\n";
1000 anHtmlFile << "<td>" << aMat.StringName() << "</td>\n";
1001 anHtmlFile << "<td>" << (aMat.MaterialType() == Graphic3d_MATERIAL_PHYSIC ? "PHYSIC" : "ASPECT") << "</td>\n";
67312b79 1002 anHtmlFile << "<td>" << aMat.Transparency() << "</td>\n";
1003 anHtmlFile << "<td>" << formatSvgColoredRect (aMat.PBRMaterial().Color().GetRGB()) << (Graphic3d_Vec3 )aMat.PBRMaterial().Color().GetRGB() << "</td>\n";
1004 anHtmlFile << "<td>" << aMat.PBRMaterial().Metallic() << "</td>\n";
1005 anHtmlFile << "<td>" << aMat.PBRMaterial().NormalizedRoughness() << "</td>\n";
1006 anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aMat.PBRMaterial().Emission())) << aMat.PBRMaterial().Emission() << "</td>\n";
1007 anHtmlFile << "<td>" << aMat.PBRMaterial().IOR() << "</td>\n";
59ee34ef 1008 anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (anAmbient)) << anAmbient << "</td>\n";
1009 anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aDiffuse)) << aDiffuse << "</td>\n";
1010 anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aSpecular)) << aSpecular << "</td>\n";
1011 anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (anEmission)) << anEmission << "</td>\n";
1012 anHtmlFile << "<td>" << aMat.Shininess() << "</td>\n";
59ee34ef 1013 anHtmlFile << "<td>" << aMat.BSDF().Kc << "</td>\n";
1014 anHtmlFile << "<td>" << aMat.BSDF().Kd << "</td>\n";
1015 anHtmlFile << "<td>" << aMat.BSDF().Ks << "</td>\n";
1016 anHtmlFile << "<td>" << aMat.BSDF().Kt << "</td>\n";
1017 anHtmlFile << "<td>" << aMat.BSDF().Le << "</td>\n";
1018 anHtmlFile << "<td>" << aMat.BSDF().Absorption << "</td>\n";
1019 anHtmlFile << "<td>" << fresnelModelString (aMat.BSDF().FresnelCoat.FresnelType()) << "</td>\n";
1020 anHtmlFile << "<td>" << fresnelModelString (aMat.BSDF().FresnelBase.FresnelType()) << "</td>\n";
67312b79 1021 anHtmlFile << "<td>" << aMat.RefractionIndex() << "</td>\n";
59ee34ef 1022 anHtmlFile << "</tr>\n";
1023 }
1024 else
1025 {
1026 theDI << aMat.StringName() << "\n";
67312b79 1027 theDI << " Transparency: " << aMat.Transparency() << "\n";
1028 theDI << " PBR.BaseColor: " << (Graphic3d_Vec3 )aMat.PBRMaterial().Color().GetRGB() << "\n";
1029 theDI << " PBR.Metallic: " << aMat.PBRMaterial().Metallic() << "\n";
1030 theDI << " PBR.Roughness: " << aMat.PBRMaterial().NormalizedRoughness() << "\n";
1031 theDI << " PBR.Emission: " << aMat.PBRMaterial().Emission() << "\n";
1032 theDI << " PBR.IOR: " << aMat.PBRMaterial().IOR() << "\n";
59ee34ef 1033 theDI << " Common.Ambient: " << anAmbient << "\n";
1034 theDI << " Common.Diffuse: " << aDiffuse << "\n";
1035 theDI << " Common.Specular: " << aSpecular << "\n";
1036 theDI << " Common.Emissive: " << anEmission << "\n";
1037 theDI << " Common.Shiness: " << aMat.Shininess() << "\n";
59ee34ef 1038 theDI << " BSDF.Kc: " << aMat.BSDF().Kc << "\n";
1039 theDI << " BSDF.Kd: " << aMat.BSDF().Kd << "\n";
1040 theDI << " BSDF.Ks: " << aMat.BSDF().Ks << "\n";
1041 theDI << " BSDF.Kt: " << aMat.BSDF().Kt << "\n";
1042 theDI << " BSDF.Le: " << aMat.BSDF().Le << "\n";
1043 theDI << " BSDF.Absorption: " << aMat.BSDF().Absorption << "\n";
1044 theDI << " BSDF.FresnelCoat: " << fresnelModelString (aMat.BSDF().FresnelCoat.FresnelType()) << "\n";
1045 theDI << " BSDF.FresnelBase: " << fresnelModelString (aMat.BSDF().FresnelBase.FresnelType()) << "\n";
67312b79 1046 theDI << " RefractionIndex: " << aMat.RefractionIndex() << "\n";
59ee34ef 1047 }
1048
1049 if (anObjFile.is_open())
1050 {
1051 anObjFile << "g " << aMatName << "\n";
1052 anObjFile << "usemtl " << aMatName << "\n";
1053 for (Standard_Integer aVertIter = 0; aVertIter < 8; ++aVertIter)
1054 {
1055 anObjFile << "v " << (aBoxVerts[aVertIter] + Graphic3d_Vec3 (3.0f * anX, -3.0f * anY, 0.0f)) << "\n";
1056 }
1057 anObjFile << "s off\n";
1058 for (Standard_Integer aFaceIter = 0; aFaceIter < 6; ++aFaceIter)
1059 {
1060 anObjFile << "f " << (aBoxQuads[aFaceIter] + Graphic3d_Vec4i (8 * aMatIndex)) << "\n";
1061 }
1062 anObjFile << "\n";
1063 if (++anX > 5)
1064 {
1065 anX = 0;
1066 ++anY;
1067 }
1068 }
1069 }
1070
1071 if (anHtmlFile.is_open())
1072 {
1073 anHtmlFile << "</tbody></table>\n</body>\n</html>\n";
1074 }
1075 return 0;
1076}
1077
1078//==============================================================================
1079//function : VListColors
1080//purpose :
1081//==============================================================================
1082static Standard_Integer VListColors (Draw_Interpretor& theDI,
1083 Standard_Integer theArgNb,
1084 const char** theArgVec)
1085{
1086 TCollection_AsciiString aDumpFile;
1087 NCollection_Sequence<Quantity_NameOfColor> aColList;
1088 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1089 {
1090 TCollection_AsciiString anArg (theArgVec[anArgIter]);
1091 anArg.LowerCase();
1092 Quantity_NameOfColor aName;
1093 if (Quantity_Color::ColorFromName (theArgVec[anArgIter], aName))
1094 {
1095 aColList.Append (aName);
1096 }
1097 else if (anArg == "*")
1098 {
1099 for (Standard_Integer aColIter = 0; aColIter <= (Standard_Integer )Quantity_NOC_WHITE; ++aColIter)
1100 {
1101 aColList.Append ((Quantity_NameOfColor )aColIter);
1102 }
1103 }
1104 else if (aDumpFile.IsEmpty()
1105 && (anArg.EndsWith (".htm")
1106 || anArg.EndsWith (".html")))
1107 {
1108 aDumpFile = theArgVec[anArgIter];
1109 }
1110 else
1111 {
23fe70ec 1112 Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
59ee34ef 1113 return 1;
1114 }
1115 }
1116 if (aColList.IsEmpty())
1117 {
1118 if (aDumpFile.IsEmpty())
1119 {
1120 for (Standard_Integer aColIter = 0; aColIter <= (Standard_Integer )Quantity_NOC_WHITE; ++aColIter)
1121 {
1122 theDI << Quantity_Color::StringName (Quantity_NameOfColor (aColIter)) << " ";
1123 }
1124 return 0;
1125 }
1126
1127 for (Standard_Integer aColIter = 0; aColIter <= (Standard_Integer )Quantity_NOC_WHITE; ++aColIter)
1128 {
1129 aColList.Append ((Quantity_NameOfColor )aColIter);
1130 }
1131 }
1132
1133 std::ofstream anHtmlFile;
1134 TCollection_AsciiString aFileNameBase, aFolder;
1135 if (aDumpFile.EndsWith (".htm")
1136 || aDumpFile.EndsWith (".html"))
1137 {
1138 OSD_Path::FolderAndFileFromPath (aDumpFile, aFolder, aFileNameBase);
1139 aFileNameBase = aFileNameBase.SubString (1, aFileNameBase.Length() - (aDumpFile.EndsWith (".htm") ? 4 : 5));
1140 }
1141 else if (!aDumpFile.IsEmpty())
1142 {
23fe70ec 1143 Message::SendFail ("Syntax error: unknown output file format");
59ee34ef 1144 return 1;
1145 }
1146
1147 Standard_Integer aMaxNameLen = 1;
1148 for (NCollection_Sequence<Quantity_NameOfColor>::Iterator aColIter (aColList); aColIter.More(); aColIter.Next())
1149 {
1150 aMaxNameLen = Max (aMaxNameLen, TCollection_AsciiString (Quantity_Color::StringName (aColIter.Value())).Length());
1151 }
1152
1153 V3d_ImageDumpOptions anImgParams;
1154 anImgParams.Width = 60;
1155 anImgParams.Height = 30;
1156 anImgParams.BufferType = Graphic3d_BT_RGB;
1157 anImgParams.StereoOptions = V3d_SDO_MONO;
1158 anImgParams.ToAdjustAspect = Standard_True;
1159 Handle(V3d_View) aView;
1160 if (!aDumpFile.IsEmpty())
1161 {
1162 ViewerTest::ViewerInit (0, 0, anImgParams.Width, anImgParams.Height, "TmpDriver/TmpViewer/TmpView");
1163 aView = ViewerTest::CurrentView();
1164 aView->SetImmediateUpdate (false);
1165 aView->SetBgGradientStyle (Aspect_GFM_NONE, false);
1166 }
1167
1168 if (!aDumpFile.IsEmpty())
1169 {
1170 OSD_OpenStream (anHtmlFile, aDumpFile.ToCString(), std::ios::out | std::ios::binary);
1171 if (!anHtmlFile.is_open())
1172 {
23fe70ec 1173 Message::SendFail ("Error: unable creating HTML file");
59ee34ef 1174 return 0;
1175 }
1176 anHtmlFile << "<html>\n"
1177 << "<head><title>OCCT Color table</title></head>\n"
1178 << "<body>\n"
1179 << "<table border='1'><tbody>\n"
1180 << "<tr>\n"
1181 << "<th>HTML</th>\n"
1182 << "<th>OCCT</th>\n"
1183 << "<th>Color name</th>\n"
1184 << "<th>sRGB hex</th>\n"
1185 << "<th>sRGB dec</th>\n"
1186 << "<th>RGB linear</th>\n"
1187 << "</tr>\n";
1188 }
1189
1190 Image_AlienPixMap anImg;
1191 Standard_Integer aColIndex = 0;
1192 for (NCollection_Sequence<Quantity_NameOfColor>::Iterator aColIter (aColList); aColIter.More(); aColIter.Next(), ++aColIndex)
1193 {
1194 Quantity_Color aCol (aColIter.Value());
1195 const TCollection_AsciiString aColName = Quantity_Color::StringName (aColIter.Value());
1196 const TCollection_AsciiString anSRgbHex = Quantity_Color::ColorToHex (aCol);
1197 const Graphic3d_Vec3i anSRgbInt ((Graphic3d_Vec3 )aCol * 255.0f);
1198 if (anHtmlFile.is_open())
1199 {
1200 const TCollection_AsciiString anImgPath = aFileNameBase + "_" + aColName + ".png";
1201 if (!aView.IsNull())
1202 {
1203 aView->SetImmediateUpdate (false);
1204 aView->SetBackgroundColor (aCol);
1205 if (!aView->ToPixMap (anImg, anImgParams)
1206 || !anImg.Save (aFolder + anImgPath))
1207 {
1208 theDI << "Error: image dump failed\n";
1209 return 0;
1210 }
1211 }
1212
1213 anHtmlFile << "<tr>\n";
1214 anHtmlFile << "<td style='background-color:" << anSRgbHex << "'><pre> </pre></td>\n";
1215 anHtmlFile << "<td><img src='" << (!aView.IsNull() ? anImgPath : "") << "'></img></td>\n";
1216 anHtmlFile << "<td style='text-align:left'>" << aColName << "</td>\n";
1217 anHtmlFile << "<td style='text-align:left'><pre>" << anSRgbHex << "</pre></td>\n";
1218 anHtmlFile << "<td style='text-align:left'>(" << anSRgbInt.r() << " " << anSRgbInt.g() << " " << anSRgbInt.b() << ")</td>\n";
1219 anHtmlFile << "<td style='text-align:left'>(" << aCol.Red() << " " << aCol.Green() << " " << aCol.Blue() << ")</td>\n";
1220 anHtmlFile << "</tr>\n";
1221 }
1222 else
1223 {
1224 TCollection_AsciiString aColNameLong (aColName);
1225 aColNameLong.RightJustify (aMaxNameLen, ' ');
1226 theDI << aColNameLong << " [" << anSRgbHex << "]: " << aCol.Red() << " " << aCol.Green() << " " << aCol.Blue() << "\n";
1227 }
1228 }
1229
1230 if (!aView.IsNull())
1231 {
1232 ViewerTest::RemoveView (aView);
1233 }
1234
1235 if (anHtmlFile.is_open())
1236 {
1237 anHtmlFile << "</tbody></table>\n</body>\n</html>\n";
1238 }
1239 return 0;
1240}
1241
67312b79 1242//==============================================================================
1243//function : envlutWriteToFile
1244//purpose :
1245//==============================================================================
1246static std::string envLutWriteToFile (Standard_ShortReal theValue)
1247{
1248 std::stringstream aStream;
1249 aStream << theValue;
1250 if (aStream.str().length() == 1)
1251 {
1252 aStream << '.';
1253 }
1254 aStream << 'f';
1255 return aStream.str();
1256}
1257
1258//==============================================================================
1259//function : VGenEnvLUT
1260//purpose :
1261//==============================================================================
1262static Standard_Integer VGenEnvLUT (Draw_Interpretor&,
1263 Standard_Integer theArgNb,
1264 const char** theArgVec)
1265{
1266 Standard_Integer aTableSize = -1;
1267 Standard_Integer aNbSamples = -1;
1268 TCollection_AsciiString aFilePath = Graphic3d_TextureRoot::TexturesFolder() + "/Textures_EnvLUT.pxx";
1269
1270 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1271 {
1272 TCollection_AsciiString anArg(theArgVec[anArgIter]);
1273 anArg.LowerCase();
1274
1275 if (anArg == "-size"
1276 || anArg == "-s")
1277 {
1278 if (anArgIter + 1 >= theArgNb)
1279 {
23fe70ec 1280 Message::SendFail ("Syntax error: size of PBR environment look up table is undefined");
67312b79 1281 return 1;
1282 }
1283
1284 aTableSize = Draw::Atoi(theArgVec[++anArgIter]);
1285
1286 if (aTableSize < 16)
1287 {
23fe70ec 1288 Message::SendFail ("Error: size of PBR environment look up table must be greater or equal 16");
67312b79 1289 return 1;
1290 }
1291 }
1292 else if (anArg == "-nbsamples"
1293 || anArg == "-samples")
1294 {
1295 if (anArgIter + 1 >= theArgNb)
1296 {
23fe70ec 1297 Message::SendFail ("Syntax error: number of samples to generate PBR environment look up table is undefined");
67312b79 1298 return 1;
1299 }
1300
1301 aNbSamples = Draw::Atoi(theArgVec[++anArgIter]);
1302
1303 if (aNbSamples < 1)
1304 {
23fe70ec 1305 Message::SendFail ("Syntax error: number of samples to generate PBR environment look up table must be greater than 1");
67312b79 1306 return 1;
1307 }
1308 }
1309 else
1310 {
23fe70ec 1311 Message::SendFail() << "Syntax error: unknown argument " << anArg;
67312b79 1312 return 1;
1313 }
1314 }
1315
1316 if (aTableSize < 0)
1317 {
1318 aTableSize = 128;
1319 }
1320
1321 if (aNbSamples < 0)
1322 {
1323 aNbSamples = 1024;
1324 }
1325
1326 std::ofstream aFile;
1327
1328 OSD_OpenStream (aFile, aFilePath, std::ios::out | std::ios::binary);
1329
1330 if (!aFile.good())
1331 {
23fe70ec 1332 Message::SendFail() << "Error: unable to write to " << aFilePath;
67312b79 1333 return 1;
1334 }
1335
1336 aFile << "//this file has been generated by vgenenvlut draw command\n";
1337 aFile << "static unsigned int Textures_EnvLUTSize = " << aTableSize << ";\n\n";
1338 aFile << "static float Textures_EnvLUT[] =\n";
1339 aFile << "{\n";
1340
1341 Handle(Image_PixMap) aPixMap = new Image_PixMap();
1342 aPixMap->InitZero (Image_Format_RGF, aTableSize, aTableSize);
1343 Graphic3d_PBRMaterial::GenerateEnvLUT (aPixMap, aNbSamples);
1344
1345 const Standard_Integer aNumbersInRow = 5;
1346 Standard_Integer aCounter = 0;
1347
1348 for (int y = 0; y < aTableSize - 1; ++y)
1349 {
1350 aCounter = 0;
1351 for (int x = 0; x < aTableSize; ++x)
1352 {
1353 aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(aTableSize - 1 - y, x).x()) << ",";
1354 aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(aTableSize - 1 - y, x).y()) << ",";
1355 if (++aCounter % aNumbersInRow == 0)
1356 {
1357 aFile << "\n";
1358 }
1359 else if (x != aTableSize - 1)
1360 {
1361 aFile << " ";
1362 }
1363 }
1364 aFile << "\n";
1365 if (aTableSize % aNumbersInRow != 0)
1366 {
1367 aFile << "\n";
1368 }
1369 }
1370
1371 aCounter = 0;
1372 for (int x = 0; x < aTableSize - 1; ++x)
1373 {
1374 aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, x).x()) << ",";
1375 aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, x).y()) << ",";
1376 if (++aCounter % aNumbersInRow == 0)
1377 {
1378 aFile << "\n";
1379 }
1380 else
1381 {
1382 aFile << " ";
1383 }
1384 }
1385
1386 aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, aTableSize - 1).x()) << ",";
1387 aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, aTableSize - 1).y()) << "\n";
1388
1389 aFile << "};";
1390 aFile.close();
1391
1392 return 0;
1393}
1394
3946774d 1395//=======================================================================
1396//function : OpenGlCommands
1397//purpose :
1398//=======================================================================
1399
1400void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
1401{
1402 const char* aGroup ="Commands for low-level TKOpenGl features";
1403
1404 theCommands.Add("vuserdraw",
1405 "vuserdraw : name - simulates drawing with help of UserDraw",
1406 __FILE__, VUserDraw, aGroup);
1981cb22 1407 theCommands.Add("vimmediatefront",
1408 "vimmediatefront : render immediate mode to front buffer or to back buffer",
1409 __FILE__, VImmediateFront, aGroup);
dac04bfa 1410 theCommands.Add("vglinfo",
72ed0644 1411 "vglinfo [-short|-basic|-complete] [-lineWidth Value=80]"
26d9c835 1412 "\n\t\t: [GL_VENDOR] [GL_RENDERER] [GL_VERSION]"
1413 "\n\t\t: [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
72ed0644 1414 "\n\t\t: print OpenGL info."
1415 "\n\t\t: -lineWidth split values longer than specified value into multiple lines;"
1416 "\n\t\t: -1 disables splitting.",
dac04bfa 1417 __FILE__, VGlInfo, aGroup);
8e0a2b19 1418 theCommands.Add("vshader",
1419 "vshader name -vert VertexShader -frag FragmentShader [-geom GeometryShader]"
1420 "\n\t\t: [-off] [-phong] [-aspect {shading|line|point|text}=shading]"
1421 "\n\t\t: [-header VersionHeader]"
1422 "\n\t\t: [-tessControl TessControlShader -tesseval TessEvaluationShader]"
0dab5817 1423 "\n\t\t: [-uniform Name FloatValue]"
d95f5ce1 1424 "\n\t\t: Assign custom GLSL program to presentation aspects."
1425 "\nvshader [-list] [-dump] [-reload] ShaderId"
1426 "\n\t\t: -list prints the list of registered GLSL programs"
1427 "\n\t\t: -dump dumps specified GLSL program (for debugging)"
1428 "\n\t\t: -reload restores dump of specified GLSL program",
392ac980 1429 __FILE__, VShaderProg, aGroup);
8e0a2b19 1430 theCommands.Add("vshaderprog", "Alias for vshader", __FILE__, VShaderProg, aGroup);
59ee34ef 1431 theCommands.Add("vlistmaterials",
1432 "vlistmaterials [*] [MaterialName1 [MaterialName2 [...]]] [dump.obj|dump.html]"
1433 "\n\t\t: Without arguments, command prints the list of standard materials."
1434 "\n\t\t: Otherwise, properties of specified materials will be printed"
1435 "\n\t\t: or dumped into specified file."
1436 "\n\t\t: * can be used to refer to complete list of standard materials.",
1437 __FILE__, VListMaterials, aGroup);
1438 theCommands.Add("vlistcolors",
1439 "vlistcolors [*] [ColorName1 [ColorName2 [...]]] [dump.html]"
1440 "\n\t\t: Without arguments, command prints the list of standard colors."
1441 "\n\t\t: Otherwise, properties of specified colors will be printed"
1442 "\n\t\t: or dumped into specified file."
1443 "\n\t\t: * can be used to refer to complete list of standard colors.",
1444 __FILE__, VListColors, aGroup);
67312b79 1445 theCommands.Add("vgenenvlut",
1446 "vgenenvlut [-size size = 128] [-nbsamples nbsamples = 1024]"
1447 "\n\t\t: Generates PBR environment look up table."
1448 "\n\t\t: Saves it as C++ source file which is expected to be included in code."
1449 "\n\t\t: The path where result will be located is 'Graphic3d_TextureRoot::TexturesFolder()'."
1450 "\n\t\t: -size size of one side of resulted square table"
1451 "\n\t\t: -nbsamples number of samples used in Monte-Carlo integration",
1452 __FILE__, VGenEnvLUT, aGroup);
3946774d 1453}