0027862: Exception in BRepOffsetAPI_MakePipeShell
[occt.git] / src / OpenGl / OpenGl_CappingAlgo.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
16#include <OpenGl_CappingAlgo.hxx>
deb02f86 17
4269bd1b 18#include <OpenGl_Workspace.hxx>
19#include <OpenGl_Context.hxx>
20#include <OpenGl_PrimitiveArray.hxx>
21#include <OpenGl_CappingPlaneResource.hxx>
22#include <OpenGl_Vec.hxx>
b64d84be 23#include <OpenGl_Structure.hxx>
deb02f86 24#include <OpenGl_ShaderManager.hxx>
4269bd1b 25
92efcf78 26IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter,OpenGl_RenderFilter)
27
4269bd1b 28namespace
29{
ca3c13d1 30#if !defined(GL_ES_VERSION_2_0)
31 static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
32 static const GLint THE_FILLPRIM_TO = GL_POLYGON;
33#else
34 static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
35 static const GLint THE_FILLPRIM_TO = GL_TRIANGLE_FAN;
36#endif
3e05329c 37
38 //! Render infinite capping plane.
39 //! @param theWorkspace [in] the GL workspace, context state.
40 //! @param thePlane [in] the graphical plane, for which the capping surface is rendered.
41 static void renderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
42 const Handle(OpenGl_CappingPlaneResource)& thePlane,
43 const OpenGl_AspectFace* theAspectFace)
44 {
45 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
46 thePlane->Update (aContext, theAspectFace != NULL ? theAspectFace->Aspect() : Handle(Graphic3d_AspectFillArea3d)());
47
48 const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace();
49 theWorkspace->SetAspectFace (thePlane->AspectFace());
50
51 // set identity model matrix
52 aContext->ModelWorldState.Push();
53 aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*thePlane->Orientation()->mat));
54 aContext->ApplyModelViewMatrix();
55
56 thePlane->Primitives().Render (theWorkspace);
57
58 aContext->ModelWorldState.Pop();
59 aContext->ApplyModelViewMatrix();
60
61 theWorkspace->SetAspectFace (aFaceAspect);
62 }
63
64 //! Render capping for specific structure.
65 static void renderCappingForStructure (const Handle(OpenGl_Workspace)& theWorkspace,
66 const OpenGl_Structure& theStructure,
67 const Handle(OpenGl_CappingPlaneResource)& thePlane)
68 {
69 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
70 const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
71 const Handle(Graphic3d_ClipPlane)& aRenderPlane = thePlane->Plane();
72 for (OpenGl_Structure::GroupIterator aGroupIter (theStructure.Groups()); aGroupIter.More(); aGroupIter.Next())
73 {
74 if (!aGroupIter.Value()->IsClosed())
75 {
76 continue;
77 }
78
79 // enable only the rendering plane to generate stencil mask
80 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
81 {
82 const Standard_Boolean isOn = (aPlaneIt.Value() == aRenderPlane);
83 aContext->ChangeClipping().SetEnabled (aContext, aPlaneIt.Value(), isOn);
84 }
85 aContext->ShaderManager()->UpdateClippingState();
86
87 glClear (GL_STENCIL_BUFFER_BIT);
88 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
89
90 // override aspects, disable culling
91 theWorkspace->SetAspectFace (&theWorkspace->NoneCulling());
92 theWorkspace->ApplyAspectFace();
93
94 // evaluate number of pair faces
95 glDisable (GL_DEPTH_TEST);
96 glDepthMask (GL_FALSE);
97 glStencilFunc (GL_ALWAYS, 1, 0x01);
98 glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
99
100 // render closed primitives
101 if (aRenderPlane->ToUseObjectProperties())
102 {
103 aGroupIter.Value()->Render (theWorkspace);
104 }
105 else
106 {
107 for (; aGroupIter.More(); aGroupIter.Next())
108 {
109 if (aGroupIter.Value()->IsClosed())
110 {
111 aGroupIter.Value()->Render (theWorkspace);
112 }
113 }
114 }
115
116 // override material, cull back faces
117 theWorkspace->SetAspectFace (&theWorkspace->FrontCulling());
118 theWorkspace->ApplyAspectFace();
119
120 // enable all clip plane except the rendered one
121 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
122 {
123 const Standard_Boolean isOn = (aPlaneIt.Value() != aRenderPlane);
124 aContext->ChangeClipping().SetEnabled (aContext, aPlaneIt.Value(), isOn);
125 }
126 aContext->ShaderManager()->UpdateClippingState();
127
128 // render capping plane using the generated stencil mask
129 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
130 glDepthMask (GL_TRUE);
131 glStencilFunc (GL_EQUAL, 1, 0x01);
132 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
133 glEnable (GL_DEPTH_TEST);
134
135 renderPlane (theWorkspace, thePlane, aRenderPlane->ToUseObjectProperties()
136 ? aGroupIter.Value()->AspectFace()
137 : NULL);
138
139 aContext->ShaderManager()->RevertClippingState();
140 aContext->ShaderManager()->RevertClippingState();
141 }
142
143 if (theStructure.InstancedStructure() != NULL)
144 {
145 renderCappingForStructure (theWorkspace, *theStructure.InstancedStructure(), thePlane);
146 }
147 }
ca3c13d1 148}
4269bd1b 149
150// =======================================================================
151// function : RenderCapping
152// purpose :
153// =======================================================================
cc6852f3 154void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
155 const OpenGl_Structure& theStructure)
4269bd1b 156{
4269bd1b 157 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
158
b859a34d 159 // check whether algorithm need to be performed
4269bd1b 160 Standard_Boolean isCapping = Standard_False;
51b10cd4 161 const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
3e05329c 162 for (Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
4269bd1b 163 {
164 const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value();
165 if (aPlane->IsCapping())
166 {
167 isCapping = Standard_True;
168 break;
169 }
170 }
171
172 // do not perform algorithm is there is nothing to render
173 if (!isCapping)
b859a34d 174 {
4269bd1b 175 return;
b859a34d 176 }
4269bd1b 177
4269bd1b 178 // remember current aspect face defined in workspace
f9ba5c4d 179 const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace();
4269bd1b 180
181 // replace primitive groups rendering filter
4269bd1b 182 Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
f8ae3605 183 theWorkspace->SetRenderFilter (theWorkspace->DefaultCappingAlgoFilter());
4269bd1b 184
185 // prepare for rendering the clip planes
186 glEnable (GL_STENCIL_TEST);
187
347423b2 188 // remember current state of depth
189 // function and change its value
190 GLint aDepthFuncPrev;
191 glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev);
192 glDepthFunc (GL_LESS);
193
4269bd1b 194 // generate capping for every clip plane
3e05329c 195 for (Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
4269bd1b 196 {
197 // get plane being rendered
198 const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
199 if (!aRenderPlane->IsCapping())
200 {
201 continue;
202 }
203
3e05329c 204 // get resource for the plane
205 const TCollection_AsciiString& aResId = aRenderPlane->GetId();
206 Handle(OpenGl_CappingPlaneResource) aPlaneRes;
207 if (!aContext->GetResource (aResId, aPlaneRes))
4269bd1b 208 {
3e05329c 209 // share and register for release once the resource is no longer used
210 aPlaneRes = new OpenGl_CappingPlaneResource (aRenderPlane);
211 aContext->ShareResource (aResId, aPlaneRes);
4269bd1b 212 }
4269bd1b 213
3e05329c 214 renderCappingForStructure (theWorkspace, theStructure, aPlaneRes);
4269bd1b 215
3e05329c 216 // set delayed resource release
217 aPlaneRes.Nullify();
218 aContext->ReleaseResource (aResId, Standard_True);
4269bd1b 219 }
220
221 // restore previous application state
222 glClear (GL_STENCIL_BUFFER_BIT);
347423b2 223 glDepthFunc (aDepthFuncPrev);
4269bd1b 224 glStencilFunc (GL_ALWAYS, 0, 0xFF);
225 glDisable (GL_STENCIL_TEST);
226
227 // enable clipping
3e05329c 228 for (Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
4269bd1b 229 {
79f4f036 230 aContext->ChangeClipping().SetEnabled (aContext, aCappingIt.Value(), Standard_True);
4269bd1b 231 }
232
233 // restore rendering aspects
234 theWorkspace->SetAspectFace (aFaceAsp);
235 theWorkspace->SetRenderFilter (aRenderFilter);
236}
237
238// =======================================================================
4269bd1b 239// function : CanRender
240// purpose :
241// =======================================================================
242Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
243{
871fa103 244 const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
245 return aPArray != NULL
ca3c13d1 246 && aPArray->DrawMode() >= THE_FILLPRIM_FROM
247 && aPArray->DrawMode() <= THE_FILLPRIM_TO;
4269bd1b 248}