1 // Created on: 2014-03-31
2 // Created by: Danila ULYANOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_Layer.hxx>
18 #include <OpenGl_BVHTreeSelector.hxx>
19 #include <OpenGl_Structure.hxx>
20 #include <OpenGl_View.hxx>
21 #include <OpenGl_Workspace.hxx>
22 #include <Graphic3d_GraphicDriver.hxx>
24 // =======================================================================
25 // function : OpenGl_Layer
27 // =======================================================================
28 OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
29 : myArray (0, theNbPriorities - 1),
31 myBVHIsLeftChildQueuedFirst (Standard_True),
32 myIsBVHPrimitivesNeedsReset (Standard_False)
37 // =======================================================================
38 // function : ~OpenGl_Layer
40 // =======================================================================
41 OpenGl_Layer::~OpenGl_Layer()
46 // =======================================================================
49 // =======================================================================
50 void OpenGl_Layer::Add (const OpenGl_Structure* theStruct,
51 const Standard_Integer thePriority,
52 Standard_Boolean isForChangePriority)
54 const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
55 if (theStruct == NULL)
60 myArray (anIndex).Add (theStruct);
61 if (theStruct->IsAlwaysRendered())
63 theStruct->MarkAsNotCulled();
65 else if (!isForChangePriority)
67 if (theStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
69 myBVHPrimitives.Add (theStruct);
73 myBVHPrimitivesTrsfPers.Add (theStruct);
79 // =======================================================================
82 // =======================================================================
83 bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
84 Standard_Integer& thePriority,
85 Standard_Boolean isForChangePriority)
87 if (theStruct == NULL)
93 const Standard_Integer aNbPriorities = myArray.Length();
94 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
96 OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
98 const Standard_Integer anIndex = aStructures.FindIndex (theStruct);
101 aStructures.Swap (anIndex, aStructures.Size());
102 aStructures.RemoveLast();
104 if (!theStruct->IsAlwaysRendered()
105 && !isForChangePriority)
107 if (!myBVHPrimitives.Remove (theStruct))
109 myBVHPrimitivesTrsfPers.Remove (theStruct);
113 thePriority = aPriorityIter;
122 // =======================================================================
123 // function : InvalidateBVHData
125 // =======================================================================
126 void OpenGl_Layer::InvalidateBVHData()
128 myIsBVHPrimitivesNeedsReset = Standard_True;
131 // =======================================================================
132 // function : renderAll
134 // =======================================================================
135 void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
137 const Standard_Integer aNbPriorities = myArray.Length();
138 const Standard_Integer aViewId = theWorkspace->View()->Identification();
139 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
141 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
142 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
144 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
145 if (!aStruct->IsVisible())
149 else if (!aStruct->ViewAffinity.IsNull()
150 && !aStruct->ViewAffinity->IsVisible (aViewId))
155 aStruct->Render (theWorkspace);
160 // =======================================================================
161 // function : renderTraverse
163 // =======================================================================
164 void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
166 if (myIsBVHPrimitivesNeedsReset)
168 myBVHPrimitives.Clear();
169 myBVHPrimitivesTrsfPers.Clear();
170 myIsBVHPrimitivesNeedsReset = Standard_False;
171 for (Standard_Integer aPriorityIdx = 0, aNbPriorities = myArray.Length(); aPriorityIdx < aNbPriorities; ++aPriorityIdx)
173 for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myArray (aPriorityIdx)); aStructIter.More(); aStructIter.Next())
175 const OpenGl_Structure* aStruct = aStructIter.Value();
177 if (aStruct->IsAlwaysRendered())
180 if (aStruct->TransformPersistence.Flags == Graphic3d_TMF_None)
182 myBVHPrimitives.Add (aStruct);
186 myBVHPrimitivesTrsfPers.Add (aStruct);
192 OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
193 traverse (aSelector);
195 const Standard_Integer aNbPriorities = myArray.Length();
196 const Standard_Integer aViewId = theWorkspace->View()->Identification();
197 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
199 const OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter);
200 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
202 const OpenGl_Structure* aStruct = aStructures.FindKey (aStructIdx);
203 if (!aStruct->IsVisible()
204 || aStruct->IsCulled())
208 else if (!aStruct->ViewAffinity.IsNull()
209 && !aStruct->ViewAffinity->IsVisible (aViewId))
214 aStruct->Render (theWorkspace);
215 aStruct->ResetCullingStatus();
220 // =======================================================================
221 // function : traverse
223 // =======================================================================
224 void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
226 // handle a case when all objects are infinite
227 if (myBVHPrimitives .Size() == 0
228 && myBVHPrimitivesTrsfPers.Size() == 0)
231 theSelector.CacheClipPtsProjections();
233 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVHTree;
235 for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
237 const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
240 if (myBVHPrimitivesTrsfPers.Size() == 0)
243 const OpenGl_Mat4& aProjection = theSelector.ProjectionMatrix();
244 const OpenGl_Mat4& aWorldView = theSelector.WorldViewMatrix();
245 const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState();
246 aBVHTree = myBVHPrimitivesTrsfPers.BVH (aProjection, aWorldView, aWVPState);
250 if (myBVHPrimitives.Size() == 0)
253 aBVHTree = myBVHPrimitives.BVH();
256 Standard_Integer aNode = 0; // a root node
258 if (!theSelector.Intersect (aBVHTree->MinPoint (0),
259 aBVHTree->MaxPoint (0)))
264 Standard_Integer aStack[32];
265 Standard_Integer aHead = -1;
268 if (!aBVHTree->IsOuter (aNode))
270 const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
271 const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
272 const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
273 aBVHTree->MaxPoint (aLeftChildIdx));
274 const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
275 aBVHTree->MaxPoint (aRightChildIdx));
279 aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
280 aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
281 myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
283 else if (isLeftChildIn
286 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
295 aNode = aStack[aHead--];
300 Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
301 const OpenGl_Structure* aStruct =
302 isTrsfPers ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx)
303 : myBVHPrimitives.GetStructureById (aIdx);
304 aStruct->MarkAsNotCulled();
310 aNode = aStack[aHead--];
316 // =======================================================================
319 // =======================================================================
320 Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
322 // the source priority list shouldn't have more priorities
323 const Standard_Integer aNbPriorities = theOther.NbPriorities();
324 if (aNbPriorities > NbPriorities())
326 return Standard_False;
329 // add all structures to destination priority list
330 for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
332 const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter);
333 for (Standard_Integer aStructIdx = 1; aStructIdx <= aStructures.Size(); ++aStructIdx)
335 Add (aStructures.FindKey (aStructIdx), aPriorityIter);
339 return Standard_True;
342 //=======================================================================
345 //=======================================================================
346 void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
347 const OpenGl_GlobalLayerSettings& theDefaultSettings) const
349 TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
351 // separate depth buffers
352 if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
354 glClear (GL_DEPTH_BUFFER_BIT);
358 if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
360 // assuming depth test is enabled by default
361 glDepthFunc (theDefaultSettings.DepthFunc);
365 glDepthFunc (GL_ALWAYS);
368 // save environment texture
369 Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
370 if (!myLayerSettings.UseEnvironmentTexture)
372 theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
375 // handle depth offset
376 if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
378 theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
379 myLayerSettings.DepthOffsetFactor,
380 myLayerSettings.DepthOffsetUnits);
384 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
385 anAppliedOffsetParams.factor,
386 anAppliedOffsetParams.units);
389 // handle depth write
390 theWorkspace->UseDepthWrite() = IsSettingEnabled (Graphic3d_ZLayerDepthWrite);
391 glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
393 // render priority list
394 theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
396 // always restore polygon offset between layers rendering
397 theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
398 anAppliedOffsetParams.factor,
399 anAppliedOffsetParams.units);
401 // restore environment texture
402 if (!myLayerSettings.UseEnvironmentTexture)
404 theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);