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_telem_util.hxx>
24 #include <OpenGl_Vec.hxx>
25 #include <OpenGl_View.hxx>
26 #include <OpenGl_Workspace.hxx>
28 #include <Graphic3d_SequenceOfHClipPlane.hxx>
31 //! Auxiliary class for bounding box presentation
32 class OpenGl_BndBoxPrs : public OpenGl_Element
38 OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox)
40 const float Xm = theBndBox.CornerMin().x();
41 const float Ym = theBndBox.CornerMin().y();
42 const float Zm = theBndBox.CornerMin().z();
43 const float XM = theBndBox.CornerMax().x();
44 const float YM = theBndBox.CornerMax().y();
45 const float ZM = theBndBox.CornerMax().z();
47 myVerts[0] = OpenGl_Vec3 (Xm, Ym, Zm);
48 myVerts[1] = OpenGl_Vec3 (Xm, Ym, ZM);
49 myVerts[2] = OpenGl_Vec3 (Xm, YM, ZM);
50 myVerts[3] = OpenGl_Vec3 (Xm, YM, Zm);
51 myVerts[4] = OpenGl_Vec3 (Xm, Ym, Zm);
52 myVerts[5] = OpenGl_Vec3 (XM, Ym, Zm);
53 myVerts[6] = OpenGl_Vec3 (XM, Ym, ZM);
54 myVerts[7] = OpenGl_Vec3 (XM, YM, ZM);
55 myVerts[8] = OpenGl_Vec3 (XM, YM, Zm);
56 myVerts[9] = OpenGl_Vec3 (XM, Ym, Zm);
57 myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
58 myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
59 myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
60 myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
61 myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
62 myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
65 //! Render presentation
66 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
68 #if !defined(GL_ES_VERSION_2_0)
70 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
71 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
73 glDisable (GL_LIGHTING);
75 // Use highlight colors
76 theWorkspace->GetGlContext()->core11->glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
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);
91 //! Release graphical resources
92 virtual void Release (OpenGl_Context*)
99 //! Protected destructor
100 virtual ~OpenGl_BndBoxPrs() {}
104 OpenGl_Vec3 myVerts[16]; //!< vertices array
108 DEFINE_STANDARD_ALLOC
112 /*----------------------------------------------------------------------*/
114 // =======================================================================
115 // function : OpenGl_Structure
117 // =======================================================================
118 OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
119 : Graphic3d_CStructure (theManager),
122 myAspectMarker (NULL),
124 myHighlightColor (NULL),
125 myInstancedStructure (NULL),
126 myIsRaytracable (Standard_False),
127 myModificationState (0),
128 myIsCulled (Standard_True),
129 myIsMirrored (Standard_False)
134 // =======================================================================
135 // function : ~OpenGl_Structure
137 // =======================================================================
138 OpenGl_Structure::~OpenGl_Structure()
140 Release (Handle(OpenGl_Context)());
143 // =======================================================================
144 // function : UpdateAspects
146 // =======================================================================
147 void OpenGl_Structure::UpdateAspects()
149 if (ContextLine.IsDef)
150 SetAspectLine (ContextLine);
152 if (ContextFillArea.IsDef)
153 SetAspectFace (ContextFillArea);
155 if (ContextMarker.IsDef)
156 SetAspectMarker (ContextMarker);
158 if (ContextText.IsDef)
159 SetAspectText (ContextText);
162 // =======================================================================
163 // function : UpdateTransformation
165 // =======================================================================
166 void OpenGl_Structure::UpdateTransformation()
168 const OpenGl_Mat4& aMat = Graphic3d_CStructure::Transformation;
169 Standard_ShortReal aDet =
170 aMat.GetValue(0, 0) * (aMat.GetValue(1, 1) * aMat.GetValue(2, 2) - aMat.GetValue(2, 1) * aMat.GetValue(1, 2)) -
171 aMat.GetValue(0, 1) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 2) - aMat.GetValue(2, 0) * aMat.GetValue(1, 2)) +
172 aMat.GetValue(0, 2) * (aMat.GetValue(1, 0) * aMat.GetValue(2, 1) - aMat.GetValue(2, 0) * aMat.GetValue(1, 1));
174 // Determinant of transform matrix less then 0 means that mirror transform applied.
175 myIsMirrored = aDet < 0.0f;
179 ++myModificationState;
183 // =======================================================================
184 // function : SetAspectLine
186 // =======================================================================
187 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect)
191 myAspectLine = new OpenGl_AspectLine();
193 myAspectLine->SetAspect (theAspect);
196 // =======================================================================
197 // function : SetAspectFace
199 // =======================================================================
200 void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
204 myAspectFace = new OpenGl_AspectFace();
206 myAspectFace->SetAspect (theAspect);
210 ++myModificationState;
214 // =======================================================================
215 // function : SetAspectMarker
217 // =======================================================================
218 void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect)
222 myAspectMarker = new OpenGl_AspectMarker();
224 myAspectMarker->SetAspect (theAspect);
227 // =======================================================================
228 // function : SetAspectText
230 // =======================================================================
231 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
235 myAspectText = new OpenGl_AspectText();
237 myAspectText->SetAspect (theAspect);
240 // =======================================================================
241 // function : clearHighlightBox
243 // =======================================================================
244 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
246 if (!myHighlightBox.IsNull())
248 myHighlightBox->Release (theGlCtx);
249 myHighlightBox.Nullify();
253 // =======================================================================
254 // function : HighlightWithColor
256 // =======================================================================
257 void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3& theColor,
258 const Standard_Boolean theToCreate)
260 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
262 setHighlightColor (aContext, theColor);
264 clearHighlightColor (aContext);
267 // =======================================================================
268 // function : HighlightWithBndBox
270 // =======================================================================
271 void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
272 const Standard_Boolean theToCreate)
274 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
277 clearHighlightBox (aContext);
281 if (!myHighlightBox.IsNull())
283 myHighlightBox->Release (aContext);
287 myHighlightBox = new OpenGl_Group (theStruct);
290 CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
291 aContextLine.IsDef = 1;
292 aContextLine.Color = HighlightColor;
293 aContextLine.LineType = Aspect_TOL_SOLID;
294 aContextLine.Width = 1.0f;
295 myHighlightBox->UpdateAspectLine (Standard_True);
297 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
298 myHighlightBox->AddElement (aBndBoxPrs);
301 // =======================================================================
302 // function : setHighlightColor
304 // =======================================================================
305 void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
306 const Graphic3d_Vec3& theColor)
308 clearHighlightBox (theGlCtx);
309 if (myHighlightColor == NULL)
311 myHighlightColor = new TEL_COLOUR();
314 myHighlightColor->rgb[0] = theColor.r();
315 myHighlightColor->rgb[1] = theColor.g();
316 myHighlightColor->rgb[2] = theColor.b();
317 myHighlightColor->rgb[3] = 1.F;
320 // =======================================================================
321 // function : clearHighlightColor
323 // =======================================================================
324 void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
326 clearHighlightBox(theGlCtx);
327 delete myHighlightColor;
328 myHighlightColor = NULL;
331 // =======================================================================
332 // function : OnVisibilityChanged
334 // =======================================================================
335 void OpenGl_Structure::OnVisibilityChanged()
339 ++myModificationState;
343 // =======================================================================
344 // function : IsRaytracable
346 // =======================================================================
347 Standard_Boolean OpenGl_Structure::IsRaytracable() const
349 if (!myGroups.IsEmpty())
351 return myIsRaytracable; // geometry structure
353 else if (myInstancedStructure != NULL)
355 return myInstancedStructure->IsRaytracable(); // instance structure
358 return Standard_False; // has no any groups or structures
361 // =======================================================================
362 // function : UpdateRaytracableState
364 // =======================================================================
365 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
367 myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
371 ++myModificationState;
375 // =======================================================================
376 // function : Connect
378 // =======================================================================
379 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
381 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
383 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
384 "Error! Instanced structure is already defined");
386 myInstancedStructure = aStruct;
388 if (aStruct->IsRaytracable())
390 UpdateStateIfRaytracable (Standard_False);
394 // =======================================================================
395 // function : Disconnect
397 // =======================================================================
398 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
400 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
402 if (myInstancedStructure == aStruct)
404 myInstancedStructure = NULL;
406 if (aStruct->IsRaytracable())
408 UpdateStateIfRaytracable();
413 // =======================================================================
414 // function : NewGroup
416 // =======================================================================
417 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
419 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
420 myGroups.Append (aGroup);
424 // =======================================================================
425 // function : RemoveGroup
427 // =======================================================================
428 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
430 if (theGroup.IsNull())
435 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
437 // Check for the given group
438 if (aGroupIter.Value() == theGroup)
440 const Standard_Boolean wasRaytracable =
441 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
443 theGroup->Clear (Standard_False);
447 UpdateStateIfRaytracable();
450 myGroups.Remove (aGroupIter);
456 // =======================================================================
459 // =======================================================================
460 void OpenGl_Structure::Clear()
462 Clear (GlDriver()->GetSharedContext());
465 // =======================================================================
468 // =======================================================================
469 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
471 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
474 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
476 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
479 aGroupIter.ChangeValue()->Release (theGlCtx);
483 if (aRaytracableGroupDeleted)
485 myIsRaytracable = Standard_False;
488 Is2dText = Standard_False;
489 IsForHighlight = Standard_False;
492 // =======================================================================
493 // function : renderGeometry
495 // =======================================================================
496 void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace,
497 bool& theHasClosed) const
499 if (myInstancedStructure != NULL)
501 myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
504 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
506 theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
507 aGroupIter.Value()->Render (theWorkspace);
511 // =======================================================================
512 // function : renderClosedGeometry
514 // =======================================================================
515 void OpenGl_Structure::renderClosedGeometry (const Handle(OpenGl_Workspace)& theWorkspace) const
517 if (myInstancedStructure != NULL)
519 myInstancedStructure->renderClosedGeometry (theWorkspace);
522 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
524 if (aGroupIter.Value()->IsClosed())
526 aGroupIter.Value()->Render (theWorkspace);
531 // =======================================================================
534 // =======================================================================
535 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
537 // Process the structure only if visible
543 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
545 // Render named status
546 const Standard_Integer aNamedStatus = theWorkspace->NamedStatus;
549 theWorkspace->NamedStatus |= OPENGL_NS_HIGHLIGHT;
552 // Apply local transformation
553 aCtx->ModelWorldState.Push();
554 aCtx->ModelWorldState.SetCurrent (Transformation);
556 // detect scale transform
557 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
558 const Standard_ShortReal aScaleX = Transformation.GetRow (0).xyz().SquareModulus();
559 if (Abs (aScaleX - 1.f) > Precision::Confusion())
561 aCtx->SetGlNormalizeEnabled (Standard_True);
564 if (TransformPersistence.Flags)
566 OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
567 OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current();
568 TransformPersistence.Apply (aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height());
570 aCtx->ProjectionState.Push();
571 aCtx->WorldViewState.Push();
572 aCtx->ProjectionState.SetCurrent (aProjection);
573 aCtx->WorldViewState.SetCurrent (aWorldView);
574 aCtx->ApplyProjectionMatrix();
577 // Take into account transform persistence
578 aCtx->ApplyModelViewMatrix();
581 const OpenGl_AspectLine *anAspectLine = theWorkspace->AspectLine (Standard_False);
582 const OpenGl_AspectFace *anAspectFace = theWorkspace->AspectFace (Standard_False);
583 const OpenGl_AspectMarker *anAspectMarker = theWorkspace->AspectMarker (Standard_False);
584 const OpenGl_AspectText *anAspectText = theWorkspace->AspectText (Standard_False);
587 theWorkspace->SetAspectLine (myAspectLine);
591 theWorkspace->SetAspectFace (myAspectFace);
595 theWorkspace->SetAspectMarker (myAspectMarker);
599 theWorkspace->SetAspectText (myAspectText);
602 // Apply correction for mirror transform
605 aCtx->core11fwd->glFrontFace (GL_CW);
608 // Apply highlight color
609 const TEL_COLOUR *aHighlightColor = theWorkspace->HighlightColor;
610 if (myHighlightColor)
611 theWorkspace->HighlightColor = myHighlightColor;
613 // Set up plane equations for non-structure transformed global model-view matrix
614 // List of planes to be applied to context state
615 NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
617 // Collect clipping planes of structure scope
618 if (!myClipPlanes.IsEmpty())
620 Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
621 for (; aClippingIter.More(); aClippingIter.Next())
623 const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
624 if (!aClipPlane->IsOn())
629 if (aUserPlanes.IsNull())
631 aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
634 aUserPlanes->Append (aClipPlane);
638 if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
640 // add planes at loaded view matrix state
641 aCtx->ChangeClipping().AddWorld (aCtx, *aUserPlanes);
643 // Set OCCT state uniform variables
644 if (!aCtx->ShaderManager()->IsEmpty())
646 aCtx->ShaderManager()->UpdateClippingState();
651 bool hasClosedPrims = false;
652 renderGeometry (theWorkspace, hasClosedPrims);
654 // Reset correction for mirror transform
657 aCtx->core11fwd->glFrontFace (GL_CCW);
660 // Render capping for structure groups
662 && !aCtx->Clipping().Planes().IsEmpty())
664 OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this);
667 // Revert structure clippings
668 if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
670 aCtx->ChangeClipping().Remove (aCtx, *aUserPlanes);
672 // Set OCCT state uniform variables
673 if (!aCtx->ShaderManager()->IsEmpty())
675 aCtx->ShaderManager()->RevertClippingState();
679 // Restore local transformation
680 aCtx->ModelWorldState.Pop();
681 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
682 if (TransformPersistence.Flags)
684 aCtx->ProjectionState.Pop();
685 aCtx->WorldViewState.Pop();
686 aCtx->ApplyProjectionMatrix();
689 // Restore highlight color
690 theWorkspace->HighlightColor = aHighlightColor;
693 theWorkspace->SetAspectLine (anAspectLine);
694 theWorkspace->SetAspectFace (anAspectFace);
695 theWorkspace->SetAspectMarker (anAspectMarker);
696 theWorkspace->SetAspectText (anAspectText);
698 // Apply highlight box
699 if (!myHighlightBox.IsNull())
701 myHighlightBox->Render (theWorkspace);
704 // Restore named status
705 theWorkspace->NamedStatus = aNamedStatus;
708 // =======================================================================
709 // function : Release
711 // =======================================================================
712 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
716 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
717 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
718 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
719 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
720 clearHighlightColor (theGlCtx);
723 // =======================================================================
724 // function : ReleaseGlResources
726 // =======================================================================
727 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
729 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
731 aGroupIter.ChangeValue()->Release (theGlCtx);
733 if (myAspectLine != NULL)
735 myAspectLine->Release (theGlCtx.operator->());
737 if (myAspectFace != NULL)
739 myAspectFace->Release (theGlCtx.operator->());
741 if (myAspectMarker != NULL)
743 myAspectMarker->Release (theGlCtx.operator->());
745 if (myAspectText != NULL)
747 myAspectText->Release (theGlCtx.operator->());
749 if (!myHighlightBox.IsNull())
751 myHighlightBox->Release (theGlCtx.operator->());
755 //=======================================================================
756 //function : ShadowLink
758 //=======================================================================
759 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
761 return new OpenGl_StructureShadow (theManager, this);