1 // Created on: 2014-03-31
2 // Created by: Danila ULYANOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_Layer.hxx>
18 #include <OpenGl_BVHTreeSelector.hxx>
19 #include <OpenGl_Structure.hxx>
20 #include <OpenGl_View.hxx>
21 #include <OpenGl_Workspace.hxx>
23 // =======================================================================
24 // function : OpenGl_PriorityList
26 // =======================================================================
27 OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
28 : myArray (0, theNbPriorities - 1),
30 myBVHIsLeftChildQueuedFirst (Standard_True),
31 myIsBVHPrimitivesNeedsReset (Standard_False)
36 // =======================================================================
37 // function : ~OpenGl_Layer
39 // =======================================================================
40 OpenGl_Layer::~OpenGl_Layer()
45 // =======================================================================
48 // =======================================================================
49 void OpenGl_Layer::Add (const OpenGl_Structure* theStruct,
50 const Standard_Integer thePriority,
51 Standard_Boolean isForChangePriority)
53 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
54 if (theStruct == NULL)
59 myArray (anIndex).Add (theStruct);
60 if (theStruct->IsAlwaysRendered())
62 theStruct->MarkAsNotCulled();
64 else if (!isForChangePriority)
66 myBVHPrimitives.Add (theStruct);
71 // =======================================================================
74 // =======================================================================
75 bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
76 Standard_Integer& thePriority,
77 Standard_Boolean isForChangePriority)
79 if (theStruct == NULL)
85 const Standard_Integer aNbPriorities = myArray.Length();
86 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
88 OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
90 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
93 aStructures.Swap (anIndex, aStructures.Size());
94 aStructures.RemoveLast();
96 if (!theStruct->IsAlwaysRendered()
97 && !isForChangePriority)
99 myBVHPrimitives.Remove (theStruct);
102 thePriority = aPriorityIter;
111 // =======================================================================
112 // function : InvalidateBVHData
114 // =======================================================================
115 void OpenGl_Layer::InvalidateBVHData()
117 myIsBVHPrimitivesNeedsReset = Standard_True;
120 // =======================================================================
121 // function : renderAll
123 // =======================================================================
124 void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
126 const Standard_Integer aNbPriorities = myArray.Length();
127 const Standard_Integer aViewId = theWorkspace->ActiveViewId();
128 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
130 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
131 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
133 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
134 if (!aStruct->IsVisible())
138 else if (!aStruct->ViewAffinity.IsNull()
139 && !aStruct->ViewAffinity->IsVisible (aViewId))
144 aStruct->Render (theWorkspace);
149 // =======================================================================
150 // function : renderTraverse
152 // =======================================================================
153 void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
155 if (myIsBVHPrimitivesNeedsReset)
157 myBVHPrimitives.Assign (myArray);
158 myIsBVHPrimitivesNeedsReset = Standard_False;
161 OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
162 traverse (aSelector);
164 const Standard_Integer aNbPriorities = myArray.Length();
165 const Standard_Integer aViewId = theWorkspace->ActiveViewId();
166 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
168 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
169 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
171 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
172 if (!aStruct->IsVisible()
173 || aStruct->IsCulled())
177 else if (!aStruct->ViewAffinity.IsNull()
178 && !aStruct->ViewAffinity->IsVisible (aViewId))
183 aStruct->Render (theWorkspace);
184 aStruct->ResetCullingStatus();
189 // =======================================================================
190 // function : traverse
192 // =======================================================================
193 void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
195 // handle a case when all objects are infinite
196 if (myBVHPrimitives.Size() == 0)
199 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
201 Standard_Integer aNode = 0; // a root node
202 theSelector.CacheClipPtsProjections();
203 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
204 aBVHTree->MaxPoint (0)))
209 Standard_Integer aStack[32];
210 Standard_Integer aHead = -1;
213 if (!aBVHTree->IsOuter (aNode))
215 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
216 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
217 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
218 aBVHTree->MaxPoint (aLeftChildIdx));
219 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
220 aBVHTree->MaxPoint (aRightChildIdx));
224 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
225 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
226 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
228 else if (isLeftChildIn
231 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
240 aNode = aStack[aHead--];
245 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
246 myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
252 aNode = aStack[aHead--];
257 // =======================================================================
260 // =======================================================================
261 Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
263 // the source priority list shouldn't have more priorities
264 const Standard_Integer aNbPriorities = theOther.NbPriorities();
265 if (aNbPriorities > NbPriorities())
267 return Standard_False;
270 // add all structures to destination priority list
271 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
273 const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
274 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
276 Add (aStructures.FindKey (aStructIdx), aPriorityIter);
280 return Standard_True;
283 //=======================================================================
286 //=======================================================================
287 void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
288 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
290 TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
292 // separate depth buffers
293 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
295 glClear (GL_DEPTH_BUFFER_BIT);
299 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
301 // assuming depth test is enabled by default
302 glDepthFunc (theDefaultSettings.DepthFunc);
306 glDepthFunc (GL_ALWAYS);
309 // handle depth offset
310 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
312 theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
313 myLayerSettings.DepthOffsetFactor,
314 myLayerSettings.DepthOffsetUnits);
318 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
319 anAppliedOffsetParams.factor,
320 anAppliedOffsetParams.units);
323 // handle depth write
324 glDepthMask (IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? GL_TRUE : GL_FALSE);
326 // render priority list
327 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
329 // always restore polygon offset between layers rendering
330 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
331 anAppliedOffsetParams.factor,
332 anAppliedOffsetParams.units);