0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / OpenGl / OpenGl_CappingAlgo.cxx
CommitLineData
4269bd1b 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_CappingAlgo.hxx>
21#include <OpenGl_Workspace.hxx>
22#include <OpenGl_Context.hxx>
23#include <OpenGl_PrimitiveArray.hxx>
24#include <OpenGl_CappingPlaneResource.hxx>
25#include <OpenGl_Vec.hxx>
26
27IMPLEMENT_STANDARD_HANDLE(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
28IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
29
30Handle(OpenGl_RenderFilter) OpenGl_CappingAlgo::myRenderFilter;
31OpenGl_AspectFace OpenGl_CappingAlgo::myFrontCulling;
32OpenGl_AspectFace OpenGl_CappingAlgo::myNoneCulling;
33Standard_Boolean OpenGl_CappingAlgo::myIsInit = Standard_False;
34
35namespace
36{
37 static const OpenGl_Vec4 THE_CAPPING_PLN_VERTS[12] =
38 { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
39 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f),
40 OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f),
41 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
42 OpenGl_Vec4 ( 0.0f, 0.0f, 1.0f, 0.0f),
43 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
44 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
45 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
46 OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f),
47 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
48 OpenGl_Vec4 ( 0.0f, 0.0f,-1.0f, 0.0f),
49 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) };
50
51 static const OpenGl_Vec4 THE_CAPPING_PLN_TCOORD[12] =
52 { OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
53 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f),
54 OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f),
55 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
56 OpenGl_Vec4 ( 0.0f, 1.0f, 0.0f, 0.0f),
57 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
58 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
59 OpenGl_Vec4 (-1.0f, 0.0f, 0.0f, 0.0f),
60 OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f),
61 OpenGl_Vec4 ( 0.0f, 0.0f, 0.0f, 1.0f),
62 OpenGl_Vec4 ( 0.0f,-1.0f, 0.0f, 0.0f),
63 OpenGl_Vec4 ( 1.0f, 0.0f, 0.0f, 0.0f) };
64};
65
66// =======================================================================
67// function : RenderCapping
68// purpose :
69// =======================================================================
70void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
71 const OpenGl_ListOfGroup& theGroups)
72{
4269bd1b 73 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
74
b859a34d 75 // check whether algorithm need to be performed
4269bd1b 76 Standard_Boolean isCapping = Standard_False;
51b10cd4 77 const Graphic3d_SequenceOfHClipPlane& aContextPlanes = aContext->Clipping().Planes();
78 Graphic3d_SequenceOfHClipPlane::Iterator aCappingIt (aContextPlanes);
4269bd1b 79 for (; aCappingIt.More(); aCappingIt.Next())
80 {
81 const Handle(Graphic3d_ClipPlane)& aPlane = aCappingIt.Value();
82 if (aPlane->IsCapping())
83 {
84 isCapping = Standard_True;
85 break;
86 }
87 }
88
89 // do not perform algorithm is there is nothing to render
90 if (!isCapping)
b859a34d 91 {
4269bd1b 92 return;
b859a34d 93 }
4269bd1b 94
95 // init internal data
96 Init();
97
98 // remember current aspect face defined in workspace
99 const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace (Standard_False);
100
101 // replace primitive groups rendering filter
102 static Handle(OpenGl_CappingAlgoFilter) aCappingFilter = new OpenGl_CappingAlgoFilter();
103 Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
104 theWorkspace->SetRenderFilter (aCappingFilter);
105
106 // prepare for rendering the clip planes
107 glEnable (GL_STENCIL_TEST);
108
109 // generate capping for every clip plane
110 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
111 {
112 // get plane being rendered
113 const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
114 if (!aRenderPlane->IsCapping())
115 {
116 continue;
117 }
118
119 // enable only the rendering plane to generate stencil mask
51b10cd4 120 Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (aContextPlanes);
4269bd1b 121 for (; aPlaneIt.More(); aPlaneIt.Next())
122 {
123 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
124 const Standard_Boolean isOn = (aPlane == aRenderPlane);
125 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
126 }
127
128 glClear (GL_STENCIL_BUFFER_BIT);
129 glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
130
131 // override aspects, disable culling
132 theWorkspace->SetAspectFace (NoneCulling());
133 theWorkspace->AspectFace (Standard_True);
134
135 // evaluate number of pair faces
136 glDisable (GL_DEPTH_TEST);
137 glDepthMask (GL_FALSE);
138 glStencilFunc (GL_ALWAYS, 1, 0x01);
139 glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
140
141 OpenGl_ListOfGroup::Iterator aGroupIt (theGroups);
142 for (; aGroupIt.More(); aGroupIt.Next())
143 {
144 aGroupIt.Value()->Render (theWorkspace);
145 }
146
b859a34d 147 // override material, cull back faces
4269bd1b 148 theWorkspace->SetAspectFace (FrontCulling());
149 theWorkspace->AspectFace (Standard_True);
150
151 // enable all clip plane except the rendered one
152 for (aPlaneIt.Init (aContextPlanes); aPlaneIt.More(); aPlaneIt.Next())
153 {
154 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
155 const Standard_Boolean isOn = (aPlane != aRenderPlane);
156 aContext->ChangeClipping().SetEnabled (aPlane, isOn);
157 }
158
159 // render capping plane using the generated stencil mask
160 glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
161 glDepthMask (GL_TRUE);
162 glDepthFunc (GL_LESS);
163 glStencilFunc (GL_EQUAL, 1, 0x01);
164 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
165 glEnable (GL_DEPTH_TEST);
166
167 RenderPlane (theWorkspace, aRenderPlane);
168 }
169
170 // restore previous application state
171 glClear (GL_STENCIL_BUFFER_BIT);
172 glStencilFunc (GL_ALWAYS, 0, 0xFF);
173 glDisable (GL_STENCIL_TEST);
174
175 // enable clipping
176 for (aCappingIt.Init (aContextPlanes); aCappingIt.More(); aCappingIt.Next())
177 {
178 aContext->ChangeClipping().SetEnabled (aCappingIt.Value(), Standard_True);
179 }
180
181 // restore rendering aspects
182 theWorkspace->SetAspectFace (aFaceAsp);
183 theWorkspace->SetRenderFilter (aRenderFilter);
184}
185
186// =======================================================================
187// function : RenderPlane
188// purpose :
189// =======================================================================
190void OpenGl_CappingAlgo::RenderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
191 const Handle(Graphic3d_ClipPlane)& thePlane)
192{
193 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
194
195 // get resource for the plane
196 TCollection_AsciiString aResId = thePlane->GetId();
197
198 Handle(OpenGl_CappingPlaneResource) aPlaneRes;
199 if (!aContext->GetResource (aResId, aPlaneRes))
200 {
201 // share and register for release once the resource is no longer used
202 aPlaneRes = new OpenGl_CappingPlaneResource (thePlane);
203 aContext->ShareResource (aResId, aPlaneRes);
204 }
205
206 aPlaneRes->Update (aContext);
207
208 const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace (Standard_False);
209 const OpenGl_AspectFace* aPlaneAspect = aPlaneRes->AspectFace();
210 if (aPlaneAspect != NULL)
211 {
212 theWorkspace->SetAspectFace (aPlaneAspect);
213 }
214
215 // apply aspect for rendering
216 theWorkspace->AspectFace (Standard_True);
217
218 // set identity model matrix
219 const OpenGl_Matrix* aModelMatrix = theWorkspace->SetStructureMatrix (&OpenGl_IdentityMatrix);
220
221 glMultMatrixf ((const GLfloat*)aPlaneRes->Orientation());
222 glNormal3f (0.0f, 1.0f, 0.0f);
223 glEnableClientState (GL_VERTEX_ARRAY);
224 glVertexPointer (4, GL_FLOAT, 0, (GLfloat* )&THE_CAPPING_PLN_VERTS);
225 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
226 glTexCoordPointer (4, GL_FLOAT, 0, (GLfloat*)&THE_CAPPING_PLN_TCOORD);
227 glDrawArrays (GL_TRIANGLES, 0, 12);
228 glDisableClientState (GL_VERTEX_ARRAY);
229 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
230
392ac980 231 theWorkspace->SetStructureMatrix (aModelMatrix, true);
4269bd1b 232 theWorkspace->SetAspectFace (aFaceAspect);
233
234 // set delayed resource release
235 aPlaneRes.Nullify();
236 aContext->ReleaseResource (aResId, Standard_True);
237}
238
239// =======================================================================
240// function : Init
241// purpose :
242// =======================================================================
243void OpenGl_CappingAlgo::Init()
244{
245 if (myIsInit)
246 return;
247
248 myRenderFilter = new OpenGl_CappingAlgoFilter();
fd4a6963 249 myNoneCulling.ChangeCullingMode() = TelCullNone;
250 myNoneCulling.ChangeEdge() = 0;
4269bd1b 251
fd4a6963 252 myFrontCulling.ChangeCullingMode() = TelCullBack;
253 myFrontCulling.ChangeEdge() = 0;
4269bd1b 254
255 myIsInit = Standard_True;
256}
257
258// =======================================================================
259// function : CanRender
260// purpose :
261// =======================================================================
262Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
263{
264 const OpenGl_PrimitiveArray* aPArray =
265 dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
266 if (!aPArray)
267 return Standard_False;
268
269 switch (aPArray->PArray()->type)
270 {
271 case TelPolygonsArrayType :
272 case TelTrianglesArrayType :
273 case TelQuadranglesArrayType :
274 case TelTriangleStripsArrayType :
275 case TelQuadrangleStripsArrayType :
276 case TelTriangleFansArrayType :
277 return Standard_True;
278
279 default:
280 return Standard_False;
281 }
282}