Fix performance issue with SelectMgr_SelectableObjectSet.
Graphic3d_ShaderVariable.lxx
Graphic3d_MapOfStructure.hxx
Graphic3d_MapIteratorOfMapOfStructure.hxx
+Graphic3d_IndexedMapOfAddress.hxx
Graphic3d_TypeOfShaderObject.hxx
Graphic3d_DataStructure.pxx
Graphic3d_StructureManager.pxx
imported transient class NMapOfTransient;
imported MapOfStructure;
+ imported IndexedMapOfAddress;
imported SequenceOfDisplayedStructures;
---------------------------------
--- /dev/null
+// Created on: 2015-04-2015
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2015 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.
+
+#ifndef _Graphic3d_IndexedMapOfAddress
+#define _Graphic3d_IndexedMapOfAddress
+
+#include <NCollection_DataMap.hxx>
+
+typedef NCollection_DataMap<const Standard_Address, Standard_Integer> Graphic3d_IndexedMapOfAddress;
+
+#endif // _Graphic3d_IndexedMapOfAddress
uses
- Array2OfReal from TColStd,
- SequenceOfAddress from TColStd,
-
- Color from Quantity,
-
- GenId from Aspect,
- TypeOfHighlightMethod from Aspect,
-
- DataStructureManager from Graphic3d,
- AspectFillArea3d from Graphic3d,
- AspectLine3d from Graphic3d,
- AspectMarker3d from Graphic3d,
- AspectText3d from Graphic3d,
- CStructure from Graphic3d,
- CStructure from Graphic3d,
- GraphicDriver from Graphic3d,
- Group from Graphic3d,
- SequenceOfGroup from Graphic3d,
- SequenceOfStructure from Graphic3d,
- HSequenceOfStructure from Graphic3d,
- MapOfStructure from Graphic3d,
- StructureManager from Graphic3d,
- StructureManagerPtr from Graphic3d,
- TypeOfComposition from Graphic3d,
- TypeOfConnection from Graphic3d,
- TypeOfPrimitive from Graphic3d,
- TypeOfStructure from Graphic3d,
- Vector from Graphic3d,
- Vertex from Graphic3d,
- TransModeFlags from Graphic3d,
- ZLayerId from Graphic3d,
- Pnt from gp,
- SequenceOfHClipPlane from Graphic3d,
- BndBox4f from Graphic3d,
- BndBox4d from Graphic3d,
- Box from Bnd
+ Array2OfReal from TColStd,
+ SequenceOfAddress from TColStd,
+
+ Color from Quantity,
+
+ GenId from Aspect,
+ TypeOfHighlightMethod from Aspect,
+
+ DataStructureManager from Graphic3d,
+ AspectFillArea3d from Graphic3d,
+ AspectLine3d from Graphic3d,
+ AspectMarker3d from Graphic3d,
+ AspectText3d from Graphic3d,
+ CStructure from Graphic3d,
+ GraphicDriver from Graphic3d,
+ Group from Graphic3d,
+ SequenceOfGroup from Graphic3d,
+ SequenceOfStructure from Graphic3d,
+ HSequenceOfStructure from Graphic3d,
+ MapOfStructure from Graphic3d,
+ IndexedMapOfAddress from Graphic3d,
+ StructureManager from Graphic3d,
+ StructureManagerPtr from Graphic3d,
+ TypeOfComposition from Graphic3d,
+ TypeOfConnection from Graphic3d,
+ TypeOfPrimitive from Graphic3d,
+ TypeOfStructure from Graphic3d,
+ Vector from Graphic3d,
+ Vertex from Graphic3d,
+ TransModeFlags from Graphic3d,
+ ZLayerId from Graphic3d,
+ Pnt from gp,
+ SequenceOfHClipPlane from Graphic3d,
+ BndBox4f from Graphic3d,
+ BndBox4d from Graphic3d,
+ Box from Bnd
raises
---C++: return const &
---C++: inline
+ AppendDescendant (me : mutable;
+ theDescendant : Address from Standard)
+ returns Boolean from Standard
+ is protected;
+ ---Level: Internal
+ ---Purpose: Appends new descendant structure.
+ ---Category: Private methods
+
+ RemoveDescendant (me : mutable;
+ theDescendant : Address from Standard)
+ returns Boolean from Standard
+ is protected;
+ ---Level: Internal
+ ---Purpose: Removes the given descendant structure.
+ ---Category: Private methods
+
+ AppendAncestor (me : mutable;
+ theAncestor : Address from Standard)
+ returns Boolean from Standard
+ is protected;
+ ---Level: Internal
+ ---Purpose: Appends new ancestor structure.
+ ---Category: Private methods
+
+ RemoveAncestor (me : mutable;
+ theAncestor : Address from Standard)
+ returns Boolean from Standard
+ is protected;
+ ---Level: Internal
+ ---Purpose: Removes the given ancestor structure.
+ ---Category: Private methods
+
fields
--
-- It is a sequence of groups of primitives.
--
- -- the associated low-level structure
- myCStructure : CStructure from Graphic3d;
+ -- the associated low-level structure
+ myCStructure : CStructure from Graphic3d;
+
+ -- the structures to which the structure is attached
+ myAncestors : SequenceOfAddress from TColStd;
+
+ -- the structures attached to the structure
+ myDescendants : SequenceOfAddress from TColStd;
- -- the structures to which the structure is attached
- myAncestors : SequenceOfAddress from TColStd;
+ -- the map of structures to which the structure is attached
+ myAncestorMap : IndexedMapOfAddress from Graphic3d;
- -- the structures attached to the structure
- myDescendants : SequenceOfAddress from TColStd;
+ -- the map of structures attached to the structure
+ myDescendantMap : IndexedMapOfAddress from Graphic3d;
-- the highlight method of the structure
myHighlightColor : Color from Quantity;
}
}
+//=============================================================================
+//function : AppendDescendant
+//purpose :
+//=============================================================================
+Standard_Boolean Graphic3d_Structure::AppendDescendant (const Standard_Address theDescendant)
+{
+ if (myDescendantMap.IsBound (theDescendant))
+ {
+ return Standard_False; // already connected
+ }
+
+ myDescendantMap.Bind (theDescendant, myDescendants.Length() + 1);
+ myDescendants.Append (theDescendant);
+
+ return Standard_True;
+}
+
+//=============================================================================
+//function : RemoveDescendant
+//purpose :
+//=============================================================================
+Standard_Boolean Graphic3d_Structure::RemoveDescendant (const Standard_Address theDescendant)
+{
+ Standard_Integer aStructIdx;
+ if (!myDescendantMap.Find (theDescendant, aStructIdx))
+ {
+ return Standard_False;
+ }
+
+ myDescendantMap.UnBind (theDescendant);
+
+ if (aStructIdx != myDescendants.Length())
+ {
+ myDescendants.Exchange (aStructIdx, myDescendants.Length());
+ myDescendantMap.Bind (myDescendants (aStructIdx), aStructIdx);
+ }
+
+ myDescendants.Remove (myDescendants.Length());
+
+ return Standard_True;
+}
+
+//=============================================================================
+//function : AppendAncestor
+//purpose :
+//=============================================================================
+Standard_Boolean Graphic3d_Structure::AppendAncestor (const Standard_Address theAncestor)
+{
+ if (myAncestorMap.IsBound (theAncestor))
+ {
+ return Standard_False; // already connected
+ }
+
+ myAncestorMap.Bind (theAncestor, myAncestors.Length() + 1);
+ myAncestors.Append (theAncestor);
+
+ return Standard_True;
+}
+
+//=============================================================================
+//function : RemoveAncestor
+//purpose :
+//=============================================================================
+Standard_Boolean Graphic3d_Structure::RemoveAncestor (const Standard_Address theAncestor)
+{
+ Standard_Integer aStructIdx;
+ if (!myAncestorMap.Find (theAncestor, aStructIdx))
+ {
+ return Standard_False;
+ }
+
+ myAncestorMap.UnBind (theAncestor);
+
+ if (aStructIdx != myAncestors.Length())
+ {
+ myAncestors.Exchange (aStructIdx, myAncestors.Length());
+ myAncestorMap.Bind (myAncestors (aStructIdx), aStructIdx);
+ }
+
+ myAncestors.Remove (myAncestors.Length());
+
+ return Standard_True;
+}
+
//=============================================================================
//function : Connect
//purpose :
const Graphic3d_TypeOfConnection theType,
const Standard_Boolean theWithCheck)
{
- if (IsDeleted()) return;
+ if (IsDeleted())
+ {
+ return;
+ }
// cycle detection
if (theWithCheck
return;
}
- switch (theType)
+ const Standard_Address aStructure = theStructure.operator->();
+
+ if (theType == Graphic3d_TOC_DESCENDANT)
{
- case Graphic3d_TOC_DESCENDANT:
+ if (!AppendDescendant (aStructure))
{
- const Standard_Integer aNbDesc = myDescendants.Length();
- for (Standard_Integer anIter = 1; anIter <= aNbDesc; ++anIter)
- {
- if (myDescendants.Value (anIter) == theStructure.operator->())
- {
- return;
- }
- }
+ return;
+ }
- myDescendants.Append (theStructure.operator->());
- CalculateBoundBox();
- theStructure->Connect (this, Graphic3d_TOC_ANCESTOR);
+ CalculateBoundBox();
+ theStructure->Connect (this, Graphic3d_TOC_ANCESTOR);
- GraphicConnect (theStructure);
- myStructureManager->Connect (this, theStructure);
+ GraphicConnect (theStructure);
+ myStructureManager->Connect (this, theStructure);
- Update();
+ Update();
+ }
+ else // Graphic3d_TOC_ANCESTOR
+ {
+ if (!AppendAncestor (aStructure))
+ {
return;
}
- case Graphic3d_TOC_ANCESTOR:
- {
- const Standard_Integer aNbAnces = myAncestors.Length();
- for (Standard_Integer anIter = 1; anIter <= aNbAnces; ++anIter)
- {
- if (myAncestors.Value (anIter) == theStructure.operator->())
- {
- return;
- }
- }
- myAncestors.Append (theStructure.operator->());
- CalculateBoundBox();
- theStructure->Connect (this, Graphic3d_TOC_DESCENDANT);
+ CalculateBoundBox();
+ theStructure->Connect (this, Graphic3d_TOC_DESCENDANT);
- // myGraphicDriver->Connect is called in case if connection between parent and child
- return;
- }
+ // myStructureManager->Connect is called in case if connection between parent and child
}
}
//=============================================================================
void Graphic3d_Structure::Disconnect (const Handle(Graphic3d_Structure)& theStructure)
{
- if (IsDeleted()) return;
-
- const Standard_Integer aNbDesc = myDescendants.Length();
- for (Standard_Integer anIter = 1; anIter <= aNbDesc; ++anIter)
+ if (IsDeleted())
{
- if (myDescendants.Value (anIter) == theStructure.operator->())
- {
- myDescendants.Remove (anIter);
- theStructure->Disconnect (this);
+ return;
+ }
- GraphicDisconnect (theStructure);
- myStructureManager->Disconnect (this, theStructure);
+ const Standard_Address aStructure = theStructure.operator->();
- CalculateBoundBox();
+ if (RemoveDescendant (aStructure))
+ {
+ theStructure->Disconnect (this);
- Update();
- return;
- }
- }
+ GraphicDisconnect (theStructure);
+ myStructureManager->Disconnect (this, theStructure);
- const Standard_Integer aNbAnces = myAncestors.Length();
- for (Standard_Integer anIter = 1; anIter <= aNbAnces; ++anIter)
+ CalculateBoundBox();
+ Update();
+ }
+ else if (RemoveAncestor (aStructure))
{
- if (myAncestors.Value (anIter) == theStructure.operator->())
- {
- myAncestors.Remove (anIter);
- theStructure->Disconnect (this);
- CalculateBoundBox();
- // no call of myGraphicDriver->Disconnect in case of an ancestor
- return;
- }
+ theStructure->Disconnect (this);
+ CalculateBoundBox();
+
+ // no call of myStructureManager->Disconnect in case of an ancestor
}
}
void Graphic3d_Structure::Remove (const Standard_Address thePtr,
const Graphic3d_TypeOfConnection theType)
{
- switch (theType)
+ if (theType == Graphic3d_TOC_DESCENDANT)
{
- case Graphic3d_TOC_DESCENDANT:
- {
- const Standard_Integer aNbDesc = myDescendants.Length();
- for (Standard_Integer anIter = 1; anIter <= aNbDesc; ++anIter)
- {
- if (myDescendants.Value (anIter) == thePtr)
- {
- myDescendants.Remove (anIter);
- return;
- }
- }
- break;
- }
- case Graphic3d_TOC_ANCESTOR:
- {
- const Standard_Integer aNbAncestors = myAncestors.Length();
- for (Standard_Integer anIter = 1; anIter <= aNbAncestors; ++anIter)
- {
- if (myAncestors.Value (anIter) == thePtr)
- {
- myAncestors.Remove (anIter);
- return;
- }
- }
- break;
- }
+ RemoveDescendant (thePtr);
+ }
+ else
+ {
+ RemoveAncestor (thePtr);
}
}
myAspectText(NULL),
myFirst(NULL),
myLast(NULL),
- myIsRaytracable (Standard_False),
- myModificationState (0)
+ myIsRaytracable (Standard_False)
{
Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
if (aStruct == NULL)
if (myIsRaytracable)
{
- ++myModificationState;
OpenGl_Structure* aStruct = GlStruct();
if (aStruct != NULL)
{
- aStruct->UpdateStateWithAncestorStructures();
+ aStruct->UpdateStateIfRaytracable (Standard_False);
}
}
}
if (OpenGl_Raytrace::IsRaytracedElement (aNode))
{
- myModificationState++;
myIsRaytracable = Standard_True;
OpenGl_Structure* aStruct = GlStruct();
if (aStruct != NULL)
{
- aStruct->UpdateStateWithAncestorStructures();
- aStruct->SetRaytracableWithAncestorStructures();
+ aStruct->UpdateStateIfRaytracable (Standard_False);
}
}
}
Release (aCtx);
Graphic3d_Group::Clear (theToUpdateStructureMgr);
+
+ myIsRaytracable = Standard_False;
}
// =======================================================================
//! Returns OpenGL face aspect.
const OpenGl_AspectFace* AspectFace() const { return myAspectFace; }
- //! Returns modification state for ray-tracing.
- Standard_Size ModificationState() const { return myModificationState; }
-
//! Is the group ray-tracable (contains ray-tracable elements)?
Standard_Boolean IsRaytracable() const { return myIsRaytracable; }
OpenGl_ElementNode* myLast;
Standard_Boolean myIsRaytracable;
- Standard_Size myModificationState;
public:
// function : IsRaytracedGroup
// purpose : Checks to see if the group contains ray-trace geometry
// =======================================================================
- Standard_Boolean IsRaytracedGroup (const OpenGl_Group *theGroup)
+ Standard_Boolean IsRaytracedGroup (const OpenGl_Group* theGroup)
{
- const OpenGl_ElementNode* aNode;
- for (aNode = theGroup->FirstNode(); aNode != NULL; aNode = aNode->next)
+ for (const OpenGl_ElementNode* aNode = theGroup->FirstNode(); aNode != NULL; aNode = aNode->next)
{
if (IsRaytracedElement (aNode))
{
// =======================================================================
Standard_Boolean IsRaytracedStructure (const OpenGl_Structure* theStructure)
{
- for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups());
- aGroupIter.More(); aGroupIter.Next())
+ for (OpenGl_Structure::GroupIterator anIter (theStructure->DrawGroups()); anIter.More(); anIter.Next())
{
- if (aGroupIter.Value()->IsRaytracable())
- return Standard_True;
- }
- for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures());
- anIts.More(); anIts.Next())
- {
- if (IsRaytracedStructure (anIts.Value()))
+ if (anIter.Value()->IsRaytracable())
+ {
return Standard_True;
+ }
}
return Standard_False;
}
// =======================================================================
OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager)
: Graphic3d_CStructure (theManager),
- myTransformation(NULL),
- myTransPers(NULL),
- myAspectLine(NULL),
- myAspectFace(NULL),
- myAspectMarker(NULL),
- myAspectText(NULL),
- myHighlightColor(NULL),
- myIsRaytracable (Standard_False),
- myModificationState (0),
- myIsCulled (Standard_True),
- myIsMirrored (Standard_False)
+ myTransformation (NULL),
+ myTransPers (NULL),
+ myAspectLine (NULL),
+ myAspectFace (NULL),
+ myAspectMarker (NULL),
+ myAspectText (NULL),
+ myHighlightColor (NULL),
+ myInstancedStructure (NULL),
+ myIsRaytracable (Standard_False),
+ myModificationState (0),
+ myIsCulled (Standard_True),
+ myIsMirrored (Standard_False)
{
//
}
matcpy (myTransformation->mat, &Graphic3d_CStructure::Transformation[0][0]);
- if (myIsRaytracable)
+ if (IsRaytracable())
{
- UpdateStateWithAncestorStructures();
+ ++myModificationState;
}
}
}
myAspectFace->SetAspect (theAspect);
- if (myIsRaytracable)
+ if (IsRaytracable())
{
- UpdateStateWithAncestorStructures();
+ ++myModificationState;
}
}
// =======================================================================
void OpenGl_Structure::OnVisibilityChanged()
{
- if (myIsRaytracable)
+ if (IsRaytracable())
{
- UpdateStateWithAncestorStructures();
+ ++myModificationState;
}
}
// =======================================================================
-// function : RegisterAncestorStructure
+// function : IsRaytracable
// purpose :
// =======================================================================
-void OpenGl_Structure::RegisterAncestorStructure (const OpenGl_Structure* theStructure) const
+Standard_Boolean OpenGl_Structure::IsRaytracable() const
{
- for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+ if (!myGroups.IsEmpty())
{
- if (anIt.Value() == theStructure)
- {
- return;
- }
+ return myIsRaytracable; // geometry structure
}
-
- myAncestorStructures.Append (theStructure);
-}
-
-// =======================================================================
-// function : UnregisterAncestorStructure
-// purpose :
-// =======================================================================
-void OpenGl_Structure::UnregisterAncestorStructure (const OpenGl_Structure* theStructure) const
-{
- for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+ else if (myInstancedStructure != NULL)
{
- if (anIt.Value() == theStructure)
- {
- myAncestorStructures.Remove (anIt);
- return;
- }
+ return myInstancedStructure->IsRaytracable(); // instance structure
}
-}
-
-// =======================================================================
-// function : UnregisterFromAncestorStructure
-// purpose :
-// =======================================================================
-void OpenGl_Structure::UnregisterFromAncestorStructure() const
-{
- for (OpenGl_ListOfStructure::Iterator anIta (myAncestorStructures); anIta.More(); anIta.Next())
- {
- OpenGl_Structure* anAncestor = const_cast<OpenGl_Structure*> (anIta.ChangeValue());
- for (OpenGl_ListOfStructure::Iterator anIts (anAncestor->myConnected); anIts.More(); anIts.Next())
- {
- if (anIts.Value() == this)
- {
- anAncestor->myConnected.Remove (anIts);
- return;
- }
- }
- }
+ return Standard_False; // has no any groups or structures
}
// =======================================================================
-// function : UpdateStateWithAncestorStructures
+// function : UpdateRaytracableState
// purpose :
// =======================================================================
-void OpenGl_Structure::UpdateStateWithAncestorStructures() const
+void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const
{
- myModificationState++;
+ myIsRaytracable = !toCheck || OpenGl_Raytrace::IsRaytracedStructure (this);
- for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
+ if (IsRaytracable())
{
- anIt.Value()->UpdateStateWithAncestorStructures();
- }
-}
-
-// =======================================================================
-// function : UpdateRaytracableWithAncestorStructures
-// purpose :
-// =======================================================================
-void OpenGl_Structure::UpdateRaytracableWithAncestorStructures() const
-{
- myIsRaytracable = OpenGl_Raytrace::IsRaytracedStructure (this);
-
- if (!myIsRaytracable)
- {
- for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
- {
- anIt.Value()->UpdateRaytracableWithAncestorStructures();
- }
- }
-}
-
-// =======================================================================
-// function : SetRaytracableWithAncestorStructures
-// purpose :
-// =======================================================================
-void OpenGl_Structure::SetRaytracableWithAncestorStructures() const
-{
- myIsRaytracable = Standard_True;
-
- for (OpenGl_ListOfStructure::Iterator anIt (myAncestorStructures); anIt.More(); anIt.Next())
- {
- if (!anIt.Value()->IsRaytracable())
- {
- anIt.Value()->SetRaytracableWithAncestorStructures();
- }
+ ++myModificationState;
}
}
// =======================================================================
void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure)
{
- OpenGl_Structure* aStruct = (OpenGl_Structure* )&theStructure;
- Disconnect (theStructure);
- myConnected.Append (aStruct);
+ OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
+
+ Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct,
+ "Error! Instanced structure is already defined");
+
+ myInstancedStructure = aStruct;
if (aStruct->IsRaytracable())
{
- UpdateStateWithAncestorStructures();
- SetRaytracableWithAncestorStructures();
+ UpdateStateIfRaytracable (Standard_False);
}
-
- aStruct->RegisterAncestorStructure (this);
}
// =======================================================================
// =======================================================================
void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure)
{
- OpenGl_Structure* aStruct = (OpenGl_Structure* )&theStructure;
- for (OpenGl_ListOfStructure::Iterator anIter (myConnected); anIter.More(); anIter.Next())
- {
- // Check for the given structure
- if (anIter.Value() == aStruct)
- {
- myConnected.Remove (anIter);
+ OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure);
- if (aStruct->IsRaytracable())
- {
- UpdateStateWithAncestorStructures();
- UpdateRaytracableWithAncestorStructures();
- }
+ if (myInstancedStructure == aStruct)
+ {
+ myInstancedStructure = NULL;
- aStruct->UnregisterAncestorStructure (this);
- return;
+ if (aStruct->IsRaytracable())
+ {
+ UpdateStateIfRaytracable();
}
}
}
// Check for the given group
if (aGroupIter.Value() == theGroup)
{
+ const Standard_Boolean wasRaytracable =
+ static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable();
+
theGroup->Clear (Standard_False);
- if (((OpenGl_Group* )theGroup.operator->())->IsRaytracable())
+ if (wasRaytracable)
{
- UpdateStateWithAncestorStructures();
- UpdateRaytracableWithAncestorStructures();
+ UpdateStateIfRaytracable();
}
myGroups.Remove (aGroupIter);
if (aRaytracableGroupDeleted)
{
- UpdateStateWithAncestorStructures();
- UpdateRaytracableWithAncestorStructures();
+ myIsRaytracable = Standard_False;
}
Is2dText = Standard_False;
if (myHighlightColor)
theWorkspace->HighlightColor = myHighlightColor;
- // Render connected structures
- OpenGl_ListOfStructure::Iterator anIter (myConnected);
- while (anIter.More())
+ // Render instanced structure (if exists)
+ if (myInstancedStructure != NULL)
{
- anIter.Value()->RenderGeometry (theWorkspace);
- anIter.Next();
+ myInstancedStructure->RenderGeometry (theWorkspace);
}
// Set up plane equations for non-structure transformed global model-view matrix
OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
clearHighlightColor (theGlCtx);
-
- // Remove from connected list of ancestor
- UnregisterFromAncestorStructure();
}
// =======================================================================
//! and will lead to broken visualization due to loosed data.
Standard_EXPORT void ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx);
- //! Returns list of connected OpenGL structures.
- const OpenGl_ListOfStructure& ConnectedStructures() const { return myConnected; }
+ //! Returns instanced OpenGL structure.
+ const OpenGl_Structure* InstancedStructure() const { return myInstancedStructure; }
//! Returns OpenGL face aspect.
const OpenGl_AspectFace* AspectFace() const { return myAspectFace; }
void ResetModificationState() const { myModificationState = 0; }
//! Is the structure ray-tracable (contains ray-tracable elements)?
- Standard_Boolean IsRaytracable() const { return myIsRaytracable; }
+ Standard_Boolean IsRaytracable() const;
protected:
Standard_EXPORT virtual ~OpenGl_Structure();
- //! Registers ancestor connected structure (for updating ray-tracing state).
- void RegisterAncestorStructure (const OpenGl_Structure* theStructure) const;
-
- //! Unregisters ancestor connected structure (for updating ray-tracing state).
- void UnregisterAncestorStructure (const OpenGl_Structure* theStructure) const;
-
- //! Unregisters structure from ancestor structure (for updating ray-tracing state).
- void UnregisterFromAncestorStructure() const;
-
- //! Updates modification state for structure and its parents.
- void UpdateStateWithAncestorStructures() const;
-
//! Updates ray-tracable status for structure and its parents.
- void UpdateRaytracableWithAncestorStructures() const;
-
- //! Sets ray-tracable status for structure and its parents.
- void SetRaytracableWithAncestorStructures() const;
+ void UpdateStateIfRaytracable (const Standard_Boolean toCheck = Standard_True) const;
protected:
Handle(OpenGl_Group) myHighlightBox;
TEL_COLOUR* myHighlightColor;
- OpenGl_ListOfStructure myConnected;
+ OpenGl_Structure* myInstancedStructure;
- mutable OpenGl_ListOfStructure myAncestorStructures;
- mutable Standard_Boolean myIsRaytracable;
- mutable Standard_Size myModificationState;
+ mutable Standard_Boolean myIsRaytracable;
+ mutable Standard_Size myModificationState;
- mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse.
+ mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse.
- Standard_Boolean myIsMirrored; //!< Used to tell OpenGl to interpret polygons in clockwise order.
+ Standard_Boolean myIsMirrored; //!< Used to tell OpenGl to interpret polygons in clockwise order.
public:
}
};
+ //! Describes state of OpenGL structure.
+ struct StructState
+ {
+ Standard_Size StructureState;
+ Standard_Size InstancedState;
+
+ //! Creates new structure state.
+ StructState (const Standard_Size theStructureState = 0,
+ const Standard_Size theInstancedState = 0)
+ : StructureState (theStructureState),
+ InstancedState (theInstancedState)
+ {
+ //
+ }
+
+ //! Creates new structure state.
+ StructState (const OpenGl_Structure* theStructure)
+ {
+ StructureState = theStructure->ModificationState();
+
+ InstancedState = theStructure->InstancedStructure() != NULL ?
+ theStructure->InstancedStructure()->ModificationState() : 0;
+ }
+ };
+
protected: //! @name methods related to ray-tracing
//! Updates 3D scene geometry for ray-tracing.
Standard_Integer myUniformLocations[2][OpenGl_RT_NbVariables];
//! State of OpenGL structures reflected to ray-tracing.
- std::map<const OpenGl_Structure*, Standard_Size> myStructureStates;
+ std::map<const OpenGl_Structure*, StructState> myStructureStates;
//! PrimitiveArray to TriangleSet map for scene partial update.
std::map<Standard_Size, OpenGl_TriangleSet*> myArrayToTrianglesMap;
else if (theMode == OpenGl_GUM_REBUILD)
{
// Actualize the hash map of structures - remove out-of-date records
- std::map<const OpenGl_Structure*, Standard_Size>::iterator anIter = myStructureStates.begin();
+ std::map<const OpenGl_Structure*, StructState>::iterator anIter = myStructureStates.begin();
while (anIter != myStructureStates.end())
{
return Standard_False; // did not contain ray-trace elements
}
- std::map<const OpenGl_Structure*, Standard_Size>::iterator aStructState = myStructureStates.find (theStructure);
+ std::map<const OpenGl_Structure*, StructState>::iterator aStructState = myStructureStates.find (theStructure);
- if (aStructState != myStructureStates.end())
+ if (aStructState == myStructureStates.end() || aStructState->second.StructureState != theStructure->ModificationState())
{
- return aStructState->second != theStructure->ModificationState();
+ return Standard_True;
+ }
+ else if (theStructure->InstancedStructure() != NULL)
+ {
+ return aStructState->second.InstancedState != theStructure->InstancedStructure()->ModificationState();
}
- return Standard_True;
+ return Standard_False;
}
// =======================================================================
{
if (!theStructure->IsVisible())
{
- myStructureStates[theStructure] = theStructure->ModificationState();
+ myStructureStates[theStructure] = StructState (theStructure);
return Standard_True;
}
theStructure->Transformation()->mat ? aStructTransform : NULL, theGlContext);
// Process all connected OpenGL structures
- for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures()); anIts.More(); anIts.Next())
+ const OpenGl_Structure* anInstanced = theStructure->InstancedStructure();
+
+ if (anInstanced != NULL && anInstanced->IsRaytracable())
{
- if (anIts.Value()->IsRaytracable())
- {
- aResult &= addRaytraceGroups (anIts.Value(), aStructMatID,
- theStructure->Transformation()->mat ? aStructTransform : NULL, theGlContext);
- }
+ aResult &= addRaytraceGroups (anInstanced, aStructMatID,
+ theStructure->Transformation()->mat ? aStructTransform : NULL, theGlContext);
}
- myStructureStates[theStructure] = theStructure->ModificationState();
+ myStructureStates[theStructure] = StructState (theStructure);
return aResult;
}
//=======================================================================
void SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject)
{
- myObjects.Append (theObject);
- myObjectIdxs.Append (myObjects.Size());
-
- MarkDirty();
+ if (Size() < myObjects.Add (theObject))
+ {
+ MarkDirty();
+ }
}
//=======================================================================
//=======================================================================
void SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject)
{
- for (Standard_Integer anObjectIdx = 1; anObjectIdx <= myObjects.Size(); ++anObjectIdx)
+ const Standard_Integer anIndex = myObjects.FindIndex (theObject);
+
+ if (anIndex != 0)
{
- if (myObjects.Value (anObjectIdx) == theObject)
- {
- myObjects.Remove (anObjectIdx);
- myObjectIdxs.Clear();
- for (Standard_Integer anObjIdxsIter = 1; anObjIdxsIter <= myObjects.Size(); ++anObjIdxsIter)
- {
- myObjectIdxs.Append (anObjIdxsIter);
- }
- MarkDirty();
- break;
- }
+ Swap (anIndex - 1, Size() - 1);
+
+ myObjects.RemoveLast();
+
+ MarkDirty();
}
}
const Standard_Integer theAxis) const
{
Select3D_BndBox3d aBndBox = Box (theIndex);
- Standard_Real aCenter = theAxis == 0 ? (aBndBox.CornerMin().x() + aBndBox.CornerMax().x()) * 0.5 :
- (theAxis == 1 ? (aBndBox.CornerMin().y() + aBndBox.CornerMax().y()) * 0.5 :
- (aBndBox.CornerMin().z() + aBndBox.CornerMax().z()) * 0.5);
- return aCenter;
+ return (aBndBox.CornerMin()[theAxis] +
+ aBndBox.CornerMax()[theAxis]) * 0.5;
}
//=======================================================================
void SelectMgr_SelectableObjectSet::Swap (const Standard_Integer theIndex1,
const Standard_Integer theIndex2)
{
- Standard_Integer anObjectIdx1 = myObjectIdxs.Value (theIndex1 + 1);
- Standard_Integer anObjectIdx2 = myObjectIdxs.Value (theIndex2 + 1);
- myObjectIdxs.ChangeValue (theIndex1 + 1) = anObjectIdx2;
- myObjectIdxs.ChangeValue (theIndex2 + 1) = anObjectIdx1;
+ const Standard_Integer aIndex1 = theIndex1 + 1;
+ const Standard_Integer aIndex2 = theIndex2 + 1;
+
+ Handle(SelectMgr_SelectableObject) anObject1 = myObjects.FindKey (aIndex1);
+ Handle(SelectMgr_SelectableObject) anObject2 = myObjects.FindKey (aIndex2);
+
+ myObjects.Substitute (aIndex1, EMPTY_OBJ);
+ myObjects.Substitute (aIndex2, anObject1);
+ myObjects.Substitute (aIndex1, anObject2);
}
//=======================================================================
//=======================================================================
Standard_Integer SelectMgr_SelectableObjectSet::Size() const
{
- return myObjectIdxs.Size();
+ return myObjects.Size();
}
//=======================================================================
// function : GetObjectById
// purpose : Returns object from set by theIndex given
//=======================================================================
-const Handle(SelectMgr_SelectableObject)& SelectMgr_SelectableObjectSet::GetObjectById
- (const Standard_Integer theIndex) const
+const Handle(SelectMgr_SelectableObject)& SelectMgr_SelectableObjectSet::GetObjectById (const Standard_Integer theIndex) const
{
- Standard_Integer anIdx = myObjectIdxs.Value (theIndex + 1);
- return myObjects.Value (anIdx);
+ return myObjects.FindKey (theIndex + 1);
}
//=======================================================================
//=======================================================================
Standard_Boolean SelectMgr_SelectableObjectSet::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
{
- for (Standard_Integer anObjectIdx = 1; anObjectIdx <= myObjects.Size(); ++anObjectIdx)
- {
- if (myObjects.Value (anObjectIdx) == theObject)
- return Standard_True;
- }
-
- return Standard_False;
+ return myObjects.Contains (theObject);
}
#include <SelectMgr_SelectableObject.hxx>
#include <SelectMgr_VectorTypes.hxx>
+#include <NCollection_IndexedMap.hxx>
+
//! The purpose of this class is to organize all selectable objects into
//! data structure, allowing to build BVH tree. For selectable objects
//! binned BVH builder is used with 32 bins and 1 element per leaf.
class SelectMgr_SelectableObjectSet : public BVH_PrimitiveSet<Standard_Real, 3>
{
+ Handle(SelectMgr_SelectableObject) EMPTY_OBJ;
+
public:
//! Creates new empty objects set and initializes BVH tree
//! builder to Binned builder with 1 element per list
SelectMgr_SelectableObjectSet();
- virtual ~SelectMgr_SelectableObjectSet() {};
+ //! Releases resources of selectable object set.
+ virtual ~SelectMgr_SelectableObjectSet() { }
//! Adds new object to the set and marks BVH tree for rebuild
void Append (const Handle(SelectMgr_SelectableObject)& theObject);
private:
- NCollection_Sequence<Handle(SelectMgr_SelectableObject)> myObjects;
- NCollection_Sequence<Standard_Integer> myObjectIdxs;
+ NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)> myObjects;
};
#endif // _SelectMgr_SelectableObjectSet_HeaderFile
//===============================================================================================
//function : VConnectTo
//purpose : Creates and displays AIS_ConnectedInteractive object from input object and location
-//Draw arg : vconnectto name Xo Yo Zo object
+//Draw arg : vconnectto name Xo Yo Zo object [-nodisplay|-noupdate|-update]
//===============================================================================================
static Standard_Integer VConnectTo (Draw_Interpretor& /*di*/,
{
// Check the viewer
Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+ ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
if (aContext.IsNull())
{
std::cout << "vconnect error : call vinit before\n";
anArg.LowerCase();
if (anArg == "-nodisplay")
return 0;
+
+ if (!anUpdateTool.parseRedrawMode (anArg))
+ {
+ std::cout << "Warning! Unknown argument '" << anArg << "' passed, -nodisplay|-noupdate|-update expected at this point.\n";
+ }
}
// Display connected object
- TheAISContext()->Display (aConnected);
+ TheAISContext()->Display (aConnected, Standard_False);
return 0;
}
__FILE__, VConnect, group);
theCommands.Add("vconnectto",
- "vconnectto : instance_name Xo Yo Zo object [-nodisplay]"
+ "vconnectto : instance_name Xo Yo Zo object [-nodisplay|-noupdate|-update]"
" Makes an instance 'instance_name' of 'object' with position (Xo Yo Zo)."
"\n\t\t: -nodisplay - only creates interactive object, but not displays it",
__FILE__, VConnectTo,group);
--- /dev/null
+puts "============"
+puts "0026029: Visualization - Poor performance of connected objects"
+puts "============"
+puts ""
+###########################################################
+# Time spent on computation of large number of connected objects
+# should grow linearly with the number of objects
+###########################################################
+
+pload MODELING VISUALIZATION
+psphere s 0.5
+tclean s
+incmesh s 0.1
+trinfo s
+
+vinit View1
+vclear
+vaxo
+#vcaps -vbo 0
+vsetdispmode 1
+vdefaults -defl 1.0 -autoTriang off
+vdisplay s
+
+# disable output of commands
+decho off
+
+set aNb1 100
+
+# display 100x100 connected instances of single presentation
+puts "Creating [expr $aNb1*$aNb1] instances..."
+set t [time {for {set i 0} {$i < $aNb1} {incr i} {for {set j 0} {$j < $aNb1} {incr j} {vconnectto s_${i}_${j} ${i} ${j} 0 s -noupdate}}}]
+set d1 [lindex $t 0]
+puts "Done in $d1 microseconds!\n"
+vclear
+
+set aNb2 200
+
+# display 200x200 connected instances of single presentation
+puts "Creating [expr $aNb2*$aNb2] instances..."
+set t [time {for {set i 0} {$i < $aNb2} {incr i} {for {set j 0} {$j < $aNb2} {incr j} {vconnectto s_${i}_${j} ${i} ${j} 0 s -noupdate}}}]
+set d2 [lindex $t 0]
+puts "Done in $d2 microseconds!\n"
+vclear
+
+# compare two CPU times: the ratio should be quasi-linear
+set expected_ratio [expr double($aNb2 * $aNb2) / double($aNb1 * $aNb1)]
+set actual_ratio [expr double($d2) / double($d1)]
+puts "Comparing CPU time for the two test cases..."
+puts "============================================="
+puts "Expected ratio: $expected_ratio"
+puts "Actual ratio: $actual_ratio"
+puts "============================================="
+
+# Allow 50% deviation from linear growth
+if {[expr $actual_ratio / $expected_ratio] > 1.5} {
+ puts "Error: non-linear time growth detected!"
+} else {
+ puts "Test passed!"
+}