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