0023525: Disappearing of highlight in screenshot
[occt.git] / src / ViewerTest / ViewerTest_OpenGlCommands.cxx
CommitLineData
3946774d 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
5e27df78 26#include <Aspect_GraphicDevice.hxx>
27#include <AIS_InteractiveContext.hxx>
3946774d 28#include <AIS_InteractiveObject.hxx>
29#include <Draw.hxx>
30#include <Draw_Interpretor.hxx>
31#include <Graphic3d_Group.hxx>
32#include <OpenGl_ArbVBO.hxx>
33#include <OpenGl_AspectFace.hxx>
34#include <OpenGl_AspectLine.hxx>
35#include <OpenGl_AspectMarker.hxx>
36#include <OpenGl_AspectText.hxx>
3946774d 37#include <OpenGl_Context.hxx>
38#include <OpenGl_Element.hxx>
39#include <OpenGl_ExtFBO.hxx>
40#include <OpenGl_GlCore20.hxx>
5e27df78 41#include <OpenGl_GraphicDriver.hxx>
3946774d 42#include <OpenGl_Workspace.hxx>
43#include <Prs3d_Presentation.hxx>
44#include <Prs3d_Root.hxx>
45#include <Select3D_SensitiveCurve.hxx>
46#include <SelectMgr_EntityOwner.hxx>
47#include <SelectMgr_Selection.hxx>
5e27df78 48#include <V3d_Viewer.hxx>
3946774d 49#include <TCollection_AsciiString.hxx>
3c4153af 50#include <V3d_View.hxx>
1981cb22 51#include <Visual3d_View.hxx>
3946774d 52
53extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
54 const Handle(AIS_InteractiveObject)& theAISObj,
55 Standard_Boolean theReplaceIfExists = Standard_True);
56
57//=======================================================================
58//function : VUserDraw
59//purpose : Checks availability and operation of UserDraw feature
60//=======================================================================
61DEFINE_STANDARD_HANDLE(VUserDrawObj, AIS_InteractiveObject)
62
63class VUserDrawObj : public AIS_InteractiveObject
64{
65public:
66 // CASCADE RTTI
67 DEFINE_STANDARD_RTTI(VUserDrawObj);
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:
86 Element (const Handle(VUserDrawObj)& theIObj,
87 CALL_DEF_BOUNDS* theBounds)
88 : myIObj( theIObj )
89 {
90 if (!myIObj.IsNull())
91 myIObj->GetBounds(theBounds);
92 }
93
94 virtual ~Element ()
95 {
96 }
97
98 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
99 {
100 if (!myIObj.IsNull())
101 myIObj->Render(theWorkspace);
102 }
103
5e27df78 104 virtual void Release (const Handle(OpenGl_Context)& theGlCtx)
105 {
106 //
107 }
108
3946774d 109 public:
110 DEFINE_STANDARD_ALLOC
111 };
112
113private:
114 // Virtual methods implementation
115 void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
116 const Handle(Prs3d_Presentation)& thePresentation,
117 const Standard_Integer theMode);
118
119 void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
120 const Standard_Integer theMode);
121
122 // Called by VUserDrawElement
123 void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
124 void GetBounds(CALL_DEF_BOUNDS* theBounds);
125
126 GLfloat myCoords[6];
127
128 friend class Element;
129};
130IMPLEMENT_STANDARD_HANDLE(VUserDrawObj, AIS_InteractiveObject)
131IMPLEMENT_STANDARD_RTTIEXT(VUserDrawObj, AIS_InteractiveObject)
132
133void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
134 const Handle(Prs3d_Presentation)& thePresentation,
135 const Standard_Integer theMode)
136{
137 thePresentation->Clear();
138
139 Handle(Graphic3d_Group) aGrp = Prs3d_Root::CurrentGroup(thePresentation);
140 aGrp->UserDraw(this, Standard_True, Standard_True);
141}
142
143void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
144 const Standard_Integer theMode)
145{
146 Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
147 Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5);
148 aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
149 aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2]));
150 aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5]));
151 aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5]));
152 aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
153 Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts);
154 theSelection->Add(aSensitive);
155}
156
157void VUserDrawObj::GetBounds(CALL_DEF_BOUNDS* theBounds)
158{
159 if (theBounds)
160 {
161 theBounds->XMin = myCoords[0];
162 theBounds->YMin = myCoords[1];
163 theBounds->ZMin = myCoords[2];
164 theBounds->XMax = myCoords[3];
165 theBounds->YMax = myCoords[4];
166 theBounds->ZMax = myCoords[5];
167 }
168}
169
170void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
171{
172 // To test linking against OpenGl_Workspace and all aspect classes
173 const OpenGl_AspectLine* aLA = theWorkspace->AspectLine(0);
174 const OpenGl_AspectFace* aFA = theWorkspace->AspectFace(0);
3946774d 175 const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker(0);
176 aMA->Type();
177 const OpenGl_AspectText* aTA = theWorkspace->AspectText(0);
178 aTA->Font();
179 TEL_COLOUR aColor = theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT ?
180 *(theWorkspace->HighlightColor) : aLA->Color();
181
182 // To test OpenGl_Window
5e27df78 183 //Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
3946774d 184
185 // Finally draw something to make sure UserDraw really works
186 glPushAttrib(GL_ENABLE_BIT);
187 glDisable(GL_LIGHTING);
188 glColor4fv(aColor.rgb);
189 glBegin(GL_LINE_LOOP);
190 glVertex3f(myCoords[0], myCoords[1], myCoords[2]);
191 glVertex3f(myCoords[3], myCoords[4], myCoords[2]);
192 glVertex3f(myCoords[3], myCoords[4], myCoords[5]);
193 glVertex3f(myCoords[0], myCoords[1], myCoords[5]);
194 glEnd();
195 glPopAttrib();
196}
197
3946774d 198OpenGl_Element* VUserDrawCallback(const CALL_DEF_USERDRAW * theUserDraw)
199{
200 Handle(VUserDrawObj) anIObj = (VUserDrawObj*)theUserDraw->Data;
201 if (anIObj.IsNull())
202 {
203 std::cout << "VUserDrawCallback error: null object passed, the custom scene element will not be rendered" << std::endl;
204 }
205
206 return new VUserDrawObj::Element(anIObj, theUserDraw->Bounds);
207}
208
209static Standard_Integer VUserDraw (Draw_Interpretor& di,
210 Standard_Integer argc,
211 const char ** argv)
212{
213 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
214 if (aContext.IsNull())
215 {
216 di << argv[0] << "Call 'vinit' before!\n";
217 return 1;
218 }
219
5e27df78 220 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Device()->GraphicDriver());
221 if (aDriver.IsNull())
222 {
223 std::cerr << "Graphic driver not available.\n";
224 return 1;
225 }
226
3946774d 227 if (argc > 2)
228 {
229 di << argv[0] << "Wrong number of arguments, only the object name expected\n";
230 return 1;
231 }
232
233 TCollection_AsciiString aName (argv[1]);
234 VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
235
236 // register the custom element factory function
5e27df78 237 aDriver->UserDrawCallback() = VUserDrawCallback;
3946774d 238
239 Handle(VUserDrawObj) anIObj = new VUserDrawObj();
240 VDisplayAISObject(aName, anIObj);
241
242 return 0;
243}
244
3c4153af 245//==============================================================================
246//function : VFeedback
247//purpose :
248//==============================================================================
249
250static int VFeedback (Draw_Interpretor& theDI,
251 Standard_Integer theArgNb,
252 const char** theArgVec)
253{
254 // get the active view
255 Handle(V3d_View) aView = ViewerTest::CurrentView();
256 if (aView.IsNull())
257 {
258 std::cerr << "No active view. Please call vinit.\n";
259 return 1;
260 }
261
262 unsigned int aBufferSize = 1024 * 1024;
263 for (;;)
264 {
265 size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat);
266 if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize)
267 {
268 // finito la commedia
269 std::cerr << "Can not allocate buffer - requested size ("
270 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
271 << " MiB) is out of address space\n";
272 return 1;
273 }
274
275 GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes);
276 if (aBuffer == NULL)
277 {
278 // finito la commedia
279 std::cerr << "Can not allocate buffer with size ("
280 << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat)))
281 << " MiB)\n";
282 return 1;
283 }
284
285 glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer);
286 glRenderMode (GL_FEEDBACK);
287
288 aView->Redraw();
289
290 GLint aResult = glRenderMode (GL_RENDER);
291 if (aResult < 0)
292 {
293 aBufferSize *= 2;
294
295 void* aPtr = aBuffer;
296 Standard::Free (aPtr);
297 aBuffer = NULL;
298 continue;
299 }
300
301 std::cout << "FeedBack result= " << aResult << "\n";
302 GLint aPntNb = 0;
303 GLint aTriNb = 0;
304 GLint aQuadsNb = 0;
305 GLint aPolyNb = 0;
306 GLint aNodesNb = 0;
307 GLint aLinesNb = 0;
308 GLint aBitmapsNb = 0;
309 GLint aPassThrNb = 0;
310 GLint aUnknownNb = 0;
311 const GLint NODE_VALUES = 2; // GL_2D
312 for (GLint anIter = 0; anIter < aResult;)
313 {
314 const GLfloat aPos = aBuffer[anIter];
315 switch ((GLint )aPos)
316 {
317 case GL_POINT_TOKEN:
318 {
319 ++aPntNb;
320 ++aNodesNb;
321 anIter += 1 + NODE_VALUES;
322 break;
323 }
324 case GL_LINE_RESET_TOKEN:
325 case GL_LINE_TOKEN:
326 {
327 ++aLinesNb;
328 aNodesNb += 2;
329 anIter += 1 + 2 * NODE_VALUES;
330 break;
331 }
332 case GL_POLYGON_TOKEN:
333 {
334 const GLint aCount = (GLint )aBuffer[++anIter];
335 aNodesNb += aCount;
336 anIter += aCount * NODE_VALUES + 1;
337 if (aCount == 3)
338 {
339 ++aTriNb;
340 }
341 else if (aCount == 4)
342 {
343 ++aQuadsNb;
344 }
345 else
346 {
347 ++aPolyNb;
348 }
349 break;
350 }
351 case GL_BITMAP_TOKEN:
352 case GL_DRAW_PIXEL_TOKEN:
353 case GL_COPY_PIXEL_TOKEN:
354 {
355 ++aBitmapsNb;
356 anIter += 1 + NODE_VALUES;
357 break;
358 }
359 case GL_PASS_THROUGH_TOKEN:
360 {
361 ++aPassThrNb;
362 anIter += 2; // header + value
363 break;
364 }
365 default:
366 {
367 ++anIter;
368 ++aUnknownNb;
369 break;
370 }
371 }
372 }
373 void* aPtr = aBuffer;
374 Standard::Free (aPtr);
375
376 // return statistics
377 theDI << "Total nodes: " << aNodesNb << "\n"
378 << "Points: " << aPntNb << "\n"
379 << "Line segments: " << aLinesNb << "\n"
380 << "Triangles: " << aTriNb << "\n"
381 << "Quads: " << aQuadsNb << "\n"
382 << "Polygons: " << aPolyNb << "\n"
383 << "Bitmap tokens: " << aBitmapsNb << "\n"
384 << "Pass through: " << aPassThrNb << "\n"
385 << "UNKNOWN: " << aUnknownNb << "\n";
386
387 double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
388 double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
389 double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb);
390 theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
391 << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"
392 << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n";
393 return 0;
394 }
395}
396
1981cb22 397//==============================================================================
398//function : VImmediateFront
399//purpose :
400//==============================================================================
401
402static int VImmediateFront (Draw_Interpretor& theDI,
403 Standard_Integer theArgNb,
404 const char** theArgVec)
405{
406 // get the context
407 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
408 if (aContextAIS.IsNull())
409 {
410 std::cerr << "No active view. Please call vinit.\n";
411 return 1;
412 }
413
414 Handle(Graphic3d_GraphicDriver) aDriver =
415 Handle(Graphic3d_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Device()->GraphicDriver());
416 if (aDriver.IsNull())
417 {
418 std::cerr << "Graphic driver not available.\n";
419 return 1;
420 }
421
422 if (theArgNb < 2)
423 {
424 //theDI << "VBO: " << aDriver->ToUseVBO() << "\n";
425 //return 0;
426 std::cerr << "Wrong number of arguments.\n";
427 return 1;
428 }
429
430 Graphic3d_CView* aCView = (Graphic3d_CView* )(ViewerTest::CurrentView()->View()->CView());
431 aDriver->SetImmediateModeDrawToFront (*aCView, atoi(theArgVec[1]) != 0);
432 return 0;
433}
434
3946774d 435//=======================================================================
436//function : OpenGlCommands
437//purpose :
438//=======================================================================
439
440void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
441{
442 const char* aGroup ="Commands for low-level TKOpenGl features";
443
444 theCommands.Add("vuserdraw",
445 "vuserdraw : name - simulates drawing with help of UserDraw",
446 __FILE__, VUserDraw, aGroup);
3c4153af 447 theCommands.Add("vfeedback",
448 "vfeedback : perform test GL feedback rendering",
449 __FILE__, VFeedback, aGroup);
1981cb22 450 theCommands.Add("vimmediatefront",
451 "vimmediatefront : render immediate mode to front buffer or to back buffer",
452 __FILE__, VImmediateFront, aGroup);
453
3946774d 454}