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