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)
71 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
73 theWorkspace->GetGlContext()->BindProgram (Handle(OpenGl_ShaderProgram)());
74 theWorkspace->GetGlContext()->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
76 glDisable (GL_LIGHTING);
78 // Use highlight colors
79 theWorkspace->GetGlContext()->core11->glColor3fv (theWorkspace->LineColor().GetData());
81 glEnableClientState (GL_VERTEX_ARRAY);
82 glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
83 glDrawArrays (GL_LINE_STRIP, 0, 16);
84 glDisableClientState (GL_VERTEX_ARRAY);
87 if (!aPrevTexture.IsNull())
89 theWorkspace->EnableTexture (aPrevTexture);
96 //! Release graphical resources
97 virtual void Release (OpenGl_Context*)
104 //! Protected destructor
105 virtual ~OpenGl_BndBoxPrs() {}
109 OpenGl_Vec3 myVerts[16]; //!< vertices array
113 DEFINE_STANDARD_ALLOC
117 /*----------------------------------------------------------------------*/
119 // =======================================================================
120 // function : OpenGl_Structure
122 // =======================================================================
123 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
124 : Graphic3d_CStructure (theManager),
125 myInstancedStructure (NULL),
126 myIsRaytracable (Standard_False),
127 myModificationState (0),
128 myIsCulled (Standard_True),
129 myIsMirrored (Standard_False)
131 updateLayerTransformation();
134 // =======================================================================
135 // function : ~OpenGl_Structure
137 // =======================================================================
138 OpenGl_Structure::~OpenGl_Structure()
140 Release (Handle(OpenGl_Context)());
143 // =======================================================================
144 // function : SetZLayer
146 // =======================================================================
147 void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
149 Graphic3d_CStructure::SetZLayer (theLayerIndex);
150 updateLayerTransformation();
153 // =======================================================================
154 // function : SetTransformation
156 // =======================================================================
157 void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
160 myIsMirrored = Standard_False;
161 if (!myTrsf.IsNull())
163 // Determinant of transform matrix less then 0 means that mirror transform applied.
164 const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3))
165 - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3))
166 + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2));
167 myIsMirrored = aDet < 0.0;
170 updateLayerTransformation();
173 ++myModificationState;
177 // =======================================================================
178 // function : SetTransformPersistence
180 // =======================================================================
181 void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
183 myTrsfPers = theTrsfPers;
184 updateLayerTransformation();
187 // =======================================================================
188 // function : updateLayerTransformation
190 // =======================================================================
191 void OpenGl_Structure::updateLayerTransformation()
194 if (!myTrsf.IsNull())
196 aRenderTrsf = myTrsf->Trsf();
199 const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
200 if (!aLayer.OriginTransformation().IsNull()
201 && myTrsfPers.IsNull())
203 aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
205 aRenderTrsf.GetMat4 (myRenderTrsf);
208 // =======================================================================
209 // function : clearHighlightBox
211 // =======================================================================
212 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
214 if (!myHighlightBox.IsNull())
216 myHighlightBox->Release (theGlCtx);
217 myHighlightBox.Nullify();
221 // =======================================================================
222 // function : HighlightWithBndBox
224 // =======================================================================
225 void OpenGl_Structure::highlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct)
227 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
229 if (!myHighlightBox.IsNull())
231 myHighlightBox->Release (aContext);
235 myHighlightBox = new OpenGl_Group (theStruct);
238 myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myHighlightStyle->Color(), Aspect_TOL_SOLID, 1.0));
240 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
241 myHighlightBox->AddElement (aBndBoxPrs);
244 // =======================================================================
245 // function : GraphicHighlight
247 // =======================================================================
248 void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle,
249 const Handle(Graphic3d_Structure)& theStruct)
251 if (!myHighlightStyle.IsNull()
252 && myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX
253 && theStyle->Method() != Aspect_TOHM_BOUNDBOX)
255 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
256 clearHighlightBox (aContext);
259 myHighlightStyle = theStyle;
262 if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
264 highlightWithBndBox (theStruct);
268 // =======================================================================
269 // function : GraphicUnhighlight
271 // =======================================================================
272 void OpenGl_Structure::GraphicUnhighlight()
276 if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
278 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
279 clearHighlightBox (aContext);
282 myHighlightStyle.Nullify();
285 // =======================================================================
286 // function : OnVisibilityChanged
288 // =======================================================================
289 void OpenGl_Structure::OnVisibilityChanged()
293 ++myModificationState;
297 // =======================================================================
298 // function : IsRaytracable
300 // =======================================================================
301 Standard_Boolean OpenGl_Structure::IsRaytracable() const
303 if (!myGroups.IsEmpty()
306 return Standard_True;
309 return myInstancedStructure != NULL
310 && myInstancedStructure->IsRaytracable();
313 // =======================================================================
314 // function : UpdateRaytracableState
316 // =======================================================================
317 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
319 myIsRaytracable = !toCheck;
320 if (!myIsRaytracable)
322 for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
324 if (anIter.Value()->IsRaytracable())
326 myIsRaytracable = Standard_True;
334 ++myModificationState;
338 // =======================================================================
339 // function : Connect
341 // =======================================================================
342 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
344 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
346 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
347 "Error! Instanced structure is already defined");
349 myInstancedStructure = aStruct;
351 if (aStruct->IsRaytracable())
353 UpdateStateIfRaytracable (Standard_False);
357 // =======================================================================
358 // function : Disconnect
360 // =======================================================================
361 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
363 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
365 if (myInstancedStructure == aStruct)
367 myInstancedStructure = NULL;
369 if (aStruct->IsRaytracable())
371 UpdateStateIfRaytracable();
376 // =======================================================================
377 // function : NewGroup
379 // =======================================================================
380 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
382 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
383 myGroups.Append (aGroup);
387 // =======================================================================
388 // function : RemoveGroup
390 // =======================================================================
391 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
393 if (theGroup.IsNull())
398 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
400 // Check for the given group
401 if (aGroupIter.Value() == theGroup)
403 const Standard_Boolean wasRaytracable =
404 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
406 theGroup->Clear (Standard_False);
410 UpdateStateIfRaytracable();
413 myGroups.Remove (aGroupIter);
419 // =======================================================================
422 // =======================================================================
423 void OpenGl_Structure::Clear()
425 Clear (GlDriver()->GetSharedContext());
428 // =======================================================================
431 // =======================================================================
432 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
434 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
437 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
439 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
442 aGroupIter.ChangeValue()->Release (theGlCtx);
446 if (aRaytracableGroupDeleted)
448 myIsRaytracable = Standard_False;
451 Is2dText = Standard_False;
452 IsForHighlight = Standard_False;
455 // =======================================================================
456 // function : renderGeometry
458 // =======================================================================
459 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
460 bool& theHasClosed) const
462 if (myInstancedStructure != NULL)
464 myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
467 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
469 theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
470 aGroupIter.Value()->Render (theWorkspace);
474 // =======================================================================
477 // =======================================================================
478 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
480 // Process the structure only if visible
486 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
488 // Render named status
489 if (highlight && myHighlightBox.IsNull())
491 theWorkspace->SetHighlightStyle (myHighlightStyle);
494 // Apply local transformation
495 aCtx->ModelWorldState.Push();
496 OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
497 aModelWorld = myRenderTrsf;
499 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
500 #if !defined(GL_ES_VERSION_2_0)
501 // detect scale transform
502 if (aCtx->core11 != NULL
505 const Standard_Real aScale = myTrsf->ScaleFactor();
506 if (Abs (aScale - 1.0) > Precision::Confusion())
508 aCtx->SetGlNormalizeEnabled (Standard_True);
513 if (!myTrsfPers.IsNull())
515 aCtx->WorldViewState.Push();
516 OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
517 myTrsfPers->Apply (theWorkspace->View()->Camera(),
518 aCtx->ProjectionState.Current(), aWorldView,
519 aCtx->Viewport()[2], aCtx->Viewport()[3]);
521 #if !defined(GL_ES_VERSION_2_0)
522 if (!aCtx->IsGlNormalizeEnabled()
523 && aCtx->core11 != NULL)
525 const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
526 if (Abs (aScale - 1.0) > Precision::Confusion())
528 aCtx->SetGlNormalizeEnabled (Standard_True);
534 // Take into account transform persistence
535 aCtx->ApplyModelViewMatrix();
538 const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->AspectLine();
539 const OpenGl_AspectFace* aPrevAspectFace = theWorkspace->AspectFace();
540 const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
541 const OpenGl_AspectText* aPrevAspectText = theWorkspace->AspectText();
543 // Apply correction for mirror transform
546 aCtx->core11fwd->glFrontFace (GL_CW);
549 // Collect clipping planes of structure scope
550 aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
552 // True if structure is fully clipped
553 bool isClipped = false;
554 bool hasDisabled = false;
555 if (aCtx->Clipping().IsClippingOrCappingOn())
557 const Graphic3d_BndBox3d& aBBox = BoundingBox();
558 if (!myClipPlanes.IsNull()
559 && myClipPlanes->ToOverrideGlobal())
561 aCtx->ChangeClipping().DisableGlobal (aCtx);
562 hasDisabled = aCtx->Clipping().HasDisabled();
564 else if (!myTrsfPers.IsNull())
566 if (myTrsfPers->IsZoomOrRotate())
568 // Zoom/rotate persistence object lives in two worlds at the same time.
569 // Global clipping planes can not be trivially applied without being converted
570 // into local space of transformation persistence object.
571 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
572 const gp_Pnt anAnchor = myTrsfPers->AnchorPoint();
573 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next())
575 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
581 // check for clipping
582 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
583 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
584 if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
592 aCtx->ChangeClipping().DisableGlobal (aCtx);
593 hasDisabled = aCtx->Clipping().HasDisabled();
596 // Set of clipping planes that do not intersect the structure,
597 // and thus can be disabled to improve rendering performance
599 && myTrsfPers.IsNull())
601 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
603 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
609 // check for clipping
610 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
611 const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
612 aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
613 aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
615 if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
621 // check for no intersection (e.g. object is "entirely not clipped")
622 const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
623 aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
624 aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
626 if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
628 aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
634 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
637 // Set OCCT state uniform variables
638 aCtx->ShaderManager()->UpdateClippingState();
643 bool hasClosedPrims = false;
646 renderGeometry (theWorkspace, hasClosedPrims);
649 // Reset correction for mirror transform
652 aCtx->core11fwd->glFrontFace (GL_CCW);
655 // Render capping for structure groups
657 && aCtx->Clipping().IsCappingOn())
659 OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
662 // Revert structure clippings
665 // enable planes that were previously disabled
666 aCtx->ChangeClipping().RestoreDisabled (aCtx);
668 aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
669 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
672 // Set OCCT state uniform variables
673 aCtx->ShaderManager()->RevertClippingState();
676 // Restore local transformation
677 aCtx->ModelWorldState.Pop();
678 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
679 if (!myTrsfPers.IsNull())
681 aCtx->WorldViewState.Pop();
685 theWorkspace->SetAspectLine (aPrevAspectLine);
686 theWorkspace->SetAspectFace (aPrevAspectFace);
687 theWorkspace->SetAspectMarker (aPrevAspectMarker);
688 theWorkspace->SetAspectText (aPrevAspectText);
690 // Apply highlight box
691 if (!myHighlightBox.IsNull())
693 theWorkspace->SetHighlightStyle (myHighlightStyle);
694 myHighlightBox->Render (theWorkspace);
697 // Restore named status
698 theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)());
701 // =======================================================================
702 // function : Release
704 // =======================================================================
705 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
709 clearHighlightBox (theGlCtx);
710 myHighlightStyle.Nullify();
713 // =======================================================================
714 // function : ReleaseGlResources
716 // =======================================================================
717 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
719 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
721 aGroupIter.ChangeValue()->Release (theGlCtx);
723 if (!myHighlightBox.IsNull())
725 myHighlightBox->Release (theGlCtx.operator->());
729 //=======================================================================
730 //function : ShadowLink
732 //=======================================================================
733 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
735 return new OpenGl_StructureShadow (theManager, this);