0027943: Visualization - fix broken shading by positional light for object with local...
[occt.git] / src / OpenGl / OpenGl_Clipping.cxx
CommitLineData
4269bd1b 1// Created on: 2013-09-05
2// Created by: Anton POLETAEV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
4269bd1b 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
4269bd1b 6//
d5f74e42 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
973c2be1 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.
4269bd1b 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
4269bd1b 15
30f0ad28 16#include <OpenGl_Clipping.hxx>
79f4f036 17
4269bd1b 18#include <OpenGl_GlCore11.hxx>
b859a34d 19#include <OpenGl_Workspace.hxx>
79f4f036 20#include <OpenGl_Context.hxx>
4269bd1b 21
3202bf1e 22// =======================================================================
23// function : OpenGl_ClippingIterator
24// purpose :
25// =======================================================================
26OpenGl_ClippingIterator::OpenGl_ClippingIterator (const OpenGl_Clipping& theClipping)
27: myDisabled (&theClipping.myDisabledPlanes),
28 myCurrIndex (1)
29{
30 if (!theClipping.myPlanesGlobal.IsNull())
31 {
32 myIter1.Init (*theClipping.myPlanesGlobal);
33 }
34 if (!theClipping.myPlanesLocal.IsNull())
35 {
36 myIter2.Init (*theClipping.myPlanesLocal);
37 }
38}
ca3c13d1 39
4269bd1b 40// =======================================================================
41// function : OpenGl_ClippingState
42// purpose :
43// =======================================================================
30f0ad28 44OpenGl_Clipping::OpenGl_Clipping ()
3202bf1e 45: myEmptyPlaneIds (new NCollection_Shared<Aspect_GenId> (1, 6)),
3b1817a9 46 myNbClipping (0),
3202bf1e 47 myNbCapping (0),
48 myNbDisabled (0)
4269bd1b 49{}
50
51// =======================================================================
52// function : Init
53// purpose :
54// =======================================================================
30f0ad28 55void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
4269bd1b 56{
3202bf1e 57 myPlanesGlobal.Nullify();
58 myPlanesLocal.Nullify();
59
3b1817a9 60 myNbClipping = 0;
61 myNbCapping = 0;
3202bf1e 62 myNbDisabled = 0;
63 myEmptyPlaneIds = new NCollection_Shared<Aspect_GenId> (1, theMaxPlanes);
4269bd1b 64}
65
66// =======================================================================
3202bf1e 67// function : Reset
4269bd1b 68// purpose :
69// =======================================================================
3202bf1e 70void OpenGl_Clipping::Reset (const Handle(OpenGl_Context)& theGlCtx,
71 const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
4269bd1b 72{
3202bf1e 73 const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
74 remove (theGlCtx, myPlanesLocal, aStartIndex);
75 remove (theGlCtx, myPlanesGlobal, 1);
4269bd1b 76
3202bf1e 77 myPlanesGlobal = thePlanes;
78 myPlanesLocal.Nullify();
4269bd1b 79
3202bf1e 80 add (theGlCtx, thePlanes, 1);
81 myNbDisabled = 0;
c827ea3a 82
3202bf1e 83 // Method ::add() implicitly extends myDisabledPlanes (NCollection_Vector::SetValue()),
84 // however we do not reset myDisabledPlanes and mySkipFilter beforehand to avoid redundant memory re-allocations.
85 // So once extended, they will never reduce their size to lower values.
86 // This should not be a problem since overall number of clipping planes is expected to be quite small.
87}
88
89// =======================================================================
90// function : SetLocalPlanes
91// purpose :
92// =======================================================================
93void OpenGl_Clipping::SetLocalPlanes (const Handle(OpenGl_Context)& theGlCtx,
94 const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
95{
96 const Standard_Integer aStartIndex = myPlanesGlobal.IsNull() ? 1 : myPlanesGlobal->Size() + 1;
97 remove (theGlCtx, myPlanesLocal, aStartIndex);
98
99 myPlanesLocal = thePlanes;
100
101 add (theGlCtx, thePlanes, aStartIndex);
4269bd1b 102}
103
104// =======================================================================
3202bf1e 105// function : add
4269bd1b 106// purpose :
107// =======================================================================
3202bf1e 108void OpenGl_Clipping::add (const Handle(OpenGl_Context)& theGlCtx,
109 const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
110 const Standard_Integer theStartIndex)
4269bd1b 111{
3202bf1e 112 if (thePlanes.IsNull())
113 {
114 return;
115 }
116
79f4f036 117#if !defined(GL_ES_VERSION_2_0)
118 const bool toUseFfp = theGlCtx->core11 != NULL
119 && theGlCtx->caps->ffpEnable;
3202bf1e 120 if (toUseFfp)
121 {
122 // Set either identity or pure view matrix.
123 theGlCtx->ApplyWorldViewMatrix();
124 }
79f4f036 125#else
126 (void )theGlCtx;
127#endif
128
3202bf1e 129 Standard_Integer aPlaneId = theStartIndex;
130 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*thePlanes); aPlaneIt.More(); aPlaneIt.Next(), ++aPlaneId)
4269bd1b 131 {
132 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
3202bf1e 133 myDisabledPlanes.SetValue (aPlaneId, Standard_False); // automatically resizes the vector
134 if (!aPlane->IsOn())
b859a34d 135 {
4269bd1b 136 continue;
b859a34d 137 }
4269bd1b 138
ca3c13d1 139 #if !defined(GL_ES_VERSION_2_0)
3202bf1e 140 if (toUseFfp && myEmptyPlaneIds->HasFree())
79f4f036 141 {
3202bf1e 142 const Standard_Integer anFfpPlaneID = GL_CLIP_PLANE0 + myEmptyPlaneIds->Next();
143 ::glEnable ((GLenum )anFfpPlaneID);
144 theGlCtx->core11->glClipPlane ((GLenum )anFfpPlaneID, aPlane->GetEquation());
79f4f036 145 }
ca3c13d1 146 #endif
3b1817a9 147 if (aPlane->IsCapping())
148 {
149 ++myNbCapping;
150 }
151 else
152 {
153 ++myNbClipping;
154 }
b859a34d 155 }
4269bd1b 156
3202bf1e 157#if !defined(GL_ES_VERSION_2_0)
158 // Restore combined model-view matrix.
159 if (toUseFfp)
b859a34d 160 {
3202bf1e 161 theGlCtx->ApplyModelViewMatrix();
4269bd1b 162 }
3202bf1e 163#endif
4269bd1b 164}
165
4269bd1b 166// =======================================================================
3202bf1e 167// function : remove
4269bd1b 168// purpose :
169// =======================================================================
3202bf1e 170void OpenGl_Clipping::remove (const Handle(OpenGl_Context)& theGlCtx,
171 const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes,
172 const Standard_Integer theStartIndex)
4269bd1b 173{
3202bf1e 174 if (thePlanes.IsNull())
175 {
176 return;
177 }
178
79f4f036 179#if !defined(GL_ES_VERSION_2_0)
180 const bool toUseFfp = theGlCtx->core11 != NULL
181 && theGlCtx->caps->ffpEnable;
182#else
183 (void )theGlCtx;
184#endif
185
3202bf1e 186 Standard_Integer aPlaneIndex = theStartIndex;
187 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*thePlanes); aPlaneIt.More(); aPlaneIt.Next(), ++aPlaneIndex)
b859a34d 188 {
189 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
3202bf1e 190 if (!aPlane->IsOn()
191 || myDisabledPlanes.Value (aPlaneIndex))
b859a34d 192 {
193 continue;
194 }
195
3202bf1e 196 #if !defined(GL_ES_VERSION_2_0)
197 const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIndex - 1;
198 if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
3b1817a9 199 {
79f4f036 200 if (toUseFfp)
201 {
3202bf1e 202 ::glDisable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
79f4f036 203 }
3202bf1e 204 myEmptyPlaneIds->Free (anFfpPlaneID);
205 }
206 #endif
207
208 if (aPlane->IsCapping())
209 {
210 --myNbCapping;
211 }
212 else
213 {
214 --myNbClipping;
215 }
216 }
217}
218
219// =======================================================================
220// function : SetEnabled
221// purpose :
222// =======================================================================
223Standard_Boolean OpenGl_Clipping::SetEnabled (const Handle(OpenGl_Context)& theGlCtx,
224 const OpenGl_ClippingIterator& thePlane,
225 const Standard_Boolean theIsEnabled)
226{
227 const Standard_Integer aPlaneIndex = thePlane.PlaneIndex();
228 Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIndex);
229 if (isDisabled == !theIsEnabled)
230 {
231 return Standard_False;
232 }
233
234 isDisabled = !theIsEnabled;
235
236#if !defined(GL_ES_VERSION_2_0)
237 const bool toUseFfp = theGlCtx->core11 != NULL
238 && theGlCtx->caps->ffpEnable;
239 if (toUseFfp)
240 {
241 const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIndex - 1;
242 if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
243 {
244 if (theIsEnabled)
3b1817a9 245 {
3202bf1e 246 ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
3b1817a9 247 }
248 else
249 {
3202bf1e 250 ::glDisable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
3b1817a9 251 }
252 }
b859a34d 253 }
3202bf1e 254#else
255 (void )theGlCtx;
256#endif
b859a34d 257
3202bf1e 258 if (thePlane.Value()->IsCapping())
b859a34d 259 {
3202bf1e 260 myNbCapping += (theIsEnabled ? 1 : -1);
261 }
262 else
263 {
264 myNbClipping += (theIsEnabled ? 1 : -1);
b859a34d 265 }
3202bf1e 266 myNbDisabled -= (theIsEnabled ? 1 : -1);
267 return Standard_True;
4269bd1b 268}
269
270// =======================================================================
3202bf1e 271// function : RestoreDisabled
4269bd1b 272// purpose :
273// =======================================================================
3202bf1e 274void OpenGl_Clipping::RestoreDisabled (const Handle(OpenGl_Context)& theGlCtx)
4269bd1b 275{
3202bf1e 276 if (myNbDisabled == 0)
b859a34d 277 {
4269bd1b 278 return;
b859a34d 279 }
4269bd1b 280
3202bf1e 281 myNbDisabled = 0;
ca3c13d1 282#if !defined(GL_ES_VERSION_2_0)
79f4f036 283 const bool toUseFfp = theGlCtx->core11 != NULL
284 && theGlCtx->caps->ffpEnable;
20aeeb7b 285#else
286 (void )theGlCtx;
ca3c13d1 287#endif
3202bf1e 288 for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
b859a34d 289 {
3202bf1e 290 Standard_Boolean& isDisabled = myDisabledPlanes.ChangeValue (aPlaneIter.PlaneIndex());
291 if (!isDisabled)
292 {
293 continue;
294 }
295
296 isDisabled = Standard_False;
ca3c13d1 297 #if !defined(GL_ES_VERSION_2_0)
79f4f036 298 if (toUseFfp)
299 {
3202bf1e 300 const Standard_Integer anFfpPlaneID = myEmptyPlaneIds->Lower() + aPlaneIter.PlaneIndex() - 1;
301 if (anFfpPlaneID <= myEmptyPlaneIds->Upper())
302 {
303 ::glEnable (GLenum(GL_CLIP_PLANE0 + anFfpPlaneID));
304 }
79f4f036 305 }
ca3c13d1 306 #endif
3202bf1e 307
308 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
309 if (aPlane->IsCapping())
3b1817a9 310 {
311 ++myNbCapping;
312 }
313 else
314 {
315 ++myNbClipping;
316 }
b859a34d 317 }
3202bf1e 318}
319
320// =======================================================================
321// function : DisableGlobal
322// purpose :
323// =======================================================================
324void OpenGl_Clipping::DisableGlobal (const Handle(OpenGl_Context)& theGlCtx)
325{
326 for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
b859a34d 327 {
3202bf1e 328 if (!aPlaneIter.IsGlobal())
79f4f036 329 {
3202bf1e 330 // local planes always follow global ones in iterator
331 return;
79f4f036 332 }
3202bf1e 333
334 SetEnabled (theGlCtx, aPlaneIter, Standard_False);
335 }
336}
337
338// =======================================================================
339// function : DisableAllExcept
340// purpose :
341// =======================================================================
342void OpenGl_Clipping::DisableAllExcept (const Handle(OpenGl_Context)& theGlCtx,
343 const OpenGl_ClippingIterator& thePlane)
344{
345 for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
346 {
347 if (aPlaneIter.IsDisabled())
3b1817a9 348 {
3202bf1e 349 mySkipFilter.SetValue (aPlaneIter.PlaneIndex(), Standard_True);
350 continue;
3b1817a9 351 }
3202bf1e 352
353 const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() == thePlane.PlaneIndex());
354 SetEnabled (theGlCtx, aPlaneIter, isOn);
355 mySkipFilter.SetValue (aPlaneIter.PlaneIndex(), Standard_False);
356 }
357}
358
359// =======================================================================
360// function : EnableAllExcept
361// purpose :
362// =======================================================================
363void OpenGl_Clipping::EnableAllExcept (const Handle(OpenGl_Context)& theGlCtx,
364 const OpenGl_ClippingIterator& thePlane)
365{
366 for (OpenGl_ClippingIterator aPlaneIter (*this); aPlaneIter.More(); aPlaneIter.Next())
367 {
368 if (mySkipFilter.Value (aPlaneIter.PlaneIndex()))
3b1817a9 369 {
3202bf1e 370 continue;
3b1817a9 371 }
4269bd1b 372
3202bf1e 373 const Standard_Boolean isOn = (aPlaneIter.PlaneIndex() != thePlane.PlaneIndex());
374 SetEnabled (theGlCtx, aPlaneIter, isOn);
375 }
4269bd1b 376}