f19232b778227574848ea388d4ba0fabae573fb8
[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 // =======================================================================
21 // function : OpenGl_ClippingState
22 // purpose  :
23 // =======================================================================
24 OpenGl_Clipping::OpenGl_Clipping ()
25 : myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE5)),
26   myNbClipping (0),
27   myNbCapping  (0)
28 {}
29
30 // =======================================================================
31 // function : Init
32 // purpose  :
33 // =======================================================================
34 void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
35 {
36   myPlanes.Clear();
37   myPlaneStates.Clear();
38   myNbClipping = 0;
39   myNbCapping  = 0;
40   Standard_Integer aLowerId = GL_CLIP_PLANE0;
41   Standard_Integer aUpperId = GL_CLIP_PLANE0 + theMaxPlanes - 1;
42   myEmptyPlaneIds = new Aspect_GenId (aLowerId, aUpperId);
43 }
44
45 // =======================================================================
46 // function : Add
47 // purpose  :
48 // =======================================================================
49 void OpenGl_Clipping::Add (Graphic3d_SequenceOfHClipPlane& thePlanes,
50                            const EquationCoords& theCoordSpace,
51                            const Handle(OpenGl_Workspace)& theWS)
52 {
53   GLint aMatrixMode;
54   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
55
56   OpenGl_Matrix aCurrentMx;
57   glGetFloatv (GL_MODELVIEW_MATRIX, (GLfloat*) &aCurrentMx);
58
59   if (aMatrixMode != GL_MODELVIEW)
60   {
61     glMatrixMode (GL_MODELVIEW);
62   }
63
64   switch (theCoordSpace)
65   {
66     case EquationCoords_View:  glLoadMatrixf ((const GLfloat*) &OpenGl_IdentityMatrix); break;
67     case EquationCoords_World: glLoadMatrixf ((const GLfloat*) theWS->ViewMatrix());    break;
68   }
69
70   Add (thePlanes, theCoordSpace);
71
72   // restore model-view matrix
73   glLoadMatrixf ((GLfloat*) &aCurrentMx);
74
75   // restore context matrix state
76   if (aMatrixMode != GL_MODELVIEW)
77   {
78     glMatrixMode (aMatrixMode);
79   }
80 }
81
82 // =======================================================================
83 // function : Add
84 // purpose  :
85 // =======================================================================
86 void OpenGl_Clipping::Add (Graphic3d_SequenceOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace)
87 {
88   Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
89   while (aPlaneIt.More() && myEmptyPlaneIds->Available() > 0)
90   {
91     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
92     if (Contains (aPlane))
93     {
94       thePlanes.Remove (aPlaneIt);
95       continue;
96     }
97
98     Standard_Integer anID = myEmptyPlaneIds->Next();
99     myPlanes.Append (aPlane);
100     myPlaneStates.Bind (aPlane, PlaneProps (theCoordSpace, anID, Standard_True));
101
102     glEnable ((GLenum)anID);
103     glClipPlane ((GLenum)anID, aPlane->GetEquation());
104     if (aPlane->IsCapping())
105     {
106       ++myNbCapping;
107     }
108     else
109     {
110       ++myNbClipping;
111     }
112
113     aPlaneIt.Next();
114   }
115
116   while (aPlaneIt.More() && myEmptyPlaneIds->Available() == 0)
117   {
118     thePlanes.Remove (aPlaneIt);
119   }
120 }
121
122 // =======================================================================
123 // function : Remove
124 // purpose  :
125 // =======================================================================
126 void OpenGl_Clipping::Remove (const Graphic3d_SequenceOfHClipPlane& thePlanes)
127 {
128   Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
129   for (; aPlaneIt.More(); aPlaneIt.Next())
130   {
131     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
132     if (!Contains (aPlane))
133     {
134       continue;
135     }
136
137     Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
138     PlaneProps& aProps = myPlaneStates.ChangeFind (aPlane);
139     if (aProps.IsEnabled)
140     {
141       glDisable ((GLenum)anID);
142       if (aPlane->IsCapping())
143       {
144         --myNbCapping;
145       }
146       else
147       {
148         --myNbClipping;
149       }
150     }
151
152     myEmptyPlaneIds->Free (anID);
153     myPlaneStates.UnBind (aPlane);
154   }
155
156   // renew collection of planes
157   aPlaneIt.Init (myPlanes);
158   while (aPlaneIt.More())
159   {
160     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
161     if (!myPlaneStates.IsBound (aPlane))
162     {
163       myPlanes.Remove (aPlaneIt);
164     }
165     else
166     {
167       aPlaneIt.Next();
168     }
169   }
170 }
171
172 // =======================================================================
173 // function : SetEnabled
174 // purpose  :
175 // =======================================================================
176 void OpenGl_Clipping::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane,
177                                   const Standard_Boolean theIsEnabled)
178 {
179   if (!Contains (thePlane))
180   {
181     return;
182   }
183
184   PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
185   if (theIsEnabled == aProps.IsEnabled)
186   {
187     return;
188   }
189
190   GLenum anID = (GLenum)aProps.ContextID;
191   if (theIsEnabled)
192   {
193     glEnable (anID);
194     if (thePlane->IsCapping())
195     {
196       ++myNbCapping;
197     }
198     else
199     {
200       ++myNbClipping;
201     }
202   }
203   else
204   {
205     glDisable (anID);
206     if (thePlane->IsCapping())
207     {
208       --myNbCapping;
209     }
210     else
211     {
212       --myNbClipping;
213     }
214   }
215
216   aProps.IsEnabled = theIsEnabled;
217 }