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 <AIS_InteractiveContext.hxx> |
3946774d |
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> |
3946774d |
36 | #include <OpenGl_Context.hxx> |
37 | #include <OpenGl_Element.hxx> |
38 | #include <OpenGl_ExtFBO.hxx> |
39 | #include <OpenGl_GlCore20.hxx> |
5e27df78 |
40 | #include <OpenGl_GraphicDriver.hxx> |
3946774d |
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> |
5e27df78 |
47 | #include <V3d_Viewer.hxx> |
3946774d |
48 | #include <TCollection_AsciiString.hxx> |
3c4153af |
49 | #include <V3d_View.hxx> |
1981cb22 |
50 | #include <Visual3d_View.hxx> |
3946774d |
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 | |
35e08fe8 |
103 | virtual void Release (const Handle(OpenGl_Context)&) |
5e27df78 |
104 | { |
105 | // |
106 | } |
107 | |
3946774d |
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 | |
35e08fe8 |
132 | void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/, |
3946774d |
133 | const Handle(Prs3d_Presentation)& thePresentation, |
35e08fe8 |
134 | const Standard_Integer /*theMode*/) |
3946774d |
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, |
35e08fe8 |
143 | const Standard_Integer /*theMode*/) |
3946774d |
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); |
3946774d |
173 | const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker(0); |
174 | aMA->Type(); |
175 | const OpenGl_AspectText* aTA = theWorkspace->AspectText(0); |
a174a3c5 |
176 | aTA->FontName(); |
3946774d |
177 | TEL_COLOUR aColor = theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT ? |
178 | *(theWorkspace->HighlightColor) : aLA->Color(); |
179 | |
180 | // To test OpenGl_Window |
5e27df78 |
181 | //Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext(); |
3946774d |
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 | |
3946774d |
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 | |
dc3fe572 |
218 | Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver()); |
5e27df78 |
219 | if (aDriver.IsNull()) |
220 | { |
221 | std::cerr << "Graphic driver not available.\n"; |
222 | return 1; |
223 | } |
224 | |
3946774d |
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 |
5e27df78 |
235 | aDriver->UserDrawCallback() = VUserDrawCallback; |
3946774d |
236 | |
237 | Handle(VUserDrawObj) anIObj = new VUserDrawObj(); |
238 | VDisplayAISObject(aName, anIObj); |
239 | |
240 | return 0; |
241 | } |
242 | |
3c4153af |
243 | //============================================================================== |
244 | //function : VFeedback |
245 | //purpose : |
246 | //============================================================================== |
247 | |
248 | static int VFeedback (Draw_Interpretor& theDI, |
35e08fe8 |
249 | Standard_Integer /*theArgNb*/, |
250 | const char** /*theArgVec*/) |
3c4153af |
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 | |
1981cb22 |
395 | //============================================================================== |
396 | //function : VImmediateFront |
397 | //purpose : |
398 | //============================================================================== |
399 | |
35e08fe8 |
400 | static int VImmediateFront (Draw_Interpretor& /*theDI*/, |
1981cb22 |
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 | |
dc3fe572 |
412 | Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver(); |
413 | |
1981cb22 |
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 | |
dac04bfa |
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 | |
3946774d |
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); |
3c4153af |
518 | theCommands.Add("vfeedback", |
519 | "vfeedback : perform test GL feedback rendering", |
520 | __FILE__, VFeedback, aGroup); |
1981cb22 |
521 | theCommands.Add("vimmediatefront", |
522 | "vimmediatefront : render immediate mode to front buffer or to back buffer", |
523 | __FILE__, VImmediateFront, aGroup); |
524 | |
dac04bfa |
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); |
3946774d |
529 | } |