0030679: Attached model hangs most of OCCT common functionality
[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),
bf5f0ca2 61 myAspects(NULL),
e276548b 62 myFirst(NULL),
b64d84be 63 myLast(NULL),
d4aaad5b 64 myIsRaytracable (Standard_False)
2166f0fa 65{
b64d84be 66 Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
c04c30b3 67 if (aStruct.IsNull())
b64d84be 68 {
9775fa61 69 throw Graphic3d_GroupDefinitionError("OpenGl_Group should be created by OpenGl_Structure!");
b64d84be 70 }
2166f0fa
SK
71}
72
4269bd1b 73// =======================================================================
74// function : ~OpenGl_Group
75// purpose :
76// =======================================================================
2166f0fa
SK
77OpenGl_Group::~OpenGl_Group()
78{
5e27df78 79 Release (Handle(OpenGl_Context)());
2166f0fa
SK
80}
81
4269bd1b 82// =======================================================================
b6472664 83// function : SetGroupPrimitivesAspect
4269bd1b 84// purpose :
85// =======================================================================
bf5f0ca2 86void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect)
2166f0fa 87{
b6472664 88 if (IsDeleted())
b64d84be 89 {
90 return;
91 }
92
bf5f0ca2 93 if (myAspects == NULL)
2166f0fa 94 {
bf5f0ca2 95 myAspects = new OpenGl_Aspects (theAspect);
2166f0fa
SK
96 }
97 else
98 {
bf5f0ca2 99 myAspects->SetAspect (theAspect);
b6472664 100 }
101
bf5f0ca2 102 if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
b6472664 103 {
bf5f0ca2 104 aStruct->UpdateStateIfRaytracable (Standard_False);
e276548b 105 }
b6472664 106
107 Update();
2166f0fa
SK
108}
109
4269bd1b 110// =======================================================================
b6472664 111// function : SetPrimitivesAspect
4269bd1b 112// purpose :
113// =======================================================================
bf5f0ca2 114void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect)
2166f0fa 115{
bf5f0ca2 116 if (myAspects == NULL)
b6472664 117 {
118 SetGroupPrimitivesAspect (theAspect);
119 return;
120 }
121 else if (IsDeleted())
b64d84be 122 {
123 return;
124 }
125
bf5f0ca2 126 OpenGl_Aspects* anAspects = new OpenGl_Aspects (theAspect);
127 AddElement (anAspects);
b6472664 128 Update();
2166f0fa
SK
129}
130
4269bd1b 131// =======================================================================
bf5f0ca2 132// function : SynchronizeAspects
b6472664 133// purpose :
134// =======================================================================
bf5f0ca2 135void OpenGl_Group::SynchronizeAspects()
b6472664 136{
bf5f0ca2 137 if (myAspects != NULL)
b6472664 138 {
bf5f0ca2 139 myAspects->SynchronizeAspects();
140 if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
141 {
142 aStruct->UpdateStateIfRaytracable (Standard_False);
143 }
2166f0fa 144 }
bf5f0ca2 145 for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next)
2166f0fa 146 {
bf5f0ca2 147 aNode->elem->SynchronizeAspects();
b6472664 148 }
b6472664 149}
150
151// =======================================================================
bf5f0ca2 152// function : ReplaceAspects
b6472664 153// purpose :
154// =======================================================================
bf5f0ca2 155void OpenGl_Group::ReplaceAspects (const Graphic3d_MapOfAspectsToAspects& theMap)
b6472664 156{
bf5f0ca2 157 if (theMap.IsEmpty())
b6472664 158 {
159 return;
2166f0fa 160 }
b6472664 161
bf5f0ca2 162 Handle(Graphic3d_Aspects) anAspect;
163 if (myAspects != NULL
164 && theMap.Find (myAspects->Aspect(), anAspect))
eaac0866 165 {
bf5f0ca2 166 myAspects->SetAspect (anAspect);
167 if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
168 {
169 aStruct->UpdateStateIfRaytracable (Standard_False);
170 }
eaac0866 171 }
172 for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next)
173 {
bf5f0ca2 174 OpenGl_Aspects* aGlAspect = dynamic_cast<OpenGl_Aspects*> (aNode->elem);
175 if (aGlAspect != NULL
176 && theMap.Find (aGlAspect->Aspect(), anAspect))
177 {
178 aGlAspect->SetAspect (anAspect);
179 }
eaac0866 180 }
181}
182
183// =======================================================================
b64d84be 184// function : AddPrimitiveArray
185// purpose :
186// =======================================================================
871fa103 187void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType,
188 const Handle(Graphic3d_IndexBuffer)& theIndices,
189 const Handle(Graphic3d_Buffer)& theAttribs,
190 const Handle(Graphic3d_BoundBuffer)& theBounds,
191 const Standard_Boolean theToEvalMinMax)
b64d84be 192{
193 if (IsDeleted()
871fa103 194 || theAttribs.IsNull())
b64d84be 195 {
196 return;
197 }
198
8d3f219f 199 OpenGl_Structure* aStruct = GlStruct();
200 const OpenGl_GraphicDriver* aDriver = aStruct->GlDriver();
201
202 OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds);
b64d84be 203 AddElement (anArray);
204
871fa103 205 Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax);
b64d84be 206}
207
208// =======================================================================
209// function : Text
210// purpose :
211// =======================================================================
212void OpenGl_Group::Text (const Standard_CString theTextUtf,
213 const Graphic3d_Vertex& thePoint,
214 const Standard_Real theHeight,
ee2be2a8 215 const Standard_Real theAngle,
b64d84be 216 const Graphic3d_TextPath theTp,
217 const Graphic3d_HorizontalTextAlignment theHta,
218 const Graphic3d_VerticalTextAlignment theVta,
219 const Standard_Boolean theToEvalMinMax)
220{
221 if (IsDeleted())
222 {
223 return;
224 }
225
226 OpenGl_TextParam aParams;
227 OpenGl_Structure* aStruct = GlStruct();
228 aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
229 aParams.HAlign = theHta;
230 aParams.VAlign = theVta;
231 const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
232 OpenGl_Text* aText = new OpenGl_Text (theTextUtf, aPoint, aParams);
233 AddElement (aText);
234 Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle,
235 theTp, theHta, theVta, theToEvalMinMax);
236}
237
238// =======================================================================
ce01ec26 239// function : Text
240// purpose :
241// =======================================================================
242void OpenGl_Group::Text (const Standard_CString theTextUtf,
243 const gp_Ax2& theOrientation,
244 const Standard_Real theHeight,
ee2be2a8 245 const Standard_Real theAngle,
ce01ec26 246 const Graphic3d_TextPath theTp,
247 const Graphic3d_HorizontalTextAlignment theHTA,
248 const Graphic3d_VerticalTextAlignment theVTA,
3f1eb0ab 249 const Standard_Boolean theToEvalMinMax,
250 const Standard_Boolean theHasOwnAnchor)
ce01ec26 251{
252 if (IsDeleted())
253 {
254 return;
255 }
256
257 OpenGl_TextParam aParams;
258 OpenGl_Structure* aStruct = GlStruct();
259
260 aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
261 aParams.HAlign = theHTA;
262 aParams.VAlign = theVTA;
263
3f1eb0ab 264 OpenGl_Text* aText = new OpenGl_Text (theTextUtf, theOrientation, aParams, theHasOwnAnchor != Standard_False);
ce01ec26 265
266 AddElement (aText);
267
268 Graphic3d_Group::Text (theTextUtf,
269 theOrientation,
270 theHeight,
271 theAngle,
272 theTp,
273 theHTA,
274 theVTA,
3f1eb0ab 275 theToEvalMinMax,
276 theHasOwnAnchor);
ce01ec26 277
278}
279
280// =======================================================================
b64d84be 281// function : SetFlippingOptions
282// purpose :
283// =======================================================================
284void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
285 const gp_Ax2& theRefPlane)
286{
287 OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
288 aFlipper->SetOptions (theIsEnabled);
289 AddElement (aFlipper);
290}
291
292// =======================================================================
293// function : SetStencilTestOptions
294// purpose :
295// =======================================================================
296void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
297{
298 OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
299 aStencilTest->SetOptions (theIsEnabled);
300 AddElement (aStencilTest);
301}
302
303// =======================================================================
4269bd1b 304// function : AddElement
305// purpose :
306// =======================================================================
5322131b 307void OpenGl_Group::AddElement (OpenGl_Element* theElem)
2166f0fa 308{
e276548b 309 OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
310
e276548b 311 aNode->elem = theElem;
312 aNode->next = NULL;
313 (myLast? myLast->next : myFirst) = aNode;
314 myLast = aNode;
315
e276548b 316 if (OpenGl_Raytrace::IsRaytracedElement (aNode))
317 {
e276548b 318 myIsRaytracable = Standard_True;
2166f0fa 319
b64d84be 320 OpenGl_Structure* aStruct = GlStruct();
321 if (aStruct != NULL)
e276548b 322 {
d4aaad5b 323 aStruct->UpdateStateIfRaytracable (Standard_False);
e276548b 324 }
325 }
2166f0fa
SK
326}
327
4269bd1b 328// =======================================================================
329// function : Render
330// purpose :
331// =======================================================================
bf75be98 332void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
2166f0fa 333{
2166f0fa 334 // Setup aspects
25c35042 335 theWorkspace->SetAllowFaceCulling (myIsClosed
336 && !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn());
bf5f0ca2 337 const OpenGl_Aspects* aBackAspects = theWorkspace->Aspects();
338 const bool isAspectSet = myAspects != NULL && renderFiltered (theWorkspace, myAspects);
2166f0fa
SK
339
340 // Render group elements
bf75be98 341 for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
2166f0fa 342 {
1b661a81 343 renderFiltered (theWorkspace, aNodeIter->elem);
2166f0fa
SK
344 }
345
346 // Restore aspects
bf5f0ca2 347 if (isAspectSet)
348 theWorkspace->SetAspects (aBackAspects);
2166f0fa
SK
349}
350
4269bd1b 351// =======================================================================
b64d84be 352// function : Clear
353// purpose :
354// =======================================================================
355void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
356{
357 if (IsDeleted())
358 {
359 return;
360 }
361
362 OpenGl_Structure* aStruct = GlStruct();
363 const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
364
365 Release (aCtx);
366 Graphic3d_Group::Clear (theToUpdateStructureMgr);
d4aaad5b 367
368 myIsRaytracable = Standard_False;
b64d84be 369}
370
371// =======================================================================
4269bd1b 372// function : Release
373// purpose :
374// =======================================================================
5e27df78 375void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
376{
377 // Delete elements
378 while (myFirst != NULL)
379 {
380 OpenGl_ElementNode* aNext = myFirst->next;
ad67e367 381 OpenGl_Element::Destroy (theGlCtx.get(), myFirst->elem);
5e27df78 382 delete myFirst;
383 myFirst = aNext;
384 }
385 myLast = NULL;
386
ad67e367 387 OpenGl_Element::Destroy (theGlCtx.get(), myAspects);
5e27df78 388}