0024682: Move out B-spline cache from curves and surfaces to dedicated classes BSplCL...
[occt.git] / src / OpenGl / OpenGl_Layer.cxx
CommitLineData
c5751993 1// Created on: 2014-03-31
2// Created by: Danila ULYANOV
3// Copyright (c) 2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
0a36ca0a 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
c5751993 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_Layer.hxx>
a1954302 17
18#include <OpenGl_BVHTreeSelector.hxx>
19#include <OpenGl_Structure.hxx>
20#include <OpenGl_View.hxx>
550f3b8b 21#include <OpenGl_Workspace.hxx>
c5751993 22
a1954302 23// =======================================================================
24// function : OpenGl_PriorityList
25// purpose :
26// =======================================================================
c5751993 27OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
a1954302 28: myArray (0, theNbPriorities - 1),
29 myNbStructures (0),
30 myBVHIsLeftChildQueuedFirst (Standard_True),
31 myIsBVHPrimitivesNeedsReset (Standard_False)
c5751993 32{
33 //
34}
35
a1954302 36// =======================================================================
37// function : ~OpenGl_Layer
38// purpose :
39// =======================================================================
40OpenGl_Layer::~OpenGl_Layer()
41{
42 //
43}
44
45// =======================================================================
46// function : Add
47// purpose :
48// =======================================================================
49void OpenGl_Layer::Add (const OpenGl_Structure* theStruct,
50 const Standard_Integer thePriority,
51 Standard_Boolean isForChangePriority)
52{
53 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
54 if (theStruct == NULL)
55 {
56 return;
57 }
58
59 myArray (anIndex).Append (theStruct);
60 if (theStruct->IsAlwaysRendered())
61 {
62 theStruct->MarkAsNotCulled();
63 }
64 else if (!isForChangePriority)
65 {
66 myBVHPrimitives.Add (theStruct);
67 }
68 ++myNbStructures;
69}
70
71// =======================================================================
72// function : Remove
73// purpose :
74// =======================================================================
75bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
76 Standard_Integer& thePriority,
77 Standard_Boolean isForChangePriority)
78{
79 if (theStruct == NULL)
80 {
81 thePriority = -1;
82 return false;
83 }
84
85 const Standard_Integer aNbPriorities = myArray.Length();
86 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
87 {
88 OpenGl_SequenceOfStructure& aSeq = myArray (aPriorityIter);
89 for (OpenGl_SequenceOfStructure::Iterator aStructIter (aSeq); aStructIter.More(); aStructIter.Next())
90 {
91 if (aStructIter.Value() == theStruct)
92 {
93 aSeq.Remove (aStructIter);
94 if (!theStruct->IsAlwaysRendered()
95 && !isForChangePriority)
96 {
97 myBVHPrimitives.Remove (theStruct);
98 }
99 --myNbStructures;
100 thePriority = aPriorityIter;
101 return true;
102 }
103 }
104 }
105
106 thePriority = -1;
107 return false;
108}
109
110// =======================================================================
111// function : InvalidateBVHData
112// purpose :
113// =======================================================================
114void OpenGl_Layer::InvalidateBVHData()
115{
116 myIsBVHPrimitivesNeedsReset = Standard_True;
117}
118
119// =======================================================================
120// function : renderAll
121// purpose :
122// =======================================================================
123void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
124{
125 const Standard_Integer aNbPriorities = myArray.Length();
a272ed94 126 const Standard_Integer aViewId = theWorkspace->ActiveViewId();
a1954302 127 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
128 {
129 for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
130 {
131 const OpenGl_Structure* aStruct = aStructIter.Value();
132 if (!aStruct->IsVisible())
133 {
134 continue;
135 }
a272ed94 136 else if (!aStruct->ViewAffinity.IsNull()
137 && !aStruct->ViewAffinity->IsVisible (aViewId))
138 {
139 continue;
140 }
a1954302 141
142 aStruct->Render (theWorkspace);
143 }
144 }
145}
146
147// =======================================================================
148// function : renderTraverse
149// purpose :
150// =======================================================================
151void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
152{
153 if (myIsBVHPrimitivesNeedsReset)
154 {
155 myBVHPrimitives.Assign (myArray);
156 myIsBVHPrimitivesNeedsReset = Standard_False;
157 }
158
159 OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
160 traverse (aSelector);
161
162 const Standard_Integer aNbPriorities = myArray.Length();
a272ed94 163 const Standard_Integer aViewId = theWorkspace->ActiveViewId();
a1954302 164 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
165 {
166 for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
167 {
168 const OpenGl_Structure* aStruct = aStructIter.Value();
169 if (!aStruct->IsVisible()
170 || aStruct->IsCulled())
171 {
172 continue;
173 }
a272ed94 174 else if (!aStruct->ViewAffinity.IsNull()
175 && !aStruct->ViewAffinity->IsVisible (aViewId))
176 {
177 continue;
178 }
a1954302 179
180 aStruct->Render (theWorkspace);
181 aStruct->ResetCullingStatus();
182 }
183 }
184}
185
186// =======================================================================
187// function : traverse
188// purpose :
189// =======================================================================
190void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
191{
192 // handle a case when all objects are infinite
193 if (myBVHPrimitives.Size() == 0)
194 return;
195
196 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
197
198 Standard_Integer aNode = 0; // a root node
199 theSelector.CacheClipPtsProjections();
200 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
201 aBVHTree->MaxPoint (0)))
202 {
203 return;
204 }
205
206 Standard_Integer aStack[32];
207 Standard_Integer aHead = -1;
208 for (;;)
209 {
210 if (!aBVHTree->IsOuter (aNode))
211 {
212 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
213 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
214 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
215 aBVHTree->MaxPoint (aLeftChildIdx));
216 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
217 aBVHTree->MaxPoint (aRightChildIdx));
218 if (isLeftChildIn
219 && isRightChildIn)
220 {
221 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
14a35e5d 222 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
a1954302 223 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
224 }
225 else if (isLeftChildIn
226 || isRightChildIn)
227 {
228 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
229 }
230 else
231 {
232 if (aHead < 0)
233 {
234 return;
235 }
236
14a35e5d 237 aNode = aStack[aHead--];
a1954302 238 }
239 }
240 else
241 {
14a35e5d 242 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
243 myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
244 if (aHead < 0)
a1954302 245 {
14a35e5d 246 return;
a1954302 247 }
14a35e5d 248
249 aNode = aStack[aHead--];
a1954302 250 }
251 }
252}
253
254// =======================================================================
255// function : Append
256// purpose :
257// =======================================================================
258Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
259{
260 // the source priority list shouldn't have more priorities
261 const Standard_Integer aNbPriorities = theOther.NbPriorities();
262 if (aNbPriorities > NbPriorities())
263 {
264 return Standard_False;
265 }
266
267 // add all structures to destination priority list
268 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
269 {
270 for (OpenGl_SequenceOfStructure::Iterator aStructIter (theOther.myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
271 {
272 Add (aStructIter.Value(), aPriorityIter);
273 }
274 }
275
276 return Standard_True;
277}
278
c5751993 279//=======================================================================
280//function : Render
a1954302 281//purpose :
c5751993 282//=======================================================================
a1954302 283void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
284 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
c5751993 285{
550f3b8b 286 TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
287
c5751993 288 // separate depth buffers
289 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
290 {
291 glClear (GL_DEPTH_BUFFER_BIT);
292 }
550f3b8b 293
c5751993 294 // handle depth test
295 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
296 {
550f3b8b 297 // assuming depth test is enabled by default
298 glDepthFunc (theDefaultSettings.DepthFunc);
c5751993 299 }
300 else
301 {
302 glDepthFunc (GL_ALWAYS);
303 }
550f3b8b 304
c5751993 305 // handle depth offset
306 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
307 {
550f3b8b 308 theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
309 myLayerSettings.DepthOffsetFactor,
310 myLayerSettings.DepthOffsetUnits);
c5751993 311 }
312 else
313 {
550f3b8b 314 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
315 anAppliedOffsetParams.factor,
316 anAppliedOffsetParams.units);
c5751993 317 }
318
319 // handle depth write
a1954302 320 glDepthMask (IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? GL_TRUE : GL_FALSE);
c5751993 321
322 // render priority list
a1954302 323 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
550f3b8b 324
325 // always restore polygon offset between layers rendering
326 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
327 anAppliedOffsetParams.factor,
328 anAppliedOffsetParams.units);
c5751993 329}