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