1 // Created on: 2012-04-09
2 // Created by: Sergey ANIKIN
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <ViewerTest.hxx>
18 #include <AIS_InteractiveContext.hxx>
19 #include <AIS_InteractiveObject.hxx>
21 #include <Draw_Interpretor.hxx>
22 #include <Graphic3d_Group.hxx>
23 #include <Graphic3d_ShaderObject.hxx>
24 #include <Graphic3d_ShaderProgram.hxx>
25 #include <OpenGl_AspectFace.hxx>
26 #include <OpenGl_AspectLine.hxx>
27 #include <OpenGl_AspectMarker.hxx>
28 #include <OpenGl_AspectText.hxx>
29 #include <OpenGl_Context.hxx>
30 #include <OpenGl_Element.hxx>
31 #include <OpenGl_GlCore20.hxx>
32 #include <OpenGl_GraphicDriver.hxx>
33 #include <OpenGl_Workspace.hxx>
34 #include <OSD_Environment.hxx>
35 #include <OSD_File.hxx>
36 #include <Prs3d_Drawer.hxx>
37 #include <Prs3d_Presentation.hxx>
38 #include <Prs3d_Root.hxx>
39 #include <Prs3d_LineAspect.hxx>
40 #include <Prs3d_ShadingAspect.hxx>
41 #include <Select3D_SensitiveCurve.hxx>
42 #include <SelectMgr_EntityOwner.hxx>
43 #include <SelectMgr_Selection.hxx>
44 #include <TCollection_AsciiString.hxx>
45 #include <V3d_View.hxx>
46 #include <V3d_Viewer.hxx>
47 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
48 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
49 #include <OpenGl_Group.hxx>
51 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
52 const Handle(AIS_InteractiveObject)& theAISObj,
53 Standard_Boolean theReplaceIfExists = Standard_True);
54 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
58 //=======================================================================
59 //function : VUserDraw
60 //purpose : Checks availability and operation of UserDraw feature
61 //=======================================================================
63 class VUserDrawObj : public AIS_InteractiveObject
67 DEFINE_STANDARD_RTTI_INLINE(VUserDrawObj,AIS_InteractiveObject);
80 class Element : public OpenGl_Element
83 Handle(VUserDrawObj) myIObj;
86 Element (const Handle(VUserDrawObj)& theIObj) : myIObj (theIObj) {}
90 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
93 myIObj->Render(theWorkspace);
96 virtual void Release (OpenGl_Context*)
102 DEFINE_STANDARD_ALLOC
106 // Virtual methods implementation
107 void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
108 const Handle(Prs3d_Presentation)& thePresentation,
109 const Standard_Integer theMode) Standard_OVERRIDE;
111 void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
112 const Standard_Integer theMode) Standard_OVERRIDE;
114 // Called by VUserDrawElement
115 void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
119 friend class Element;
122 void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
123 const Handle(Prs3d_Presentation)& thePrs,
124 const Standard_Integer /*theMode*/)
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());
133 aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
134 VUserDrawObj::Element* anElem = new VUserDrawObj::Element (this);
135 aGroup->AddElement(anElem);
137 // invalidate bounding box of the scene
138 thePrsMgr->StructureManager()->Update (thePrsMgr->StructureManager()->UpdateMode());
141 void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
142 const Standard_Integer /*theMode*/)
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);
155 void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
157 // this sample does not use GLSL programs - make sure it is disabled
158 Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
159 aCtx->BindProgram (NULL);
161 // To test linking against OpenGl_Workspace and all aspect classes
162 const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker();
164 const OpenGl_AspectText* aTA = theWorkspace->AspectText();
166 TEL_COLOUR aColor = theWorkspace->LineColor();
168 // Finally draw something to make sure UserDraw really works
169 glPushAttrib(GL_ENABLE_BIT);
170 glDisable(GL_LIGHTING);
171 glColor4fv(aColor.rgb);
172 glBegin(GL_LINE_LOOP);
173 glVertex3f(myCoords[0], myCoords[1], myCoords[2]);
174 glVertex3f(myCoords[3], myCoords[4], myCoords[2]);
175 glVertex3f(myCoords[3], myCoords[4], myCoords[5]);
176 glVertex3f(myCoords[0], myCoords[1], myCoords[5]);
181 } // end of anonymous namespace
183 static Standard_Integer VUserDraw (Draw_Interpretor& di,
184 Standard_Integer argc,
187 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
188 if (aContext.IsNull())
190 di << argv[0] << "Call 'vinit' before!\n";
194 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
195 if (aDriver.IsNull())
197 std::cerr << "Graphic driver not available.\n";
203 di << argv[0] << "Wrong number of arguments, only the object name expected\n";
207 TCollection_AsciiString aName (argv[1]);
208 VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
210 Handle(VUserDrawObj) anIObj = new VUserDrawObj();
211 VDisplayAISObject(aName, anIObj);
216 //==============================================================================
217 //function : VFeedback
219 //==============================================================================
221 static int VFeedback (Draw_Interpretor& theDI,
222 Standard_Integer /*theArgNb*/,
223 const char** /*theArgVec*/)
225 // get the active view
226 Handle(V3d_View) aView = ViewerTest::CurrentView();
229 std::cerr << "No active view. Please call vinit.\n";
233 unsigned int aBufferSize = 1024 * 1024;
236 size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat);
237 if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize)
239 // finito la commedia
240 std::cerr << "Can not allocate buffer - requested size ("
241 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
242 << " MiB) is out of address space\n";
246 GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes);
249 // finito la commedia
250 std::cerr << "Can not allocate buffer with size ("
251 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
256 glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer);
257 glRenderMode (GL_FEEDBACK);
261 GLint aResult = glRenderMode (GL_RENDER);
266 void* aPtr = aBuffer;
267 Standard::Free (aPtr);
272 std::cout << "FeedBack result= " << aResult << "\n";
279 GLint aBitmapsNb = 0;
280 GLint aPassThrNb = 0;
281 GLint aUnknownNb = 0;
282 const GLint NODE_VALUES = 2; // GL_2D
283 for (GLint anIter = 0; anIter < aResult;)
285 const GLfloat aPos = aBuffer[anIter];
286 switch ((GLint )aPos)
292 anIter += 1 + NODE_VALUES;
295 case GL_LINE_RESET_TOKEN:
300 anIter += 1 + 2 * NODE_VALUES;
303 case GL_POLYGON_TOKEN:
305 const GLint aCount = (GLint )aBuffer[++anIter];
307 anIter += aCount * NODE_VALUES + 1;
312 else if (aCount == 4)
322 case GL_BITMAP_TOKEN:
323 case GL_DRAW_PIXEL_TOKEN:
324 case GL_COPY_PIXEL_TOKEN:
327 anIter += 1 + NODE_VALUES;
330 case GL_PASS_THROUGH_TOKEN:
333 anIter += 2; // header + value
344 void* aPtr = aBuffer;
345 Standard::Free (aPtr);
348 theDI << "Total nodes: " << aNodesNb << "\n"
349 << "Points: " << aPntNb << "\n"
350 << "Line segments: " << aLinesNb << "\n"
351 << "Triangles: " << aTriNb << "\n"
352 << "Quads: " << aQuadsNb << "\n"
353 << "Polygons: " << aPolyNb << "\n"
354 << "Bitmap tokens: " << aBitmapsNb << "\n"
355 << "Pass through: " << aPassThrNb << "\n"
356 << "UNKNOWN: " << aUnknownNb << "\n";
358 double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
359 double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
360 double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
361 theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
362 << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
363 << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n";
368 //==============================================================================
369 //function : VImmediateFront
371 //==============================================================================
373 static int VImmediateFront (Draw_Interpretor& /*theDI*/,
374 Standard_Integer theArgNb,
375 const char** theArgVec)
378 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
379 if (aContextAIS.IsNull())
381 std::cerr << "No active view. Please call vinit.\n";
385 Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
387 if (aDriver.IsNull())
389 std::cerr << "Graphic driver not available.\n";
395 std::cerr << "Wrong number of arguments.\n";
399 ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0);
404 //==============================================================================
407 //==============================================================================
409 static int VGlInfo (Draw_Interpretor& theDI,
410 Standard_Integer theArgNb,
411 const char** theArgVec)
413 // get the active view
414 Handle(V3d_View) aView = ViewerTest::CurrentView();
417 std::cerr << "No active view. Please call vinit.\n";
423 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
424 if (aDriver.IsNull())
426 std::cerr << "Error: view does not use OpenGL.\n";
429 Handle(OpenGl_Context) aCtx = aDriver->GetSharedContext();
430 Standard_CString aDebugInfo = !aCtx.IsNull() && aCtx->IsDebugContext()
433 theDI << "OpenGL info:\n"
434 << " GLvendor = '" << (const char* )glGetString(GL_VENDOR) << "'\n"
435 << " GLdevice = '" << (const char* )glGetString(GL_RENDERER) << "'\n"
436 << " GLversion = '" << (const char* )glGetString(GL_VERSION) << "'\n"
437 << " GLSLversion = '" << (const char* )glGetString(GL_SHADING_LANGUAGE_VERSION) << "'\n"
442 const Standard_Boolean isList = theArgNb >= 3;
443 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
445 TCollection_AsciiString aName (theArgVec[anIter]);
447 const char* aValue = NULL;
448 if (aName.Search ("VENDOR") != -1)
450 aValue = (const char* )glGetString (GL_VENDOR);
452 else if (aName.Search ("RENDERER") != -1)
454 aValue = (const char* )glGetString (GL_RENDERER);
456 else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1
457 || aName.Search ("GLSL") != -1)
459 aValue = (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION);
461 else if (aName.Search ("VERSION") != -1)
463 aValue = (const char* )glGetString (GL_VERSION);
465 else if (aName.Search ("EXTENSIONS") != -1)
467 aValue = (const char* )glGetString (GL_EXTENSIONS);
471 std::cerr << "Unknown key '" << aName.ToCString() << "'\n";
477 theDI << "{" << aValue << "} ";
489 //==============================================================================
490 //function : VShaderProg
491 //purpose : Sets the pair of vertex and fragment shaders for the object
492 //==============================================================================
493 static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
494 Standard_Integer theArgNb,
495 const char** theArgVec)
497 Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
500 std::cerr << "Use 'vinit' command before " << theArgVec[0] << "\n";
503 else if (theArgNb < 2)
505 std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
509 TCollection_AsciiString aLastArg (theArgVec[theArgNb - 1]);
510 aLastArg.UpperCase();
511 const Standard_Boolean toTurnOff = aLastArg == "OFF";
512 Standard_Integer anArgsNb = theArgNb - 1;
513 Handle(Graphic3d_ShaderProgram) aProgram;
515 && aLastArg == "PHONG")
517 aProgram = new Graphic3d_ShaderProgram (Graphic3d_ShaderProgram::ShaderName_Phong);
520 && aProgram.IsNull())
524 std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
528 const TCollection_AsciiString aSrcVert = theArgVec[theArgNb - 2];
529 const TCollection_AsciiString aSrcFrag = theArgVec[theArgNb - 1];
530 if (!aSrcVert.IsEmpty()
531 && !OSD_File (aSrcVert).Exists())
533 std::cerr << "Non-existing vertex shader source\n";
536 if (!aSrcFrag.IsEmpty()
537 && !OSD_File (aSrcFrag).Exists())
539 std::cerr << "Non-existing fragment shader source\n";
543 aProgram = new Graphic3d_ShaderProgram();
544 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
545 aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
546 anArgsNb = theArgNb - 2;
549 Handle(AIS_InteractiveObject) anIO;
551 || *theArgVec[1] == '*')
553 for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
554 anIter.More(); anIter.Next())
556 anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
559 anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
560 aCtx->Redisplay (anIO, Standard_False);
563 aCtx->UpdateCurrentViewer();
567 for (Standard_Integer anArgIter = 1; anArgIter < anArgsNb; ++anArgIter)
569 const TCollection_AsciiString aName (theArgVec[anArgIter]);
570 if (!GetMapOfAIS().IsBound2 (aName))
572 std::cerr << "Warning: " << aName.ToCString() << " is not displayed\n";
575 anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
578 std::cerr << "Warning: " << aName.ToCString() << " is not an AIS object\n";
581 anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
582 aCtx->Redisplay (anIO, Standard_False);
585 aCtx->UpdateCurrentViewer();
589 //=======================================================================
590 //function : OpenGlCommands
592 //=======================================================================
594 void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
596 const char* aGroup ="Commands for low-level TKOpenGl features";
598 theCommands.Add("vuserdraw",
599 "vuserdraw : name - simulates drawing with help of UserDraw",
600 __FILE__, VUserDraw, aGroup);
601 theCommands.Add("vfeedback",
602 "vfeedback : perform test GL feedback rendering",
603 __FILE__, VFeedback, aGroup);
604 theCommands.Add("vimmediatefront",
605 "vimmediatefront : render immediate mode to front buffer or to back buffer",
606 __FILE__, VImmediateFront, aGroup);
607 theCommands.Add("vglinfo",
608 "vglinfo [GL_VENDOR] [GL_RENDERER] [GL_VERSION] [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
610 __FILE__, VGlInfo, aGroup);
611 theCommands.Add("vshaderprog",
612 " 'vshaderprog [name] pathToVertexShader pathToFragmentShader'"
613 "\n\t\t: or 'vshaderprog [name] off' to disable GLSL program"
614 "\n\t\t: or 'vshaderprog [name] phong' to enable per-pixel lighting calculations"
615 "\n\t\t: * might be used to specify all displayed objects",
616 __FILE__, VShaderProg, aGroup);