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> |
bf5f0ca2 |
25 | #include <OpenGl_Aspects.hxx> |
3946774d |
26 | #include <OpenGl_Context.hxx> |
27 | #include <OpenGl_Element.hxx> |
3946774d |
28 | #include <OpenGl_GlCore20.hxx> |
5e27df78 |
29 | #include <OpenGl_GraphicDriver.hxx> |
8613985b |
30 | #include <OpenGl_ShaderManager.hxx> |
3946774d |
31 | #include <OpenGl_Workspace.hxx> |
392ac980 |
32 | #include <OSD_Environment.hxx> |
33 | #include <OSD_File.hxx> |
6262338c |
34 | #include <Prs3d_Drawer.hxx> |
3946774d |
35 | #include <Prs3d_Presentation.hxx> |
36 | #include <Prs3d_Root.hxx> |
2831708b |
37 | #include <Prs3d_LineAspect.hxx> |
392ac980 |
38 | #include <Prs3d_ShadingAspect.hxx> |
3946774d |
39 | #include <Select3D_SensitiveCurve.hxx> |
40 | #include <SelectMgr_EntityOwner.hxx> |
41 | #include <SelectMgr_Selection.hxx> |
42 | #include <TCollection_AsciiString.hxx> |
3c4153af |
43 | #include <V3d_View.hxx> |
392ac980 |
44 | #include <V3d_Viewer.hxx> |
392ac980 |
45 | #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx> |
46 | #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx> |
92efcf78 |
47 | #include <OpenGl_Group.hxx> |
3946774d |
48 | |
49 | extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName, |
50 | const Handle(AIS_InteractiveObject)& theAISObj, |
51 | Standard_Boolean theReplaceIfExists = Standard_True); |
392ac980 |
52 | extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(); |
3946774d |
53 | |
c04c30b3 |
54 | namespace { |
55 | |
3946774d |
56 | //======================================================================= |
57 | //function : VUserDraw |
58 | //purpose : Checks availability and operation of UserDraw feature |
59 | //======================================================================= |
3946774d |
60 | |
61 | class VUserDrawObj : public AIS_InteractiveObject |
62 | { |
63 | public: |
64 | // CASCADE RTTI |
92efcf78 |
65 | DEFINE_STANDARD_RTTI_INLINE(VUserDrawObj,AIS_InteractiveObject); |
3946774d |
66 | |
67 | VUserDrawObj() |
68 | { |
69 | myCoords[0] = -10.; |
70 | myCoords[1] = -20.; |
71 | myCoords[2] = -30.; |
72 | myCoords[3] = 10.; |
73 | myCoords[4] = 20.; |
74 | myCoords[5] = 30.; |
75 | } |
76 | |
77 | public: |
78 | class Element : public OpenGl_Element |
79 | { |
80 | private: |
81 | Handle(VUserDrawObj) myIObj; |
82 | |
83 | public: |
a521d90d |
84 | Element (const Handle(VUserDrawObj)& theIObj) : myIObj (theIObj) {} |
3946774d |
85 | |
a521d90d |
86 | virtual ~Element() {} |
3946774d |
87 | |
88 | virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const |
89 | { |
90 | if (!myIObj.IsNull()) |
91 | myIObj->Render(theWorkspace); |
92 | } |
93 | |
10b9c7df |
94 | virtual void Release (OpenGl_Context*) |
5e27df78 |
95 | { |
96 | // |
97 | } |
98 | |
3946774d |
99 | public: |
100 | DEFINE_STANDARD_ALLOC |
101 | }; |
102 | |
103 | private: |
104 | // Virtual methods implementation |
105 | void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, |
106 | const Handle(Prs3d_Presentation)& thePresentation, |
79104795 |
107 | const Standard_Integer theMode) Standard_OVERRIDE; |
3946774d |
108 | |
109 | void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, |
79104795 |
110 | const Standard_Integer theMode) Standard_OVERRIDE; |
3946774d |
111 | |
112 | // Called by VUserDrawElement |
113 | void Render(const Handle(OpenGl_Workspace)& theWorkspace) const; |
3946774d |
114 | |
a521d90d |
115 | private: |
3946774d |
116 | GLfloat myCoords[6]; |
3946774d |
117 | friend class Element; |
118 | }; |
ec357c5c |
119 | |
a521d90d |
120 | void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, |
121 | const Handle(Prs3d_Presentation)& thePrs, |
35e08fe8 |
122 | const Standard_Integer /*theMode*/) |
3946774d |
123 | { |
a521d90d |
124 | thePrs->Clear(); |
125 | |
126 | Graphic3d_Vec4 aBndMin (myCoords[0], myCoords[1], myCoords[2], 1.0f); |
127 | Graphic3d_Vec4 aBndMax (myCoords[3], myCoords[4], myCoords[5], 1.0f); |
128 | Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast (thePrs->NewGroup()); |
129 | aGroup->SetMinMaxValues (aBndMin.x(), aBndMin.y(), aBndMin.z(), |
130 | aBndMax.x(), aBndMax.y(), aBndMax.z()); |
2831708b |
131 | aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect()); |
a521d90d |
132 | VUserDrawObj::Element* anElem = new VUserDrawObj::Element (this); |
133 | aGroup->AddElement(anElem); |
134 | |
135 | // invalidate bounding box of the scene |
cfece3ef |
136 | thePrsMgr->StructureManager()->Update(); |
3946774d |
137 | } |
138 | |
139 | void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, |
35e08fe8 |
140 | const Standard_Integer /*theMode*/) |
3946774d |
141 | { |
142 | Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this); |
143 | Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5); |
144 | aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2])); |
145 | aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2])); |
146 | aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5])); |
147 | aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5])); |
148 | aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2])); |
149 | Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts); |
150 | theSelection->Add(aSensitive); |
151 | } |
152 | |
3946774d |
153 | void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const |
154 | { |
1136702b |
155 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
a521d90d |
156 | |
3946774d |
157 | // To test linking against OpenGl_Workspace and all aspect classes |
bf5f0ca2 |
158 | const OpenGl_Aspects* aMA = theWorkspace->Aspects(); |
159 | aMA->Aspect()->MarkerType(); |
160 | OpenGl_Vec4 aColor = theWorkspace->InteriorColor(); |
3946774d |
161 | |
c40eb6b9 |
162 | aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, |
163 | Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false, |
164 | Handle(OpenGl_ShaderProgram)()); |
1136702b |
165 | aCtx->SetColor4fv (aColor); |
166 | |
167 | const OpenGl_Vec3 aVertArray[4] = |
168 | { |
169 | OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[2]), |
170 | OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[2]), |
171 | OpenGl_Vec3(myCoords[3], myCoords[4], myCoords[5]), |
172 | OpenGl_Vec3(myCoords[0], myCoords[1], myCoords[5]), |
173 | }; |
174 | Handle(OpenGl_VertexBuffer) aVertBuffer = new OpenGl_VertexBuffer(); |
175 | aVertBuffer->Init (aCtx, 3, 4, aVertArray[0].GetData()); |
176 | |
3946774d |
177 | // Finally draw something to make sure UserDraw really works |
1136702b |
178 | aVertBuffer->BindAttribute (aCtx, Graphic3d_TOA_POS); |
179 | glDrawArrays(GL_LINE_LOOP, 0, aVertBuffer->GetElemsNb()); |
180 | aVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS); |
181 | aVertBuffer->Release (aCtx.get()); |
3946774d |
182 | } |
183 | |
c04c30b3 |
184 | } // end of anonymous namespace |
185 | |
3946774d |
186 | static Standard_Integer VUserDraw (Draw_Interpretor& di, |
187 | Standard_Integer argc, |
188 | const char ** argv) |
189 | { |
190 | Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext(); |
191 | if (aContext.IsNull()) |
192 | { |
193 | di << argv[0] << "Call 'vinit' before!\n"; |
194 | return 1; |
195 | } |
196 | |
dc3fe572 |
197 | Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver()); |
5e27df78 |
198 | if (aDriver.IsNull()) |
199 | { |
200 | std::cerr << "Graphic driver not available.\n"; |
201 | return 1; |
202 | } |
203 | |
3946774d |
204 | if (argc > 2) |
205 | { |
206 | di << argv[0] << "Wrong number of arguments, only the object name expected\n"; |
207 | return 1; |
208 | } |
209 | |
210 | TCollection_AsciiString aName (argv[1]); |
211 | VDisplayAISObject(aName, Handle(AIS_InteractiveObject)()); |
212 | |
3946774d |
213 | Handle(VUserDrawObj) anIObj = new VUserDrawObj(); |
214 | VDisplayAISObject(aName, anIObj); |
215 | |
216 | return 0; |
217 | } |
218 | |
3c4153af |
219 | //============================================================================== |
220 | //function : VFeedback |
221 | //purpose : |
222 | //============================================================================== |
223 | |
224 | static int VFeedback (Draw_Interpretor& theDI, |
35e08fe8 |
225 | Standard_Integer /*theArgNb*/, |
226 | const char** /*theArgVec*/) |
3c4153af |
227 | { |
1ce0716b |
228 | #if !defined(GL_ES_VERSION_2_0) |
3c4153af |
229 | // get the active view |
230 | Handle(V3d_View) aView = ViewerTest::CurrentView(); |
231 | if (aView.IsNull()) |
232 | { |
233 | std::cerr << "No active view. Please call vinit.\n"; |
234 | return 1; |
235 | } |
236 | |
237 | unsigned int aBufferSize = 1024 * 1024; |
238 | for (;;) |
239 | { |
240 | size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat); |
241 | if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize) |
242 | { |
243 | // finito la commedia |
244 | std::cerr << "Can not allocate buffer - requested size (" |
245 | << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat))) |
246 | << " MiB) is out of address space\n"; |
247 | return 1; |
248 | } |
249 | |
250 | GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes); |
251 | if (aBuffer == NULL) |
252 | { |
253 | // finito la commedia |
254 | std::cerr << "Can not allocate buffer with size (" |
255 | << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat))) |
256 | << " MiB)\n"; |
257 | return 1; |
258 | } |
259 | |
260 | glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer); |
261 | glRenderMode (GL_FEEDBACK); |
262 | |
263 | aView->Redraw(); |
264 | |
265 | GLint aResult = glRenderMode (GL_RENDER); |
266 | if (aResult < 0) |
267 | { |
268 | aBufferSize *= 2; |
269 | |
270 | void* aPtr = aBuffer; |
271 | Standard::Free (aPtr); |
272 | aBuffer = NULL; |
273 | continue; |
274 | } |
275 | |
276 | std::cout << "FeedBack result= " << aResult << "\n"; |
277 | GLint aPntNb = 0; |
278 | GLint aTriNb = 0; |
279 | GLint aQuadsNb = 0; |
280 | GLint aPolyNb = 0; |
281 | GLint aNodesNb = 0; |
282 | GLint aLinesNb = 0; |
283 | GLint aBitmapsNb = 0; |
284 | GLint aPassThrNb = 0; |
285 | GLint aUnknownNb = 0; |
286 | const GLint NODE_VALUES = 2; // GL_2D |
287 | for (GLint anIter = 0; anIter < aResult;) |
288 | { |
289 | const GLfloat aPos = aBuffer[anIter]; |
290 | switch ((GLint )aPos) |
291 | { |
292 | case GL_POINT_TOKEN: |
293 | { |
294 | ++aPntNb; |
295 | ++aNodesNb; |
296 | anIter += 1 + NODE_VALUES; |
297 | break; |
298 | } |
299 | case GL_LINE_RESET_TOKEN: |
300 | case GL_LINE_TOKEN: |
301 | { |
302 | ++aLinesNb; |
303 | aNodesNb += 2; |
304 | anIter += 1 + 2 * NODE_VALUES; |
305 | break; |
306 | } |
307 | case GL_POLYGON_TOKEN: |
308 | { |
309 | const GLint aCount = (GLint )aBuffer[++anIter]; |
310 | aNodesNb += aCount; |
311 | anIter += aCount * NODE_VALUES + 1; |
312 | if (aCount == 3) |
313 | { |
314 | ++aTriNb; |
315 | } |
316 | else if (aCount == 4) |
317 | { |
318 | ++aQuadsNb; |
319 | } |
320 | else |
321 | { |
322 | ++aPolyNb; |
323 | } |
324 | break; |
325 | } |
326 | case GL_BITMAP_TOKEN: |
327 | case GL_DRAW_PIXEL_TOKEN: |
328 | case GL_COPY_PIXEL_TOKEN: |
329 | { |
330 | ++aBitmapsNb; |
331 | anIter += 1 + NODE_VALUES; |
332 | break; |
333 | } |
334 | case GL_PASS_THROUGH_TOKEN: |
335 | { |
336 | ++aPassThrNb; |
337 | anIter += 2; // header + value |
338 | break; |
339 | } |
340 | default: |
341 | { |
342 | ++anIter; |
343 | ++aUnknownNb; |
344 | break; |
345 | } |
346 | } |
347 | } |
348 | void* aPtr = aBuffer; |
349 | Standard::Free (aPtr); |
350 | |
351 | // return statistics |
352 | theDI << "Total nodes: " << aNodesNb << "\n" |
353 | << "Points: " << aPntNb << "\n" |
354 | << "Line segments: " << aLinesNb << "\n" |
355 | << "Triangles: " << aTriNb << "\n" |
356 | << "Quads: " << aQuadsNb << "\n" |
357 | << "Polygons: " << aPolyNb << "\n" |
358 | << "Bitmap tokens: " << aBitmapsNb << "\n" |
359 | << "Pass through: " << aPassThrNb << "\n" |
360 | << "UNKNOWN: " << aUnknownNb << "\n"; |
361 | |
362 | double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb); |
363 | double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb); |
364 | double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb); |
365 | theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n" |
366 | << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n" |
367 | << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"; |
368 | return 0; |
369 | } |
1ce0716b |
370 | #else |
371 | (void )theDI; |
372 | std::cout << "Command is unsupported on current platform.\n"; |
373 | return 1; |
374 | #endif |
3c4153af |
375 | } |
376 | |
1981cb22 |
377 | //============================================================================== |
378 | //function : VImmediateFront |
379 | //purpose : |
380 | //============================================================================== |
381 | |
35e08fe8 |
382 | static int VImmediateFront (Draw_Interpretor& /*theDI*/, |
1981cb22 |
383 | Standard_Integer theArgNb, |
384 | const char** theArgVec) |
385 | { |
386 | // get the context |
387 | Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext(); |
388 | if (aContextAIS.IsNull()) |
389 | { |
390 | std::cerr << "No active view. Please call vinit.\n"; |
391 | return 1; |
392 | } |
393 | |
dc3fe572 |
394 | Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver(); |
395 | |
1981cb22 |
396 | if (aDriver.IsNull()) |
397 | { |
398 | std::cerr << "Graphic driver not available.\n"; |
399 | return 1; |
400 | } |
401 | |
402 | if (theArgNb < 2) |
403 | { |
1981cb22 |
404 | std::cerr << "Wrong number of arguments.\n"; |
405 | return 1; |
406 | } |
407 | |
c357e426 |
408 | ViewerTest::CurrentView()->View()->SetImmediateModeDrawToFront (atoi(theArgVec[1]) != 0); |
409 | |
1981cb22 |
410 | return 0; |
411 | } |
412 | |
26d9c835 |
413 | //! Search the info from the key. |
414 | inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict, |
415 | const TCollection_AsciiString& theKey) |
416 | { |
417 | for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next()) |
418 | { |
419 | if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False)) |
420 | { |
421 | return anIter.Value(); |
422 | } |
423 | } |
424 | return TCollection_AsciiString(); |
425 | } |
426 | |
dac04bfa |
427 | //============================================================================== |
428 | //function : VGlInfo |
429 | //purpose : |
430 | //============================================================================== |
431 | |
432 | static int VGlInfo (Draw_Interpretor& theDI, |
433 | Standard_Integer theArgNb, |
434 | const char** theArgVec) |
435 | { |
436 | // get the active view |
437 | Handle(V3d_View) aView = ViewerTest::CurrentView(); |
438 | if (aView.IsNull()) |
439 | { |
440 | std::cerr << "No active view. Please call vinit.\n"; |
441 | return 1; |
442 | } |
443 | |
26d9c835 |
444 | Standard_Integer anArgIter = 1; |
445 | Graphic3d_DiagnosticInfo anInfoLevel = Graphic3d_DiagnosticInfo_Basic; |
446 | if (theArgNb == 2) |
dac04bfa |
447 | { |
26d9c835 |
448 | TCollection_AsciiString aName (theArgVec[1]); |
449 | aName.LowerCase(); |
450 | if (aName == "-short") |
4e1523ef |
451 | { |
26d9c835 |
452 | ++anArgIter; |
453 | anInfoLevel = Graphic3d_DiagnosticInfo_Short; |
454 | } |
455 | else if (aName == "-basic") |
456 | { |
457 | ++anArgIter; |
458 | anInfoLevel = Graphic3d_DiagnosticInfo_Basic; |
4e1523ef |
459 | } |
26d9c835 |
460 | else if (aName == "-complete" |
461 | || aName == "-full") |
462 | { |
463 | ++anArgIter; |
464 | anInfoLevel = Graphic3d_DiagnosticInfo_Complete; |
465 | } |
466 | } |
467 | |
468 | TColStd_IndexedDataMapOfStringString aDict; |
469 | if (anArgIter >= theArgNb) |
470 | { |
471 | aView->DiagnosticInformation (aDict, anInfoLevel); |
472 | TCollection_AsciiString aText; |
473 | for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aDict); aValueIter.More(); aValueIter.Next()) |
474 | { |
475 | if (!aText.IsEmpty()) |
476 | { |
477 | aText += "\n"; |
478 | } |
479 | aText += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value(); |
480 | } |
481 | |
dac04bfa |
482 | theDI << "OpenGL info:\n" |
26d9c835 |
483 | << aText; |
dac04bfa |
484 | return 0; |
485 | } |
486 | |
487 | const Standard_Boolean isList = theArgNb >= 3; |
26d9c835 |
488 | aView->DiagnosticInformation (aDict, Graphic3d_DiagnosticInfo_Complete); |
489 | for (; anArgIter < theArgNb; ++anArgIter) |
dac04bfa |
490 | { |
26d9c835 |
491 | TCollection_AsciiString aName (theArgVec[anArgIter]); |
dac04bfa |
492 | aName.UpperCase(); |
26d9c835 |
493 | TCollection_AsciiString aValue; |
dac04bfa |
494 | if (aName.Search ("VENDOR") != -1) |
495 | { |
26d9c835 |
496 | aValue = searchInfo (aDict, "GLvendor"); |
dac04bfa |
497 | } |
498 | else if (aName.Search ("RENDERER") != -1) |
499 | { |
26d9c835 |
500 | aValue = searchInfo (aDict, "GLdevice"); |
dac04bfa |
501 | } |
502 | else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1 |
503 | || aName.Search ("GLSL") != -1) |
504 | { |
26d9c835 |
505 | aValue = searchInfo (aDict, "GLSLversion"); |
dac04bfa |
506 | } |
507 | else if (aName.Search ("VERSION") != -1) |
508 | { |
26d9c835 |
509 | aValue = searchInfo (aDict, "GLversion"); |
dac04bfa |
510 | } |
511 | else if (aName.Search ("EXTENSIONS") != -1) |
512 | { |
26d9c835 |
513 | aValue = searchInfo (aDict, "GLextensions"); |
dac04bfa |
514 | } |
515 | else |
516 | { |
517 | std::cerr << "Unknown key '" << aName.ToCString() << "'\n"; |
518 | return 1; |
519 | } |
520 | |
521 | if (isList) |
522 | { |
523 | theDI << "{" << aValue << "} "; |
524 | } |
525 | else |
526 | { |
527 | theDI << aValue; |
528 | } |
529 | } |
530 | |
531 | return 0; |
532 | } |
533 | |
8e0a2b19 |
534 | //! Parse shader type argument. |
535 | static bool parseShaderTypeArg (Graphic3d_TypeOfShaderObject& theType, |
536 | const TCollection_AsciiString& theArg) |
537 | { |
538 | if (theArg == "-vertex" |
539 | || theArg == "-vert") |
540 | { |
541 | theType = Graphic3d_TOS_VERTEX; |
542 | } |
543 | else if (theArg == "-tessevaluation" |
544 | || theArg == "-tesseval" |
545 | || theArg == "-evaluation" |
546 | || theArg == "-eval") |
547 | { |
548 | theType = Graphic3d_TOS_TESS_EVALUATION; |
549 | } |
550 | else if (theArg == "-tesscontrol" |
551 | || theArg == "-tessctrl" |
552 | || theArg == "-control" |
553 | || theArg == "-ctrl") |
554 | { |
555 | theType = Graphic3d_TOS_TESS_CONTROL; |
556 | } |
557 | else if (theArg == "-geometry" |
558 | || theArg == "-geom") |
559 | { |
560 | theType = Graphic3d_TOS_GEOMETRY; |
561 | } |
562 | else if (theArg == "-fragment" |
563 | || theArg == "-frag") |
564 | { |
565 | theType = Graphic3d_TOS_FRAGMENT; |
566 | } |
567 | else if (theArg == "-compute" |
568 | || theArg == "-comp") |
569 | { |
570 | theType = Graphic3d_TOS_COMPUTE; |
571 | } |
572 | else |
573 | { |
574 | return false; |
575 | } |
576 | return true; |
577 | } |
392ac980 |
578 | |
579 | //============================================================================== |
580 | //function : VShaderProg |
581 | //purpose : Sets the pair of vertex and fragment shaders for the object |
582 | //============================================================================== |
d95f5ce1 |
583 | static Standard_Integer VShaderProg (Draw_Interpretor& theDI, |
392ac980 |
584 | Standard_Integer theArgNb, |
585 | const char** theArgVec) |
586 | { |
587 | Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext(); |
588 | if (aCtx.IsNull()) |
589 | { |
8e0a2b19 |
590 | std::cout << "Error: no active view.\n"; |
392ac980 |
591 | return 1; |
592 | } |
593 | else if (theArgNb < 2) |
594 | { |
8e0a2b19 |
595 | std::cout << "Syntax error: lack of arguments\n"; |
392ac980 |
596 | return 1; |
597 | } |
598 | |
8e0a2b19 |
599 | bool isExplicitShaderType = false; |
600 | Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram(); |
601 | NCollection_Sequence<Handle(AIS_InteractiveObject)> aPrsList; |
602 | Graphic3d_GroupAspect aGroupAspect = Graphic3d_ASPECT_FILL_AREA; |
603 | bool isSetGroupAspect = false; |
604 | for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) |
392ac980 |
605 | { |
8e0a2b19 |
606 | TCollection_AsciiString anArg (theArgVec[anArgIter]); |
607 | anArg.LowerCase(); |
608 | Graphic3d_TypeOfShaderObject aShaderTypeArg = Graphic3d_TypeOfShaderObject(-1); |
d95f5ce1 |
609 | if (anArg == "-list" |
610 | || ((anArg == "-update" |
611 | || anArg == "-dump" |
612 | || anArg == "-debug" |
613 | || anArg == "-reload" |
614 | || anArg == "-load") |
615 | && anArgIter + 1 < theArgNb)) |
616 | { |
617 | Handle(OpenGl_Context) aGlCtx; |
618 | if (Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aCtx->CurrentViewer()->Driver())) |
619 | { |
620 | aGlCtx = aDriver->GetSharedContext(); |
621 | } |
622 | if (aGlCtx.IsNull()) |
623 | { |
624 | std::cout << "Error: no OpenGl_Context\n"; |
625 | return 1; |
626 | } |
627 | |
628 | if (anArg == "-list") |
629 | { |
630 | for (OpenGl_Context::OpenGl_ResourcesMap::Iterator aResIter (aGlCtx->SharedResources()); aResIter.More(); aResIter.Next()) |
631 | { |
632 | if (Handle(OpenGl_ShaderProgram) aResProg = Handle(OpenGl_ShaderProgram)::DownCast (aResIter.Value())) |
633 | { |
634 | theDI << aResProg->ResourceId() << " "; |
635 | } |
636 | } |
637 | } |
638 | else |
639 | { |
640 | TCollection_AsciiString aShaderName = theArgVec[++anArgIter]; |
641 | Handle(OpenGl_ShaderProgram) aResProg; |
642 | if (!aGlCtx->GetResource (aShaderName, aResProg)) |
643 | { |
644 | std::cout << "Syntax error: shader resource '" << aShaderName << "' is not found\n"; |
645 | return 1; |
646 | } |
647 | if (aResProg->UpdateDebugDump (aGlCtx, "", false, anArg == "-dump")) |
648 | { |
649 | aCtx->UpdateCurrentViewer(); |
650 | } |
651 | } |
652 | if (anArgIter + 1 < theArgNb) |
653 | { |
654 | std::cout << "Syntax error: wrong number of arguments\n"; |
655 | return 1; |
656 | } |
657 | return 0; |
658 | } |
659 | else if (!aProgram.IsNull() |
660 | && aProgram->ShaderObjects().IsEmpty() |
661 | && (anArg == "-off" |
662 | || anArg == "off")) |
8e0a2b19 |
663 | { |
664 | aProgram.Nullify(); |
665 | } |
666 | else if (!aProgram.IsNull() |
667 | && aProgram->ShaderObjects().IsEmpty() |
668 | && (anArg == "-phong" |
669 | || anArg == "phong")) |
670 | { |
671 | const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder(); |
672 | if (aShadersRoot.IsEmpty()) |
673 | { |
674 | std::cout << "Error: both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n" |
675 | "At least one should be defined to load Phong program.\n"; |
676 | return 1; |
677 | } |
ee5befae |
678 | |
8e0a2b19 |
679 | const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs"; |
680 | const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs"; |
681 | if (!aSrcVert.IsEmpty() |
682 | && !OSD_File (aSrcVert).Exists()) |
683 | { |
684 | std::cout << "Error: PhongShading.vs is not found\n"; |
685 | return 1; |
686 | } |
687 | if (!aSrcFrag.IsEmpty() |
688 | && !OSD_File (aSrcFrag).Exists()) |
689 | { |
690 | std::cout << "Error: PhongShading.fs is not found\n"; |
691 | return 1; |
692 | } |
ee5befae |
693 | |
8e0a2b19 |
694 | aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert)); |
695 | aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag)); |
ee5befae |
696 | } |
8e0a2b19 |
697 | else if (aPrsList.IsEmpty() |
698 | && anArg == "*") |
ee5befae |
699 | { |
8e0a2b19 |
700 | // |
392ac980 |
701 | } |
8e0a2b19 |
702 | else if (!isSetGroupAspect |
703 | && anArgIter + 1 < theArgNb |
704 | && (anArg == "-primtype" |
705 | || anArg == "-primitivetype" |
706 | || anArg == "-groupaspect" |
707 | || anArg == "-aspecttype" |
708 | || anArg == "-aspect")) |
709 | { |
710 | isSetGroupAspect = true; |
711 | TCollection_AsciiString aPrimTypeStr (theArgVec[++anArgIter]); |
712 | aPrimTypeStr.LowerCase(); |
713 | if (aPrimTypeStr == "line") |
714 | { |
715 | aGroupAspect = Graphic3d_ASPECT_LINE; |
716 | } |
717 | else if (aPrimTypeStr == "tris" |
718 | || aPrimTypeStr == "triangles" |
719 | || aPrimTypeStr == "fill" |
720 | || aPrimTypeStr == "fillarea" |
721 | || aPrimTypeStr == "shading" |
722 | || aPrimTypeStr == "shade") |
723 | { |
724 | aGroupAspect = Graphic3d_ASPECT_FILL_AREA; |
725 | } |
726 | else if (aPrimTypeStr == "text") |
727 | { |
728 | aGroupAspect = Graphic3d_ASPECT_TEXT; |
729 | } |
730 | else if (aPrimTypeStr == "marker" |
731 | || aPrimTypeStr == "point" |
732 | || aPrimTypeStr == "pnt") |
733 | { |
734 | aGroupAspect = Graphic3d_ASPECT_MARKER; |
735 | } |
736 | else |
737 | { |
738 | std::cerr << "Syntax error at '" << aPrimTypeStr << "'\n"; |
739 | return 1; |
740 | } |
392ac980 |
741 | } |
8e0a2b19 |
742 | else if (anArgIter + 1 < theArgNb |
743 | && !aProgram.IsNull() |
744 | && aProgram->Header().IsEmpty() |
745 | && (anArg == "-version" |
746 | || anArg == "-glslversion" |
747 | || anArg == "-header" |
748 | || anArg == "-glslheader")) |
392ac980 |
749 | { |
8e0a2b19 |
750 | TCollection_AsciiString aHeader (theArgVec[++anArgIter]); |
751 | if (aHeader.IsIntegerValue()) |
752 | { |
753 | aHeader = TCollection_AsciiString ("#version ") + aHeader; |
754 | } |
755 | aProgram->SetHeader (aHeader); |
cc8cbabe |
756 | } |
8e0a2b19 |
757 | else if (!anArg.StartsWith ("-") |
758 | && GetMapOfAIS().IsBound2 (theArgVec[anArgIter])) |
cc8cbabe |
759 | { |
8f521168 |
760 | Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (theArgVec[anArgIter]); |
8e0a2b19 |
761 | if (anIO.IsNull()) |
762 | { |
763 | std::cerr << "Syntax error: " << theArgVec[anArgIter] << " is not an AIS object\n"; |
764 | return 1; |
765 | } |
766 | aPrsList.Append (anIO); |
392ac980 |
767 | } |
8e0a2b19 |
768 | else if (!aProgram.IsNull() |
769 | && ((anArgIter + 1 < theArgNb && parseShaderTypeArg (aShaderTypeArg, anArg)) |
770 | || (!isExplicitShaderType && aProgram->ShaderObjects().Size() < 2))) |
392ac980 |
771 | { |
8e0a2b19 |
772 | TCollection_AsciiString aShaderPath (theArgVec[anArgIter]); |
773 | if (aShaderTypeArg != Graphic3d_TypeOfShaderObject(-1)) |
392ac980 |
774 | { |
8e0a2b19 |
775 | aShaderPath = (theArgVec[++anArgIter]); |
776 | isExplicitShaderType = true; |
fb66bb28 |
777 | } |
778 | |
8e0a2b19 |
779 | const bool isSrcFile = OSD_File (aShaderPath).Exists(); |
780 | Handle(Graphic3d_ShaderObject) aShader = isSrcFile |
781 | ? Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aShaderPath) |
782 | : Graphic3d_ShaderObject::CreateFromSource(Graphic3d_TOS_VERTEX, aShaderPath); |
783 | const TCollection_AsciiString& aShaderSrc = aShader->Source(); |
784 | |
785 | const bool hasVertPos = aShaderSrc.Search ("gl_Position") != -1; |
b17e5bae |
786 | const bool hasFragColor = aShaderSrc.Search ("occSetFragColor") != -1 |
787 | || aShaderSrc.Search ("occFragColor") != -1 |
8e0a2b19 |
788 | || aShaderSrc.Search ("gl_FragColor") != -1 |
789 | || aShaderSrc.Search ("gl_FragData") != -1; |
790 | Graphic3d_TypeOfShaderObject aShaderType = aShaderTypeArg; |
791 | if (aShaderType == Graphic3d_TypeOfShaderObject(-1)) |
fb66bb28 |
792 | { |
8e0a2b19 |
793 | if (hasVertPos |
794 | && !hasFragColor) |
795 | { |
796 | aShaderType = Graphic3d_TOS_VERTEX; |
797 | } |
798 | if (hasFragColor |
799 | && !hasVertPos) |
800 | { |
801 | aShaderType = Graphic3d_TOS_FRAGMENT; |
802 | } |
392ac980 |
803 | } |
8e0a2b19 |
804 | if (aShaderType == Graphic3d_TypeOfShaderObject(-1)) |
fb66bb28 |
805 | { |
8e0a2b19 |
806 | std::cerr << "Error: non-existing or invalid shader source\n"; |
807 | return 1; |
fb66bb28 |
808 | } |
8e0a2b19 |
809 | |
810 | aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aShaderType, aShaderSrc)); |
811 | } |
812 | else |
813 | { |
814 | std::cerr << "Syntax error at '" << anArg << "'\n"; |
815 | return 1; |
392ac980 |
816 | } |
392ac980 |
817 | } |
818 | |
b17e5bae |
819 | if (!aProgram.IsNull() |
820 | && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT) |
821 | { |
822 | aProgram->SetNbFragmentOutputs (2); |
823 | aProgram->SetWeightOitOutput (true); |
824 | } |
825 | |
8e0a2b19 |
826 | ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS()); |
827 | NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (aPrsList); |
828 | const bool isGlobalList = aPrsList.IsEmpty(); |
829 | for (;;) |
392ac980 |
830 | { |
8e0a2b19 |
831 | Handle(AIS_InteractiveObject) anIO; |
832 | if (isGlobalList) |
392ac980 |
833 | { |
8e0a2b19 |
834 | if (!aGlobalPrsIter.More()) |
835 | { |
836 | break; |
837 | } |
8f521168 |
838 | anIO = aGlobalPrsIter.Key1(); |
8e0a2b19 |
839 | aGlobalPrsIter.Next(); |
840 | if (anIO.IsNull()) |
841 | { |
842 | continue; |
843 | } |
392ac980 |
844 | } |
8e0a2b19 |
845 | else |
392ac980 |
846 | { |
8e0a2b19 |
847 | if (!aPrsIter.More()) |
848 | { |
849 | break; |
850 | } |
851 | anIO = aPrsIter.Value(); |
852 | aPrsIter.Next(); |
392ac980 |
853 | } |
fb66bb28 |
854 | |
8e0a2b19 |
855 | if (anIO->Attributes()->SetShaderProgram (aProgram, aGroupAspect, true)) |
fb66bb28 |
856 | { |
fb66bb28 |
857 | aCtx->Redisplay (anIO, Standard_False); |
858 | } |
859 | else |
860 | { |
fb66bb28 |
861 | anIO->SynchronizeAspects(); |
862 | } |
392ac980 |
863 | } |
864 | |
865 | aCtx->UpdateCurrentViewer(); |
866 | return 0; |
867 | } |
868 | |
3946774d |
869 | //======================================================================= |
870 | //function : OpenGlCommands |
871 | //purpose : |
872 | //======================================================================= |
873 | |
874 | void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands) |
875 | { |
876 | const char* aGroup ="Commands for low-level TKOpenGl features"; |
877 | |
878 | theCommands.Add("vuserdraw", |
879 | "vuserdraw : name - simulates drawing with help of UserDraw", |
880 | __FILE__, VUserDraw, aGroup); |
3c4153af |
881 | theCommands.Add("vfeedback", |
882 | "vfeedback : perform test GL feedback rendering", |
883 | __FILE__, VFeedback, aGroup); |
1981cb22 |
884 | theCommands.Add("vimmediatefront", |
885 | "vimmediatefront : render immediate mode to front buffer or to back buffer", |
886 | __FILE__, VImmediateFront, aGroup); |
dac04bfa |
887 | theCommands.Add("vglinfo", |
26d9c835 |
888 | "vglinfo [-short|-basic|-complete]" |
889 | "\n\t\t: [GL_VENDOR] [GL_RENDERER] [GL_VERSION]" |
890 | "\n\t\t: [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]" |
891 | "\n\t\t: print OpenGL info", |
dac04bfa |
892 | __FILE__, VGlInfo, aGroup); |
8e0a2b19 |
893 | theCommands.Add("vshader", |
894 | "vshader name -vert VertexShader -frag FragmentShader [-geom GeometryShader]" |
895 | "\n\t\t: [-off] [-phong] [-aspect {shading|line|point|text}=shading]" |
896 | "\n\t\t: [-header VersionHeader]" |
897 | "\n\t\t: [-tessControl TessControlShader -tesseval TessEvaluationShader]" |
d95f5ce1 |
898 | "\n\t\t: Assign custom GLSL program to presentation aspects." |
899 | "\nvshader [-list] [-dump] [-reload] ShaderId" |
900 | "\n\t\t: -list prints the list of registered GLSL programs" |
901 | "\n\t\t: -dump dumps specified GLSL program (for debugging)" |
902 | "\n\t\t: -reload restores dump of specified GLSL program", |
392ac980 |
903 | __FILE__, VShaderProg, aGroup); |
8e0a2b19 |
904 | theCommands.Add("vshaderprog", "Alias for vshader", __FILE__, VShaderProg, aGroup); |
3946774d |
905 | } |