0025219: Visualization, TKOpenGl - disable code paths unavailable on OpenGL ES 2.0
[occt.git] / src / OpenGl / OpenGl_PriorityList.cxx
1 // Created on: 2011-11-02
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_PriorityList.hxx>
17
18 #include <OpenGl_BVHTreeSelector.hxx>
19 #include <OpenGl_Structure.hxx>
20 #include <OpenGl_View.hxx>
21
22 // =======================================================================
23 // function : OpenGl_PriorityList
24 // purpose  :
25 // =======================================================================
26 OpenGl_PriorityList::OpenGl_PriorityList (const Standard_Integer theNbPriorities)
27 : myArray (0, theNbPriorities - 1),
28   myNbStructures (0),
29   myBVHIsLeftChildQueuedFirst (Standard_True),
30   myIsBVHPrimitivesNeedsReset (Standard_False)
31 {
32   //
33 }
34
35 // =======================================================================
36 // function : ~OpenGl_PriorityList
37 // purpose  :
38 // =======================================================================
39 OpenGl_PriorityList::~OpenGl_PriorityList()
40 {
41   //
42 }
43
44 // =======================================================================
45 // function : Add
46 // purpose  :
47 // =======================================================================
48 void OpenGl_PriorityList::Add (const OpenGl_Structure* theStructure,
49                                const Standard_Integer  thePriority,
50                                Standard_Boolean isForChangePriority)
51 {
52   const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
53
54   myArray (anIndex).Append (theStructure);
55   if (theStructure->IsAlwaysRendered())
56   {
57     theStructure->MarkAsNotCulled();
58   }
59   else if (!isForChangePriority)
60   {
61     myBVHPrimitives.Add (theStructure);
62   }
63   ++myNbStructures;
64 }
65
66 // =======================================================================
67 // function : Remove
68 // purpose  :
69 // =======================================================================
70 Standard_Integer OpenGl_PriorityList::Remove (const OpenGl_Structure* theStructure,
71                                               Standard_Boolean isForChangePriority)
72 {
73   const Standard_Integer aNbPriorities = myArray.Length();
74   OpenGl_SequenceOfStructure::Iterator aStructIter;
75   for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
76   {
77     OpenGl_SequenceOfStructure& aSeq = myArray (aPriorityIter);
78     for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
79     {
80       if (aStructIter.Value() == theStructure)
81       {
82         aSeq.Remove (aStructIter);
83         if (!theStructure->IsAlwaysRendered()
84             && !isForChangePriority)
85         {
86           myBVHPrimitives.Remove (theStructure);
87         }
88         --myNbStructures;
89         return aPriorityIter;
90       }
91     }
92   }
93
94   return -1;
95 }
96
97 // =======================================================================
98 // function : InvalidateBVHData
99 // purpose  :
100 // =======================================================================
101 void OpenGl_PriorityList::InvalidateBVHData()
102 {
103   myIsBVHPrimitivesNeedsReset = Standard_True;
104 }
105
106 // =======================================================================
107 // function : Render
108 // purpose  :
109 // =======================================================================
110 void OpenGl_PriorityList::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
111 {
112   theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
113 }
114
115 // =======================================================================
116 // function : renderAll
117 // purpose  :
118 // =======================================================================
119 void OpenGl_PriorityList::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
120 {
121   const Standard_Integer aNbPriorities = myArray.Length();
122   OpenGl_SequenceOfStructure::Iterator aStructIter;
123   for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
124   {
125     for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
126     {
127       aStructIter.Value()->Render (theWorkspace);
128     }
129   }
130 }
131
132 // =======================================================================
133 // function : renderTraverse
134 // purpose  :
135 // =======================================================================
136 void OpenGl_PriorityList::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
137 {
138   if (myIsBVHPrimitivesNeedsReset)
139   {
140     myBVHPrimitives.Assign (myArray);
141     myIsBVHPrimitivesNeedsReset = Standard_False;
142   }
143
144   OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
145   traverse (aSelector);
146
147   const Standard_Integer aNbPriorities = myArray.Length();
148   OpenGl_SequenceOfStructure::Iterator aStructIter;
149   for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
150   {
151     for (aStructIter.Init (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
152     {
153       if (!aStructIter.Value()->IsCulled())
154       {
155         aStructIter.Value()->Render (theWorkspace);
156         aStructIter.Value()->ResetCullingStatus();
157       }
158     }
159   }
160 }
161
162 // =======================================================================
163 // function : traverse
164 // purpose  :
165 // =======================================================================
166 void OpenGl_PriorityList::traverse (OpenGl_BVHTreeSelector& theSelector) const
167 {
168   // handle a case when all objects are infinite
169   if (myBVHPrimitives.Size() == 0)
170     return;
171
172   const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
173
174   Standard_Integer aNode = 0; // a root node
175   theSelector.CacheClipPtsProjections();
176   if (!theSelector.Intersect (aBVHTree->MinPoint (0),
177                               aBVHTree->MaxPoint (0)))
178   {
179     return;
180   }
181
182   Standard_Integer aStack[32];
183   Standard_Integer aHead = -1;
184   for (;;)
185   {
186     if (!aBVHTree->IsOuter (aNode))
187     {
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));
194       if (isLeftChildIn
195        && isRightChildIn)
196       {
197         aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
198         ++aHead;
199         aStack[aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
200         myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
201       }
202       else if (isLeftChildIn
203             || isRightChildIn)
204       {
205         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
206       }
207       else
208       {
209         if (aHead < 0)
210         {
211           return;
212         }
213
214         aNode = aStack[aHead];
215         --aHead;
216       }
217     }
218     else
219     {
220       if (theSelector.Intersect (aBVHTree->MinPoint (aNode),
221                                  aBVHTree->MaxPoint (aNode)))
222       {
223         Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
224         myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
225         if (aHead < 0)
226         {
227           return;
228         }
229
230         aNode = aStack[aHead];
231         --aHead;
232       }
233     }
234   }
235 }
236
237 // =======================================================================
238 // function : Append
239 // purpose  :
240 // =======================================================================
241 Standard_Boolean OpenGl_PriorityList::Append (const OpenGl_PriorityList& theOther)
242 {
243   // the source priority list shouldn't have more priorities
244   const Standard_Integer aNbPriorities = theOther.NbPriorities ();
245   if (aNbPriorities > NbPriorities())
246   {
247     return Standard_False;
248   }
249
250   // add all structures to destination priority list
251   OpenGl_SequenceOfStructure::Iterator aStructIter;
252   for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
253   {
254     const OpenGl_SequenceOfStructure& aSeq = theOther.myArray (aPriorityIter);
255     for (aStructIter.Init (aSeq); aStructIter.More(); aStructIter.Next())
256     {
257       Add (aStructIter.Value(), aPriorityIter);
258     }
259   }
260
261   return Standard_True;
262 }
263
264 // =======================================================================
265 // function : NbPriorities
266 // purpose  :
267 // =======================================================================
268 Standard_Integer OpenGl_PriorityList::NbPriorities() const
269 {
270   return myArray.Length();
271 }