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_BndBox4f& theBndBox)
41 const float Xm = theBndBox.CornerMin().x();
42 const float Ym = theBndBox.CornerMin().y();
43 const float Zm = theBndBox.CornerMin().z();
44 const float XM = theBndBox.CornerMax().x();
45 const float YM = theBndBox.CornerMax().y();
46 const float ZM = 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 myHighlightColor (NULL),
123 myInstancedStructure (NULL),
124 myIsRaytracable (Standard_False),
125 myModificationState (0),
126 myIsCulled (Standard_True),
127 myIsMirrored (Standard_False)
132 // =======================================================================
133 // function : ~OpenGl_Structure
135 // =======================================================================
136 OpenGl_Structure::~OpenGl_Structure()
138 Release (Handle(OpenGl_Context)());
141 // =======================================================================
142 // function : UpdateTransformation
144 // =======================================================================
145 void OpenGl_Structure::UpdateTransformation()
147 const OpenGl_Mat4& aMat = Graphic3d_CStructure::Transformation;
148 Standard_ShortReal aDet =
149 aMat.GetValue(0, 0) * (aMat.GetValue(1, 1) * aMat.GetValue(2, 2) - aMat.GetValue(2, 1) * aMat.GetValue(1, 2)) -
150 aMat.GetValue(0, 1) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 2) - aMat.GetValue(2, 0) * aMat.GetValue(1, 2)) +
151 aMat.GetValue(0, 2) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 1) - aMat.GetValue(2, 0) * aMat.GetValue(1, 1));
153 // Determinant of transform matrix less then 0 means that mirror transform applied.
154 myIsMirrored = aDet < 0.0f;
158 ++myModificationState;
162 // =======================================================================
163 // function : clearHighlightBox
165 // =======================================================================
166 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
168 if (!myHighlightBox.IsNull())
170 myHighlightBox->Release (theGlCtx);
171 myHighlightBox.Nullify();
175 // =======================================================================
176 // function : HighlightWithColor
178 // =======================================================================
179 void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3& theColor,
180 const Standard_Boolean theToCreate)
182 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
184 setHighlightColor (aContext, theColor);
186 clearHighlightColor (aContext);
189 // =======================================================================
190 // function : HighlightWithBndBox
192 // =======================================================================
193 void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
194 const Standard_Boolean theToCreate)
196 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
199 clearHighlightBox (aContext);
203 if (!myHighlightBox.IsNull())
205 myHighlightBox->Release (aContext);
209 myHighlightBox = new OpenGl_Group (theStruct);
212 myHighlightBox->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (HighlightColor, Aspect_TOL_SOLID, 1.0));
214 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
215 myHighlightBox->AddElement (aBndBoxPrs);
218 // =======================================================================
219 // function : setHighlightColor
221 // =======================================================================
222 void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
223 const Graphic3d_Vec3& theColor)
225 clearHighlightBox (theGlCtx);
226 if (myHighlightColor == NULL)
228 myHighlightColor = new OpenGl_Vec4 (theColor, 1.0f);
232 myHighlightColor->xyz() = theColor;
236 // =======================================================================
237 // function : clearHighlightColor
239 // =======================================================================
240 void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
242 clearHighlightBox(theGlCtx);
243 delete myHighlightColor;
244 myHighlightColor = NULL;
247 // =======================================================================
248 // function : OnVisibilityChanged
250 // =======================================================================
251 void OpenGl_Structure::OnVisibilityChanged()
255 ++myModificationState;
259 // =======================================================================
260 // function : IsRaytracable
262 // =======================================================================
263 Standard_Boolean OpenGl_Structure::IsRaytracable() const
265 if (!myGroups.IsEmpty()
268 return Standard_True;
271 return myInstancedStructure != NULL
272 && myInstancedStructure->IsRaytracable();
275 // =======================================================================
276 // function : UpdateRaytracableState
278 // =======================================================================
279 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
281 myIsRaytracable = !toCheck;
282 if (!myIsRaytracable)
284 for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next())
286 if (anIter.Value()->IsRaytracable())
288 myIsRaytracable = Standard_True;
296 ++myModificationState;
300 // =======================================================================
301 // function : Connect
303 // =======================================================================
304 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
306 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
308 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
309 "Error! Instanced structure is already defined");
311 myInstancedStructure = aStruct;
313 if (aStruct->IsRaytracable())
315 UpdateStateIfRaytracable (Standard_False);
319 // =======================================================================
320 // function : Disconnect
322 // =======================================================================
323 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
325 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
327 if (myInstancedStructure == aStruct)
329 myInstancedStructure = NULL;
331 if (aStruct->IsRaytracable())
333 UpdateStateIfRaytracable();
338 // =======================================================================
339 // function : NewGroup
341 // =======================================================================
342 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
344 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
345 myGroups.Append (aGroup);
349 // =======================================================================
350 // function : RemoveGroup
352 // =======================================================================
353 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
355 if (theGroup.IsNull())
360 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
362 // Check for the given group
363 if (aGroupIter.Value() == theGroup)
365 const Standard_Boolean wasRaytracable =
366 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
368 theGroup->Clear (Standard_False);
372 UpdateStateIfRaytracable();
375 myGroups.Remove (aGroupIter);
381 // =======================================================================
384 // =======================================================================
385 void OpenGl_Structure::Clear()
387 Clear (GlDriver()->GetSharedContext());
390 // =======================================================================
393 // =======================================================================
394 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
396 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
399 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
401 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
404 aGroupIter.ChangeValue()->Release (theGlCtx);
408 if (aRaytracableGroupDeleted)
410 myIsRaytracable = Standard_False;
413 Is2dText = Standard_False;
414 IsForHighlight = Standard_False;
417 // =======================================================================
418 // function : renderGeometry
420 // =======================================================================
421 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
422 bool& theHasClosed) const
424 if (myInstancedStructure != NULL)
426 myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
429 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
431 theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
432 aGroupIter.Value()->Render (theWorkspace);
436 // =======================================================================
439 // =======================================================================
440 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
442 // Process the structure only if visible
448 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
450 // Render named status
453 theWorkspace->SetHighlight (true);
456 // Apply local transformation
457 aCtx->ModelWorldState.Push();
458 aCtx->ModelWorldState.SetCurrent (Transformation);
460 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
462 #if !defined(GL_ES_VERSION_2_0)
463 // detect scale transform
464 if (aCtx->core11 != NULL)
466 const Standard_ShortReal aScaleX = Transformation.GetRow (0).xyz().SquareModulus();
467 if (Abs (aScaleX - 1.f) > Precision::Confusion())
469 aCtx->SetGlNormalizeEnabled (Standard_True);
474 if (!myTrsfPers.IsNull())
476 OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current();
477 myTrsfPers->Apply (theWorkspace->View()->Camera(), aCtx->ProjectionState.Current(), aWorldView,
478 aCtx->Viewport()[2], aCtx->Viewport()[3]);
480 aCtx->WorldViewState.Push();
481 aCtx->WorldViewState.SetCurrent (aWorldView);
483 #if !defined(GL_ES_VERSION_2_0)
484 if (!aCtx->IsGlNormalizeEnabled()
485 && aCtx->core11 != NULL)
487 const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
488 if (Abs (aScale - 1.0f) > Precision::Confusion())
490 aCtx->SetGlNormalizeEnabled (Standard_True);
496 // Take into account transform persistence
497 aCtx->ApplyModelViewMatrix();
500 const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->AspectLine();
501 const OpenGl_AspectFace* aPrevAspectFace = theWorkspace->AspectFace();
502 const OpenGl_AspectMarker* aPrevAspectMarker = theWorkspace->AspectMarker();
503 const OpenGl_AspectText* aPrevAspectText = theWorkspace->AspectText();
505 // Apply correction for mirror transform
508 aCtx->core11fwd->glFrontFace (GL_CW);
511 // Apply highlight color
512 const OpenGl_Vec4* aHighlightColor = theWorkspace->HighlightColor;
513 if (myHighlightColor)
514 theWorkspace->HighlightColor = myHighlightColor;
516 // Collect clipping planes of structure scope
517 aCtx->ChangeClipping().SetLocalPlanes (aCtx, myClipPlanes);
519 // True if structure is fully clipped
520 bool isClipped = false;
521 bool hasDisabled = false;
522 if (aCtx->Clipping().IsClippingOrCappingOn())
524 const Graphic3d_BndBox4f& aBBox = BoundingBox();
525 if ((!myTrsfPers.IsNull() && myTrsfPers->IsTrihedronOr2d())
526 || (!myClipPlanes.IsNull() && myClipPlanes->ToOverrideGlobal()))
528 aCtx->ChangeClipping().DisableGlobal (aCtx);
529 hasDisabled = aCtx->Clipping().HasDisabled();
532 // Set of clipping planes that do not intersect the structure,
533 // and thus can be disabled to improve rendering performance
535 && myTrsfPers.IsNull())
537 for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next())
539 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
545 // check for clipping
546 const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
547 const Graphic3d_Vec4d aMaxPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMax().x() : aBBox.CornerMin().x(),
548 aPlaneEquation.y() > 0.0 ? aBBox.CornerMax().y() : aBBox.CornerMin().y(),
549 aPlaneEquation.z() > 0.0 ? aBBox.CornerMax().z() : aBBox.CornerMin().z(),
551 if (aPlaneEquation.Dot (aMaxPnt) < 0.0) // max vertex is outside the half-space
557 // check for no intersection (e.g. object is "entirely not clipped")
558 const Graphic3d_Vec4d aMinPnt (aPlaneEquation.x() > 0.0 ? aBBox.CornerMin().x() : aBBox.CornerMax().x(),
559 aPlaneEquation.y() > 0.0 ? aBBox.CornerMin().y() : aBBox.CornerMax().y(),
560 aPlaneEquation.z() > 0.0 ? aBBox.CornerMin().z() : aBBox.CornerMax().z(),
562 if (aPlaneEquation.Dot (aMinPnt) > 0.0) // min vertex is inside the half-space
564 aCtx->ChangeClipping().SetEnabled (aCtx, aPlaneIt, Standard_False);
570 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
573 // Set OCCT state uniform variables
574 aCtx->ShaderManager()->UpdateClippingState();
579 bool hasClosedPrims = false;
582 renderGeometry (theWorkspace, hasClosedPrims);
585 // Reset correction for mirror transform
588 aCtx->core11fwd->glFrontFace (GL_CCW);
591 // Render capping for structure groups
593 && aCtx->Clipping().IsCappingOn())
595 OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
598 // Revert structure clippings
601 // enable planes that were previously disabled
602 aCtx->ChangeClipping().RestoreDisabled (aCtx);
604 aCtx->ChangeClipping().SetLocalPlanes (aCtx, Handle(Graphic3d_SequenceOfHClipPlane)());
605 if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty())
608 // Set OCCT state uniform variables
609 aCtx->ShaderManager()->RevertClippingState();
612 // Restore local transformation
613 aCtx->ModelWorldState.Pop();
614 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
615 if (!myTrsfPers.IsNull())
617 aCtx->WorldViewState.Pop();
620 // Restore highlight color
621 theWorkspace->HighlightColor = aHighlightColor;
624 theWorkspace->SetAspectLine (aPrevAspectLine);
625 theWorkspace->SetAspectFace (aPrevAspectFace);
626 theWorkspace->SetAspectMarker (aPrevAspectMarker);
627 theWorkspace->SetAspectText (aPrevAspectText);
629 // Apply highlight box
630 if (!myHighlightBox.IsNull())
632 myHighlightBox->Render (theWorkspace);
635 // Restore named status
636 theWorkspace->SetHighlight (false);
639 // =======================================================================
640 // function : Release
642 // =======================================================================
643 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
647 clearHighlightColor (theGlCtx);
650 // =======================================================================
651 // function : ReleaseGlResources
653 // =======================================================================
654 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
656 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
658 aGroupIter.ChangeValue()->Release (theGlCtx);
660 if (!myHighlightBox.IsNull())
662 myHighlightBox->Release (theGlCtx.operator->());
666 //=======================================================================
667 //function : ShadowLink
669 //=======================================================================
670 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
672 return new OpenGl_StructureShadow (theManager, this);