0023947: Eliminate trivial compiler warnings in MSVC++ with warning level 4
[occt.git] / src / ViewerTest / ViewerTest_OpenGlCommands.cxx
1 // Created on: 2012-04-09
2 // Created by: Sergey ANIKIN
3 // Copyright (c) 2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <ViewerTest.hxx>
25
26 #include <AIS_InteractiveContext.hxx>
27 #include <AIS_InteractiveObject.hxx>
28 #include <Draw.hxx>
29 #include <Draw_Interpretor.hxx>
30 #include <Graphic3d_Group.hxx>
31 #include <OpenGl_ArbVBO.hxx>
32 #include <OpenGl_AspectFace.hxx>
33 #include <OpenGl_AspectLine.hxx>
34 #include <OpenGl_AspectMarker.hxx>
35 #include <OpenGl_AspectText.hxx>
36 #include <OpenGl_Context.hxx>
37 #include <OpenGl_Element.hxx>
38 #include <OpenGl_ExtFBO.hxx>
39 #include <OpenGl_GlCore20.hxx>
40 #include <OpenGl_GraphicDriver.hxx>
41 #include <OpenGl_Workspace.hxx>
42 #include <Prs3d_Presentation.hxx>
43 #include <Prs3d_Root.hxx>
44 #include <Select3D_SensitiveCurve.hxx>
45 #include <SelectMgr_EntityOwner.hxx>
46 #include <SelectMgr_Selection.hxx>
47 #include <V3d_Viewer.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <V3d_View.hxx>
50 #include <Visual3d_View.hxx>
51
52 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
53                                            const Handle(AIS_InteractiveObject)& theAISObj,
54                                            Standard_Boolean theReplaceIfExists = Standard_True);
55
56 //=======================================================================
57 //function : VUserDraw
58 //purpose  : Checks availability and operation of UserDraw feature
59 //=======================================================================
60 DEFINE_STANDARD_HANDLE(VUserDrawObj, AIS_InteractiveObject)
61
62 class VUserDrawObj : public AIS_InteractiveObject
63 {
64 public:
65     // CASCADE RTTI
66     DEFINE_STANDARD_RTTI(VUserDrawObj);
67
68     VUserDrawObj()
69     {
70       myCoords[0] = -10.;
71       myCoords[1] = -20.;
72       myCoords[2] = -30.;
73       myCoords[3] =  10.;
74       myCoords[4] =  20.;
75       myCoords[5] =  30.;
76     }
77
78 public:
79   class Element : public OpenGl_Element
80   {
81   private:
82     Handle(VUserDrawObj) myIObj;
83
84   public:
85     Element (const Handle(VUserDrawObj)& theIObj,
86              CALL_DEF_BOUNDS* theBounds)
87     : myIObj( theIObj )
88     {
89       if (!myIObj.IsNull())
90         myIObj->GetBounds(theBounds);
91     }
92
93     virtual ~Element ()
94     {
95     }
96
97     virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
98     {
99       if (!myIObj.IsNull())
100         myIObj->Render(theWorkspace);
101     }
102
103     virtual void Release (const Handle(OpenGl_Context)& theGlCtx)
104     {
105       //
106     }
107
108   public:
109     DEFINE_STANDARD_ALLOC
110   };
111
112 private:
113     // Virtual methods implementation
114     void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
115                   const Handle(Prs3d_Presentation)& thePresentation,
116                   const Standard_Integer theMode);
117
118     void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
119                            const Standard_Integer theMode);
120
121     // Called by VUserDrawElement
122     void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
123     void GetBounds(CALL_DEF_BOUNDS* theBounds);
124
125     GLfloat myCoords[6];
126
127     friend class Element;
128 };
129 IMPLEMENT_STANDARD_HANDLE(VUserDrawObj, AIS_InteractiveObject)
130 IMPLEMENT_STANDARD_RTTIEXT(VUserDrawObj, AIS_InteractiveObject)
131
132 void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
133                            const Handle(Prs3d_Presentation)& thePresentation,
134                            const Standard_Integer theMode)
135 {
136   thePresentation->Clear();
137
138   Handle(Graphic3d_Group) aGrp = Prs3d_Root::CurrentGroup(thePresentation);
139   aGrp->UserDraw(this, Standard_True, Standard_True);
140 }
141
142 void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
143                                      const Standard_Integer theMode)
144 {
145   Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
146   Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5);
147   aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
148   aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2]));
149   aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5]));
150   aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5]));
151   aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
152   Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts);
153   theSelection->Add(aSensitive);
154 }
155
156 void VUserDrawObj::GetBounds(CALL_DEF_BOUNDS* theBounds)
157 {
158   if (theBounds)
159   {
160     theBounds->XMin = myCoords[0];
161     theBounds->YMin = myCoords[1];
162     theBounds->ZMin = myCoords[2];
163     theBounds->XMax = myCoords[3];
164     theBounds->YMax = myCoords[4];
165     theBounds->ZMax = myCoords[5];
166   }
167 }
168
169 void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
170 {
171   // To test linking against OpenGl_Workspace and all aspect classes
172   const OpenGl_AspectLine* aLA = theWorkspace->AspectLine(0);
173   const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker(0);
174   aMA->Type();
175   const OpenGl_AspectText* aTA = theWorkspace->AspectText(0);
176   aTA->FontName();
177   TEL_COLOUR aColor = theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT ?
178     *(theWorkspace->HighlightColor) : aLA->Color();
179
180   // To test OpenGl_Window
181   //Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
182
183   // Finally draw something to make sure UserDraw really works
184   glPushAttrib(GL_ENABLE_BIT);
185   glDisable(GL_LIGHTING);
186   glColor4fv(aColor.rgb);
187   glBegin(GL_LINE_LOOP);
188   glVertex3f(myCoords[0], myCoords[1], myCoords[2]);
189   glVertex3f(myCoords[3], myCoords[4], myCoords[2]);
190   glVertex3f(myCoords[3], myCoords[4], myCoords[5]);
191   glVertex3f(myCoords[0], myCoords[1], myCoords[5]);
192   glEnd();
193   glPopAttrib();
194 }
195
196 OpenGl_Element* VUserDrawCallback(const CALL_DEF_USERDRAW * theUserDraw)
197 {
198   Handle(VUserDrawObj) anIObj = (VUserDrawObj*)theUserDraw->Data;
199   if (anIObj.IsNull())
200   {
201     std::cout << "VUserDrawCallback error: null object passed, the custom scene element will not be rendered" << std::endl;
202   }
203
204   return new VUserDrawObj::Element(anIObj, theUserDraw->Bounds);
205 }
206
207 static Standard_Integer VUserDraw (Draw_Interpretor& di,
208                                     Standard_Integer argc,
209                                     const char ** argv)
210 {
211   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
212   if (aContext.IsNull())
213   {
214     di << argv[0] << "Call 'vinit' before!\n";
215     return 1;
216   }
217
218   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
219   if (aDriver.IsNull())
220   {
221     std::cerr << "Graphic driver not available.\n";
222     return 1;
223   }
224
225   if (argc > 2)
226   {
227     di << argv[0] << "Wrong number of arguments, only the object name expected\n";
228     return 1;
229   }
230
231   TCollection_AsciiString aName (argv[1]);
232   VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
233
234   // register the custom element factory function
235   aDriver->UserDrawCallback() = VUserDrawCallback;
236
237   Handle(VUserDrawObj) anIObj = new VUserDrawObj();
238   VDisplayAISObject(aName, anIObj);
239
240   return 0;
241 }
242
243 //==============================================================================
244 //function : VFeedback
245 //purpose  :
246 //==============================================================================
247
248 static int VFeedback (Draw_Interpretor& theDI,
249                       Standard_Integer  theArgNb,
250                       const char**      theArgVec)
251 {
252   // get the active view
253   Handle(V3d_View) aView = ViewerTest::CurrentView();
254   if (aView.IsNull())
255   {
256     std::cerr << "No active view. Please call vinit.\n";
257     return 1;
258   }
259
260   unsigned int aBufferSize = 1024 * 1024;
261   for (;;)
262   {
263     size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat);
264     if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize)
265     {
266       // finito la commedia
267       std::cerr << "Can not allocate buffer - requested size ("
268                 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
269                 << " MiB) is out of address space\n";
270       return 1;
271     }
272
273     GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes);
274     if (aBuffer == NULL)
275     {
276       // finito la commedia
277       std::cerr << "Can not allocate buffer with size ("
278                 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
279                 << " MiB)\n";
280       return 1;
281     }
282
283     glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer);
284     glRenderMode (GL_FEEDBACK);
285
286     aView->Redraw();
287
288     GLint aResult = glRenderMode (GL_RENDER);
289     if (aResult < 0)
290     {
291       aBufferSize *= 2;
292
293       void* aPtr = aBuffer;
294       Standard::Free (aPtr);
295       aBuffer = NULL;
296       continue;
297     }
298
299     std::cout << "FeedBack result= " << aResult << "\n";
300     GLint aPntNb     = 0;
301     GLint aTriNb     = 0;
302     GLint aQuadsNb   = 0;
303     GLint aPolyNb    = 0;
304     GLint aNodesNb   = 0;
305     GLint aLinesNb   = 0;
306     GLint aBitmapsNb = 0;
307     GLint aPassThrNb = 0;
308     GLint aUnknownNb = 0;
309     const GLint NODE_VALUES = 2; // GL_2D
310     for (GLint anIter = 0; anIter < aResult;)
311     {
312         const GLfloat aPos = aBuffer[anIter];
313         switch ((GLint )aPos)
314         {
315           case GL_POINT_TOKEN:
316           {
317             ++aPntNb;
318             ++aNodesNb;
319             anIter += 1 + NODE_VALUES;
320             break;
321           }
322           case GL_LINE_RESET_TOKEN:
323           case GL_LINE_TOKEN:
324           {
325             ++aLinesNb;
326             aNodesNb += 2;
327             anIter += 1 + 2 * NODE_VALUES;
328             break;
329           }
330           case GL_POLYGON_TOKEN:
331           {
332             const GLint aCount = (GLint )aBuffer[++anIter];
333             aNodesNb += aCount;
334             anIter += aCount * NODE_VALUES + 1;
335             if (aCount == 3)
336             {
337               ++aTriNb;
338             }
339             else if (aCount == 4)
340             {
341               ++aQuadsNb;
342             }
343             else
344             {
345               ++aPolyNb;
346             }
347             break;
348           }
349           case GL_BITMAP_TOKEN:
350           case GL_DRAW_PIXEL_TOKEN:
351           case GL_COPY_PIXEL_TOKEN:
352           {
353             ++aBitmapsNb;
354             anIter += 1 + NODE_VALUES;
355             break;
356           }
357           case GL_PASS_THROUGH_TOKEN:
358           {
359             ++aPassThrNb;
360             anIter += 2; // header + value
361             break;
362           }
363           default:
364           {
365             ++anIter;
366             ++aUnknownNb;
367             break;
368           }
369        }
370     }
371     void* aPtr = aBuffer;
372     Standard::Free (aPtr);
373
374     // return statistics
375     theDI << "Total nodes:   " << aNodesNb   << "\n"
376           << "Points:        " << aPntNb     << "\n"
377           << "Line segments: " << aLinesNb   << "\n"
378           << "Triangles:     " << aTriNb     << "\n"
379           << "Quads:         " << aQuadsNb   << "\n"
380           << "Polygons:      " << aPolyNb    << "\n"
381           << "Bitmap tokens: " << aBitmapsNb << "\n"
382           << "Pass through:  " << aPassThrNb << "\n"
383           << "UNKNOWN:       " << aUnknownNb << "\n";
384
385     double aLen2D      = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
386     double aLen3D      = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
387     double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
388     theDI << "Buffer size GL_2D:       " << aLen2D      * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
389           << "Buffer size GL_3D:       " << aLen3D      * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
390           << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n";
391     return 0;
392   }
393 }
394
395 //==============================================================================
396 //function : VImmediateFront
397 //purpose  :
398 //==============================================================================
399
400 static int VImmediateFront (Draw_Interpretor& theDI,
401                             Standard_Integer  theArgNb,
402                             const char**      theArgVec)
403 {
404   // get the context
405   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
406   if (aContextAIS.IsNull())
407   {
408     std::cerr << "No active view. Please call vinit.\n";
409     return 1;
410   }
411
412   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
413
414   if (aDriver.IsNull())
415   {
416     std::cerr << "Graphic driver not available.\n";
417     return 1;
418   }
419
420   if (theArgNb < 2)
421   {
422     //theDI << "VBO: " << aDriver->ToUseVBO() << "\n";
423     //return 0;
424     std::cerr << "Wrong number of arguments.\n";
425     return 1;
426   }
427
428   Graphic3d_CView* aCView = (Graphic3d_CView* )(ViewerTest::CurrentView()->View()->CView());
429   aDriver->SetImmediateModeDrawToFront (*aCView, atoi(theArgVec[1]) != 0);
430   return 0;
431 }
432
433 //==============================================================================
434 //function : VGlInfo
435 //purpose  :
436 //==============================================================================
437
438 static int VGlInfo (Draw_Interpretor& theDI,
439                     Standard_Integer  theArgNb,
440                     const char**      theArgVec)
441 {
442   // get the active view
443   Handle(V3d_View) aView = ViewerTest::CurrentView();
444   if (aView.IsNull())
445   {
446     std::cerr << "No active view. Please call vinit.\n";
447     return 1;
448   }
449
450   if (theArgNb <= 1)
451   {
452     theDI << "OpenGL info:\n"
453           << "  GLvendor    = '" << (const char* )glGetString(GL_VENDOR)   << "'\n"
454           << "  GLdevice    = '" << (const char* )glGetString(GL_RENDERER) << "'\n"
455           << "  GLversion   = '" << (const char* )glGetString(GL_VERSION)  << "'\n"
456           << "  GLSLversion = '" << (const char* )glGetString(GL_SHADING_LANGUAGE_VERSION) << "'\n";
457     return 0;
458   }
459
460   const Standard_Boolean isList = theArgNb >= 3;
461   for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
462   {
463     TCollection_AsciiString aName (theArgVec[anIter]);
464     aName.UpperCase();
465     const char* aValue = NULL;
466     if (aName.Search ("VENDOR") != -1)
467     {
468       aValue = (const char* )glGetString (GL_VENDOR);
469     }
470     else if (aName.Search ("RENDERER") != -1)
471     {
472       aValue = (const char* )glGetString (GL_RENDERER);
473     }
474     else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1
475           || aName.Search ("GLSL") != -1)
476     {
477       aValue = (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION);
478     }
479     else if (aName.Search ("VERSION") != -1)
480     {
481       aValue = (const char* )glGetString (GL_VERSION);
482     }
483     else if (aName.Search ("EXTENSIONS") != -1)
484     {
485       aValue = (const char* )glGetString (GL_EXTENSIONS);
486     }
487     else
488     {
489       std::cerr << "Unknown key '" << aName.ToCString() << "'\n";
490       return 1;
491     }
492
493     if (isList)
494     {
495       theDI << "{" << aValue << "} ";
496     }
497     else
498     {
499       theDI << aValue;
500     }
501   }
502
503   return 0;
504 }
505
506 //=======================================================================
507 //function : OpenGlCommands
508 //purpose  :
509 //=======================================================================
510
511 void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
512 {
513   const char* aGroup ="Commands for low-level TKOpenGl features";
514
515   theCommands.Add("vuserdraw",
516     "vuserdraw : name - simulates drawing with help of UserDraw",
517     __FILE__, VUserDraw, aGroup);
518   theCommands.Add("vfeedback",
519     "vfeedback       : perform test GL feedback rendering",
520     __FILE__, VFeedback, aGroup);
521   theCommands.Add("vimmediatefront",
522     "vimmediatefront : render immediate mode to front buffer or to back buffer",
523     __FILE__, VImmediateFront, aGroup);
524
525   theCommands.Add("vglinfo",
526     "vglinfo [GL_VENDOR] [GL_RENDERER] [GL_VERSION] [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
527     " : prints GL info",
528     __FILE__, VGlInfo, aGroup);
529 }