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