25398dc5125960ce7fb075df5501beb64d4c9861
[occt.git] / src / OpenGl / OpenGl_Clipping.cxx
1 // Created on: 2013-09-05
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-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_Clipping.hxx>
17
18 #include <OpenGl_GlCore11.hxx>
19 #include <OpenGl_Workspace.hxx>
20 #include <OpenGl_Context.hxx>
21
22 #if defined(GL_ES_VERSION_2_0)
23   // id does not matter for GLSL-based clipping, just for consistency
24   #define GL_CLIP_PLANE0 0x3000
25 #endif
26
27 // =======================================================================
28 // function : OpenGl_ClippingState
29 // purpose  :
30 // =======================================================================
31 OpenGl_Clipping::OpenGl_Clipping ()
32 : myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE0 + 5)),
33   myNbClipping (0),
34   myNbCapping  (0)
35 {}
36
37 // =======================================================================
38 // function : Init
39 // purpose  :
40 // =======================================================================
41 void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
42 {
43   myPlanes.Clear();
44   myPlaneStates.Clear();
45   myNbClipping = 0;
46   myNbCapping  = 0;
47   Standard_Integer aLowerId = GL_CLIP_PLANE0;
48   Standard_Integer aUpperId = GL_CLIP_PLANE0 + theMaxPlanes - 1;
49   myEmptyPlaneIds = new Aspect_GenId (aLowerId, aUpperId);
50 }
51
52 // =======================================================================
53 // function : add
54 // purpose  :
55 // =======================================================================
56 void OpenGl_Clipping::add (const Handle(OpenGl_Context)&   theGlCtx,
57                            Graphic3d_SequenceOfHClipPlane& thePlanes)
58 {
59   const bool toUseFfp = theGlCtx->core11 != NULL
60                      && theGlCtx->caps->ffpEnable;
61   if (!toUseFfp)
62   {
63     addLazy (theGlCtx, thePlanes);
64     return;
65   }
66
67   // Set either identity or pure view matrix.
68   theGlCtx->ApplyWorldViewMatrix();
69
70   addLazy (theGlCtx, thePlanes);
71
72   // Restore combined model-view matrix.
73   theGlCtx->ApplyModelViewMatrix();
74 }
75
76 // =======================================================================
77 // function : addLazy
78 // purpose  :
79 // =======================================================================
80 void OpenGl_Clipping::addLazy (const Handle(OpenGl_Context)&   theGlCtx,
81                                Graphic3d_SequenceOfHClipPlane& thePlanes)
82 {
83 #if !defined(GL_ES_VERSION_2_0)
84   const bool toUseFfp = theGlCtx->core11 != NULL
85                      && theGlCtx->caps->ffpEnable;
86 #else
87   (void )theGlCtx;
88 #endif
89
90   Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
91   while (aPlaneIt.More() && myEmptyPlaneIds->HasFree())
92   {
93     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
94     if (Contains (aPlane))
95     {
96       thePlanes.Remove (aPlaneIt);
97       continue;
98     }
99
100     Standard_Integer anID = myEmptyPlaneIds->Next();
101     myPlanes.Append (aPlane);
102     myPlaneStates.Bind (aPlane, PlaneProps (anID, Standard_True));
103
104   #if !defined(GL_ES_VERSION_2_0)
105     if (toUseFfp)
106     {
107       ::glEnable ((GLenum)anID);
108       theGlCtx->core11->glClipPlane ((GLenum)anID, aPlane->GetEquation());
109     }
110   #endif
111     if (aPlane->IsCapping())
112     {
113       ++myNbCapping;
114     }
115     else
116     {
117       ++myNbClipping;
118     }
119
120     aPlaneIt.Next();
121   }
122
123   if (!myEmptyPlaneIds->HasFree())
124   {
125     while (aPlaneIt.More())
126     {
127       thePlanes.Remove (aPlaneIt);
128     }
129   }
130 }
131
132 // =======================================================================
133 // function : Remove
134 // purpose  :
135 // =======================================================================
136 void OpenGl_Clipping::Remove (const Handle(OpenGl_Context)&         theGlCtx,
137                               const Graphic3d_SequenceOfHClipPlane& thePlanes)
138 {
139 #if !defined(GL_ES_VERSION_2_0)
140   const bool toUseFfp = theGlCtx->core11 != NULL
141                      && theGlCtx->caps->ffpEnable;
142 #else
143   (void )theGlCtx;
144 #endif
145
146   Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
147   for (; aPlaneIt.More(); aPlaneIt.Next())
148   {
149     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
150     if (!Contains (aPlane))
151     {
152       continue;
153     }
154
155     Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
156     PlaneProps& aProps = myPlaneStates.ChangeFind (aPlane);
157     if (aProps.IsEnabled)
158     {
159     #if !defined(GL_ES_VERSION_2_0)
160       if (toUseFfp)
161       {
162         ::glDisable ((GLenum)anID);
163       }
164     #endif
165       if (aPlane->IsCapping())
166       {
167         --myNbCapping;
168       }
169       else
170       {
171         --myNbClipping;
172       }
173     }
174
175     myEmptyPlaneIds->Free (anID);
176     myPlaneStates.UnBind (aPlane);
177   }
178
179   // renew collection of planes
180   aPlaneIt.Init (myPlanes);
181   while (aPlaneIt.More())
182   {
183     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
184     if (!myPlaneStates.IsBound (aPlane))
185     {
186       myPlanes.Remove (aPlaneIt);
187     }
188     else
189     {
190       aPlaneIt.Next();
191     }
192   }
193 }
194
195 // =======================================================================
196 // function : SetEnabled
197 // purpose  :
198 // =======================================================================
199 void OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&      theGlCtx,
200                                   const Handle(Graphic3d_ClipPlane)& thePlane,
201                                   const Standard_Boolean             theIsEnabled)
202 {
203   if (!Contains (thePlane))
204   {
205     return;
206   }
207
208   PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
209   if (theIsEnabled == aProps.IsEnabled)
210   {
211     return;
212   }
213
214 #if !defined(GL_ES_VERSION_2_0)
215   GLenum anID = (GLenum)aProps.ContextID;
216   const bool toUseFfp = theGlCtx->core11 != NULL
217                      && theGlCtx->caps->ffpEnable;
218 #else
219   (void )theGlCtx;
220 #endif
221   if (theIsEnabled)
222   {
223   #if !defined(GL_ES_VERSION_2_0)
224     if (toUseFfp)
225     {
226       ::glEnable (anID);
227     }
228   #endif
229     if (thePlane->IsCapping())
230     {
231       ++myNbCapping;
232     }
233     else
234     {
235       ++myNbClipping;
236     }
237   }
238   else
239   {
240   #if !defined(GL_ES_VERSION_2_0)
241     if (toUseFfp)
242     {
243       ::glDisable (anID);
244     }
245   #endif
246     if (thePlane->IsCapping())
247     {
248       --myNbCapping;
249     }
250     else
251     {
252       --myNbClipping;
253     }
254   }
255
256   aProps.IsEnabled = theIsEnabled;
257 }