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 | // ======================================================================= |
825aa485 |
25 | // function : OpenGl_Layer |
a1954302 |
26 | // purpose : |
27 | // ======================================================================= |
c5751993 |
28 | OpenGl_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 | // ======================================================================= |
41 | OpenGl_Layer::~OpenGl_Layer() |
42 | { |
43 | // |
44 | } |
45 | |
46 | // ======================================================================= |
47 | // function : Add |
48 | // purpose : |
49 | // ======================================================================= |
50 | void 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 | { |
97f937cc |
67 | if (theStruct->TransformPersistence.Flags == Graphic3d_TMF_None) |
825aa485 |
68 | { |
69 | myBVHPrimitives.Add (theStruct); |
70 | } |
71 | else |
72 | { |
73 | myBVHPrimitivesTrsfPers.Add (theStruct); |
74 | } |
a1954302 |
75 | } |
76 | ++myNbStructures; |
77 | } |
78 | |
79 | // ======================================================================= |
80 | // function : Remove |
81 | // purpose : |
82 | // ======================================================================= |
83 | bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct, |
84 | Standard_Integer& thePriority, |
85 | Standard_Boolean isForChangePriority) |
86 | { |
87 | if (theStruct == NULL) |
88 | { |
89 | thePriority = -1; |
90 | return false; |
91 | } |
92 | |
93 | const Standard_Integer aNbPriorities = myArray.Length(); |
94 | for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) |
95 | { |
9f112210 |
96 | OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter); |
97 | |
98 | const Standard_Integer anIndex = aStructures.FindIndex (theStruct); |
99 | if (anIndex != 0) |
a1954302 |
100 | { |
9f112210 |
101 | aStructures.Swap (anIndex, aStructures.Size()); |
102 | aStructures.RemoveLast(); |
103 | |
104 | if (!theStruct->IsAlwaysRendered() |
105 | && !isForChangePriority) |
a1954302 |
106 | { |
825aa485 |
107 | if (!myBVHPrimitives.Remove (theStruct)) |
108 | { |
109 | myBVHPrimitivesTrsfPers.Remove (theStruct); |
110 | } |
a1954302 |
111 | } |
9f112210 |
112 | --myNbStructures; |
113 | thePriority = aPriorityIter; |
114 | return true; |
a1954302 |
115 | } |
116 | } |
117 | |
118 | thePriority = -1; |
119 | return false; |
120 | } |
121 | |
122 | // ======================================================================= |
123 | // function : InvalidateBVHData |
124 | // purpose : |
125 | // ======================================================================= |
126 | void OpenGl_Layer::InvalidateBVHData() |
127 | { |
128 | myIsBVHPrimitivesNeedsReset = Standard_True; |
129 | } |
130 | |
131 | // ======================================================================= |
132 | // function : renderAll |
133 | // purpose : |
134 | // ======================================================================= |
135 | void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const |
136 | { |
137 | const Standard_Integer aNbPriorities = myArray.Length(); |
c357e426 |
138 | const Standard_Integer aViewId = theWorkspace->View()->Identification(); |
a1954302 |
139 | for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) |
140 | { |
9f112210 |
141 | const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter); |
142 | for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) |
a1954302 |
143 | { |
9f112210 |
144 | const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx); |
a1954302 |
145 | if (!aStruct->IsVisible()) |
146 | { |
147 | continue; |
148 | } |
a272ed94 |
149 | else if (!aStruct->ViewAffinity.IsNull() |
150 | && !aStruct->ViewAffinity->IsVisible (aViewId)) |
151 | { |
152 | continue; |
153 | } |
a1954302 |
154 | |
155 | aStruct->Render (theWorkspace); |
156 | } |
157 | } |
158 | } |
159 | |
160 | // ======================================================================= |
161 | // function : renderTraverse |
162 | // purpose : |
163 | // ======================================================================= |
164 | void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const |
165 | { |
166 | if (myIsBVHPrimitivesNeedsReset) |
167 | { |
825aa485 |
168 | myBVHPrimitives.Clear(); |
169 | myBVHPrimitivesTrsfPers.Clear(); |
a1954302 |
170 | myIsBVHPrimitivesNeedsReset = Standard_False; |
825aa485 |
171 | for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx) |
172 | { |
173 | for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next()) |
174 | { |
175 | const OpenGl_Structure* aStruct = aStructIter.Value(); |
176 | |
177 | if (aStruct->IsAlwaysRendered()) |
178 | continue; |
179 | |
97f937cc |
180 | if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None) |
825aa485 |
181 | { |
182 | myBVHPrimitives.Add (aStruct); |
183 | } |
184 | else |
185 | { |
186 | myBVHPrimitivesTrsfPers.Add (aStruct); |
187 | } |
188 | } |
189 | } |
a1954302 |
190 | } |
191 | |
c357e426 |
192 | OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector(); |
a1954302 |
193 | traverse (aSelector); |
194 | |
195 | const Standard_Integer aNbPriorities = myArray.Length(); |
c357e426 |
196 | const Standard_Integer aViewId = theWorkspace->View()->Identification(); |
a1954302 |
197 | for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) |
198 | { |
9f112210 |
199 | const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter); |
200 | for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) |
a1954302 |
201 | { |
9f112210 |
202 | const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx); |
a1954302 |
203 | if (!aStruct->IsVisible() |
204 | || aStruct->IsCulled()) |
205 | { |
206 | continue; |
207 | } |
a272ed94 |
208 | else if (!aStruct->ViewAffinity.IsNull() |
209 | && !aStruct->ViewAffinity->IsVisible (aViewId)) |
210 | { |
211 | continue; |
212 | } |
a1954302 |
213 | |
214 | aStruct->Render (theWorkspace); |
215 | aStruct->ResetCullingStatus(); |
216 | } |
217 | } |
218 | } |
219 | |
220 | // ======================================================================= |
221 | // function : traverse |
222 | // purpose : |
223 | // ======================================================================= |
224 | void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const |
225 | { |
226 | // handle a case when all objects are infinite |
97f937cc |
227 | if (myBVHPrimitives .Size() == 0 |
228 | && myBVHPrimitivesTrsfPers.Size() == 0) |
a1954302 |
229 | return; |
230 | |
a1954302 |
231 | theSelector.CacheClipPtsProjections(); |
a1954302 |
232 | |
825aa485 |
233 | NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVHTree; |
234 | |
235 | for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) |
a1954302 |
236 | { |
825aa485 |
237 | const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; |
238 | if (isTrsfPers) |
a1954302 |
239 | { |
825aa485 |
240 | if (myBVHPrimitivesTrsfPers.Size() == 0) |
825aa485 |
241 | continue; |
97f937cc |
242 | |
243 | const OpenGl_Mat4& aProjection = theSelector.ProjectionMatrix(); |
244 | const OpenGl_Mat4& aWorldView = theSelector.WorldViewMatrix(); |
825aa485 |
245 | const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState(); |
246 | aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aWVPState); |
247 | } |
248 | else |
249 | { |
250 | if (myBVHPrimitives.Size() == 0) |
825aa485 |
251 | continue; |
97f937cc |
252 | |
825aa485 |
253 | aBVHTree = myBVHPrimitives.BVH(); |
254 | } |
255 | |
256 | Standard_Integer aNode = 0; // a root node |
257 | |
258 | if (!theSelector.Intersect (aBVHTree->MinPoint (0), |
259 | aBVHTree->MaxPoint (0))) |
260 | { |
261 | continue; |
262 | } |
263 | |
264 | Standard_Integer aStack[32]; |
265 | Standard_Integer aHead = -1; |
266 | for (;;) |
267 | { |
268 | if (!aBVHTree->IsOuter (aNode)) |
a1954302 |
269 | { |
825aa485 |
270 | const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode); |
271 | const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode); |
272 | const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx), |
273 | aBVHTree->MaxPoint (aLeftChildIdx)); |
274 | const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx), |
275 | aBVHTree->MaxPoint (aRightChildIdx)); |
276 | if (isLeftChildIn |
277 | && isRightChildIn) |
278 | { |
279 | aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx; |
280 | aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; |
281 | myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; |
282 | } |
283 | else if (isLeftChildIn |
284 | || isRightChildIn) |
285 | { |
286 | aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; |
287 | } |
288 | else |
289 | { |
290 | if (aHead < 0) |
291 | { |
292 | break; |
293 | } |
294 | |
295 | aNode = aStack[aHead--]; |
296 | } |
a1954302 |
297 | } |
298 | else |
299 | { |
825aa485 |
300 | Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); |
301 | const OpenGl_Structure* aStruct = |
302 | isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) |
303 | : myBVHPrimitives.GetStructureById (aIdx); |
304 | aStruct->MarkAsNotCulled(); |
a1954302 |
305 | if (aHead < 0) |
306 | { |
825aa485 |
307 | break; |
a1954302 |
308 | } |
309 | |
14a35e5d |
310 | aNode = aStack[aHead--]; |
a1954302 |
311 | } |
312 | } |
a1954302 |
313 | } |
314 | } |
315 | |
316 | // ======================================================================= |
317 | // function : Append |
318 | // purpose : |
319 | // ======================================================================= |
320 | Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther) |
321 | { |
322 | // the source priority list shouldn't have more priorities |
323 | const Standard_Integer aNbPriorities = theOther.NbPriorities(); |
324 | if (aNbPriorities > NbPriorities()) |
325 | { |
326 | return Standard_False; |
327 | } |
328 | |
329 | // add all structures to destination priority list |
330 | for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) |
331 | { |
9f112210 |
332 | const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter); |
333 | for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx) |
a1954302 |
334 | { |
9f112210 |
335 | Add (aStructures.FindKey (aStructIdx), aPriorityIter); |
a1954302 |
336 | } |
337 | } |
338 | |
339 | return Standard_True; |
340 | } |
341 | |
c5751993 |
342 | //======================================================================= |
343 | //function : Render |
a1954302 |
344 | //purpose : |
c5751993 |
345 | //======================================================================= |
a1954302 |
346 | void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace, |
347 | const OpenGl_GlobalLayerSettings& theDefaultSettings) const |
c5751993 |
348 | { |
550f3b8b |
349 | TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset(); |
350 | |
c5751993 |
351 | // separate depth buffers |
352 | if (IsSettingEnabled (Graphic3d_ZLayerDepthClear)) |
353 | { |
354 | glClear (GL_DEPTH_BUFFER_BIT); |
355 | } |
eae454e3 |
356 | |
c5751993 |
357 | // handle depth test |
358 | if (IsSettingEnabled (Graphic3d_ZLayerDepthTest)) |
359 | { |
550f3b8b |
360 | // assuming depth test is enabled by default |
361 | glDepthFunc (theDefaultSettings.DepthFunc); |
c5751993 |
362 | } |
363 | else |
364 | { |
365 | glDepthFunc (GL_ALWAYS); |
366 | } |
eae454e3 |
367 | |
c5751993 |
368 | // handle depth offset |
369 | if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset)) |
370 | { |
550f3b8b |
371 | theWorkspace->SetPolygonOffset (Aspect_POM_Fill, |
372 | myLayerSettings.DepthOffsetFactor, |
373 | myLayerSettings.DepthOffsetUnits); |
c5751993 |
374 | } |
375 | else |
376 | { |
550f3b8b |
377 | theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode, |
378 | anAppliedOffsetParams.factor, |
379 | anAppliedOffsetParams.units); |
c5751993 |
380 | } |
381 | |
382 | // handle depth write |
eae454e3 |
383 | theWorkspace->UseDepthWrite() = IsSettingEnabled (Graphic3d_ZLayerDepthWrite); |
384 | glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE); |
c5751993 |
385 | |
386 | // render priority list |
a1954302 |
387 | theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace); |
550f3b8b |
388 | |
389 | // always restore polygon offset between layers rendering |
390 | theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode, |
391 | anAppliedOffsetParams.factor, |
392 | anAppliedOffsetParams.units); |
c5751993 |
393 | } |