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