0024224: Suspicious logics in changing clipping planes at OpenGl_Structure
[occt.git] / src / OpenGl / OpenGl_ClippingState.cxx
1 // Created on: 2013-09-05
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <OpenGl_ClippingState.hxx>
21 #include <OpenGl_GlCore11.hxx>
22 #include <OpenGl_Workspace.hxx>
23
24 namespace
25 {
26   static const GLdouble OpenGl_DefaultPlaneEq[] = {0.0, 0.0, 0.0, 0.0};
27 };
28
29 // =======================================================================
30 // function : OpenGl_ClippingState
31 // purpose  :
32 // =======================================================================
33 OpenGl_ClippingState::OpenGl_ClippingState ()
34 : myPlanes(),
35   myPlaneStates(),
36   myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE5))
37 {}
38
39 // =======================================================================
40 // function : Init
41 // purpose  :
42 // =======================================================================
43 void OpenGl_ClippingState::Init (const Standard_Integer theMaxPlanes)
44 {
45   myPlanes.Clear();
46   myPlaneStates.Clear();
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_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes,
57                                 const EquationCoords& theCoordSpace,
58                                 const Handle(OpenGl_Workspace)& theWS)
59 {
60   GLint aMatrixMode;
61   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
62
63   OpenGl_Matrix aCurrentMx;
64   glGetFloatv (GL_MODELVIEW_MATRIX, (GLfloat*) &aCurrentMx);
65
66   if (aMatrixMode != GL_MODELVIEW)
67   {
68     glMatrixMode (GL_MODELVIEW);
69   }
70
71   switch (theCoordSpace)
72   {
73     case EquationCoords_View:  glLoadMatrixf ((const GLfloat*) &OpenGl_IdentityMatrix); break;
74     case EquationCoords_World: glLoadMatrixf ((const GLfloat*) theWS->ViewMatrix());    break;
75   }
76
77   Add (thePlanes, theCoordSpace);
78
79   // restore model-view matrix
80   glLoadMatrixf ((GLfloat*) &aCurrentMx);
81
82   // restore context matrix state
83   if (aMatrixMode != GL_MODELVIEW)
84   {
85     glMatrixMode (aMatrixMode);
86   }
87 }
88
89 // =======================================================================
90 // function : Add
91 // purpose  :
92 // =======================================================================
93 void OpenGl_ClippingState::Add (Graphic3d_SetOfHClipPlane& thePlanes, const EquationCoords& theCoordSpace)
94 {
95   Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes);
96   while (aPlaneIt.More() && myEmptyPlaneIds->Available() > 0)
97   {
98     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
99     if (Contains (aPlane))
100     {
101       thePlanes.Remove (aPlaneIt);
102       continue;
103     }
104
105     Standard_Integer anID = myEmptyPlaneIds->Next();
106     myPlanes.Add (aPlane);
107     myPlaneStates.Bind (aPlane, PlaneProps (theCoordSpace, anID, Standard_True));
108
109     glEnable ((GLenum)anID);
110     glClipPlane ((GLenum)anID, aPlane->GetEquation());
111     aPlaneIt.Next();
112   }
113
114   while (aPlaneIt.More() && myEmptyPlaneIds->Available() == 0)
115   {
116     thePlanes.Remove (aPlaneIt);
117   }
118 }
119
120 // =======================================================================
121 // function : Remove
122 // purpose  :
123 // =======================================================================
124 void OpenGl_ClippingState::Remove (const Graphic3d_SetOfHClipPlane& thePlanes)
125 {
126   Graphic3d_SetOfHClipPlane::Iterator aPlaneIt (thePlanes);
127   for (; aPlaneIt.More(); aPlaneIt.Next())
128   {
129     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
130     if (!Contains (aPlane))
131     {
132       continue;
133     }
134
135     Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
136     myEmptyPlaneIds->Free (anID);
137     myPlaneStates.UnBind (aPlane);
138
139     glDisable ((GLenum)anID);
140   }
141
142   // renew collection of planes
143   aPlaneIt.Init (myPlanes);
144   while (aPlaneIt.More())
145   {
146     const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
147     if (!myPlaneStates.IsBound (aPlane))
148     {
149       myPlanes.Remove (aPlaneIt);
150     }
151     else
152     {
153       aPlaneIt.Next();
154     }
155   }
156 }
157
158 // =======================================================================
159 // function : SetEnabled
160 // purpose  :
161 // =======================================================================
162 void OpenGl_ClippingState::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane,
163                                        const Standard_Boolean theIsEnabled)
164 {
165   if (!Contains (thePlane))
166   {
167     return;
168   }
169
170   PlaneProps& aProps = myPlaneStates.ChangeFind (thePlane);
171   if (theIsEnabled == aProps.IsEnabled)
172   {
173     return;
174   }
175
176   GLenum anID = (GLenum)aProps.ContextID;
177   if (theIsEnabled)
178   {
179     glEnable (anID);
180   }
181   else
182   {
183     glDisable (anID);
184   }
185
186   aProps.IsEnabled = theIsEnabled;
187 }