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 glDisable (GL_LIGHTING);
75 // Use highlight colors
76 theWorkspace->GetGlContext()->core11->glColor3fv (theWorkspace->LineColor().GetData());
78 glEnableClientState (GL_VERTEX_ARRAY);
79 glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
80 glDrawArrays (GL_LINE_STRIP, 0, 16);
81 glDisableClientState (GL_VERTEX_ARRAY);
84 if (!aPrevTexture.IsNull())
86 theWorkspace->EnableTexture (aPrevTexture);
93 //! Release graphical resources
94 virtual void Release (OpenGl_Context*)
101 //! Protected destructor
102 virtual ~OpenGl_BndBoxPrs() {}
106 OpenGl_Vec3 myVerts[16]; //!< vertices array
110 DEFINE_STANDARD_ALLOC
114 /*----------------------------------------------------------------------*/
116 // =======================================================================
117 // function : OpenGl_Structure
119 // =======================================================================
120 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
121 : Graphic3d_CStructure (theManager),
122 myInstancedStructure (NULL),
123 myIsRaytracable (Standard_False),
124 myModificationState (0),
125 myIsCulled (Standard_True),
126 myIsMirrored (Standard_False)
128 updateLayerTransformation();
131 // =======================================================================
132 // function : ~OpenGl_Structure
134 // =======================================================================
135 OpenGl_Structure::~OpenGl_Structure()
137 Release (Handle(OpenGl_Context)());
140 // =======================================================================
141 // function : SetZLayer
143 // =======================================================================
144 void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex)
146 Graphic3d_CStructure::SetZLayer (theLayerIndex);
147 updateLayerTransformation();
150 // =======================================================================
151 // function : SetTransformation
153 // =======================================================================
154 void OpenGl_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf)
157 myIsMirrored = Standard_False;
158 if (!myTrsf.IsNull())
160 // Determinant of transform matrix less then 0 means that mirror transform applied.
161 const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3))
162 - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3))
163 + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2));
164 myIsMirrored = aDet < 0.0;
167 updateLayerTransformation();
170 ++myModificationState;
174 // =======================================================================
175 // function : SetTransformPersistence
177 // =======================================================================
178 void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers)
180 myTrsfPers = theTrsfPers;
181 updateLayerTransformation();
184 // =======================================================================
185 // function : updateLayerTransformation
187 // =======================================================================
188 void OpenGl_Structure::updateLayerTransformation()
191 if (!myTrsf.IsNull())
193 aRenderTrsf = myTrsf->Trsf();
196 const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer);
197 if (!aLayer.OriginTransformation().IsNull()
198 && myTrsfPers.IsNull())
200 aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin());
202 aRenderTrsf.GetMat4 (myRenderTrsf);
205 // =======================================================================
206 // function : clearHighlightBox
208 // =======================================================================
209 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
211 if (!myHighlightBox.IsNull())
213 myHighlightBox->Release (theGlCtx);
214 myHighlightBox.Nullify();
218 // =======================================================================
219 // function : HighlightWithBndBox
221 // =======================================================================
222 void OpenGl_Structure::highlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct)
224 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
226 if (!myHighlightBox.IsNull())
228 myHighlightBox->Release (aContext);
232 myHighlightBox = new OpenGl_Group (theStruct);
235 myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (myHighlightStyle->Color(), Aspect_TOL_SOLID, 1.0));
237 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
238 myHighlightBox->AddElement (aBndBoxPrs);
241 // =======================================================================
242 // function : GraphicHighlight
244 // =======================================================================
245 void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_HighlightStyle)& theStyle,
246 const Handle(Graphic3d_Structure)& theStruct)
248 myHighlightStyle = theStyle;
251 if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
253 highlightWithBndBox (theStruct);
257 // =======================================================================
258 // function : GraphicUnhighlight
260 // =======================================================================
261 void OpenGl_Structure::GraphicUnhighlight()
265 if (myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX)
267 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
268 clearHighlightBox (aContext);
271 myHighlightStyle.Nullify();
274 // =======================================================================
275 // function : OnVisibilityChanged
277 // =======================================================================
278 void OpenGl_Structure::OnVisibilityChanged()
282 ++myModificationState;
286 // =======================================================================
287 // function : IsRaytracable
289 // =======================================================================
290 Standard_Boolean OpenGl_Structure::IsRaytracable() const
292 if (!myGroups.IsEmpty()
295 return Standard_True;
298 return myInstancedStructure != NULL
299 && myInstancedStructure->IsRaytracable();
302 // =======================================================================
303 // function : UpdateRaytracableState
305 // =======================================================================
306 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
308 myIsRaytracable = !toCheck;
309 if (!myIsRaytracable)
311 for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
313 if (anIter.Value()->IsRaytracable())
315 myIsRaytracable = Standard_True;
323 ++myModificationState;
327 // =======================================================================
328 // function : Connect
330 // =======================================================================
331 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
333 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
335 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
336 "Error! Instanced structure is already defined");
338 myInstancedStructure = aStruct;
340 if (aStruct->IsRaytracable())
342 UpdateStateIfRaytracable (Standard_False);
346 // =======================================================================
347 // function : Disconnect
349 // =======================================================================
350 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
352 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
354 if (myInstancedStructure == aStruct)
356 myInstancedStructure = NULL;
358 if (aStruct->IsRaytracable())
360 UpdateStateIfRaytracable();
365 // =======================================================================
366 // function : NewGroup
368 // =======================================================================
369 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
371 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
372 myGroups.Append (aGroup);
376 // =======================================================================
377 // function : RemoveGroup
379 // =======================================================================
380 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
382 if (theGroup.IsNull())
387 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
389 // Check for the given group
390 if (aGroupIter.Value() == theGroup)
392 const Standard_Boolean wasRaytracable =
393 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
395 theGroup->Clear (Standard_False);
399 UpdateStateIfRaytracable();
402 myGroups.Remove (aGroupIter);
408 // =======================================================================
411 // =======================================================================
412 void OpenGl_Structure::Clear()
414 Clear (GlDriver()->GetSharedContext());
417 // =======================================================================
420 // =======================================================================
421 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
423 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
426 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
428 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
431 aGroupIter.ChangeValue()->Release (theGlCtx);
435 if (aRaytracableGroupDeleted)
437 myIsRaytracable = Standard_False;
440 Is2dText = Standard_False;
441 IsForHighlight = Standard_False;
444 // =======================================================================
445 // function : renderGeometry
447 // =======================================================================
448 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
449 bool& theHasClosed) const
451 if (myInstancedStructure != NULL)
453 myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
456 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
458 theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
459 aGroupIter.Value()->Render (theWorkspace);
463 // =======================================================================
466 // =======================================================================
467 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
469 // Process the structure only if visible
475 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
477 // Render named status
478 if (highlight && myHighlightBox.IsNull())
480 theWorkspace->SetHighlight (true);
483 // Apply local transformation
484 aCtx->ModelWorldState.Push();
485 OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent();
486 aModelWorld = myRenderTrsf;
488 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
489 #if !defined(GL_ES_VERSION_2_0)
490 // detect scale transform
491 if (aCtx->core11 != NULL
494 const Standard_Real aScale = myTrsf->ScaleFactor();
495 if (Abs (aScale - 1.0) > Precision::Confusion())
497 aCtx->SetGlNormalizeEnabled (Standard_True);
502 if (!myTrsfPers.IsNull())
504 aCtx->WorldViewState.Push();
505 OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
506 myTrsfPers->Apply (theWorkspace->View()->Camera(),
507 aCtx->ProjectionState.Current(), aWorldView,
508 aCtx->Viewport()[2], aCtx->Viewport()[3]);
510 #if !defined(GL_ES_VERSION_2_0)
511 if (!aCtx->IsGlNormalizeEnabled()
512 && aCtx->core11 != NULL)
514 const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
515 if (Abs (aScale - 1.0) > Precision::Confusion())
517 aCtx->SetGlNormalizeEnabled (Standard_True);
523 // Take into account transform persistence
524 aCtx->ApplyModelViewMatrix();
527 const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->AspectLine();
528 const OpenGl_AspectFace* aPrevAspectFace = theWorkspace->AspectFace();
529 const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
530 const OpenGl_AspectText* aPrevAspectText = theWorkspace->AspectText();
532 // Apply correction for mirror transform
535 aCtx->core11fwd->glFrontFace (GL_CW);
538 // Apply highlight color
539 const OpenGl_Vec4* aHighlightColor = theWorkspace->HighlightColor;
540 if (!myHighlightStyle.IsNull())
541 theWorkspace->HighlightColor = myHighlightStyle->ColorFltPtr();
543 // Collect clipping planes of structure scope
544 aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
546 // True if structure is fully clipped
547 bool isClipped = false;
548 bool hasDisabled = false;
549 if (aCtx->Clipping().IsClippingOrCappingOn())
551 const Graphic3d_BndBox3d& aBBox = BoundingBox();
552 if (!myClipPlanes.IsNull()
553 && myClipPlanes->ToOverrideGlobal())
555 aCtx->ChangeClipping().DisableGlobal (aCtx);
556 hasDisabled = aCtx->Clipping().HasDisabled();
558 else if (!myTrsfPers.IsNull())
560 if (myTrsfPers->IsZoomOrRotate())
562 // Zoom/rotate persistence object lives in two worlds at the same time.
563 // Global clipping planes can not be trivially applied without being converted
564 // into local space of transformation persistence object.
565 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
566 const gp_Pnt anAnchor = myTrsfPers->AnchorPoint();
567 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next())
569 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
575 // check for clipping
576 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
577 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
578 if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
586 aCtx->ChangeClipping().DisableGlobal (aCtx);
587 hasDisabled = aCtx->Clipping().HasDisabled();
590 // Set of clipping planes that do not intersect the structure,
591 // and thus can be disabled to improve rendering performance
593 && myTrsfPers.IsNull())
595 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
597 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
603 // check for clipping
604 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
605 const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
606 aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
607 aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
609 if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
615 // check for no intersection (e.g. object is "entirely not clipped")
616 const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
617 aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
618 aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
620 if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
622 aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
628 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
631 // Set OCCT state uniform variables
632 aCtx->ShaderManager()->UpdateClippingState();
637 bool hasClosedPrims = false;
640 renderGeometry (theWorkspace, hasClosedPrims);
643 // Reset correction for mirror transform
646 aCtx->core11fwd->glFrontFace (GL_CCW);
649 // Render capping for structure groups
651 && aCtx->Clipping().IsCappingOn())
653 OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
656 // Revert structure clippings
659 // enable planes that were previously disabled
660 aCtx->ChangeClipping().RestoreDisabled (aCtx);
662 aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
663 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
666 // Set OCCT state uniform variables
667 aCtx->ShaderManager()->RevertClippingState();
670 // Restore local transformation
671 aCtx->ModelWorldState.Pop();
672 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
673 if (!myTrsfPers.IsNull())
675 aCtx->WorldViewState.Pop();
678 // Restore highlight color
679 theWorkspace->HighlightColor = aHighlightColor;
682 theWorkspace->SetAspectLine (aPrevAspectLine);
683 theWorkspace->SetAspectFace (aPrevAspectFace);
684 theWorkspace->SetAspectMarker (aPrevAspectMarker);
685 theWorkspace->SetAspectText (aPrevAspectText);
687 // Apply highlight box
688 if (!myHighlightBox.IsNull())
690 myHighlightBox->Render (theWorkspace);
693 // Restore named status
694 theWorkspace->SetHighlight (false);
697 // =======================================================================
698 // function : Release
700 // =======================================================================
701 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
705 clearHighlightBox (theGlCtx);
706 myHighlightStyle.Nullify();
709 // =======================================================================
710 // function : ReleaseGlResources
712 // =======================================================================
713 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
715 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
717 aGroupIter.ChangeValue()->Release (theGlCtx);
719 if (!myHighlightBox.IsNull())
721 myHighlightBox->Release (theGlCtx.operator->());
725 //=======================================================================
726 //function : ShadowLink
728 //=======================================================================
729 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
731 return new OpenGl_StructureShadow (theManager, this);