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>
30 IMPLEMENT_STANDARD_HANDLE (OpenGl_Structure, Graphic3d_CStructure)
31 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure, Graphic3d_CStructure)
33 //! Auxiliary class for bounding box presentation
34 class OpenGl_BndBoxPrs : public OpenGl_Element
40 OpenGl_BndBoxPrs (const Graphic3d_BndBox4f& theBndBox)
42 const float Xm = theBndBox.CornerMin().x();
43 const float Ym = theBndBox.CornerMin().y();
44 const float Zm = theBndBox.CornerMin().z();
45 const float XM = theBndBox.CornerMax().x();
46 const float YM = theBndBox.CornerMax().y();
47 const float ZM = theBndBox.CornerMax().z();
49 myVerts[0] = OpenGl_Vec3 (Xm, Ym, Zm);
50 myVerts[1] = OpenGl_Vec3 (Xm, Ym, ZM);
51 myVerts[2] = OpenGl_Vec3 (Xm, YM, ZM);
52 myVerts[3] = OpenGl_Vec3 (Xm, YM, Zm);
53 myVerts[4] = OpenGl_Vec3 (Xm, Ym, Zm);
54 myVerts[5] = OpenGl_Vec3 (XM, Ym, Zm);
55 myVerts[6] = OpenGl_Vec3 (XM, Ym, ZM);
56 myVerts[7] = OpenGl_Vec3 (XM, YM, ZM);
57 myVerts[8] = OpenGl_Vec3 (XM, YM, Zm);
58 myVerts[9] = OpenGl_Vec3 (XM, Ym, Zm);
59 myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
60 myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
61 myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
62 myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
63 myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
64 myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
67 //! Render presentation
68 virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
70 #if !defined(GL_ES_VERSION_2_0)
72 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
73 const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
75 glDisable (GL_LIGHTING);
77 // Use highlight colors
78 theWorkspace->GetGlContext()->core11->glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
80 glEnableClientState (GL_VERTEX_ARRAY);
81 glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
82 glDrawArrays (GL_LINE_STRIP, 0, 16);
83 glDisableClientState (GL_VERTEX_ARRAY);
86 if (!aPrevTexture.IsNull())
88 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 myTransformation (NULL),
126 myAspectMarker (NULL),
128 myHighlightColor (NULL),
129 myInstancedStructure (NULL),
130 myIsRaytracable (Standard_False),
131 myModificationState (0),
132 myIsCulled (Standard_True),
133 myIsMirrored (Standard_False)
138 // =======================================================================
139 // function : ~OpenGl_Structure
141 // =======================================================================
142 OpenGl_Structure::~OpenGl_Structure()
144 Release (Handle(OpenGl_Context)());
145 delete myTransformation; myTransformation = NULL;
146 delete myTransPers; myTransPers = NULL;
149 // =======================================================================
150 // function : UpdateAspects
152 // =======================================================================
153 void OpenGl_Structure::UpdateAspects()
155 SetTransformPersistence (TransformPersistence);
157 if (ContextLine.IsDef)
158 SetAspectLine (ContextLine);
160 if (ContextFillArea.IsDef)
161 SetAspectFace (ContextFillArea);
163 if (ContextMarker.IsDef)
164 SetAspectMarker (ContextMarker);
166 if (ContextText.IsDef)
167 SetAspectText (ContextText);
170 // =======================================================================
171 // function : UpdateTransformation
173 // =======================================================================
174 void OpenGl_Structure::UpdateTransformation()
176 if (myTransformation == NULL)
178 myTransformation = new OpenGl_Matrix();
181 Standard_ShortReal (*aMat)[4] = Graphic3d_CStructure::Transformation;
183 Standard_ShortReal aDet =
184 aMat[0][0] * (aMat[1][1] * aMat[2][2] - aMat[2][1] * aMat[1][2]) -
185 aMat[0][1] * (aMat[1][0] * aMat[2][2] - aMat[2][0] * aMat[1][2]) +
186 aMat[0][2] * (aMat[1][0] * aMat[2][1] - aMat[2][0] * aMat[1][1]);
188 // Determinant of transform matrix less then 0 means that mirror transform applied.
189 myIsMirrored = aDet < 0.0f;
191 matcpy (myTransformation->mat, &Graphic3d_CStructure::Transformation[0][0]);
195 ++myModificationState;
199 // =======================================================================
200 // function : SetTransformPersistence
202 // =======================================================================
203 void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
206 myTransPers = new TEL_TRANSFORM_PERSISTENCE;
208 myTransPers->mode = ATransPers.Flag;
209 myTransPers->pointX = ATransPers.Point.x;
210 myTransPers->pointY = ATransPers.Point.y;
211 myTransPers->pointZ = ATransPers.Point.z;
215 // =======================================================================
216 // function : SetAspectLine
218 // =======================================================================
219 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect)
223 myAspectLine = new OpenGl_AspectLine();
225 myAspectLine->SetAspect (theAspect);
228 // =======================================================================
229 // function : SetAspectFace
231 // =======================================================================
232 void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
236 myAspectFace = new OpenGl_AspectFace();
238 myAspectFace->SetAspect (theAspect);
242 ++myModificationState;
246 // =======================================================================
247 // function : SetAspectMarker
249 // =======================================================================
250 void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect)
254 myAspectMarker = new OpenGl_AspectMarker();
256 myAspectMarker->SetAspect (theAspect);
259 // =======================================================================
260 // function : SetAspectText
262 // =======================================================================
263 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
267 myAspectText = new OpenGl_AspectText();
269 myAspectText->SetAspect (theAspect);
272 // =======================================================================
273 // function : clearHighlightBox
275 // =======================================================================
276 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
278 if (!myHighlightBox.IsNull())
280 myHighlightBox->Release (theGlCtx);
281 myHighlightBox.Nullify();
285 // =======================================================================
286 // function : HighlightWithColor
288 // =======================================================================
289 void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3& theColor,
290 const Standard_Boolean theToCreate)
292 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
294 setHighlightColor (aContext, theColor);
296 clearHighlightColor (aContext);
299 // =======================================================================
300 // function : HighlightWithBndBox
302 // =======================================================================
303 void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
304 const Standard_Boolean theToCreate)
306 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
309 clearHighlightBox (aContext);
313 if (!myHighlightBox.IsNull())
315 myHighlightBox->Release (aContext);
319 myHighlightBox = new OpenGl_Group (theStruct);
322 CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
323 aContextLine.IsDef = 1;
324 aContextLine.Color = HighlightColor;
325 aContextLine.LineType = Aspect_TOL_SOLID;
326 aContextLine.Width = 1.0f;
327 myHighlightBox->UpdateAspectLine (Standard_True);
329 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
330 myHighlightBox->AddElement (aBndBoxPrs);
333 // =======================================================================
334 // function : setHighlightColor
336 // =======================================================================
337 void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
338 const Graphic3d_Vec3& theColor)
340 clearHighlightBox (theGlCtx);
341 if (myHighlightColor == NULL)
343 myHighlightColor = new TEL_COLOUR();
346 myHighlightColor->rgb[0] = theColor.r();
347 myHighlightColor->rgb[1] = theColor.g();
348 myHighlightColor->rgb[2] = theColor.b();
349 myHighlightColor->rgb[3] = 1.F;
352 // =======================================================================
353 // function : clearHighlightColor
355 // =======================================================================
356 void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
358 clearHighlightBox(theGlCtx);
359 delete myHighlightColor;
360 myHighlightColor = NULL;
363 // =======================================================================
364 // function : OnVisibilityChanged
366 // =======================================================================
367 void OpenGl_Structure::OnVisibilityChanged()
371 ++myModificationState;
375 // =======================================================================
376 // function : IsRaytracable
378 // =======================================================================
379 Standard_Boolean OpenGl_Structure::IsRaytracable() const
381 if (!myGroups.IsEmpty())
383 return myIsRaytracable; // geometry structure
385 else if (myInstancedStructure != NULL)
387 return myInstancedStructure->IsRaytracable(); // instance structure
390 return Standard_False; // has no any groups or structures
393 // =======================================================================
394 // function : UpdateRaytracableState
396 // =======================================================================
397 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
399 myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
403 ++myModificationState;
407 // =======================================================================
408 // function : Connect
410 // =======================================================================
411 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
413 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
415 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
416 "Error! Instanced structure is already defined");
418 myInstancedStructure = aStruct;
420 if (aStruct->IsRaytracable())
422 UpdateStateIfRaytracable (Standard_False);
426 // =======================================================================
427 // function : Disconnect
429 // =======================================================================
430 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
432 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
434 if (myInstancedStructure == aStruct)
436 myInstancedStructure = NULL;
438 if (aStruct->IsRaytracable())
440 UpdateStateIfRaytracable();
445 // =======================================================================
446 // function : NewGroup
448 // =======================================================================
449 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
451 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
452 myGroups.Append (aGroup);
456 // =======================================================================
457 // function : RemoveGroup
459 // =======================================================================
460 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
462 if (theGroup.IsNull())
467 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
469 // Check for the given group
470 if (aGroupIter.Value() == theGroup)
472 const Standard_Boolean wasRaytracable =
473 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
475 theGroup->Clear (Standard_False);
479 UpdateStateIfRaytracable();
482 myGroups.Remove (aGroupIter);
488 // =======================================================================
491 // =======================================================================
492 void OpenGl_Structure::Clear()
494 Clear (GlDriver()->GetSharedContext());
497 // =======================================================================
500 // =======================================================================
501 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
503 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
506 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
508 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
511 aGroupIter.ChangeValue()->Release (theGlCtx);
515 if (aRaytracableGroupDeleted)
517 myIsRaytracable = Standard_False;
520 Is2dText = Standard_False;
521 IsForHighlight = Standard_False;
524 // =======================================================================
525 // function : RenderGeometry
527 // =======================================================================
528 void OpenGl_Structure::RenderGeometry (const Handle(OpenGl_Workspace) &theWorkspace) const
531 const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
532 for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
534 aGroupIter.Value()->Render (theWorkspace);
538 // =======================================================================
541 // =======================================================================
542 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
544 // Process the structure only if visible
550 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
552 // Render named status
553 const Standard_Integer aNamedStatus = theWorkspace->NamedStatus;
556 theWorkspace->NamedStatus |= OPENGL_NS_HIGHLIGHT;
559 // Do we need to restore GL_NORMALIZE?
560 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
562 // Apply local transformation
563 if (myTransformation)
565 OpenGl_Matrix aModelWorld;
566 OpenGl_Transposemat3 (&aModelWorld, myTransformation);
567 aCtx->ModelWorldState.Push();
568 aCtx->ModelWorldState.SetCurrent (OpenGl_Mat4::Map ((Standard_ShortReal* )aModelWorld.mat));
570 Standard_ShortReal aScaleX = OpenGl_Vec3 (myTransformation->mat[0][0],
571 myTransformation->mat[0][1],
572 myTransformation->mat[0][2]).SquareModulus();
573 // Scale transform detected.
574 if (Abs (aScaleX - 1.f) > Precision::Confusion())
576 aCtx->SetGlNormalizeEnabled (Standard_True);
580 // Apply transform persistence
581 const TEL_TRANSFORM_PERSISTENCE *aTransPersistence = NULL;
582 if ( myTransPers && myTransPers->mode != 0 )
584 aTransPersistence = theWorkspace->ActiveView()->BeginTransformPersistence (aCtx, myTransPers, theWorkspace->Width(), theWorkspace->Height());
587 // Take into account transform persistence
588 aCtx->ApplyModelViewMatrix();
591 const OpenGl_AspectLine *anAspectLine = theWorkspace->AspectLine (Standard_False);
592 const OpenGl_AspectFace *anAspectFace = theWorkspace->AspectFace (Standard_False);
593 const OpenGl_AspectMarker *anAspectMarker = theWorkspace->AspectMarker (Standard_False);
594 const OpenGl_AspectText *anAspectText = theWorkspace->AspectText (Standard_False);
597 theWorkspace->SetAspectLine (myAspectLine);
601 theWorkspace->SetAspectFace (myAspectFace);
605 theWorkspace->SetAspectMarker (myAspectMarker);
609 theWorkspace->SetAspectText (myAspectText);
612 // Apply correction for mirror transform
615 aCtx->core11fwd->glFrontFace (GL_CW);
618 // Apply highlight color
619 const TEL_COLOUR *aHighlightColor = theWorkspace->HighlightColor;
620 if (myHighlightColor)
621 theWorkspace->HighlightColor = myHighlightColor;
623 // Render instanced structure (if exists)
624 if (myInstancedStructure != NULL)
626 myInstancedStructure->RenderGeometry (theWorkspace);
629 // Set up plane equations for non-structure transformed global model-view matrix
630 // List of planes to be applied to context state
631 NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
633 // Collect clipping planes of structure scope
634 if (!myClipPlanes.IsEmpty())
636 Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
637 for (; aClippingIter.More(); aClippingIter.Next())
639 const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
640 if (!aClipPlane->IsOn())
645 if (aUserPlanes.IsNull())
647 aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
650 aUserPlanes->Append (aClipPlane);
654 if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
656 // add planes at loaded view matrix state
657 aCtx->ChangeClipping().AddWorld (*aUserPlanes, theWorkspace);
659 // Set OCCT state uniform variables
660 if (!aCtx->ShaderManager()->IsEmpty())
662 aCtx->ShaderManager()->UpdateClippingState();
667 const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
668 for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
670 aGroupIter.Value()->Render (theWorkspace);
673 // Reset correction for mirror transform
676 aCtx->core11fwd->glFrontFace (GL_CCW);
679 // Render capping for structure groups
680 if (!aCtx->Clipping().Planes().IsEmpty())
682 OpenGl_CappingAlgo::RenderCapping (theWorkspace, aGroups);
685 // Revert structure clippings
686 if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
688 aCtx->ChangeClipping().Remove (*aUserPlanes);
690 // Set OCCT state uniform variables
691 if (!aCtx->ShaderManager()->IsEmpty())
693 aCtx->ShaderManager()->RevertClippingState();
697 // Apply local transformation
698 if (myTransformation)
700 aCtx->ModelWorldState.Pop();
701 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
704 // Restore highlight color
705 theWorkspace->HighlightColor = aHighlightColor;
708 theWorkspace->SetAspectLine (anAspectLine);
709 theWorkspace->SetAspectFace (anAspectFace);
710 theWorkspace->SetAspectMarker (anAspectMarker);
711 theWorkspace->SetAspectText (anAspectText);
713 // Restore transform persistence
714 if ( myTransPers && myTransPers->mode != 0 )
716 theWorkspace->ActiveView()->BeginTransformPersistence (aCtx, aTransPersistence, theWorkspace->Width(), theWorkspace->Height());
719 // Apply highlight box
720 if (!myHighlightBox.IsNull())
722 myHighlightBox->Render (theWorkspace);
725 // Restore named status
726 theWorkspace->NamedStatus = aNamedStatus;
729 // =======================================================================
730 // function : Release
732 // =======================================================================
733 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
737 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
738 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
739 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
740 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
741 clearHighlightColor (theGlCtx);
744 // =======================================================================
745 // function : ReleaseGlResources
747 // =======================================================================
748 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
750 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
752 aGroupIter.ChangeValue()->Release (theGlCtx);
754 if (myAspectLine != NULL)
756 myAspectLine->Release (theGlCtx.operator->());
758 if (myAspectFace != NULL)
760 myAspectFace->Release (theGlCtx.operator->());
762 if (myAspectMarker != NULL)
764 myAspectMarker->Release (theGlCtx.operator->());
766 if (myAspectText != NULL)
768 myAspectText->Release (theGlCtx.operator->());
770 if (!myHighlightBox.IsNull())
772 myHighlightBox->Release (theGlCtx.operator->());
776 //=======================================================================
777 //function : ShadowLink
779 //=======================================================================
780 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
782 return new OpenGl_StructureShadow (theManager, this);