1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00
Files
occt/src/OpenGl/OpenGl_Group.cxx

502 lines
16 KiB
C++

// Created on: 2011-08-01
// Created by: Sergey ZERCHANINOV
// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <OpenGl_Group.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_Flipper.hxx>
#include <OpenGl_PrimitiveArray.hxx>
#include <OpenGl_SceneGeometry.hxx>
#include <OpenGl_StencilTest.hxx>
#include <OpenGl_Structure.hxx>
#include <OpenGl_Text.hxx>
#include <OpenGl_Workspace.hxx>
#include <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_GroupDefinitionError.hxx>
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group,Graphic3d_Group)
namespace
{
//! Render element if it passes the filtering procedure. This method should
//! be used for elements which can be used in scope of rendering algorithms.
//! E.g. elements of groups during recursive rendering.
//! If render filter is null, pure rendering is performed.
//! @param theWorkspace [in] the rendering workspace.
//! @param theFilter [in] the rendering filter to check whether the element
//! should be rendered or not.
//! @return True if element passes the check and renders,
static bool renderFiltered (const Handle(OpenGl_Workspace)& theWorkspace,
const Handle(OpenGl_Element)& theElement)
{
if (!theWorkspace->ShouldRender (theElement))
{
return false;
}
theElement->Render (theWorkspace);
return true;
}
}
// =======================================================================
// function : OpenGl_Group
// purpose :
// =======================================================================
OpenGl_Group::OpenGl_Group (const Handle(Graphic3d_Structure)& theStruct)
: Graphic3d_Group (theStruct),
myIsRaytracable (Standard_False)
{
Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
if (aStruct.IsNull())
{
throw Graphic3d_GroupDefinitionError("OpenGl_Group should be created by OpenGl_Structure!");
}
}
// =======================================================================
// function : ~OpenGl_Group
// purpose :
// =======================================================================
OpenGl_Group::~OpenGl_Group()
{
Release (Handle(OpenGl_Context)());
}
// =======================================================================
// function : SetGroupPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectLine3d)& theAspect)
{
if (IsDeleted())
{
return;
}
if (myAspectLine.IsNull())
{
myAspectLine = new OpenGl_AspectLine (theAspect);
}
else
{
myAspectLine->SetAspect (theAspect);
}
Update();
}
// =======================================================================
// function : SetPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectLine3d)& theAspect)
{
if (myAspectLine.IsNull())
{
SetGroupPrimitivesAspect (theAspect);
return;
}
else if (IsDeleted())
{
return;
}
Handle(OpenGl_AspectLine) anAspectLine = new OpenGl_AspectLine (theAspect);
AddElement (anAspectLine);
Update();
}
// =======================================================================
// function : SetGroupPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
{
if (IsDeleted())
{
return;
}
if (myAspectFace.IsNull())
{
myAspectFace = new OpenGl_AspectFace (theAspect);
}
else
{
myAspectFace->SetAspect (theAspect);
}
if (myIsRaytracable)
{
OpenGl_Structure* aStruct = GlStruct();
if (aStruct != NULL)
{
aStruct->UpdateStateIfRaytracable (Standard_False);
}
}
Update();
}
// =======================================================================
// function : SetPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
{
if (myAspectFace.IsNull())
{
SetGroupPrimitivesAspect (theAspect);
return;
}
else if (IsDeleted())
{
return;
}
Handle(OpenGl_AspectFace) anAspectFace = new OpenGl_AspectFace (theAspect);
AddElement (anAspectFace);
Update();
}
// =======================================================================
// function : SetGroupPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d)& theAspMarker)
{
if (IsDeleted())
{
return;
}
if (myAspectMarker.IsNull())
{
myAspectMarker = new OpenGl_AspectMarker (theAspMarker);
}
else
{
myAspectMarker->SetAspect (theAspMarker);
}
Update();
}
// =======================================================================
// function : SetPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectMarker3d)& theAspMarker)
{
if (myAspectMarker.IsNull())
{
SetGroupPrimitivesAspect (theAspMarker);
return;
}
else if (IsDeleted())
{
return;
}
Handle(OpenGl_AspectMarker) anAspectMarker = new OpenGl_AspectMarker (theAspMarker);
AddElement (anAspectMarker);
Update();
}
// =======================================================================
// function : SetGroupPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_AspectText3d)& theAspText)
{
if (IsDeleted())
{
return;
}
if (myAspectText.IsNull())
{
myAspectText = new OpenGl_AspectText (theAspText);
}
else
{
myAspectText->SetAspect (theAspText);
}
Update();
}
// =======================================================================
// function : SetPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_AspectText3d)& theAspText)
{
if (myAspectText.IsNull())
{
SetGroupPrimitivesAspect (theAspText);
return;
}
else if (IsDeleted())
{
return;
}
Handle(OpenGl_AspectText) anAspectText = new OpenGl_AspectText (theAspText);
AddElement (anAspectText);
Update();
}
// =======================================================================
// function : SynchronizeAspects
// purpose :
// =======================================================================
void OpenGl_Group::SynchronizeAspects()
{
if (!myAspectFace.IsNull())
{
myAspectFace->SynchronizeAspects();
}
if (!myAspectLine.IsNull())
{
myAspectLine->SynchronizeAspects();
}
if (!myAspectMarker.IsNull())
{
myAspectMarker->SynchronizeAspects();
}
if (!myAspectText.IsNull())
{
myAspectText->SynchronizeAspects();
}
for (OpenGl_ElementNodes::Iterator anElemIterator(myElements); anElemIterator.More(); anElemIterator.Next())
{
anElemIterator.ChangeValue()->SynchronizeAspects();
}
}
// =======================================================================
// function : AddPrimitiveArray
// purpose :
// =======================================================================
void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType,
const Handle(Graphic3d_IndexBuffer)& theIndices,
const Handle(Graphic3d_Buffer)& theAttribs,
const Handle(Graphic3d_BoundBuffer)& theBounds,
const Standard_Boolean theToEvalMinMax)
{
if (IsDeleted()
|| theAttribs.IsNull())
{
return;
}
OpenGl_Structure* aStruct = GlStruct();
const OpenGl_GraphicDriver* aDriver = aStruct->GlDriver();
Handle(OpenGl_PrimitiveArray) anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds);
AddElement (anArray);
Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax);
}
// =======================================================================
// function : Text
// purpose :
// =======================================================================
void OpenGl_Group::Text (const Standard_CString theTextUtf,
const Graphic3d_Vertex& thePoint,
const Standard_Real theHeight,
const Standard_Real theAngle,
const Graphic3d_TextPath theTp,
const Graphic3d_HorizontalTextAlignment theHta,
const Graphic3d_VerticalTextAlignment theVta,
const Standard_Boolean theToEvalMinMax)
{
if (IsDeleted())
{
return;
}
OpenGl_TextParam aParams;
OpenGl_Structure* aStruct = GlStruct();
aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
aParams.HAlign = theHta;
aParams.VAlign = theVta;
const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
Handle(OpenGl_Text) aText = new OpenGl_Text (theTextUtf, aPoint, aParams);
AddElement (aText);
Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle,
theTp, theHta, theVta, theToEvalMinMax);
}
// =======================================================================
// function : Text
// purpose :
// =======================================================================
void OpenGl_Group::Text (const Standard_CString theTextUtf,
const gp_Ax2& theOrientation,
const Standard_Real theHeight,
const Standard_Real theAngle,
const Graphic3d_TextPath theTp,
const Graphic3d_HorizontalTextAlignment theHTA,
const Graphic3d_VerticalTextAlignment theVTA,
const Standard_Boolean theToEvalMinMax,
const Standard_Boolean theHasOwnAnchor)
{
if (IsDeleted())
{
return;
}
OpenGl_TextParam aParams;
OpenGl_Structure* aStruct = GlStruct();
aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
aParams.HAlign = theHTA;
aParams.VAlign = theVTA;
Handle(OpenGl_Text) aText = new OpenGl_Text (theTextUtf, theOrientation, aParams, theHasOwnAnchor != Standard_False);
AddElement (aText);
Graphic3d_Group::Text (theTextUtf,
theOrientation,
theHeight,
theAngle,
theTp,
theHTA,
theVTA,
theToEvalMinMax,
theHasOwnAnchor);
}
// =======================================================================
// function : SetFlippingOptions
// purpose :
// =======================================================================
void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
const gp_Ax2& theRefPlane)
{
Handle(OpenGl_Flipper) aFlipper = new OpenGl_Flipper (theRefPlane);
aFlipper->SetOptions (theIsEnabled);
AddElement (aFlipper);
}
// =======================================================================
// function : SetStencilTestOptions
// purpose :
// =======================================================================
void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
{
Handle(OpenGl_StencilTest) aStencilTest = new OpenGl_StencilTest();
aStencilTest->SetOptions (theIsEnabled);
AddElement (aStencilTest);
}
// =======================================================================
// function : AddElement
// purpose :
// =======================================================================
void OpenGl_Group::AddElement (Handle(OpenGl_Element) theElem)
{
myElements.Append (theElem);
if (OpenGl_Raytrace::IsRaytracedElement (theElem))
{
myIsRaytracable = Standard_True;
OpenGl_Structure* aStruct = GlStruct();
if (aStruct != NULL)
{
aStruct->UpdateStateIfRaytracable (Standard_False);
}
}
}
// =======================================================================
// function : Render
// purpose :
// =======================================================================
void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
{
// Setup aspects
theWorkspace->SetAllowFaceCulling (myIsClosed
&& !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn());
const Handle(OpenGl_AspectLine)& aBackAspectLine = theWorkspace->AspectLine();
const Handle(OpenGl_AspectFace)& aBackAspectFace = theWorkspace->AspectFace();
const Handle(OpenGl_AspectMarker)& aBackAspectMarker = theWorkspace->AspectMarker();
const Handle(OpenGl_AspectText)& aBackAspectText = theWorkspace->AspectText();
const bool isLineSet = !myAspectLine.IsNull() && renderFiltered (theWorkspace, myAspectLine);
const bool isFaceSet = !myAspectFace.IsNull() && renderFiltered (theWorkspace, myAspectFace);
const bool isMarkerSet = !myAspectMarker.IsNull() && renderFiltered (theWorkspace, myAspectMarker);
const bool isTextSet = !myAspectText.IsNull() && renderFiltered (theWorkspace, myAspectText);
// Render group elements
for (OpenGl_ElementNodes::Iterator anElemIterator(myElements); anElemIterator.More(); anElemIterator.Next())
{
renderFiltered (theWorkspace, anElemIterator.Value());
}
// Restore aspects
if (isLineSet)
theWorkspace->SetAspectLine (aBackAspectLine);
if (isFaceSet)
theWorkspace->SetAspectFace (aBackAspectFace);
if (isMarkerSet)
theWorkspace->SetAspectMarker (aBackAspectMarker);
if (isTextSet)
theWorkspace->SetAspectText (aBackAspectText);
}
// =======================================================================
// function : Clear
// purpose :
// =======================================================================
void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
{
if (IsDeleted())
{
return;
}
OpenGl_Structure* aStruct = GlStruct();
const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
Release (aCtx);
Graphic3d_Group::Clear (theToUpdateStructureMgr);
myIsRaytracable = Standard_False;
}
// =======================================================================
// function : Release
// purpose :
// =======================================================================
void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
{
// Delete elements
for (OpenGl_ElementNodes::Iterator anElemIterator(myElements); anElemIterator.More(); anElemIterator.Next())
{
OpenGl_Element::Destroy (theGlCtx.operator->(), anElemIterator.ChangeValue());
}
myElements.Clear();
OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
}