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