0026122: Visualization, TKOpenGl - clipping and capping is broken when ffp is disable...
[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                            const EquationCoords&           theCoordSpace,
58                            Graphic3d_SequenceOfHClipPlane& thePlanes)
59 {
60   const bool toUseFfp = theGlCtx->core11 != NULL
61                      && theGlCtx->caps->ffpEnable;
62   if (!toUseFfp)
63   {
64     addLazy (theGlCtx, theCoordSpace, thePlanes);
65     return;
66   }
67
68   if (EquationCoords_View == theCoordSpace)
69   {
70     theGlCtx->WorldViewState.Push();
71     theGlCtx->WorldViewState.SetIdentity();
72   }
73
74   // Set either identity or pure view matrix.
75   theGlCtx->ApplyWorldViewMatrix();
76
77   addLazy (theGlCtx, theCoordSpace, thePlanes);
78
79   if (EquationCoords_View == theCoordSpace)
80   {
81     theGlCtx->WorldViewState.Pop();
82   }
83
84   // Restore combined model-view matrix.
85   theGlCtx->ApplyModelViewMatrix();
86 }
87
88 // =======================================================================
89 // function : addLazy
90 // purpose  :
91 // =======================================================================
92 void OpenGl_Clipping::addLazy (const Handle(OpenGl_Context)&   theGlCtx,
93                                const EquationCoords&           theCoordSpace,
94                                Graphic3d_SequenceOfHClipPlane& thePlanes)
95 {
96 #if !defined(GL_ES_VERSION_2_0)
97   const bool toUseFfp = theGlCtx->core11 != NULL
98                      && theGlCtx->caps->ffpEnable;
99 #else
100   (void )theGlCtx;
101 #endif
102
103   Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
104   while (aPlaneIt.More() && myEmptyPlaneIds->HasFree())
105   {
106     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
107     if (Contains (aPlane))
108     {
109       thePlanes.Remove (aPlaneIt);
110       continue;
111     }
112
113     Standard_Integer anID = myEmptyPlaneIds->Next();
114     myPlanes.Append (aPlane);
115     myPlaneStates.Bind (aPlane, PlaneProps (theCoordSpace, anID, Standard_True));
116
117   #if !defined(GL_ES_VERSION_2_0)
118     if (toUseFfp)
119     {
120       ::glEnable ((GLenum)anID);
121       theGlCtx->core11->glClipPlane ((GLenum)anID, aPlane->GetEquation());
122     }
123   #endif
124     if (aPlane->IsCapping())
125     {
126       ++myNbCapping;
127     }
128     else
129     {
130       ++myNbClipping;
131     }
132
133     aPlaneIt.Next();
134   }
135
136   if (!myEmptyPlaneIds->HasFree())
137   {
138     while (aPlaneIt.More())
139     {
140       thePlanes.Remove (aPlaneIt);
141     }
142   }
143 }
144
145 // =======================================================================
146 // function : Remove
147 // purpose  :
148 // =======================================================================
149 void OpenGl_Clipping::Remove (const Handle(OpenGl_Context)&         theGlCtx,
150                               const Graphic3d_SequenceOfHClipPlane& thePlanes)
151 {
152 #if !defined(GL_ES_VERSION_2_0)
153   const bool toUseFfp = theGlCtx->core11 != NULL
154                      && theGlCtx->caps->ffpEnable;
155 #else
156   (void )theGlCtx;
157 #endif
158
159   Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
160   for (; aPlaneIt.More(); aPlaneIt.Next())
161   {
162     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
163     if (!Contains (aPlane))
164     {
165       continue;
166     }
167
168     Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
169     PlaneProps& aProps = myPlaneStates.ChangeFind (aPlane);
170     if (aProps.IsEnabled)
171     {
172     #if !defined(GL_ES_VERSION_2_0)
173       if (toUseFfp)
174       {
175         ::glDisable ((GLenum)anID);
176       }
177     #endif
178       if (aPlane->IsCapping())
179       {
180         --myNbCapping;
181       }
182       else
183       {
184         --myNbClipping;
185       }
186     }
187
188     myEmptyPlaneIds->Free (anID);
189     myPlaneStates.UnBind (aPlane);
190   }
191
192   // renew collection of planes
193   aPlaneIt.Init (myPlanes);
194   while (aPlaneIt.More())
195   {
196     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
197     if (!myPlaneStates.IsBound (aPlane))
198     {
199       myPlanes.Remove (aPlaneIt);
200     }
201     else
202     {
203       aPlaneIt.Next();
204     }
205   }
206 }
207
208 // =======================================================================
209 // function : SetEnabled
210 // purpose  :
211 // =======================================================================
212 void OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)&      theGlCtx,
213                                   const Handle(Graphic3d_ClipPlane)& thePlane,
214                                   const Standard_Boolean             theIsEnabled)
215 {
216   if (!Contains (thePlane))
217   {
218     return;
219   }
220
221   PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
222   if (theIsEnabled == aProps.IsEnabled)
223   {
224     return;
225   }
226
227 #if !defined(GL_ES_VERSION_2_0)
228   GLenum anID = (GLenum)aProps.ContextID;
229   const bool toUseFfp = theGlCtx->core11 != NULL
230                      && theGlCtx->caps->ffpEnable;
231 #endif
232   if (theIsEnabled)
233   {
234   #if !defined(GL_ES_VERSION_2_0)
235     if (toUseFfp)
236     {
237       ::glEnable (anID);
238     }
239   #endif
240     if (thePlane->IsCapping())
241     {
242       ++myNbCapping;
243     }
244     else
245     {
246       ++myNbClipping;
247     }
248   }
249   else
250   {
251   #if !defined(GL_ES_VERSION_2_0)
252     if (toUseFfp)
253     {
254       ::glDisable (anID);
255     }
256   #endif
257     if (thePlane->IsCapping())
258     {
259       --myNbCapping;
260     }
261     else
262     {
263       --myNbClipping;
264     }
265   }
266
267   aProps.IsEnabled = theIsEnabled;
268 }