0028127: Visualization - transparent object breaks Z-Layer depth buffer clear
[occt.git] / src / OpenGl / OpenGl_LayerList.cxx
1 // Created on: 2012-02-02
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2012-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_GlCore11.hxx>
17
18 #include <OpenGl_LayerList.hxx>
19 #include <OpenGl_Structure.hxx>
20 #include <OpenGl_Workspace.hxx>
21
22 #include <Graphic3d_GraphicDriver.hxx>
23
24 //=======================================================================
25 //function : OpenGl_LayerList
26 //purpose  : Constructor
27 //=======================================================================
28
29 OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
30 : myDefaultLayerIndex (0),
31   myNbPriorities (theNbPriorities),
32   myNbStructures (0),
33   myImmediateNbStructures (0),
34   myModifStateOfRaytraceable (0)
35 {
36   // insert default priority layers
37   myLayers.Append (OpenGl_Layer (myNbPriorities));
38   myLayerIds.Bind (Graphic3d_ZLayerId_BotOSD,  myLayers.Upper());
39
40   myLayers.Append (OpenGl_Layer (myNbPriorities));
41   myLayerIds.Bind (Graphic3d_ZLayerId_Default, myLayers.Upper());
42
43   myLayers.Append (OpenGl_Layer (myNbPriorities));
44   myLayerIds.Bind (Graphic3d_ZLayerId_Top,     myLayers.Upper());
45
46   myLayers.Append (OpenGl_Layer (myNbPriorities));
47   myLayerIds.Bind (Graphic3d_ZLayerId_Topmost, myLayers.Upper());
48
49   myLayers.Append (OpenGl_Layer (myNbPriorities));
50   myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD,  myLayers.Upper());
51
52   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
53 }
54
55 //=======================================================================
56 //function : ~OpenGl_LayerList
57 //purpose  : Destructor
58 //=======================================================================
59
60 OpenGl_LayerList::~OpenGl_LayerList()
61 {
62 }
63
64 //=======================================================================
65 //function : AddLayer
66 //purpose  : 
67 //=======================================================================
68
69 void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
70 {
71   if (myLayerIds.IsBound (theLayerId))
72   {
73     return;
74   }
75
76   // add the new layer
77   myLayers.Append (OpenGl_Layer (myNbPriorities));
78   myLayerIds.Bind (theLayerId, myLayers.Length());
79 }
80
81 //=======================================================================
82 //function : Layer
83 //purpose  : 
84 //=======================================================================
85 OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId)
86 {
87   return myLayers.ChangeValue (myLayerIds.Find (theLayerId));
88 }
89
90 //=======================================================================
91 //function : Layer
92 //purpose  : 
93 //=======================================================================
94 const OpenGl_Layer& OpenGl_LayerList::Layer (const Graphic3d_ZLayerId theLayerId) const
95 {
96   return myLayers.Value (myLayerIds.Find (theLayerId));
97 }
98
99 //=======================================================================
100 //function : RemoveLayer
101 //purpose  :
102 //=======================================================================
103
104 void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
105 {
106   if (!myLayerIds.IsBound (theLayerId)
107     || theLayerId <= 0)
108   {
109     return;
110   }
111
112   const Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
113   
114   // move all displayed structures to first layer
115   const OpenGl_Layer& aLayerToMove = myLayers.Value (aRemovePos);
116   myLayers.ChangeFirst().Append (aLayerToMove);
117
118   // remove layer
119   myLayers.Remove (aRemovePos);
120   myLayerIds.UnBind (theLayerId);
121
122   // updated sequence indexes in map
123   for (OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds); aMapIt.More(); aMapIt.Next())
124   {
125     Standard_Integer& aSeqIdx = aMapIt.ChangeValue();
126     if (aSeqIdx > aRemovePos)
127       aSeqIdx--;
128   }
129
130   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
131 }
132
133 //=======================================================================
134 //function : AddStructure
135 //purpose  :
136 //=======================================================================
137
138 void OpenGl_LayerList::AddStructure (const OpenGl_Structure*  theStruct,
139                                      const Graphic3d_ZLayerId theLayerId,
140                                      const Standard_Integer   thePriority,
141                                      Standard_Boolean         isForChangePriority)
142 {
143   // add structure to associated layer,
144   // if layer doesn't exists, display structure in default layer
145   Standard_Integer aSeqPos = myLayers.Lower();
146   myLayerIds.Find (theLayerId, aSeqPos);
147
148   OpenGl_Layer& aLayer = myLayers.ChangeValue (aSeqPos);
149   aLayer.Add (theStruct, thePriority, isForChangePriority);
150   ++myNbStructures;
151   if (aLayer.IsImmediate())
152   {
153     ++myImmediateNbStructures;
154   }
155
156   // Note: In ray-tracing mode we don't modify modification
157   // state here. It is redundant, because the possible changes
158   // will be handled in the loop for structures
159 }
160
161 //=======================================================================
162 //function : RemoveStructure
163 //purpose  :
164 //=======================================================================
165
166 void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
167 {
168   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
169
170   Standard_Integer aSeqPos = myLayers.Lower();
171   myLayerIds.Find (aLayerId, aSeqPos);
172
173   OpenGl_Layer&    aLayer    = myLayers.ChangeValue (aSeqPos);
174   Standard_Integer aPriority = -1;
175
176   // remove structure from associated list
177   // if the structure is not found there,
178   // scan through layers and remove it
179   if (aLayer.Remove (theStructure, aPriority))
180   {
181     --myNbStructures;
182     if (aLayer.IsImmediate())
183     {
184       --myImmediateNbStructures;
185     }
186
187     if (aLayerId == Graphic3d_ZLayerId_Default
188      && theStructure->IsRaytracable())
189     {
190       ++myModifStateOfRaytraceable;
191     }
192
193     return;
194   }
195
196   // scan through layers and remove it
197   Standard_Integer aSeqId = 1;
198   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
199   {
200     OpenGl_Layer& aLayerEx = anIts.ChangeValue();
201     if (aSeqPos == aSeqId)
202     {
203       continue;
204     }
205
206     if (aLayerEx.Remove (theStructure, aPriority))
207     {
208       --myNbStructures;
209       if (aLayerEx.IsImmediate())
210       {
211         --myImmediateNbStructures;
212       }
213
214       if (aSeqId == myDefaultLayerIndex
215        && theStructure->IsRaytracable())
216       {
217         ++myModifStateOfRaytraceable;
218       }
219       return;
220     }
221   }
222 }
223
224 //=======================================================================
225 //function : InvalidateBVHData
226 //purpose  :
227 //=======================================================================
228 void OpenGl_LayerList::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
229 {
230   Standard_Integer aSeqPos = myLayers.Lower();
231   myLayerIds.Find (theLayerId, aSeqPos);
232   OpenGl_Layer& aLayer = myLayers.ChangeValue (aSeqPos);
233   aLayer.InvalidateBVHData();
234 }
235
236 //=======================================================================
237 //function : ChangeLayer
238 //purpose  :
239 //=======================================================================
240
241 void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure*  theStructure,
242                                     const Graphic3d_ZLayerId theOldLayerId,
243                                     const Graphic3d_ZLayerId theNewLayerId)
244 {
245   Standard_Integer aSeqPos = myLayers.Lower();
246   myLayerIds.Find (theOldLayerId, aSeqPos);
247   OpenGl_Layer&    aLayer    = myLayers.ChangeValue (aSeqPos);
248   Standard_Integer aPriority = -1;
249
250   // take priority and remove structure from list found by <theOldLayerId>
251   // if the structure is not found there, scan through all other layers
252   if (aLayer.Remove (theStructure, aPriority, Standard_False))
253   {
254     if (theOldLayerId == Graphic3d_ZLayerId_Default
255      && theStructure->IsRaytracable())
256     {
257       ++myModifStateOfRaytraceable;
258     }
259
260     --myNbStructures;
261     if (aLayer.IsImmediate())
262     {
263       --myImmediateNbStructures;
264     }
265
266     // isForChangePriority should be Standard_False below, because we want
267     // the BVH tree in the target layer to be updated with theStructure
268     AddStructure (theStructure, theNewLayerId, aPriority);
269     return;
270   }
271
272   // scan through layers and remove it
273   Standard_Integer aSeqId = 1;
274   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
275   {
276     if (aSeqPos == aSeqId)
277     {
278       continue;
279     }
280   
281     // try to remove structure and get priority value from this layer
282     OpenGl_Layer& aLayerEx = anIts.ChangeValue();
283     if (aLayerEx.Remove (theStructure, aPriority, Standard_True))
284     {
285       if (aSeqId == myDefaultLayerIndex
286        && theStructure->IsRaytracable())
287       {
288         ++myModifStateOfRaytraceable;
289       }
290
291       --myNbStructures;
292       if (aLayerEx.IsImmediate())
293       {
294         --myImmediateNbStructures;
295       }
296
297       // isForChangePriority should be Standard_False below, because we want
298       // the BVH tree in the target layer to be updated with theStructure
299       AddStructure (theStructure, theNewLayerId, aPriority);
300       return;
301     }
302   }
303 }
304
305 //=======================================================================
306 //function : ChangePriority
307 //purpose  :
308 //=======================================================================
309 void OpenGl_LayerList::ChangePriority (const OpenGl_Structure*  theStructure,
310                                        const Graphic3d_ZLayerId theLayerId,
311                                        const Standard_Integer   theNewPriority)
312 {
313   Standard_Integer aSeqPos = myLayers.Lower();
314   myLayerIds.Find (theLayerId, aSeqPos);
315   OpenGl_Layer&    aLayer        = myLayers.ChangeValue (aSeqPos);
316   Standard_Integer anOldPriority = -1;
317
318   if (aLayer.Remove (theStructure, anOldPriority, Standard_True))
319   {
320     --myNbStructures;
321     if (aLayer.IsImmediate())
322     {
323       --myImmediateNbStructures;
324     }
325
326     AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
327     return;
328   }
329
330   Standard_Integer aSeqId = 1;
331   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
332   {
333     if (aSeqPos == aSeqId)
334     {
335       continue;
336     }
337
338     OpenGl_Layer& aLayerEx = anIts.ChangeValue();
339     if (aLayerEx.Remove (theStructure, anOldPriority, Standard_True))
340     {
341       --myNbStructures;
342       if (aLayerEx.IsImmediate())
343       {
344         --myImmediateNbStructures;
345       }
346
347       AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
348       return;
349     }
350   }
351 }
352
353 //=======================================================================
354 //function : SetLayerSettings
355 //purpose  :
356 //=======================================================================
357 void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId        theLayerId,
358                                          const Graphic3d_ZLayerSettings& theSettings)
359 {
360   OpenGl_Layer& aLayer = Layer (theLayerId);
361   if (aLayer.LayerSettings().IsImmediate() != theSettings.IsImmediate())
362   {
363     if (theSettings.IsImmediate())
364     {
365       myImmediateNbStructures += aLayer.NbStructures();
366     }
367     else
368     {
369       myImmediateNbStructures -= aLayer.NbStructures();
370     }
371   }
372   aLayer.SetLayerSettings (theSettings);
373 }
374
375 //=======================================================================
376 //function : Render
377 //purpose  :
378 //=======================================================================
379 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
380                                const Standard_Boolean          theToDrawImmediate,
381                                const OpenGl_LayerFilter        theLayersToProcess) const
382 {
383   OpenGl_GlobalLayerSettings aDefaultSettings;
384
385   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
386   aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDefaultSettings.DepthFunc);
387   aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aDefaultSettings.DepthMask);
388
389   Standard_Integer aSeqId = myLayers.Lower();
390   bool toClearDepth = false;
391   for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
392   {
393     if (theLayersToProcess == OpenGl_LF_Bottom)
394     {
395       if (aSeqId >= myDefaultLayerIndex) continue;
396     }
397     else if (theLayersToProcess == OpenGl_LF_Upper)
398     {
399       if (aSeqId <= myDefaultLayerIndex) continue;
400     }
401     else if (theLayersToProcess == OpenGl_LF_Default)
402     {
403       if (aSeqId != myDefaultLayerIndex) continue;
404     }
405
406     const OpenGl_Layer& aLayer = anIts.Value();
407     if (aLayer.IsImmediate() != theToDrawImmediate)
408     {
409       continue;
410     }
411     else if (aLayer.NbStructures() < 1)
412     {
413       // make sure to clear depth of previous layers even if layer has no structures
414       toClearDepth = toClearDepth || aLayer.LayerSettings().ToClearDepth();
415       continue;
416     }
417
418     // depth buffers
419     if (toClearDepth
420      || aLayer.LayerSettings().ToClearDepth())
421     {
422       toClearDepth = false;
423       glDepthMask (GL_TRUE);
424       glClear (GL_DEPTH_BUFFER_BIT);
425     }
426
427     aLayer.Render (theWorkspace, aDefaultSettings);
428   }
429
430   if (toClearDepth)
431   {
432     glDepthMask (GL_TRUE);
433     glClear (GL_DEPTH_BUFFER_BIT);
434   }
435
436   aCtx->core11fwd->glDepthMask (aDefaultSettings.DepthMask);
437   aCtx->core11fwd->glDepthFunc (aDefaultSettings.DepthFunc);
438 }