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