1 // Created on: 2011-11-02
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-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_PriorityList.hxx>
18 #include <OpenGl_BVHTreeSelector.hxx>
19 #include <OpenGl_Structure.hxx>
20 #include <OpenGl_View.hxx>
22 // =======================================================================
23 // function : OpenGl_PriorityList
25 // =======================================================================
26 OpenGl_PriorityList::OpenGl_PriorityList (const Standard_Integer theNbPriorities)
27 : myArray (0, theNbPriorities - 1),
29 myBVHIsLeftChildQueuedFirst (Standard_True),
30 myIsBVHPrimitivesNeedsReset (Standard_False)
35 // =======================================================================
36 // function : ~OpenGl_PriorityList
38 // =======================================================================
39 OpenGl_PriorityList::~OpenGl_PriorityList()
44 // =======================================================================
47 // =======================================================================
48 void OpenGl_PriorityList::Add (const OpenGl_Structure* theStructure,
49 const Standard_Integer thePriority,
50 Standard_Boolean isForChangePriority)
52 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
54 myArray (anIndex).Append (theStructure);
55 if (theStructure->IsAlwaysRendered())
57 theStructure->MarkAsNotCulled();
59 else if (!isForChangePriority)
61 myBVHPrimitives.Add (theStructure);
66 // =======================================================================
69 // =======================================================================
70 Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure* theStructure,
71 Standard_Boolean isForChangePriority)
73 const Standard_Integer aNbPriorities = myArray.Length();
74 OpenGl_SequenceOfStructure::Iterator aStructIter;
75 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
77 OpenGl_SequenceOfStructure& aSeq = myArray (aPriorityIter);
78 for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
80 if (aStructIter.Value() == theStructure)
82 aSeq.Remove (aStructIter);
83 if (!theStructure->IsAlwaysRendered()
84 && !isForChangePriority)
86 myBVHPrimitives.Remove (theStructure);
97 // =======================================================================
98 // function : InvalidateBVHData
100 // =======================================================================
101 void OpenGl_PriorityList::InvalidateBVHData()
103 myIsBVHPrimitivesNeedsReset = Standard_True;
106 // =======================================================================
109 // =======================================================================
110 void OpenGl_PriorityList::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
112 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
115 // =======================================================================
116 // function : renderAll
118 // =======================================================================
119 void OpenGl_PriorityList::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
121 const Standard_Integer aNbPriorities = myArray.Length();
122 OpenGl_SequenceOfStructure::Iterator aStructIter;
123 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
125 for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
127 aStructIter.Value()->Render (theWorkspace);
132 // =======================================================================
133 // function : renderTraverse
135 // =======================================================================
136 void OpenGl_PriorityList::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
138 if (myIsBVHPrimitivesNeedsReset)
140 myBVHPrimitives.Assign (myArray);
141 myIsBVHPrimitivesNeedsReset = Standard_False;
144 OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
145 traverse (aSelector);
147 const Standard_Integer aNbPriorities = myArray.Length();
148 OpenGl_SequenceOfStructure::Iterator aStructIter;
149 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
151 for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
153 if (!aStructIter.Value()->IsCulled())
155 aStructIter.Value()->Render (theWorkspace);
156 aStructIter.Value()->ResetCullingStatus();
162 // =======================================================================
163 // function : traverse
165 // =======================================================================
166 void OpenGl_PriorityList::traverse (OpenGl_BVHTreeSelector& theSelector) const
168 // handle a case when all objects are infinite
169 if (myBVHPrimitives.Size() == 0)
172 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
174 Standard_Integer aNode = 0; // a root node
175 theSelector.CacheClipPtsProjections();
176 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
177 aBVHTree->MaxPoint (0)))
182 Standard_Integer aStack[32];
183 Standard_Integer aHead = -1;
186 if (!aBVHTree->IsOuter (aNode))
188 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
189 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
190 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
191 aBVHTree->MaxPoint (aLeftChildIdx));
192 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
193 aBVHTree->MaxPoint (aRightChildIdx));
197 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
199 aStack[aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
200 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
202 else if (isLeftChildIn
205 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
214 aNode = aStack[aHead];
220 if (theSelector.Intersect (aBVHTree->MinPoint (aNode),
221 aBVHTree->MaxPoint (aNode)))
223 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
224 myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
230 aNode = aStack[aHead];
237 // =======================================================================
240 // =======================================================================
241 Standard_Boolean OpenGl_PriorityList::Append (const OpenGl_PriorityList& theOther)
243 // the source priority list shouldn't have more priorities
244 const Standard_Integer aNbPriorities = theOther.NbPriorities ();
245 if (aNbPriorities > NbPriorities())
247 return Standard_False;
250 // add all structures to destination priority list
251 OpenGl_SequenceOfStructure::Iterator aStructIter;
252 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
254 const OpenGl_SequenceOfStructure& aSeq = theOther.myArray (aPriorityIter);
255 for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
257 Add (aStructIter.Value(), aPriorityIter);
261 return Standard_True;
264 // =======================================================================
265 // function : NbPriorities
267 // =======================================================================
268 Standard_Integer OpenGl_PriorityList::NbPriorities() const
270 return myArray.Length();