0030180: Data Exchange - VrmlAPI_Writer is expected to return export state
[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
b64d84be 183// =======================================================================
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// =======================================================================
8ed07085 209// function : AddText
b64d84be 210// purpose :
211// =======================================================================
8ed07085 212void OpenGl_Group::AddText (const Handle(Graphic3d_Text)& theTextParams,
213 const Standard_Boolean theToEvalMinMax)
b64d84be 214{
215 if (IsDeleted())
216 {
217 return;
218 }
219
8ed07085 220 if (theTextParams->Height() < 2.0)
ce01ec26 221 {
8ed07085 222 // TODO - this should be handled in different way (throw exception / take default text height without modifying Graphic3d_Text / log warning, etc.)
223 OpenGl_Structure* aStruct = GlStruct();
224 theTextParams->SetHeight (aStruct->GlDriver()->DefaultTextHeight());
ce01ec26 225 }
8ed07085 226 OpenGl_Text* aText = new OpenGl_Text (theTextParams);
ce01ec26 227
228 AddElement (aText);
8ed07085 229 Graphic3d_Group::AddText (theTextParams, theToEvalMinMax);
ce01ec26 230}
231
b64d84be 232// =======================================================================
233// function : SetFlippingOptions
234// purpose :
235// =======================================================================
236void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
237 const gp_Ax2& theRefPlane)
238{
239 OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
240 aFlipper->SetOptions (theIsEnabled);
241 AddElement (aFlipper);
242}
243
244// =======================================================================
245// function : SetStencilTestOptions
246// purpose :
247// =======================================================================
248void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
249{
250 OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
251 aStencilTest->SetOptions (theIsEnabled);
252 AddElement (aStencilTest);
253}
254
4269bd1b 255// =======================================================================
256// function : AddElement
257// purpose :
258// =======================================================================
5322131b 259void OpenGl_Group::AddElement (OpenGl_Element* theElem)
2166f0fa 260{
e276548b 261 OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
262
e276548b 263 aNode->elem = theElem;
264 aNode->next = NULL;
265 (myLast? myLast->next : myFirst) = aNode;
266 myLast = aNode;
267
e276548b 268 if (OpenGl_Raytrace::IsRaytracedElement (aNode))
269 {
e276548b 270 myIsRaytracable = Standard_True;
2166f0fa 271
b64d84be 272 OpenGl_Structure* aStruct = GlStruct();
273 if (aStruct != NULL)
e276548b 274 {
d4aaad5b 275 aStruct->UpdateStateIfRaytracable (Standard_False);
e276548b 276 }
277 }
2166f0fa
SK
278}
279
4269bd1b 280// =======================================================================
281// function : Render
282// purpose :
283// =======================================================================
bf75be98 284void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
2166f0fa 285{
2166f0fa 286 // Setup aspects
25c35042 287 theWorkspace->SetAllowFaceCulling (myIsClosed
288 && !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn());
bf5f0ca2 289 const OpenGl_Aspects* aBackAspects = theWorkspace->Aspects();
290 const bool isAspectSet = myAspects != NULL && renderFiltered (theWorkspace, myAspects);
2166f0fa
SK
291
292 // Render group elements
bf75be98 293 for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
2166f0fa 294 {
1b661a81 295 renderFiltered (theWorkspace, aNodeIter->elem);
2166f0fa
SK
296 }
297
298 // Restore aspects
bf5f0ca2 299 if (isAspectSet)
300 theWorkspace->SetAspects (aBackAspects);
2166f0fa
SK
301}
302
b64d84be 303// =======================================================================
304// function : Clear
305// purpose :
306// =======================================================================
307void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
308{
309 if (IsDeleted())
310 {
311 return;
312 }
313
314 OpenGl_Structure* aStruct = GlStruct();
315 const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
316
317 Release (aCtx);
318 Graphic3d_Group::Clear (theToUpdateStructureMgr);
d4aaad5b 319
320 myIsRaytracable = Standard_False;
b64d84be 321}
322
4269bd1b 323// =======================================================================
324// function : Release
325// purpose :
326// =======================================================================
5e27df78 327void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
328{
329 // Delete elements
330 while (myFirst != NULL)
331 {
332 OpenGl_ElementNode* aNext = myFirst->next;
ad67e367 333 OpenGl_Element::Destroy (theGlCtx.get(), myFirst->elem);
5e27df78 334 delete myFirst;
335 myFirst = aNext;
336 }
337 myLast = NULL;
338
ad67e367 339 OpenGl_Element::Destroy (theGlCtx.get(), myAspects);
5e27df78 340}