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> |
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 | |
5e27df78 |
103 | virtual void Release (const Handle(OpenGl_Context)& theGlCtx) |
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 | |
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_AspectFace* aFA = theWorkspace->AspectFace(0); |
174 | aFA->Context(); |
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 | |
198 | |
199 | |
200 | OpenGl_Element* VUserDrawCallback(const CALL_DEF_USERDRAW * theUserDraw) |
201 | { |
202 | Handle(VUserDrawObj) anIObj = (VUserDrawObj*)theUserDraw->Data; |
203 | if (anIObj.IsNull()) |
204 | { |
205 | std::cout << "VUserDrawCallback error: null object passed, the custom scene element will not be rendered" << std::endl; |
206 | } |
207 | |
208 | return new VUserDrawObj::Element(anIObj, theUserDraw->Bounds); |
209 | } |
210 | |
211 | static Standard_Integer VUserDraw (Draw_Interpretor& di, |
212 | Standard_Integer argc, |
213 | const char ** argv) |
214 | { |
215 | Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext(); |
216 | if (aContext.IsNull()) |
217 | { |
218 | di << argv[0] << "Call 'vinit' before!\n"; |
219 | return 1; |
220 | } |
221 | |
5e27df78 |
222 | Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Device()->GraphicDriver()); |
223 | if (aDriver.IsNull()) |
224 | { |
225 | std::cerr << "Graphic driver not available.\n"; |
226 | return 1; |
227 | } |
228 | |
3946774d |
229 | if (argc > 2) |
230 | { |
231 | di << argv[0] << "Wrong number of arguments, only the object name expected\n"; |
232 | return 1; |
233 | } |
234 | |
235 | TCollection_AsciiString aName (argv[1]); |
236 | VDisplayAISObject(aName, Handle(AIS_InteractiveObject)()); |
237 | |
238 | // register the custom element factory function |
5e27df78 |
239 | aDriver->UserDrawCallback() = VUserDrawCallback; |
3946774d |
240 | |
241 | Handle(VUserDrawObj) anIObj = new VUserDrawObj(); |
242 | VDisplayAISObject(aName, anIObj); |
243 | |
244 | return 0; |
245 | } |
246 | |
3c4153af |
247 | //============================================================================== |
248 | //function : VFeedback |
249 | //purpose : |
250 | //============================================================================== |
251 | |
252 | static int VFeedback (Draw_Interpretor& theDI, |
253 | Standard_Integer theArgNb, |
254 | const char** theArgVec) |
255 | { |
256 | // get the active view |
257 | Handle(V3d_View) aView = ViewerTest::CurrentView(); |
258 | if (aView.IsNull()) |
259 | { |
260 | std::cerr << "No active view. Please call vinit.\n"; |
261 | return 1; |
262 | } |
263 | |
264 | unsigned int aBufferSize = 1024 * 1024; |
265 | for (;;) |
266 | { |
267 | size_t aBytes = (size_t )aBufferSize * sizeof(GLfloat); |
268 | if (aBytes / sizeof(GLfloat) != (size_t )aBufferSize) |
269 | { |
270 | // finito la commedia |
271 | std::cerr << "Can not allocate buffer - requested size (" |
272 | << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat))) |
273 | << " MiB) is out of address space\n"; |
274 | return 1; |
275 | } |
276 | |
277 | GLfloat* aBuffer = (GLfloat* )Standard::Allocate (aBytes); |
278 | if (aBuffer == NULL) |
279 | { |
280 | // finito la commedia |
281 | std::cerr << "Can not allocate buffer with size (" |
282 | << (double(aBufferSize / (1024 * 1024)) * double(sizeof(GLfloat))) |
283 | << " MiB)\n"; |
284 | return 1; |
285 | } |
286 | |
287 | glFeedbackBuffer ((GLsizei )aBufferSize, GL_2D, aBuffer); |
288 | glRenderMode (GL_FEEDBACK); |
289 | |
290 | aView->Redraw(); |
291 | |
292 | GLint aResult = glRenderMode (GL_RENDER); |
293 | if (aResult < 0) |
294 | { |
295 | aBufferSize *= 2; |
296 | |
297 | void* aPtr = aBuffer; |
298 | Standard::Free (aPtr); |
299 | aBuffer = NULL; |
300 | continue; |
301 | } |
302 | |
303 | std::cout << "FeedBack result= " << aResult << "\n"; |
304 | GLint aPntNb = 0; |
305 | GLint aTriNb = 0; |
306 | GLint aQuadsNb = 0; |
307 | GLint aPolyNb = 0; |
308 | GLint aNodesNb = 0; |
309 | GLint aLinesNb = 0; |
310 | GLint aBitmapsNb = 0; |
311 | GLint aPassThrNb = 0; |
312 | GLint aUnknownNb = 0; |
313 | const GLint NODE_VALUES = 2; // GL_2D |
314 | for (GLint anIter = 0; anIter < aResult;) |
315 | { |
316 | const GLfloat aPos = aBuffer[anIter]; |
317 | switch ((GLint )aPos) |
318 | { |
319 | case GL_POINT_TOKEN: |
320 | { |
321 | ++aPntNb; |
322 | ++aNodesNb; |
323 | anIter += 1 + NODE_VALUES; |
324 | break; |
325 | } |
326 | case GL_LINE_RESET_TOKEN: |
327 | case GL_LINE_TOKEN: |
328 | { |
329 | ++aLinesNb; |
330 | aNodesNb += 2; |
331 | anIter += 1 + 2 * NODE_VALUES; |
332 | break; |
333 | } |
334 | case GL_POLYGON_TOKEN: |
335 | { |
336 | const GLint aCount = (GLint )aBuffer[++anIter]; |
337 | aNodesNb += aCount; |
338 | anIter += aCount * NODE_VALUES + 1; |
339 | if (aCount == 3) |
340 | { |
341 | ++aTriNb; |
342 | } |
343 | else if (aCount == 4) |
344 | { |
345 | ++aQuadsNb; |
346 | } |
347 | else |
348 | { |
349 | ++aPolyNb; |
350 | } |
351 | break; |
352 | } |
353 | case GL_BITMAP_TOKEN: |
354 | case GL_DRAW_PIXEL_TOKEN: |
355 | case GL_COPY_PIXEL_TOKEN: |
356 | { |
357 | ++aBitmapsNb; |
358 | anIter += 1 + NODE_VALUES; |
359 | break; |
360 | } |
361 | case GL_PASS_THROUGH_TOKEN: |
362 | { |
363 | ++aPassThrNb; |
364 | anIter += 2; // header + value |
365 | break; |
366 | } |
367 | default: |
368 | { |
369 | ++anIter; |
370 | ++aUnknownNb; |
371 | break; |
372 | } |
373 | } |
374 | } |
375 | void* aPtr = aBuffer; |
376 | Standard::Free (aPtr); |
377 | |
378 | // return statistics |
379 | theDI << "Total nodes: " << aNodesNb << "\n" |
380 | << "Points: " << aPntNb << "\n" |
381 | << "Line segments: " << aLinesNb << "\n" |
382 | << "Triangles: " << aTriNb << "\n" |
383 | << "Quads: " << aQuadsNb << "\n" |
384 | << "Polygons: " << aPolyNb << "\n" |
385 | << "Bitmap tokens: " << aBitmapsNb << "\n" |
386 | << "Pass through: " << aPassThrNb << "\n" |
387 | << "UNKNOWN: " << aUnknownNb << "\n"; |
388 | |
389 | double aLen2D = double(aNodesNb * 2 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb); |
390 | double aLen3D = double(aNodesNb * 3 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb); |
391 | double aLen3D_rgba = double(aNodesNb * 7 + aPntNb + aLinesNb * 2 + (aTriNb + aQuadsNb + aPolyNb) * 2 + aBitmapsNb + aPassThrNb); |
392 | theDI << "Buffer size GL_2D: " << aLen2D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n" |
393 | << "Buffer size GL_3D: " << aLen3D * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n" |
394 | << "Buffer size GL_3D_COLOR: " << aLen3D_rgba * double(sizeof(GLfloat)) / double(1024 * 1024) << " MiB\n"; |
395 | return 0; |
396 | } |
397 | } |
398 | |
3946774d |
399 | //======================================================================= |
400 | //function : OpenGlCommands |
401 | //purpose : |
402 | //======================================================================= |
403 | |
404 | void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands) |
405 | { |
406 | const char* aGroup ="Commands for low-level TKOpenGl features"; |
407 | |
408 | theCommands.Add("vuserdraw", |
409 | "vuserdraw : name - simulates drawing with help of UserDraw", |
410 | __FILE__, VUserDraw, aGroup); |
3c4153af |
411 | theCommands.Add("vfeedback", |
412 | "vfeedback : perform test GL feedback rendering", |
413 | __FILE__, VFeedback, aGroup); |
3946774d |
414 | } |