0029729: Visualization, Graphic3d_ClipPlane - add support of clipping plane chains
[occt.git] / src / OpenGl / OpenGl_Group.cxx
1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_Group.hxx>
17
18 #include <OpenGl_GraphicDriver.hxx>
19 #include <OpenGl_Flipper.hxx>
20 #include <OpenGl_PrimitiveArray.hxx>
21 #include <OpenGl_SceneGeometry.hxx>
22 #include <OpenGl_StencilTest.hxx>
23 #include <OpenGl_Structure.hxx>
24 #include <OpenGl_Text.hxx>
25 #include <OpenGl_Workspace.hxx>
26
27 #include <Graphic3d_ArrayOfPrimitives.hxx>
28 #include <Graphic3d_GroupDefinitionError.hxx>
29
30
31 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group,Graphic3d_Group)
32
33 // =======================================================================
34 // function : OpenGl_Group
35 // purpose  :
36 // =======================================================================
37 OpenGl_Group::OpenGl_Group (const Handle(Graphic3d_Structure)& theStruct)
38 : Graphic3d_Group (theStruct),
39   myAspectLine(NULL),
40   myAspectFace(NULL),
41   myAspectMarker(NULL),
42   myAspectText(NULL),
43   myFirst(NULL),
44   myLast(NULL),
45   myIsRaytracable (Standard_False)
46 {
47   Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
48   if (aStruct.IsNull())
49   {
50     throw Graphic3d_GroupDefinitionError("OpenGl_Group should be created by OpenGl_Structure!");
51   }
52 }
53
54 // =======================================================================
55 // function : ~OpenGl_Group
56 // purpose  :
57 // =======================================================================
58 OpenGl_Group::~OpenGl_Group()
59 {
60   Release (Handle(OpenGl_Context)());
61 }
62
63 // =======================================================================
64 // function : SetGroupPrimitivesAspect
65 // purpose  :
66 // =======================================================================
67 void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectLine3d)& theAspect)
68 {
69   if (IsDeleted())
70   {
71     return;
72   }
73
74   if (myAspectLine == NULL)
75   {
76     myAspectLine = new OpenGl_AspectLine (theAspect);
77   }
78   else
79   {
80     myAspectLine->SetAspect (theAspect);
81   }
82   Update();
83 }
84
85 // =======================================================================
86 // function : SetPrimitivesAspect
87 // purpose  :
88 // =======================================================================
89 void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectLine3d)& theAspect)
90 {
91   if (myAspectLine == NULL)
92   {
93     SetGroupPrimitivesAspect (theAspect);
94     return;
95   }
96   else if (IsDeleted())
97   {
98     return;
99   }
100
101   OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine (theAspect);
102   AddElement (anAspectLine);
103   Update();
104 }
105
106 // =======================================================================
107 // function : SetGroupPrimitivesAspect
108 // purpose  :
109 // =======================================================================
110 void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
111 {
112   if (IsDeleted())
113   {
114     return;
115   }
116
117   if (myAspectFace == NULL)
118   {
119     myAspectFace = new OpenGl_AspectFace (theAspect);
120   }
121   else
122   {
123     myAspectFace->SetAspect (theAspect);
124   }
125
126   if (myIsRaytracable)
127   {
128     OpenGl_Structure* aStruct = GlStruct();
129     if (aStruct != NULL)
130     {
131       aStruct->UpdateStateIfRaytracable (Standard_False);
132     }
133   }
134
135   Update();
136 }
137
138 // =======================================================================
139 // function : SetPrimitivesAspect
140 // purpose  :
141 // =======================================================================
142 void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
143 {
144   if (myAspectFace == NULL)
145   {
146     SetGroupPrimitivesAspect (theAspect);
147     return;
148   }
149   else if (IsDeleted())
150   {
151     return;
152   }
153
154   OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace (theAspect);
155   AddElement (anAspectFace);
156   Update();
157 }
158
159 // =======================================================================
160 // function : SetGroupPrimitivesAspect
161 // purpose  :
162 // =======================================================================
163 void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d)& theAspMarker)
164 {
165   if (IsDeleted())
166   {
167     return;
168   }
169
170   if (myAspectMarker == NULL)
171   {
172     myAspectMarker = new OpenGl_AspectMarker (theAspMarker);
173   }
174   else
175   {
176     myAspectMarker->SetAspect (theAspMarker);
177   }
178   Update();
179 }
180
181 // =======================================================================
182 // function : SetPrimitivesAspect
183 // purpose  :
184 // =======================================================================
185 void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d)& theAspMarker)
186 {
187   if (myAspectMarker == NULL)
188   {
189     SetGroupPrimitivesAspect (theAspMarker);
190     return;
191   }
192   else if (IsDeleted())
193   {
194     return;
195   }
196
197   OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker (theAspMarker);
198   AddElement (anAspectMarker);
199   Update();
200 }
201
202 // =======================================================================
203 // function : SetGroupPrimitivesAspect
204 // purpose  :
205 // =======================================================================
206 void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectText3d)& theAspText)
207 {
208   if (IsDeleted())
209   {
210     return;
211   }
212
213   if (myAspectText == NULL)
214   {
215     myAspectText = new OpenGl_AspectText (theAspText);
216   }
217   else
218   {
219     myAspectText->SetAspect (theAspText);
220   }
221   Update();
222 }
223
224 // =======================================================================
225 // function : SetPrimitivesAspect
226 // purpose  :
227 // =======================================================================
228 void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectText3d)& theAspText)
229 {
230   if (myAspectText == NULL)
231   {
232     SetGroupPrimitivesAspect (theAspText);
233     return;
234   }
235   else if (IsDeleted())
236   {
237     return;
238   }
239
240   OpenGl_AspectText* anAspectText = new OpenGl_AspectText (theAspText);
241   AddElement (anAspectText);
242   Update();
243 }
244
245 // =======================================================================
246 // function : AddPrimitiveArray
247 // purpose  :
248 // =======================================================================
249 void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType,
250                                       const Handle(Graphic3d_IndexBuffer)& theIndices,
251                                       const Handle(Graphic3d_Buffer)&      theAttribs,
252                                       const Handle(Graphic3d_BoundBuffer)& theBounds,
253                                       const Standard_Boolean               theToEvalMinMax)
254 {
255   if (IsDeleted()
256    || theAttribs.IsNull())
257   {
258     return;
259   }
260
261   OpenGl_Structure* aStruct = GlStruct();
262   const OpenGl_GraphicDriver* aDriver = aStruct->GlDriver();
263
264   OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds);
265   AddElement (anArray);
266
267   Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax);
268 }
269
270 // =======================================================================
271 // function : Text
272 // purpose  :
273 // =======================================================================
274 void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
275                          const Graphic3d_Vertex&                 thePoint,
276                          const Standard_Real                     theHeight,
277                          const Standard_Real                     theAngle,
278                          const Graphic3d_TextPath                theTp,
279                          const Graphic3d_HorizontalTextAlignment theHta,
280                          const Graphic3d_VerticalTextAlignment   theVta,
281                          const Standard_Boolean                  theToEvalMinMax)
282 {
283   if (IsDeleted())
284   {
285     return;
286   }
287
288   OpenGl_TextParam  aParams;
289   OpenGl_Structure* aStruct = GlStruct();
290   aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
291   aParams.HAlign = theHta;
292   aParams.VAlign = theVta;
293   const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
294   OpenGl_Text* aText = new OpenGl_Text (theTextUtf, aPoint, aParams);
295   AddElement (aText);
296   Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle,
297                          theTp, theHta, theVta, theToEvalMinMax);
298 }
299
300 // =======================================================================
301 // function : Text
302 // purpose  :
303 // =======================================================================
304 void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
305                          const gp_Ax2&                           theOrientation,
306                          const Standard_Real                     theHeight,
307                          const Standard_Real                     theAngle,
308                          const Graphic3d_TextPath                theTp,
309                          const Graphic3d_HorizontalTextAlignment theHTA,
310                          const Graphic3d_VerticalTextAlignment   theVTA,
311                          const Standard_Boolean                  theToEvalMinMax,
312                          const Standard_Boolean                  theHasOwnAnchor)
313 {
314   if (IsDeleted())
315   {
316     return;
317   }
318
319   OpenGl_TextParam  aParams;
320   OpenGl_Structure* aStruct = GlStruct();
321
322   aParams.Height      = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
323   aParams.HAlign      = theHTA;
324   aParams.VAlign      = theVTA;
325
326   OpenGl_Text* aText = new OpenGl_Text (theTextUtf, theOrientation, aParams, theHasOwnAnchor != Standard_False);
327
328   AddElement (aText);
329
330   Graphic3d_Group::Text (theTextUtf,
331                          theOrientation,
332                          theHeight,
333                          theAngle,
334                          theTp,
335                          theHTA,
336                          theVTA,
337                          theToEvalMinMax,
338                          theHasOwnAnchor);
339
340 }
341
342 // =======================================================================
343 // function : SetFlippingOptions
344 // purpose  :
345 // =======================================================================
346 void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
347                                        const gp_Ax2&          theRefPlane)
348 {
349   OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
350   aFlipper->SetOptions (theIsEnabled);
351   AddElement (aFlipper);
352 }
353
354 // =======================================================================
355 // function : SetStencilTestOptions
356 // purpose  :
357 // =======================================================================
358 void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
359 {
360   OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
361   aStencilTest->SetOptions (theIsEnabled);
362   AddElement (aStencilTest);
363 }
364
365 // =======================================================================
366 // function : AddElement
367 // purpose  :
368 // =======================================================================
369 void OpenGl_Group::AddElement (OpenGl_Element* theElem)
370 {
371   OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
372
373   aNode->elem = theElem;
374   aNode->next = NULL;
375   (myLast? myLast->next : myFirst) = aNode;
376   myLast = aNode;
377
378   if (OpenGl_Raytrace::IsRaytracedElement (aNode))
379   {
380     myIsRaytracable = Standard_True;
381
382     OpenGl_Structure* aStruct = GlStruct();
383     if (aStruct != NULL)
384     {
385       aStruct->UpdateStateIfRaytracable (Standard_False);
386     }
387   }
388 }
389
390 // =======================================================================
391 // function : Render
392 // purpose  :
393 // =======================================================================
394 void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
395 {
396   const Handle(OpenGl_RenderFilter)& aFilter = theWorkspace->GetRenderFilter();
397
398   // Setup aspects
399   theWorkspace->SetAllowFaceCulling (myIsClosed
400                                  && !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn());
401   const OpenGl_AspectLine*   aBackAspectLine   = theWorkspace->AspectLine();
402   const OpenGl_AspectFace*   aBackAspectFace   = theWorkspace->AspectFace();
403   const OpenGl_AspectMarker* aBackAspectMarker = theWorkspace->AspectMarker();
404   const OpenGl_AspectText*   aBackAspectText   = theWorkspace->AspectText();
405   Standard_Boolean isLineSet   = myAspectLine   && myAspectLine->RenderFiltered (theWorkspace, aFilter);
406   Standard_Boolean isFaceSet   = myAspectFace   && myAspectFace->RenderFiltered (theWorkspace, aFilter);
407   Standard_Boolean isMarkerSet = myAspectMarker && myAspectMarker->RenderFiltered (theWorkspace, aFilter);
408   Standard_Boolean isTextSet   = myAspectText   && myAspectText->RenderFiltered (theWorkspace, aFilter);
409
410   // Render group elements
411   for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
412   {
413     aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
414   }
415
416   // Restore aspects
417   if (isLineSet)
418     theWorkspace->SetAspectLine (aBackAspectLine);
419   if (isFaceSet)
420     theWorkspace->SetAspectFace (aBackAspectFace);
421   if (isMarkerSet)
422     theWorkspace->SetAspectMarker (aBackAspectMarker);
423   if (isTextSet)
424     theWorkspace->SetAspectText (aBackAspectText);
425 }
426
427 // =======================================================================
428 // function : Clear
429 // purpose  :
430 // =======================================================================
431 void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
432 {
433   if (IsDeleted())
434   {
435     return;
436   }
437
438   OpenGl_Structure* aStruct = GlStruct();
439   const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
440
441   Release (aCtx);
442   Graphic3d_Group::Clear (theToUpdateStructureMgr);
443
444   myIsRaytracable = Standard_False;
445 }
446
447 // =======================================================================
448 // function : Release
449 // purpose  :
450 // =======================================================================
451 void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
452 {
453   // Delete elements
454   while (myFirst != NULL)
455   {
456     OpenGl_ElementNode* aNext = myFirst->next;
457     OpenGl_Element::Destroy (theGlCtx.operator->(), myFirst->elem);
458     delete myFirst;
459     myFirst = aNext;
460   }
461   myLast = NULL;
462
463   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
464   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
465   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
466   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
467 }