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