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

355 lines
11 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 <Font_TextFormatter.hxx>
#include <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_AspectFillCapping.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,
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),
myAspects(NULL),
myFirst(NULL),
myLast(NULL),
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_Aspects)& theAspect)
{
if (IsDeleted())
{
return;
}
if (!theAspect.IsNull() && theAspect->IsKind (STANDARD_TYPE(Graphic3d_AspectFillCapping)))
{
Handle(Graphic3d_AspectFillCapping) aFillCappingAspect = Handle(Graphic3d_AspectFillCapping)::DownCast (theAspect);
if (myAspectFillCapping == NULL)
{
myAspectFillCapping = new OpenGl_CappingPlaneResource (aFillCappingAspect);
}
else
{
myAspectFillCapping->SetAspect (aFillCappingAspect);
}
return;
}
if (myAspects == NULL)
{
myAspects = new OpenGl_Aspects (theAspect);
}
else
{
myAspects->SetAspect (theAspect);
}
if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
{
aStruct->UpdateStateIfRaytracable (Standard_False);
}
Update();
}
// =======================================================================
// function : SetPrimitivesAspect
// purpose :
// =======================================================================
void OpenGl_Group::SetPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect)
{
if (myAspects == NULL)
{
SetGroupPrimitivesAspect (theAspect);
return;
}
else if (IsDeleted())
{
return;
}
OpenGl_Aspects* anAspects = new OpenGl_Aspects (theAspect);
AddElement (anAspects);
Update();
}
// =======================================================================
// function : SynchronizeAspects
// purpose :
// =======================================================================
void OpenGl_Group::SynchronizeAspects()
{
if (myAspects != NULL)
{
myAspects->SynchronizeAspects();
if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
{
aStruct->UpdateStateIfRaytracable (Standard_False);
}
}
for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next)
{
aNode->elem->SynchronizeAspects();
}
}
// =======================================================================
// function : ReplaceAspects
// purpose :
// =======================================================================
void OpenGl_Group::ReplaceAspects (const Graphic3d_MapOfAspectsToAspects& theMap)
{
if (theMap.IsEmpty())
{
return;
}
Handle(Graphic3d_Aspects) anAspect;
if (myAspects != NULL
&& theMap.Find (myAspects->Aspect(), anAspect))
{
myAspects->SetAspect (anAspect);
if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL)
{
aStruct->UpdateStateIfRaytracable (Standard_False);
}
}
for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next)
{
OpenGl_Aspects* aGlAspect = dynamic_cast<OpenGl_Aspects*> (aNode->elem);
if (aGlAspect != NULL
&& theMap.Find (aGlAspect->Aspect(), anAspect))
{
aGlAspect->SetAspect (anAspect);
}
}
}
// =======================================================================
// 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();
OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds);
AddElement (anArray);
Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax);
}
// =======================================================================
// function : AddText
// purpose :
// =======================================================================
void OpenGl_Group::AddText (const Handle(Graphic3d_Text)& theTextParams,
const Standard_Boolean theToEvalMinMax)
{
if (IsDeleted())
{
return;
}
OpenGl_Structure* aStruct = GlStruct();
if (theTextParams->Height() < 2.0)
theTextParams->SetHeight (int (aStruct->GlDriver()->DefaultTextHeight()));
OpenGl_Text* aText = new OpenGl_Text (theTextParams);
AddElement (aText);
Graphic3d_Group::AddText (theTextParams, theToEvalMinMax);
}
// =======================================================================
// function : SetFlippingOptions
// purpose :
// =======================================================================
void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
const gp_Ax2& theRefPlane)
{
OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
aFlipper->SetOptions (theIsEnabled);
AddElement (aFlipper);
}
// =======================================================================
// function : SetStencilTestOptions
// purpose :
// =======================================================================
void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
{
OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
aStencilTest->SetOptions (theIsEnabled);
AddElement (aStencilTest);
}
// =======================================================================
// function : AddElement
// purpose :
// =======================================================================
void OpenGl_Group::AddElement (OpenGl_Element* theElem)
{
OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
aNode->elem = theElem;
aNode->next = NULL;
(myLast? myLast->next : myFirst) = aNode;
myLast = aNode;
if (OpenGl_Raytrace::IsRaytracedElement (aNode))
{
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 OpenGl_Aspects* aBackAspects = theWorkspace->Aspects();
const bool isAspectSet = myAspects != NULL && renderFiltered (theWorkspace, myAspects);
// Render group elements
for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
{
renderFiltered (theWorkspace, aNodeIter->elem);
}
// Restore aspects
if (isAspectSet)
theWorkspace->SetAspects (aBackAspects);
}
// =======================================================================
// 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
while (myFirst != NULL)
{
OpenGl_ElementNode* aNext = myFirst->next;
OpenGl_Element::Destroy (theGlCtx.get(), myFirst->elem);
delete myFirst;
myFirst = aNext;
}
myLast = NULL;
OpenGl_Element::Destroy (theGlCtx.get(), myAspects);
}