1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-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_CappingAlgo.hxx>
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_GlCore11.hxx>
19 #include <OpenGl_GraphicDriver.hxx>
20 #include <OpenGl_ShaderManager.hxx>
21 #include <OpenGl_ShaderProgram.hxx>
22 #include <OpenGl_StructureShadow.hxx>
23 #include <OpenGl_Vec.hxx>
24 #include <OpenGl_View.hxx>
25 #include <OpenGl_Workspace.hxx>
27 #include <Graphic3d_SequenceOfHClipPlane.hxx>
30 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure)
32 //! Auxiliary class for bounding box presentation
33 class OpenGl_BndBoxPrs : public OpenGl_Element
39 OpenGl_BndBoxPrs (const Graphic3d_BndBox3d& theBndBox)
41 const float Xm = (float )theBndBox.CornerMin().x();
42 const float Ym = (float)theBndBox.CornerMin().y();
43 const float Zm = (float)theBndBox.CornerMin().z();
44 const float XM = (float)theBndBox.CornerMax().x();
45 const float YM = (float)theBndBox.CornerMax().y();
46 const float ZM = (float)theBndBox.CornerMax().z();
48 myVerts[0] = OpenGl_Vec3 (Xm, Ym, Zm);
49 myVerts[1] = OpenGl_Vec3 (Xm, Ym, ZM);
50 myVerts[2] = OpenGl_Vec3 (Xm, YM, ZM);
51 myVerts[3] = OpenGl_Vec3 (Xm, YM, Zm);
52 myVerts[4] = OpenGl_Vec3 (Xm, Ym, Zm);
53 myVerts[5] = OpenGl_Vec3 (XM, Ym, Zm);
54 myVerts[6] = OpenGl_Vec3 (XM, Ym, ZM);
55 myVerts[7] = OpenGl_Vec3 (XM, YM, ZM);
56 myVerts[8] = OpenGl_Vec3 (XM, YM, Zm);
57 myVerts[9] = OpenGl_Vec3 (XM, Ym, Zm);
58 myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
59 myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
60 myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
61 myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
62 myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
63 myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
66 //! Render presentation
67 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
69 #if !defined(GL_ES_VERSION_2_0)
70 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
71 if (aCtx->core11 == NULL)
76 const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
77 aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
78 aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
80 glDisable (GL_LIGHTING);
82 // Use highlight colors
83 aCtx->core11->glColor3fv (theWorkspace->LineColor().GetData());
85 glEnableClientState (GL_VERTEX_ARRAY);
86 glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
87 glDrawArrays (GL_LINE_STRIP, 0, 16);
88 glDisableClientState (GL_VERTEX_ARRAY);
91 if (!aPrevTexture.IsNull())
93 aCtx->BindTextures (aPrevTexture);
100 //! Release graphical resources
101 virtual void Release (OpenGl_Context*)
108 //! Protected destructor
109 virtual ~OpenGl_BndBoxPrs() {}
113 OpenGl_Vec3 myVerts[16]; //!< vertices array
117 DEFINE_STANDARD_ALLOC
121 /*----------------------------------------------------------------------*/
123 // =======================================================================
124 // function : OpenGl_Structure
126 // =======================================================================
127 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
128 : Graphic3d_CStructure (theManager),
129 myInstancedStructure (NULL),
130 myIsRaytracable (Standard_False),
131 myModificationState (0),
132 myIsCulled (Standard_True),
133 myIsMirrored (Standard_False)
135 updateLayerTransformation();
138 // =======================================================================
139 // function : ~OpenGl_Structure
141 // =======================================================================
142 OpenGl_Structure::~OpenGl_Structure()
144 Release (Handle(OpenGl_Context)());
147 // =======================================================================
148 // function : SetZLayer
150 // =======================================================================
151 void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
153 Graphic3d_CStructure::SetZLayer (theLayerIndex);
154 updateLayerTransformation();
157 // =======================================================================
158 // function : SetTransformation
160 // =======================================================================
161 void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
164 myIsMirrored = Standard_False;
165 if (!myTrsf.IsNull())
167 // Determinant of transform matrix less then 0 means that mirror transform applied.
168 const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3))
169 - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3))
170 + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2));
171 myIsMirrored = aDet < 0.0;
174 updateLayerTransformation();
177 ++myModificationState;
181 // =======================================================================
182 // function : SetTransformPersistence
184 // =======================================================================
185 void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
187 myTrsfPers = theTrsfPers;
188 updateLayerTransformation();
191 // =======================================================================
192 // function : updateLayerTransformation
194 // =======================================================================
195 void OpenGl_Structure::updateLayerTransformation()
198 if (!myTrsf.IsNull())
200 aRenderTrsf = myTrsf->Trsf();
203 const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
204 if (!aLayer.OriginTransformation().IsNull()
205 && myTrsfPers.IsNull())
207 aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
209 aRenderTrsf.GetMat4 (myRenderTrsf);
212 // =======================================================================
213 // function : clearHighlightBox
215 // =======================================================================
216 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
218 if (!myHighlightBox.IsNull())
220 myHighlightBox->Release (theGlCtx);
221 myHighlightBox.Nullify();
225 // =======================================================================
226 // function : HighlightWithBndBox
228 // =======================================================================
229 void OpenGl_Structure::highlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct)
231 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
233 if (!myHighlightBox.IsNull())
235 myHighlightBox->Release (aContext);
239 myHighlightBox = new OpenGl_Group (theStruct);
242 myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myHighlightStyle->Color(), Aspect_TOL_SOLID, 1.0));
244 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
245 myHighlightBox->AddElement (aBndBoxPrs);
248 // =======================================================================
249 // function : GraphicHighlight
251 // =======================================================================
252 void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle,
253 const Handle(Graphic3d_Structure)& theStruct)
255 if (!myHighlightStyle.IsNull()
256 && myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX
257 && theStyle->Method() != Aspect_TOHM_BOUNDBOX)
259 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
260 clearHighlightBox (aContext);
263 myHighlightStyle = theStyle;
266 if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
268 highlightWithBndBox (theStruct);
272 // =======================================================================
273 // function : GraphicUnhighlight
275 // =======================================================================
276 void OpenGl_Structure::GraphicUnhighlight()
280 if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
282 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
283 clearHighlightBox (aContext);
286 myHighlightStyle.Nullify();
289 // =======================================================================
290 // function : OnVisibilityChanged
292 // =======================================================================
293 void OpenGl_Structure::OnVisibilityChanged()
297 ++myModificationState;
301 // =======================================================================
302 // function : IsRaytracable
304 // =======================================================================
305 Standard_Boolean OpenGl_Structure::IsRaytracable() const
307 if (!myGroups.IsEmpty()
310 return Standard_True;
313 return myInstancedStructure != NULL
314 && myInstancedStructure->IsRaytracable();
317 // =======================================================================
318 // function : UpdateRaytracableState
320 // =======================================================================
321 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
323 myIsRaytracable = !toCheck;
324 if (!myIsRaytracable)
326 for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
328 if (anIter.Value()->IsRaytracable())
330 myIsRaytracable = Standard_True;
338 ++myModificationState;
342 // =======================================================================
343 // function : Connect
345 // =======================================================================
346 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
348 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
350 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
351 "Error! Instanced structure is already defined");
353 myInstancedStructure = aStruct;
355 if (aStruct->IsRaytracable())
357 UpdateStateIfRaytracable (Standard_False);
361 // =======================================================================
362 // function : Disconnect
364 // =======================================================================
365 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
367 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
369 if (myInstancedStructure == aStruct)
371 myInstancedStructure = NULL;
373 if (aStruct->IsRaytracable())
375 UpdateStateIfRaytracable();
380 // =======================================================================
381 // function : NewGroup
383 // =======================================================================
384 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
386 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
387 myGroups.Append (aGroup);
391 // =======================================================================
392 // function : RemoveGroup
394 // =======================================================================
395 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
397 if (theGroup.IsNull())
402 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
404 // Check for the given group
405 if (aGroupIter.Value() == theGroup)
407 const Standard_Boolean wasRaytracable =
408 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
410 theGroup->Clear (Standard_False);
414 UpdateStateIfRaytracable();
417 myGroups.Remove (aGroupIter);
423 // =======================================================================
426 // =======================================================================
427 void OpenGl_Structure::Clear()
429 Clear (GlDriver()->GetSharedContext());
432 // =======================================================================
435 // =======================================================================
436 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
438 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
441 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
443 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
446 aGroupIter.ChangeValue()->Release (theGlCtx);
450 if (aRaytracableGroupDeleted)
452 myIsRaytracable = Standard_False;
455 Is2dText = Standard_False;
456 IsForHighlight = Standard_False;
459 // =======================================================================
460 // function : renderGeometry
462 // =======================================================================
463 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
464 bool& theHasClosed) const
466 if (myInstancedStructure != NULL)
468 myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
471 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
473 theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
474 aGroupIter.Value()->Render (theWorkspace);
478 // =======================================================================
481 // =======================================================================
482 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
484 // Process the structure only if visible
490 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
492 // Render named status
493 if (highlight && myHighlightBox.IsNull())
495 theWorkspace->SetHighlightStyle (myHighlightStyle);
498 // Apply local transformation
499 aCtx->ModelWorldState.Push();
500 OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
501 aModelWorld = myRenderTrsf;
503 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
504 #if !defined(GL_ES_VERSION_2_0)
505 // detect scale transform
506 if (aCtx->core11 != NULL
509 const Standard_Real aScale = myTrsf->ScaleFactor();
510 if (Abs (aScale - 1.0) > Precision::Confusion())
512 aCtx->SetGlNormalizeEnabled (Standard_True);
517 if (!myTrsfPers.IsNull())
519 aCtx->WorldViewState.Push();
520 OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
521 myTrsfPers->Apply (theWorkspace->View()->Camera(),
522 aCtx->ProjectionState.Current(), aWorldView,
523 aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
525 #if !defined(GL_ES_VERSION_2_0)
526 if (!aCtx->IsGlNormalizeEnabled()
527 && aCtx->core11 != NULL)
529 const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
530 if (Abs (aScale - 1.0) > Precision::Confusion())
532 aCtx->SetGlNormalizeEnabled (Standard_True);
538 // Take into account transform persistence
539 aCtx->ApplyModelViewMatrix();
542 const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->AspectLine();
543 const OpenGl_AspectFace* aPrevAspectFace = theWorkspace->AspectFace();
544 const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
545 const OpenGl_AspectText* aPrevAspectText = theWorkspace->AspectText();
547 // Apply correction for mirror transform
550 aCtx->core11fwd->glFrontFace (GL_CW);
553 // Collect clipping planes of structure scope
554 aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
556 // True if structure is fully clipped
557 bool isClipped = false;
558 bool hasDisabled = false;
559 if (aCtx->Clipping().IsClippingOrCappingOn())
561 const Graphic3d_BndBox3d& aBBox = BoundingBox();
562 if (!myClipPlanes.IsNull()
563 && myClipPlanes->ToOverrideGlobal())
565 aCtx->ChangeClipping().DisableGlobal (aCtx);
566 hasDisabled = aCtx->Clipping().HasDisabled();
568 else if (!myTrsfPers.IsNull())
570 if (myTrsfPers->IsZoomOrRotate())
572 // Zoom/rotate persistence object lives in two worlds at the same time.
573 // Global clipping planes can not be trivially applied without being converted
574 // into local space of transformation persistence object.
575 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
576 const gp_Pnt anAnchor = myTrsfPers->AnchorPoint();
577 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next())
579 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
585 // check for clipping
586 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
587 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
588 if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
596 aCtx->ChangeClipping().DisableGlobal (aCtx);
597 hasDisabled = aCtx->Clipping().HasDisabled();
600 // Set of clipping planes that do not intersect the structure,
601 // and thus can be disabled to improve rendering performance
603 && myTrsfPers.IsNull())
605 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
607 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
608 if (aPlaneIt.IsDisabled())
613 // check for clipping
614 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
615 const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
616 aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
617 aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
619 if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
625 // check for no intersection (e.g. object is "entirely not clipped")
626 const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
627 aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
628 aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
630 if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
632 aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
638 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
641 // Set OCCT state uniform variables
642 aCtx->ShaderManager()->UpdateClippingState();
647 bool hasClosedPrims = false;
650 renderGeometry (theWorkspace, hasClosedPrims);
653 // Reset correction for mirror transform
656 aCtx->core11fwd->glFrontFace (GL_CCW);
659 // Render capping for structure groups
661 && aCtx->Clipping().IsCappingOn())
663 OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
666 // Revert structure clippings
669 // enable planes that were previously disabled
670 aCtx->ChangeClipping().RestoreDisabled (aCtx);
672 aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
673 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
676 // Set OCCT state uniform variables
677 aCtx->ShaderManager()->RevertClippingState();
680 // Restore local transformation
681 aCtx->ModelWorldState.Pop();
682 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
683 if (!myTrsfPers.IsNull())
685 aCtx->WorldViewState.Pop();
689 theWorkspace->SetAspectLine (aPrevAspectLine);
690 theWorkspace->SetAspectFace (aPrevAspectFace);
691 theWorkspace->SetAspectMarker (aPrevAspectMarker);
692 theWorkspace->SetAspectText (aPrevAspectText);
694 // Apply highlight box
695 if (!myHighlightBox.IsNull())
697 theWorkspace->SetHighlightStyle (myHighlightStyle);
698 myHighlightBox->Render (theWorkspace);
701 // Restore named status
702 theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
705 // =======================================================================
706 // function : Release
708 // =======================================================================
709 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
713 clearHighlightBox (theGlCtx);
714 myHighlightStyle.Nullify();
717 // =======================================================================
718 // function : ReleaseGlResources
720 // =======================================================================
721 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
723 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
725 aGroupIter.ChangeValue()->Release (theGlCtx);
727 if (!myHighlightBox.IsNull())
729 myHighlightBox->Release (theGlCtx.operator->());
733 //=======================================================================
734 //function : ShadowLink
736 //=======================================================================
737 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
739 return new OpenGl_StructureShadow (theManager, this);