- Added a new mode in SelectMgr_ViewerSelector for computing BVH for Select3D_SensitiveEntity in background which can be activated via method SelectMgr_ViewerSelector::SetToPrebuildBVH(). Default behavior has not been changed.
- New class SelectMgr_BVHThreadPool manages background processing of BVH building queue.
- Added Select3D_SensitiveEntity::ToBuildBVH() method that checks if BVH (if it used) is in invalidated state. Defined this method for all standard classes inherited from Select3D_SensitiveEntity.
const Handle(SelectMgr_EntityOwner)& anOwner = aSelEntIter.Value()->BaseSensitive()->OwnerId();
anOwner->SetSelectable (aThis);
}
-
- StdSelect_BRepSelectionTool::PreBuildBVH (theSelection);
}
//=======================================================================
Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
+
Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
Standard_EXPORT virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE;
}
}
- StdSelect_BRepSelectionTool::PreBuildBVH (theSelection);
-
if (toShowComputeSelectionTime)
{
Standard_Real sec, cpu;
//! transformation is set, it will be applied
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
+
//! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
}
}
+//=======================================================================
+// function : ToBuildBVH
+// purpose :
+//=======================================================================
+Standard_Boolean Select3D_SensitiveCircle::ToBuildBVH() const
+{
+ if (mySensType != Select3D_TOS_BOUNDARY)
+ {
+ return Standard_False;
+ }
+
+ return Select3D_SensitivePoly::ToBuildBVH();
+}
+
//=======================================================================
// function : Matches
// purpose : Checks whether the circle overlaps current selecting volume
//! Builds BVH tree for a circle's edge segments if needed
Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ Standard_EXPORT virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE;
+
protected:
//! Calculates distance from the 3d projection of used-picked screen point
//! Builds BVH tree for a sensitive if needed
virtual void BVH() {}
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const { return Standard_True; }
+
//! Clears up all resources and memory
virtual void Clear() { Set (Handle(SelectMgr_EntityOwner)()); }
//! Builds BVH tree for the face
Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return myFacePoints->ToBuildBVH(); }
+
//! Returns the amount of sub-entities (points or planar convex polygons)
Standard_EXPORT virtual Standard_Integer NbSubElements() const Standard_OVERRIDE;
//! transformation is set, it will be applied
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
+
//! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
//! transformation is set, it will be applied
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
+
public:
//! changes the start Point of the Segment;
//! but element by element
Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return myContent.IsDirty(); }
+
//! Sets the method (builder) used to construct BVH.
void SetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder) { myContent.SetBuilder (theBuilder); }
//! will be applied
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
+ //! Returns TRUE if BVH tree is in invalidated state
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
+
//! Returns the amount of points
virtual Standard_Integer NbSubElements() const Standard_OVERRIDE { return 3; }
SelectMgr_AndOrFilter.hxx
SelectMgr_BaseFrustum.cxx
SelectMgr_BaseFrustum.hxx
+SelectMgr_BVHThreadPool.cxx
+SelectMgr_BVHThreadPool.hxx
SelectMgr_CompositionFilter.cxx
SelectMgr_CompositionFilter.hxx
SelectMgr_CompositionFilter.lxx
--- /dev/null
+// Copyright (c) 2020 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 <SelectMgr_BVHThreadPool.hxx>
+#include <Message.hxx>
+#include <OSD.hxx>
+#include <OSD_Parallel.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_BVHThreadPool, Standard_Transient)
+
+//==================================================
+// Function: SelectMgr_BVHThreadPool
+// Purpose :
+//==================================================
+SelectMgr_BVHThreadPool::SelectMgr_BVHThreadPool (Standard_Integer theNbThreads)
+: myToStopBVHThread(Standard_False),
+ myWakeEvent(Standard_False),
+ myIdleEvent(Standard_True),
+ myIsStarted(Standard_False)
+{
+ Standard_Integer aBVHThreadsNum = Max (1, theNbThreads);
+ myBVHThreads.Resize (1, aBVHThreadsNum, Standard_False);
+
+ Standard_Boolean toCatchFpe = OSD::ToCatchFloatingSignals();
+
+ for (Standard_Integer i = myBVHThreads.Lower(); i <= myBVHThreads.Upper(); ++i)
+ {
+ BVHThread& aThread = myBVHThreads.ChangeValue(i);
+ aThread.SetFunction (&BVHThread::runThread);
+ aThread.myPool = this;
+ aThread.myToCatchFpe = toCatchFpe;
+ }
+}
+
+//==================================================
+// Function: ~SelectMgr_BVHThreadPool
+// Purpose :
+//==================================================
+SelectMgr_BVHThreadPool::~SelectMgr_BVHThreadPool()
+{
+ StopThreads();
+}
+
+//==================================================
+// Function: StopThreads
+// Purpose :
+//==================================================
+void SelectMgr_BVHThreadPool::StopThreads()
+{
+ if (!myIsStarted)
+ {
+ return;
+ }
+ myToStopBVHThread = Standard_True;
+ myWakeEvent.Set();
+ for (Standard_Integer i = myBVHThreads.Lower(); i <= myBVHThreads.Upper(); ++i)
+ {
+ myBVHThreads.ChangeValue(i).Wait();
+ }
+ myToStopBVHThread = Standard_False;
+ myIsStarted = Standard_False;
+}
+
+//==================================================
+// Function: WaitThreads
+// Purpose :
+//==================================================
+void SelectMgr_BVHThreadPool::WaitThreads()
+{
+ myIdleEvent.Wait();
+
+ Sentry aSentry (this);
+}
+
+//=======================================================================
+//function : AddEntity
+//purpose :
+//=======================================================================
+void SelectMgr_BVHThreadPool::AddEntity (const Handle(Select3D_SensitiveEntity)& theEntity)
+{
+ if (!theEntity->ToBuildBVH())
+ {
+ return;
+ }
+
+ {
+ Standard_Mutex::Sentry aSentry (myBVHListMutex);
+ myBVHToBuildList.Append (theEntity);
+ myWakeEvent.Set();
+ myIdleEvent.Reset();
+ }
+
+ if (!myIsStarted)
+ {
+ myIsStarted = Standard_True;
+ for (Standard_Integer i = myBVHThreads.Lower(); i <= myBVHThreads.Upper(); ++i)
+ {
+ myBVHThreads.ChangeValue(i).Run ((Standard_Address) (&myBVHThreads.ChangeValue(i)));
+ }
+ }
+}
+
+//=======================================================================
+//function : performThread
+//purpose :
+//=======================================================================
+void SelectMgr_BVHThreadPool::BVHThread::performThread()
+{
+ OSD::SetThreadLocalSignal (OSD::SignalMode(), myToCatchFpe);
+
+ for (;;)
+ {
+ myPool->myWakeEvent.Wait();
+
+ if (myPool->myToStopBVHThread)
+ {
+ return;
+ }
+
+ myPool->myBVHListMutex.Lock();
+ if (myPool->myBVHToBuildList.IsEmpty())
+ {
+ myPool->myWakeEvent.Reset();
+ myPool->myIdleEvent.Set();
+ myPool->myBVHListMutex.Unlock();
+ continue;
+ }
+ Handle(Select3D_SensitiveEntity) anEntity = myPool->myBVHToBuildList.First();
+ myPool->myBVHToBuildList.RemoveFirst();
+
+ Standard_Mutex::Sentry anEntry (myMutex);
+ myPool->myBVHListMutex.Unlock();
+
+ if (!anEntity.IsNull())
+ {
+ try
+ {
+ OCC_CATCH_SIGNALS
+ anEntity->BVH();
+ }
+ catch (Standard_Failure const& aFailure)
+ {
+ TCollection_AsciiString aMsg = TCollection_AsciiString (aFailure.DynamicType()->Name())
+ + ": " + aFailure.GetMessageString();
+ Message::DefaultMessenger()->SendFail (aMsg);
+ }
+ catch (std::exception& anStdException)
+ {
+ TCollection_AsciiString aMsg = TCollection_AsciiString (typeid(anStdException).name())
+ + ": " + anStdException.what();
+ Message::DefaultMessenger()->SendFail (aMsg);
+ }
+ catch (...)
+ {
+ Message::DefaultMessenger()->SendFail ("Error: Unknown exception");
+ }
+ }
+ }
+}
+
+// =======================================================================
+// function : runThread
+// purpose :
+// =======================================================================
+Standard_Address SelectMgr_BVHThreadPool::BVHThread::runThread (Standard_Address theTask)
+{
+ BVHThread* aThread = static_cast<BVHThread*>(theTask);
+ aThread->performThread();
+ return NULL;
+}
--- /dev/null
+// Copyright (c) 2020 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 _SelectMgr_BVHThreadPool_HeaderFile
+#define _SelectMgr_BVHThreadPool_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <OSD_Thread.hxx>
+#include <Standard_Mutex.hxx>
+#include <Select3D_SensitiveEntity.hxx>
+#include <Standard_Condition.hxx>
+#include <Message_Messenger.hxx>
+
+//! Class defining a thread pool for building BVH for the list of Select3D_SensitiveEntity within background thread(s).
+class SelectMgr_BVHThreadPool : public Standard_Transient
+{
+ DEFINE_STANDARD_RTTIEXT(SelectMgr_BVHThreadPool, Standard_Transient)
+public:
+ //! Main constructor
+ Standard_EXPORT SelectMgr_BVHThreadPool (Standard_Integer theNbThreads);
+
+ //! Destructor
+ Standard_EXPORT virtual ~SelectMgr_BVHThreadPool();
+
+public:
+
+ //! Thread with back reference to thread pool and thread mutex in it.
+ class BVHThread : public OSD_Thread
+ {
+ friend class SelectMgr_BVHThreadPool;
+ public:
+
+ BVHThread()
+ : OSD_Thread(),
+ myToCatchFpe (Standard_False)
+ {
+
+ }
+
+ //! Returns mutex used for BVH building
+ Standard_Mutex& BVHMutex()
+ {
+ return myMutex;
+ }
+
+ //! Assignment operator.
+ BVHThread& operator= (const BVHThread& theCopy)
+ {
+ Assign (theCopy);
+ return *this;
+ }
+
+ //! Assignment operator.
+ void Assign (const BVHThread& theCopy)
+ {
+ OSD_Thread::Assign (theCopy);
+ myPool = theCopy.myPool;
+ myToCatchFpe = theCopy.myToCatchFpe;
+ }
+
+ private:
+ //! Method is executed in the context of thread.
+ void performThread();
+
+ //! Method is executed in the context of thread.
+ static Standard_Address runThread (Standard_Address theTask);
+
+ private:
+
+ SelectMgr_BVHThreadPool* myPool;
+ Standard_Mutex myMutex;
+ bool myToCatchFpe;
+ };
+
+public:
+ //! Queue a sensitive entity to build its BVH
+ Standard_EXPORT void AddEntity (const Handle(Select3D_SensitiveEntity)& theEntity);
+
+ //! Stops threads
+ Standard_EXPORT void StopThreads();
+
+ //! Waits for all threads finish their jobs
+ Standard_EXPORT void WaitThreads();
+
+ //! Returns array of threads
+ NCollection_Array1<BVHThread>& Threads()
+ {
+ return myBVHThreads;
+ }
+
+public:
+
+ //! Class providing a simple interface to mutexes for list of BVHThread
+ class Sentry
+ {
+ public:
+
+ //! Constructor - initializes the sentry object and locks list of mutexes immediately
+ Sentry (const Handle(SelectMgr_BVHThreadPool)& thePool)
+ : myPool (thePool)
+ {
+ Lock();
+ }
+
+ //! Destructor - unlocks list of mutexes if already locked.
+ ~Sentry()
+ {
+ Unlock();
+ }
+
+ //! Lock list of mutexes
+ void Lock()
+ {
+ if (!myPool.IsNull())
+ {
+ for (Standard_Integer i = myPool->Threads().Lower(); i <= myPool->Threads().Upper(); ++i)
+ {
+ myPool->Threads().ChangeValue(i).BVHMutex().Lock();
+ }
+ }
+ }
+
+ //! Unlock list of mutexes
+ void Unlock()
+ {
+ if (!myPool.IsNull())
+ {
+ for (Standard_Integer i = myPool->Threads().Lower(); i <= myPool->Threads().Upper(); ++i)
+ {
+ myPool->Threads().ChangeValue(i).BVHMutex().Unlock();
+ }
+ }
+ }
+
+ //! This method should not be called (prohibited).
+ Sentry (const Sentry &);
+ //! This method should not be called (prohibited).
+ Sentry& operator = (const Sentry &);
+
+ private:
+ Handle(SelectMgr_BVHThreadPool) myPool;
+ };
+
+protected:
+
+ NCollection_List<Handle(Select3D_SensitiveEntity)> myBVHToBuildList; //!< list of queued sensitive entities
+ NCollection_Array1<BVHThread> myBVHThreads; //!< threads to build BVH
+ Standard_Boolean myToStopBVHThread; //!< flag to stop BVH threads
+ Standard_Mutex myBVHListMutex; //!< mutex for interaction with myBVHToBuildList
+ Standard_Condition myWakeEvent; //!< raises when any sensitive is added to the BVH list
+ Standard_Condition myIdleEvent; //!< raises when BVH list become empty
+ Standard_Boolean myIsStarted; //!< indicates that threads are running
+};
+
+#endif
#include <SelectMgr_SelectionManager.hxx>
+#include <Select3D_SensitiveGroup.hxx>
#include <SelectMgr_SelectableObject.hxx>
#include <SelectMgr_Selection.hxx>
+#include <StdSelect_BRepSelectionTool.hxx>
#include <TCollection_AsciiString.hxx>
IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_SelectionManager,Standard_Transient)
theObject->AddSelection (aNewSel, theMode);
aNewSel->UpdateBVHStatus (SelectMgr_TBU_Remove);
aNewSel->SetSelectionState (SelectMgr_SOS_Deactivated);
+
+ buildBVH (aNewSel);
}
}
return;
mySelector->AddSelectionToObject (theObject, aNewSel);
aNewSel->UpdateBVHStatus (SelectMgr_TBU_None);
}
+
+ buildBVH (aNewSel);
+}
+
+//==================================================
+// Function: buildBVH
+// Purpose : Private Method
+//==================================================
+void SelectMgr_SelectionManager::buildBVH (const Handle(SelectMgr_Selection)& theSelection)
+{
+ if (mySelector->ToPrebuildBVH())
+ {
+ for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator anIter (theSelection->Entities()); anIter.More(); anIter.Next())
+ {
+ const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value()->BaseSensitive();
+ mySelector->QueueBVHBuild (anEntity);
+
+ if (Handle(Select3D_SensitiveGroup) aGroup = Handle(Select3D_SensitiveGroup)::DownCast (anEntity))
+ {
+ for (Select3D_IndexedMapOfEntity::Iterator aSubEntitiesIter (aGroup->Entities()); aSubEntitiesIter.More(); aSubEntitiesIter.Next())
+ {
+ const Handle(Select3D_SensitiveEntity)& aSubEntity = aSubEntitiesIter.Value();
+ mySelector->QueueBVHBuild (aSubEntity);
+ }
+ }
+ }
+ }
+ else
+ {
+ StdSelect_BRepSelectionTool::PreBuildBVH (theSelection);
+ }
}
//=======================================================================
Standard_EXPORT void loadMode (const Handle(SelectMgr_SelectableObject)& theObject,
const Standard_Integer theMode);
+ //! In multi-thread mode queues sensitive entities to build its BVH in separate threads.
+ //! Otherwise, builds BVH for heavyweight entities immediately.
+ Standard_EXPORT void buildBVH (const Handle(SelectMgr_Selection)& theSelection);
+
private:
Handle(SelectMgr_ViewerSelector) mySelector;
preferclosest(Standard_True),
myToUpdateTolerance (Standard_True),
myCameraScale (1.0),
+myToPrebuildBVH (Standard_False),
myCurRank (0),
myIsLeftChildQueuedFirst (Standard_False),
myEntityIdx (0)
//=======================================================================
void SelectMgr_ViewerSelector::TraverseSensitives()
{
+ SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
+
mystored.Clear();
Standard_Integer aWidth;
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myEntityIdx)
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
}
+
+//=======================================================================
+//function : SetToPrebuildBVH
+//purpose :
+//=======================================================================
+void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
+{
+ if (!theToPrebuild && !myBVHThreadPool.IsNull())
+ {
+ myBVHThreadPool.Nullify();
+ }
+ else if (theToPrebuild)
+ {
+ myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
+ }
+ myToPrebuildBVH = theToPrebuild;
+}
+
+//=======================================================================
+//function : QueueBVHBuild
+//purpose :
+//=======================================================================
+void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
+{
+ if (myToPrebuildBVH)
+ {
+ myBVHThreadPool->AddEntity (theEntity);
+ }
+}
+
+//=======================================================================
+//function : WaitForBVHBuild
+//purpose :
+//=======================================================================
+void SelectMgr_ViewerSelector::WaitForBVHBuild()
+{
+ if (myToPrebuildBVH)
+ {
+ myBVHThreadPool->WaitThreads();
+ }
+}
#include <SelectMgr_StateOfSelection.hxx>
#include <SelectMgr_ToleranceMap.hxx>
#include <Standard_OStream.hxx>
+#include <SelectMgr_BVHThreadPool.hxx>
class SelectMgr_SelectionManager;
class SelectMgr_SensitiveEntitySet;
Standard_DEPRECATED("Deprecated method DetectedEntity() should be replaced by DetectedEntity(int)")
Standard_EXPORT const Handle(Select3D_SensitiveEntity)& DetectedEntity() const;
+public:
+
+ //! Enables/disables building BVH for sensitives in separate threads
+ Standard_EXPORT void SetToPrebuildBVH(Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum = -1);
+
+ //! Queues a sensitive entity to build its BVH
+ Standard_EXPORT void QueueBVHBuild(const Handle(Select3D_SensitiveEntity)& theEntity);
+
+ //! Waits BVH threads finished building
+ Standard_EXPORT void WaitForBVHBuild();
+
+ //! Returns TRUE if building BVH for sensitives in separate threads is enabled
+ Standard_Boolean ToPrebuildBVH() const
+ {
+ return myToPrebuildBVH;
+ }
+
protected:
Standard_EXPORT SelectMgr_ViewerSelector();
gp_Dir myCameraDir;
Standard_Real myCameraScale;
+ Standard_Boolean myToPrebuildBVH;
+ Handle(SelectMgr_BVHThreadPool) myBVHThreadPool;
+
private:
Handle(TColStd_HArray1OfInteger) myIndexes;
const Handle(SelectMgr_EntityOwner)& anOwner = aSelEntIter.Value()->BaseSensitive()->OwnerId();
anOwner->SetSelectable (theSelectableObj);
}
-
- PreBuildBVH (theSelection);
}
//==================================================
#include <NCollection_LocalArray.hxx>
#include <NCollection_Vector.hxx>
#include <OSD.hxx>
+#include <OSD_Parallel.hxx>
#include <OSD_Timer.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <Prs3d_ShadingAspect.hxx>
return 0;
}
+//===============================================================================================
+//function : VBVHPrebuid
+//purpose :
+//===============================================================================================
+static int VSelBvhBuild (Draw_Interpretor& /*theDI*/, Standard_Integer theNbArgs, const char** theArgVec)
+{
+ const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+ if (aCtx.IsNull())
+ {
+ Message::SendFail ("Error: no active viewer");
+ return 1;
+ }
+
+ if (theNbArgs < 2)
+ {
+ Message::SendFail ("Error: command syntax is incorrect, see help");
+ return 1;
+ }
+
+ Standard_Integer toEnable = -1;
+ Standard_Integer aThreadsNb = -1;
+ Standard_Boolean toWait = Standard_False;
+
+ for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ anArg.LowerCase();
+
+ if (anArg == "-nbthreads"
+ && anArgIter + 1 < theNbArgs)
+ {
+ aThreadsNb = Draw::Atoi (theArgVec[++anArgIter]);
+ if (aThreadsNb < 1)
+ {
+ aThreadsNb = Max (1, OSD_Parallel::NbLogicalProcessors() - 1);
+ }
+ }
+ else if (anArg == "-wait")
+ {
+ toWait = Standard_True;
+ }
+ else if (toEnable == -1)
+ {
+ Standard_Boolean toEnableValue = Standard_True;
+ if (Draw::ParseOnOff (anArg.ToCString(), toEnableValue))
+ {
+ toEnable = toEnableValue ? 1 : 0;
+ }
+ else
+ {
+ Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
+ return 1;
+ }
+ }
+ else
+ {
+ Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
+ return 1;
+ }
+ }
+
+ if (aThreadsNb == -1)
+ {
+ aThreadsNb = 1;
+ }
+ if (toEnable != -1)
+ {
+ aCtx->MainSelector()->SetToPrebuildBVH (toEnable == 1, aThreadsNb);
+ }
+ if (toWait)
+ {
+ aCtx->MainSelector()->WaitForBVHBuild();
+ }
+
+ return 0;
+}
+
//=======================================================================
//function : ViewerCommands
//purpose :
theCommands.Add("vcolordiff" ,
"vcolordiff R1 G1 B1 R2 G2 B2: returns CIEDE2000 color difference between two RGB colors",
__FILE__,VColorDiff,group);
+ theCommands.Add("vselbvhbuild",
+ "vselbvhbuild [{0|1}] [-nbThreads value] [-wait]"
+ "\n\t\t: Turns on/off prebuilding of BVH within background thread(s)"
+ "\n\t\t: -nbThreads number of threads, 1 by default; if < 1 then used (NbLogicalProcessors - 1)"
+ "\n\t\t: -wait waits for building all of BVH",
+ __FILE__,VSelBvhBuild,group);
}
--- /dev/null
+puts "========"
+puts "OCC31757: Visualization - Prebuild BVH for Select3D_SensitiveEntity in separate threads"
+puts "========"
+
+vclear
+set aShape [locate_data_file occ/Motor-c.brep]
+restore $aShape s
+vdisplay s
+vfit
+vselbvhbuild 1 -nbThreads 1
+vselmode s FACE 1
+vselbvhbuild -wait
+vselect 0 0 512 512
+vdump $imagedir/${test_image}.png
\ No newline at end of file