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),
120 myTransformation (NULL),
123 myAspectMarker (NULL),
125 myHighlightColor (NULL),
126 myInstancedStructure (NULL),
127 myIsRaytracable (Standard_False),
128 myModificationState (0),
129 myIsCulled (Standard_True),
130 myIsMirrored (Standard_False)
135 // =======================================================================
136 // function : ~OpenGl_Structure
138 // =======================================================================
139 OpenGl_Structure::~OpenGl_Structure()
141 Release (Handle(OpenGl_Context)());
142 delete myTransformation; myTransformation = NULL;
145 // =======================================================================
146 // function : UpdateAspects
148 // =======================================================================
149 void OpenGl_Structure::UpdateAspects()
151 if (ContextLine.IsDef)
152 SetAspectLine (ContextLine);
154 if (ContextFillArea.IsDef)
155 SetAspectFace (ContextFillArea);
157 if (ContextMarker.IsDef)
158 SetAspectMarker (ContextMarker);
160 if (ContextText.IsDef)
161 SetAspectText (ContextText);
164 // =======================================================================
165 // function : UpdateTransformation
167 // =======================================================================
168 void OpenGl_Structure::UpdateTransformation()
170 if (myTransformation == NULL)
172 myTransformation = new OpenGl_Matrix();
175 Standard_ShortReal (*aMat)[4] = Graphic3d_CStructure::Transformation;
177 Standard_ShortReal aDet =
178 aMat[0][0] * (aMat[1][1] * aMat[2][2] - aMat[2][1] * aMat[1][2]) -
179 aMat[0][1] * (aMat[1][0] * aMat[2][2] - aMat[2][0] * aMat[1][2]) +
180 aMat[0][2] * (aMat[1][0] * aMat[2][1] - aMat[2][0] * aMat[1][1]);
182 // Determinant of transform matrix less then 0 means that mirror transform applied.
183 myIsMirrored = aDet < 0.0f;
185 matcpy (myTransformation->mat, &Graphic3d_CStructure::Transformation[0][0]);
189 ++myModificationState;
193 // =======================================================================
194 // function : SetAspectLine
196 // =======================================================================
197 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &theAspect)
201 myAspectLine = new OpenGl_AspectLine();
203 myAspectLine->SetAspect (theAspect);
206 // =======================================================================
207 // function : SetAspectFace
209 // =======================================================================
210 void OpenGl_Structure::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect)
214 myAspectFace = new OpenGl_AspectFace();
216 myAspectFace->SetAspect (theAspect);
220 ++myModificationState;
224 // =======================================================================
225 // function : SetAspectMarker
227 // =======================================================================
228 void OpenGl_Structure::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect)
232 myAspectMarker = new OpenGl_AspectMarker();
234 myAspectMarker->SetAspect (theAspect);
237 // =======================================================================
238 // function : SetAspectText
240 // =======================================================================
241 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
245 myAspectText = new OpenGl_AspectText();
247 myAspectText->SetAspect (theAspect);
250 // =======================================================================
251 // function : clearHighlightBox
253 // =======================================================================
254 void OpenGl_Structure::clearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
256 if (!myHighlightBox.IsNull())
258 myHighlightBox->Release (theGlCtx);
259 myHighlightBox.Nullify();
263 // =======================================================================
264 // function : HighlightWithColor
266 // =======================================================================
267 void OpenGl_Structure::HighlightWithColor (const Graphic3d_Vec3& theColor,
268 const Standard_Boolean theToCreate)
270 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
272 setHighlightColor (aContext, theColor);
274 clearHighlightColor (aContext);
277 // =======================================================================
278 // function : HighlightWithBndBox
280 // =======================================================================
281 void OpenGl_Structure::HighlightWithBndBox (const Handle(Graphic3d_Structure)& theStruct,
282 const Standard_Boolean theToCreate)
284 const Handle(OpenGl_Context)& aContext = GlDriver()->GetSharedContext();
287 clearHighlightBox (aContext);
291 if (!myHighlightBox.IsNull())
293 myHighlightBox->Release (aContext);
297 myHighlightBox = new OpenGl_Group (theStruct);
300 CALL_DEF_CONTEXTLINE& aContextLine = myHighlightBox->ChangeContextLine();
301 aContextLine.IsDef = 1;
302 aContextLine.Color = HighlightColor;
303 aContextLine.LineType = Aspect_TOL_SOLID;
304 aContextLine.Width = 1.0f;
305 myHighlightBox->UpdateAspectLine (Standard_True);
307 OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (myBndBox);
308 myHighlightBox->AddElement (aBndBoxPrs);
311 // =======================================================================
312 // function : setHighlightColor
314 // =======================================================================
315 void OpenGl_Structure::setHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
316 const Graphic3d_Vec3& theColor)
318 clearHighlightBox (theGlCtx);
319 if (myHighlightColor == NULL)
321 myHighlightColor = new TEL_COLOUR();
324 myHighlightColor->rgb[0] = theColor.r();
325 myHighlightColor->rgb[1] = theColor.g();
326 myHighlightColor->rgb[2] = theColor.b();
327 myHighlightColor->rgb[3] = 1.F;
330 // =======================================================================
331 // function : clearHighlightColor
333 // =======================================================================
334 void OpenGl_Structure::clearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
336 clearHighlightBox(theGlCtx);
337 delete myHighlightColor;
338 myHighlightColor = NULL;
341 // =======================================================================
342 // function : OnVisibilityChanged
344 // =======================================================================
345 void OpenGl_Structure::OnVisibilityChanged()
349 ++myModificationState;
353 // =======================================================================
354 // function : IsRaytracable
356 // =======================================================================
357 Standard_Boolean OpenGl_Structure::IsRaytracable() const
359 if (!myGroups.IsEmpty())
361 return myIsRaytracable; // geometry structure
363 else if (myInstancedStructure != NULL)
365 return myInstancedStructure->IsRaytracable(); // instance structure
368 return Standard_False; // has no any groups or structures
371 // =======================================================================
372 // function : UpdateRaytracableState
374 // =======================================================================
375 void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
377 myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
381 ++myModificationState;
385 // =======================================================================
386 // function : Connect
388 // =======================================================================
389 void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
391 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
393 Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
394 "Error! Instanced structure is already defined");
396 myInstancedStructure = aStruct;
398 if (aStruct->IsRaytracable())
400 UpdateStateIfRaytracable (Standard_False);
404 // =======================================================================
405 // function : Disconnect
407 // =======================================================================
408 void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
410 OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
412 if (myInstancedStructure == aStruct)
414 myInstancedStructure = NULL;
416 if (aStruct->IsRaytracable())
418 UpdateStateIfRaytracable();
423 // =======================================================================
424 // function : NewGroup
426 // =======================================================================
427 Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct)
429 Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct);
430 myGroups.Append (aGroup);
434 // =======================================================================
435 // function : RemoveGroup
437 // =======================================================================
438 void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup)
440 if (theGroup.IsNull())
445 for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
447 // Check for the given group
448 if (aGroupIter.Value() == theGroup)
450 const Standard_Boolean wasRaytracable =
451 static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
453 theGroup->Clear (Standard_False);
457 UpdateStateIfRaytracable();
460 myGroups.Remove (aGroupIter);
466 // =======================================================================
469 // =======================================================================
470 void OpenGl_Structure::Clear()
472 Clear (GlDriver()->GetSharedContext());
475 // =======================================================================
478 // =======================================================================
479 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
481 Standard_Boolean aRaytracableGroupDeleted (Standard_False);
484 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
486 aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable();
489 aGroupIter.ChangeValue()->Release (theGlCtx);
493 if (aRaytracableGroupDeleted)
495 myIsRaytracable = Standard_False;
498 Is2dText = Standard_False;
499 IsForHighlight = Standard_False;
502 // =======================================================================
503 // function : RenderGeometry
505 // =======================================================================
506 void OpenGl_Structure::RenderGeometry (const Handle(OpenGl_Workspace) &theWorkspace) const
509 const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
510 for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
512 aGroupIter.Value()->Render (theWorkspace);
516 // =======================================================================
519 // =======================================================================
520 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
522 // Process the structure only if visible
528 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
530 // Render named status
531 const Standard_Integer aNamedStatus = theWorkspace->NamedStatus;
534 theWorkspace->NamedStatus |= OPENGL_NS_HIGHLIGHT;
537 // Do we need to restore GL_NORMALIZE?
538 const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
540 // Apply local transformation
541 if (myTransformation)
543 OpenGl_Matrix aModelWorld;
544 OpenGl_Transposemat3 (&aModelWorld, myTransformation);
545 aCtx->ModelWorldState.Push();
546 aCtx->ModelWorldState.SetCurrent (OpenGl_Mat4::Map ((Standard_ShortReal* )aModelWorld.mat));
548 Standard_ShortReal aScaleX = OpenGl_Vec3 (myTransformation->mat[0][0],
549 myTransformation->mat[0][1],
550 myTransformation->mat[0][2]).SquareModulus();
551 // Scale transform detected.
552 if (Abs (aScaleX - 1.f) > Precision::Confusion())
554 aCtx->SetGlNormalizeEnabled (Standard_True);
557 if (TransformPersistence.Flags)
559 OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
560 OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current();
561 TransformPersistence.Apply (aProjection, aWorldView, theWorkspace->Width(), theWorkspace->Height());
563 aCtx->ProjectionState.Push();
564 aCtx->WorldViewState.Push();
565 aCtx->ProjectionState.SetCurrent (aProjection);
566 aCtx->WorldViewState.SetCurrent (aWorldView);
567 aCtx->ApplyProjectionMatrix();
570 // Take into account transform persistence
571 aCtx->ApplyModelViewMatrix();
574 const OpenGl_AspectLine *anAspectLine = theWorkspace->AspectLine (Standard_False);
575 const OpenGl_AspectFace *anAspectFace = theWorkspace->AspectFace (Standard_False);
576 const OpenGl_AspectMarker *anAspectMarker = theWorkspace->AspectMarker (Standard_False);
577 const OpenGl_AspectText *anAspectText = theWorkspace->AspectText (Standard_False);
580 theWorkspace->SetAspectLine (myAspectLine);
584 theWorkspace->SetAspectFace (myAspectFace);
588 theWorkspace->SetAspectMarker (myAspectMarker);
592 theWorkspace->SetAspectText (myAspectText);
595 // Apply correction for mirror transform
598 aCtx->core11fwd->glFrontFace (GL_CW);
601 // Apply highlight color
602 const TEL_COLOUR *aHighlightColor = theWorkspace->HighlightColor;
603 if (myHighlightColor)
604 theWorkspace->HighlightColor = myHighlightColor;
606 // Render instanced structure (if exists)
607 if (myInstancedStructure != NULL)
609 myInstancedStructure->RenderGeometry (theWorkspace);
612 // Set up plane equations for non-structure transformed global model-view matrix
613 // List of planes to be applied to context state
614 NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
616 // Collect clipping planes of structure scope
617 if (!myClipPlanes.IsEmpty())
619 Graphic3d_SequenceOfHClipPlane::Iterator aClippingIter (myClipPlanes);
620 for (; aClippingIter.More(); aClippingIter.Next())
622 const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIter.Value();
623 if (!aClipPlane->IsOn())
628 if (aUserPlanes.IsNull())
630 aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
633 aUserPlanes->Append (aClipPlane);
637 if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
639 // add planes at loaded view matrix state
640 aCtx->ChangeClipping().AddWorld (aCtx, *aUserPlanes);
642 // Set OCCT state uniform variables
643 if (!aCtx->ShaderManager()->IsEmpty())
645 aCtx->ShaderManager()->UpdateClippingState();
650 const Graphic3d_SequenceOfGroup& aGroups = DrawGroups();
651 for (OpenGl_Structure::GroupIterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
653 aGroupIter.Value()->Render (theWorkspace);
656 // Reset correction for mirror transform
659 aCtx->core11fwd->glFrontFace (GL_CCW);
662 // Render capping for structure groups
663 if (!aCtx->Clipping().Planes().IsEmpty())
665 OpenGl_CappingAlgo::RenderCapping (theWorkspace, aGroups);
668 // Revert structure clippings
669 if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
671 aCtx->ChangeClipping().Remove (aCtx, *aUserPlanes);
673 // Set OCCT state uniform variables
674 if (!aCtx->ShaderManager()->IsEmpty())
676 aCtx->ShaderManager()->RevertClippingState();
680 // Restore local transformation
681 if (myTransformation)
683 aCtx->ModelWorldState.Pop();
684 aCtx->SetGlNormalizeEnabled (anOldGlNormalize);
686 if (TransformPersistence.Flags)
688 aCtx->ProjectionState.Pop();
689 aCtx->WorldViewState.Pop();
690 aCtx->ApplyProjectionMatrix();
693 // Restore highlight color
694 theWorkspace->HighlightColor = aHighlightColor;
697 theWorkspace->SetAspectLine (anAspectLine);
698 theWorkspace->SetAspectFace (anAspectFace);
699 theWorkspace->SetAspectMarker (anAspectMarker);
700 theWorkspace->SetAspectText (anAspectText);
702 // Apply highlight box
703 if (!myHighlightBox.IsNull())
705 myHighlightBox->Render (theWorkspace);
708 // Restore named status
709 theWorkspace->NamedStatus = aNamedStatus;
712 // =======================================================================
713 // function : Release
715 // =======================================================================
716 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
720 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
721 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
722 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
723 OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
724 clearHighlightColor (theGlCtx);
727 // =======================================================================
728 // function : ReleaseGlResources
730 // =======================================================================
731 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
733 for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
735 aGroupIter.ChangeValue()->Release (theGlCtx);
737 if (myAspectLine != NULL)
739 myAspectLine->Release (theGlCtx.operator->());
741 if (myAspectFace != NULL)
743 myAspectFace->Release (theGlCtx.operator->());
745 if (myAspectMarker != NULL)
747 myAspectMarker->Release (theGlCtx.operator->());
749 if (myAspectText != NULL)
751 myAspectText->Release (theGlCtx.operator->());
753 if (!myHighlightBox.IsNull())
755 myHighlightBox->Release (theGlCtx.operator->());
759 //=======================================================================
760 //function : ShadowLink
762 //=======================================================================
763 Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const
765 return new OpenGl_StructureShadow (theManager, this);