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