0024023: Revamp the OCCT Handle -- general
[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_StencilTest.hxx>
22 #include <OpenGl_Structure.hxx>
23 #include <OpenGl_Text.hxx>
24 #include <OpenGl_Workspace.hxx>
25
26 #include <Graphic3d_ArrayOfPrimitives.hxx>
27 #include <Graphic3d_CUserDraw.hxx>
28 #include <Graphic3d_GroupDefinitionError.hxx>
29
30
31 // =======================================================================
32 // function : OpenGl_Group
33 // purpose  :
34 // =======================================================================
35 OpenGl_Group::OpenGl_Group (const Handle(Graphic3d_Structure)& theStruct)
36 : Graphic3d_Group (theStruct),
37   myAspectLine(NULL),
38   myAspectFace(NULL),
39   myAspectMarker(NULL),
40   myAspectText(NULL),
41   myFirst(NULL),
42   myLast(NULL),
43   myIsRaytracable (Standard_False)
44 {
45   Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
46   if (aStruct.IsNull())
47   {
48     Graphic3d_GroupDefinitionError::Raise ("OpenGl_Group should be created by OpenGl_Structure!");
49   }
50 }
51
52 // =======================================================================
53 // function : ~OpenGl_Group
54 // purpose  :
55 // =======================================================================
56 OpenGl_Group::~OpenGl_Group()
57 {
58   Release (Handle(OpenGl_Context)());
59 }
60
61 // =======================================================================
62 // function : UpdateAspectLine
63 // purpose  :
64 // =======================================================================
65 void OpenGl_Group::UpdateAspectLine (const Standard_Boolean theIsGlobal)
66 {
67   if (!ContextLine.IsDef)
68   {
69     return;
70   }
71
72   if (theIsGlobal || myFirst == NULL)
73   {
74     if (myAspectLine == NULL)
75     {
76       myAspectLine = new OpenGl_AspectLine();
77     }
78     myAspectLine->SetAspect (ContextLine);
79   }
80   else
81   {
82     OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
83     anAspectLine->SetAspect (ContextLine);
84     AddElement (anAspectLine);
85   }
86 }
87
88 // =======================================================================
89 // function : UpdateAspectFace
90 // purpose  :
91 // =======================================================================
92 void OpenGl_Group::UpdateAspectFace (const Standard_Boolean theIsGlobal)
93 {
94   if (!ContextFillArea.IsDef)
95   {
96     return;
97   }
98
99   if (theIsGlobal || myFirst == NULL)
100   {
101     if (myAspectFace == NULL)
102     {
103       myAspectFace = new OpenGl_AspectFace();
104     }
105     myAspectFace->SetAspect (ContextFillArea);
106   }
107   else
108   {
109     OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
110     anAspectFace->SetAspect (ContextFillArea);
111     AddElement (anAspectFace);
112   }
113
114   if (myIsRaytracable)
115   {
116     OpenGl_Structure* aStruct = GlStruct();
117     if (aStruct != NULL)
118     {
119       aStruct->UpdateStateIfRaytracable (Standard_False);
120     }
121   }
122 }
123
124 // =======================================================================
125 // function : UpdateAspectMarker
126 // purpose  :
127 // =======================================================================
128 void OpenGl_Group::UpdateAspectMarker (const Standard_Boolean theIsGlobal)
129 {
130   if (!ContextMarker.IsDef)
131   {
132     return;
133   }
134
135   if (theIsGlobal || myFirst == NULL)
136   {
137     if (myAspectMarker == NULL)
138     {
139       myAspectMarker = new OpenGl_AspectMarker();
140     }
141     myAspectMarker->SetAspect (ContextMarker);
142   }
143   else
144   {
145     OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
146     anAspectMarker->SetAspect (ContextMarker);
147     AddElement (anAspectMarker);
148   }
149 }
150
151 // =======================================================================
152 // function : UpdateAspectText
153 // purpose  :
154 // =======================================================================
155 void OpenGl_Group::UpdateAspectText (const Standard_Boolean theIsGlobal)
156 {
157   if (!ContextText.IsDef)
158   {
159     return;
160   }
161
162   if (theIsGlobal || myFirst == NULL)
163   {
164     if (myAspectText == NULL)
165     {
166       myAspectText = new OpenGl_AspectText();
167     }
168     myAspectText->SetAspect (ContextText);
169   }
170   else
171   {
172     OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
173     anAspectText->SetAspect (ContextText);
174     AddElement (anAspectText);
175   }
176 }
177
178 // =======================================================================
179 // function : AddPrimitiveArray
180 // purpose  :
181 // =======================================================================
182 void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType,
183                                       const Handle(Graphic3d_IndexBuffer)& theIndices,
184                                       const Handle(Graphic3d_Buffer)&      theAttribs,
185                                       const Handle(Graphic3d_BoundBuffer)& theBounds,
186                                       const Standard_Boolean               theToEvalMinMax)
187 {
188   if (IsDeleted()
189    || theAttribs.IsNull())
190   {
191     return;
192   }
193
194   OpenGl_Structure* aStruct = GlStruct();
195   const OpenGl_GraphicDriver* aDriver = aStruct->GlDriver();
196
197   OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds);
198   AddElement (anArray);
199
200   Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax);
201 }
202
203 // =======================================================================
204 // function : Text
205 // purpose  :
206 // =======================================================================
207 void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
208                          const Graphic3d_Vertex&                 thePoint,
209                          const Standard_Real                     theHeight,
210                          const Quantity_PlaneAngle               theAngle,
211                          const Graphic3d_TextPath                theTp,
212                          const Graphic3d_HorizontalTextAlignment theHta,
213                          const Graphic3d_VerticalTextAlignment   theVta,
214                          const Standard_Boolean                  theToEvalMinMax)
215 {
216   if (IsDeleted())
217   {
218     return;
219   }
220
221   OpenGl_TextParam  aParams;
222   OpenGl_Structure* aStruct = GlStruct();
223   aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
224   aParams.HAlign = theHta;
225   aParams.VAlign = theVta;
226   const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
227   OpenGl_Text* aText = new OpenGl_Text (theTextUtf, aPoint, aParams);
228   AddElement (aText);
229   Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle,
230                          theTp, theHta, theVta, theToEvalMinMax);
231 }
232
233 // =======================================================================
234 // function : UserDraw
235 // purpose  :
236 // =======================================================================
237 void OpenGl_Group::UserDraw (const Standard_Address theObject,
238                              const Standard_Boolean theToEvalMinMax,
239                              const Standard_Boolean theContainsFacet)
240 {
241   if (IsDeleted())
242   {
243     return;
244   }
245
246   OpenGl_Structure* aStruct = GlStruct();
247   if (aStruct->GlDriver()->UserDrawCallback() == NULL)
248   {
249     return;
250   }
251
252   Graphic3d_CUserDraw aUserDraw;
253   aUserDraw.Data   = theObject;
254   aUserDraw.Bounds = theToEvalMinMax ? &myBounds : NULL;
255   OpenGl_Element* aUserDrawElem = aStruct->GlDriver()->UserDrawCallback()(&aUserDraw);
256   if (aUserDrawElem != NULL)
257   {
258     AddElement (aUserDrawElem);
259   }
260   Graphic3d_Group::UserDraw (theObject, theToEvalMinMax, theContainsFacet);
261 }
262
263 // =======================================================================
264 // function : SetFlippingOptions
265 // purpose  :
266 // =======================================================================
267 void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
268                                        const gp_Ax2&          theRefPlane)
269 {
270   OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
271   aFlipper->SetOptions (theIsEnabled);
272   AddElement (aFlipper);
273 }
274
275 // =======================================================================
276 // function : SetStencilTestOptions
277 // purpose  :
278 // =======================================================================
279 void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
280 {
281   OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
282   aStencilTest->SetOptions (theIsEnabled);
283   AddElement (aStencilTest);
284 }
285
286 // =======================================================================
287 // function : AddElement
288 // purpose  :
289 // =======================================================================
290 void OpenGl_Group::AddElement (OpenGl_Element* theElem)
291 {
292   OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
293
294   aNode->elem = theElem;
295   aNode->next = NULL;
296   (myLast? myLast->next : myFirst) = aNode;
297   myLast = aNode;
298
299   if (OpenGl_Raytrace::IsRaytracedElement (aNode))
300   {
301     myIsRaytracable = Standard_True;
302
303     OpenGl_Structure* aStruct = GlStruct();
304     if (aStruct != NULL)
305     {
306       aStruct->UpdateStateIfRaytracable (Standard_False);
307     }
308   }
309 }
310
311 // =======================================================================
312 // function : Render
313 // purpose  :
314 // =======================================================================
315 void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
316 {
317   // Is rendering in ADD or IMMEDIATE mode?
318   const Handle(OpenGl_RenderFilter)& aFilter = theWorkspace->GetRenderFilter();
319
320   // Setup aspects
321   const OpenGl_AspectLine*   aBackAspectLine   = theWorkspace->AspectLine   (Standard_False);
322   const OpenGl_AspectFace*   aBackAspectFace   = theWorkspace->AspectFace   (Standard_False);
323   const OpenGl_AspectMarker* aBackAspectMarker = theWorkspace->AspectMarker (Standard_False);
324   const OpenGl_AspectText*   aBackAspectText   = theWorkspace->AspectText   (Standard_False);
325   Standard_Boolean isLineSet   = myAspectLine   && myAspectLine->RenderFiltered (theWorkspace, aFilter);
326   Standard_Boolean isFaceSet   = myAspectFace   && myAspectFace->RenderFiltered (theWorkspace, aFilter);
327   Standard_Boolean isMarkerSet = myAspectMarker && myAspectMarker->RenderFiltered (theWorkspace, aFilter);
328   Standard_Boolean isTextSet   = myAspectText   && myAspectText->RenderFiltered (theWorkspace, aFilter);
329
330   // Render group elements
331   for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
332   {
333     aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
334   }
335
336   // Restore aspects
337   if (isLineSet)
338     theWorkspace->SetAspectLine (aBackAspectLine);
339   if (isFaceSet)
340     theWorkspace->SetAspectFace (aBackAspectFace);
341   if (isMarkerSet)
342     theWorkspace->SetAspectMarker (aBackAspectMarker);
343   if (isTextSet)
344     theWorkspace->SetAspectText (aBackAspectText);
345 }
346
347 // =======================================================================
348 // function : Clear
349 // purpose  :
350 // =======================================================================
351 void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
352 {
353   if (IsDeleted())
354   {
355     return;
356   }
357
358   OpenGl_Structure* aStruct = GlStruct();
359   const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
360
361   Release (aCtx);
362   Graphic3d_Group::Clear (theToUpdateStructureMgr);
363
364   myIsRaytracable = Standard_False;
365 }
366
367 // =======================================================================
368 // function : Release
369 // purpose  :
370 // =======================================================================
371 void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
372 {
373   // Delete elements
374   while (myFirst != NULL)
375   {
376     OpenGl_ElementNode* aNext = myFirst->next;
377     OpenGl_Element::Destroy (theGlCtx.operator->(), myFirst->elem);
378     delete myFirst;
379     myFirst = aNext;
380   }
381   myLast = NULL;
382
383   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
384   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
385   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
386   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
387 }