0025867: Visualization, TKOpenGl - fix misprint in transformation persistence math
[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();
126 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
127 {
128 for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
129 {
130 const OpenGl_Structure* aStruct = aStructIter.Value();
131 if (!aStruct->IsVisible())
132 {
133 continue;
134 }
135
136 aStruct->Render (theWorkspace);
137 }
138 }
139}
140
141// =======================================================================
142// function : renderTraverse
143// purpose :
144// =======================================================================
145void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
146{
147 if (myIsBVHPrimitivesNeedsReset)
148 {
149 myBVHPrimitives.Assign (myArray);
150 myIsBVHPrimitivesNeedsReset = Standard_False;
151 }
152
153 OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
154 traverse (aSelector);
155
156 const Standard_Integer aNbPriorities = myArray.Length();
157 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
158 {
159 for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
160 {
161 const OpenGl_Structure* aStruct = aStructIter.Value();
162 if (!aStruct->IsVisible()
163 || aStruct->IsCulled())
164 {
165 continue;
166 }
167
168 aStruct->Render (theWorkspace);
169 aStruct->ResetCullingStatus();
170 }
171 }
172}
173
174// =======================================================================
175// function : traverse
176// purpose :
177// =======================================================================
178void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
179{
180 // handle a case when all objects are infinite
181 if (myBVHPrimitives.Size() == 0)
182 return;
183
184 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
185
186 Standard_Integer aNode = 0; // a root node
187 theSelector.CacheClipPtsProjections();
188 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
189 aBVHTree->MaxPoint (0)))
190 {
191 return;
192 }
193
194 Standard_Integer aStack[32];
195 Standard_Integer aHead = -1;
196 for (;;)
197 {
198 if (!aBVHTree->IsOuter (aNode))
199 {
200 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
201 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
202 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
203 aBVHTree->MaxPoint (aLeftChildIdx));
204 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
205 aBVHTree->MaxPoint (aRightChildIdx));
206 if (isLeftChildIn
207 && isRightChildIn)
208 {
209 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
14a35e5d 210 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
a1954302 211 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
212 }
213 else if (isLeftChildIn
214 || isRightChildIn)
215 {
216 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
217 }
218 else
219 {
220 if (aHead < 0)
221 {
222 return;
223 }
224
14a35e5d 225 aNode = aStack[aHead--];
a1954302 226 }
227 }
228 else
229 {
14a35e5d 230 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
231 myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
232 if (aHead < 0)
a1954302 233 {
14a35e5d 234 return;
a1954302 235 }
14a35e5d 236
237 aNode = aStack[aHead--];
a1954302 238 }
239 }
240}
241
242// =======================================================================
243// function : Append
244// purpose :
245// =======================================================================
246Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
247{
248 // the source priority list shouldn't have more priorities
249 const Standard_Integer aNbPriorities = theOther.NbPriorities();
250 if (aNbPriorities > NbPriorities())
251 {
252 return Standard_False;
253 }
254
255 // add all structures to destination priority list
256 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
257 {
258 for (OpenGl_SequenceOfStructure::Iterator aStructIter (theOther.myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
259 {
260 Add (aStructIter.Value(), aPriorityIter);
261 }
262 }
263
264 return Standard_True;
265}
266
c5751993 267//=======================================================================
268//function : Render
a1954302 269//purpose :
c5751993 270//=======================================================================
a1954302 271void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
272 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
c5751993 273{
550f3b8b 274 TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
275
c5751993 276 // separate depth buffers
277 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
278 {
279 glClear (GL_DEPTH_BUFFER_BIT);
280 }
550f3b8b 281
c5751993 282 // handle depth test
283 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
284 {
550f3b8b 285 // assuming depth test is enabled by default
286 glDepthFunc (theDefaultSettings.DepthFunc);
c5751993 287 }
288 else
289 {
290 glDepthFunc (GL_ALWAYS);
291 }
550f3b8b 292
c5751993 293 // handle depth offset
294 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
295 {
550f3b8b 296 theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
297 myLayerSettings.DepthOffsetFactor,
298 myLayerSettings.DepthOffsetUnits);
c5751993 299 }
300 else
301 {
550f3b8b 302 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
303 anAppliedOffsetParams.factor,
304 anAppliedOffsetParams.units);
c5751993 305 }
306
307 // handle depth write
a1954302 308 glDepthMask (IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? GL_TRUE : GL_FALSE);
c5751993 309
310 // render priority list
a1954302 311 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
550f3b8b 312
313 // always restore polygon offset between layers rendering
314 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
315 anAppliedOffsetParams.factor,
316 anAppliedOffsetParams.units);
c5751993 317}