Graphic3d_BndBox4f aBnd;
for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myCStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
{
+ if (!aGroupIter.Value()->TransformPersistence().IsNull())
+ {
+ continue;
+ }
aBnd.Combine (aGroupIter.Value()->BoundingBox());
}
return aBnd;
#include <SelectMgr_SelectingVolumeManager.hxx>
#include <TopLoc_Location.hxx>
+class Graphic3d_TransformPers;
class SelectMgr_EntityOwner;
//! Abstract framework to define 3D sensitive entities.
//! Otherwise, returns identity matrix.
virtual gp_GTrsf InvInitLocation() const { return gp_GTrsf(); }
+ //! Return transformation persistence.
+ const Handle(Graphic3d_TransformPers)& TransformPersistence() const { return myTrsfPers; }
+
+ //! Set transformation persistence.
+ virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) { myTrsfPers = theTrsfPers; }
+
//! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
protected:
Handle(SelectMgr_EntityOwner) myOwnerId;
+ Handle(Graphic3d_TransformPers) myTrsfPers;
Standard_Integer mySFactor;
};
Bnd_Box aBoundingBox;
anObject->BoundingBox (aBoundingBox);
- if (aBoundingBox.IsVoid()
- || anObject->TransformPersistence().IsNull())
+ if (!aBoundingBox.IsVoid()
+ && !anObject->TransformPersistence().IsNull())
+ {
+ anObject->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox);
+ }
+ // processing presentations with own transform persistence
+ PrsMgr_Presentations& aPresentations = anObject->Presentations();
+ for (PrsMgr_Presentations::Iterator aPrsIter (aPresentations); aPrsIter.More(); aPrsIter.Next())
+ {
+ const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.ChangeValue();
+ for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPrs3d->Groups()); aGroupIter.More(); aGroupIter.Next())
+ {
+ if (!aGroupIter.Value()->TransformPersistence().IsNull())
+ {
+ const Graphic3d_BndBox4f& aBndBox = aGroupIter.Value()->BoundingBox();
+ if (!aBndBox.IsValid())
+ {
+ continue;
+ }
+ Bnd_Box aGroupBoundingBox;
+ aGroupBoundingBox.Update (aBndBox.CornerMin().x(), aBndBox.CornerMin().y(), aBndBox.CornerMin().z(),
+ aBndBox.CornerMax().x(), aBndBox.CornerMax().y(), aBndBox.CornerMax().z());
+ aGroupIter.Value()->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aGroupBoundingBox);
+
+ const gp_Pnt aMin = aGroupBoundingBox.CornerMin();
+ const gp_Pnt aMax = aGroupBoundingBox.CornerMax();
+ aBoundingBox.Add (aGroupBoundingBox);
+ }
+ }
+ }
+
+ if (aBoundingBox.IsVoid())
{
myBoundings.Add (new Select3D_HBndBox3d());
}
else
{
- anObject->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox);
-
const gp_Pnt aMin = aBoundingBox.CornerMin();
const gp_Pnt aMax = aBoundingBox.CornerMax();
myBoundings.Add (new Select3D_HBndBox3d (Select3D_Vec3 (aMin.X(), aMin.Y(), aMin.Z()),
{
if (theObject->TransformPersistence().IsNull())
{
+ PrsMgr_Presentations& aPresentations = theObject->Presentations();
+ for (PrsMgr_Presentations::Iterator aPrsIter (aPresentations); aPrsIter.More(); aPrsIter.Next())
+ {
+ const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.ChangeValue();
+ for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPrs3d->Groups()); aGroupIter.More(); aGroupIter.Next())
+ {
+ if (!aGroupIter.Value()->TransformPersistence().IsNull())
+ {
+ return SelectMgr_SelectableObjectSet::BVHSubset_3dPersistent;
+ }
+ }
+ }
return SelectMgr_SelectableObjectSet::BVHSubset_3d;
}
else if (theObject->TransformPersistence()->Mode() == Graphic3d_TMF_2d)
#include <SelectMgr_SensitiveEntitySet.hxx>
+#include <Graphic3d_TransformPers.hxx>
#include <Select3D_SensitiveEntity.hxx>
#include <SelectMgr_SensitiveEntity.hxx>
IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_SensitiveEntitySet, BVH_PrimitiveSet3d)
+class SelectMgr_AdaptorPersistent : public Standard_Transient
+{
+ DEFINE_STANDARD_RTTIEXT(SelectMgr_AdaptorPersistent, Standard_Transient)
+public:
+ SelectMgr_AdaptorPersistent(const Handle(Graphic3d_Camera)& theCamera,
+ const Graphic3d_Mat4d& theProjectionMat,
+ const Graphic3d_Mat4d& theWorldViewMat,
+ const Graphic3d_WorldViewProjState& theViewState,
+ const Standard_Integer theViewportWidth,
+ const Standard_Integer theViewportHeight)
+ : myCamera (theCamera), myProjectionMat (theProjectionMat),
+ myWorldViewMat (theWorldViewMat), myViewState (theViewState),
+ myViewportWidth (theViewportWidth), myViewportHeight (theViewportHeight) {}
+
+ const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
+ const Graphic3d_Mat4d& ProjectionMat() const { return myProjectionMat; }
+ const Graphic3d_Mat4d& WorldViewMat() const { return myWorldViewMat; }
+ const Graphic3d_WorldViewProjState& ViewState() const { return myViewState; }
+ Standard_Integer ViewportWidth() const { return myViewportWidth; }
+ Standard_Integer ViewportHeight() const { return myViewportHeight; }
+
+private:
+ Handle(Graphic3d_Camera) myCamera;
+ Graphic3d_Mat4d myProjectionMat;
+ Graphic3d_Mat4d myWorldViewMat;
+ Graphic3d_WorldViewProjState myViewState;
+ Standard_Integer myViewportWidth;
+ Standard_Integer myViewportHeight;
+};
+
+DEFINE_STANDARD_HANDLE(SelectMgr_AdaptorPersistent, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_AdaptorPersistent, Standard_Transient)
+
//=======================================================================
// function : SelectMgr_SensitiveEntitySet
// purpose :
{
addOwner (theEntity->BaseSensitive()->OwnerId());
}
+ mySensitives.Add (theEntity);
+ if (!theEntity->BaseSensitive()->TransformPersistence().IsNull())
+ {
+ myHasEntityWithPersistence = Standard_True;
+ }
MarkDirty();
}
{
addOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId());
}
+ mySensitives.Add (aSelEntIter.Value());
+ if (!aSelEntIter.Value()->BaseSensitive()->TransformPersistence().IsNull())
+ {
+ myHasEntityWithPersistence = Standard_True;
+ }
}
MarkDirty();
}
mySensitives.RemoveLast();
removeOwner (aSelEntIter.Value()->BaseSensitive()->OwnerId());
+ // TODO: update myHasEntityWithPersistence state, clear myAdaptorPersistent if false
}
MarkDirty();
//=======================================================================
Select3D_BndBox3d SelectMgr_SensitiveEntitySet::Box (const Standard_Integer theIndex) const
{
- return GetSensitiveById (theIndex)->BaseSensitive()->BoundingBox();
+ const Handle(Select3D_SensitiveEntity)& aSensitive = GetSensitiveById (theIndex)->BaseSensitive();
+ if (aSensitive->TransformPersistence().IsNull() || myAdaptorPersistent.IsNull())
+ {
+ return GetSensitiveById (theIndex)->BaseSensitive()->BoundingBox();
+ }
+
+ Select3D_BndBox3d aSensitiveBndBox = GetSensitiveById (theIndex)->BaseSensitive()->BoundingBox();
+ Select3D_BndBox3d aBndBoxInPersistence;
+
+ Bnd_Box aBndBox (
+ gp_Pnt (aSensitiveBndBox.CornerMin().x(), aSensitiveBndBox.CornerMin().y(), aSensitiveBndBox.CornerMin().z()),
+ gp_Pnt (aSensitiveBndBox.CornerMax().x(), aSensitiveBndBox.CornerMin().y(), aSensitiveBndBox.CornerMin().z()));
+
+ aSensitive->TransformPersistence()->Apply (
+ myAdaptorPersistent->Camera(),
+ myAdaptorPersistent->ProjectionMat(),
+ myAdaptorPersistent->WorldViewMat(),
+ myAdaptorPersistent->ViewportWidth(),
+ myAdaptorPersistent->ViewportHeight(),
+ aBndBox);
+
+ gp_Pnt aBndBoxMin = aBndBox.CornerMin();
+ gp_Pnt aBndBoxMax = aBndBox.CornerMax();
+ return Select3D_BndBox3d (SelectMgr_Vec3 (aBndBoxMin.X(), aBndBoxMin.Y(), aBndBoxMin.Z()),
+ SelectMgr_Vec3 (aBndBoxMax.X(), aBndBoxMax.Y(), aBndBoxMax.Z()));
}
//=======================================================================
}
}
}
+
+//=======================================================================
+// function : UpdateBVH
+// purpose :
+//=======================================================================
+void SelectMgr_SensitiveEntitySet::UpdateBVH (const Handle(Graphic3d_Camera)& theCamera,
+ const Graphic3d_Mat4d& theProjectionMat,
+ const Graphic3d_Mat4d& theWorldViewMat,
+ const Graphic3d_WorldViewProjState& theViewState,
+ const Standard_Integer theViewportWidth,
+ const Standard_Integer theViewportHeight)
+{
+ if (!myHasEntityWithPersistence)
+ {
+ return;
+ }
+ myAdaptorPersistent = new SelectMgr_AdaptorPersistent(theCamera, theProjectionMat,
+ theWorldViewMat,
+ theViewState,
+ theViewportWidth,
+ theViewportHeight);
+
+ MarkDirty();
+ BVH();
+ myAdaptorPersistent.Nullify();
+}
#include <SelectMgr_SensitiveEntity.hxx>
#include <SelectMgr_Selection.hxx>
+class SelectMgr_AdaptorPersistent;
+
typedef NCollection_IndexedMap<Handle(SelectMgr_SensitiveEntity)> SelectMgr_IndexedMapOfHSensitive;
typedef NCollection_DataMap<Handle(SelectMgr_EntityOwner), Standard_Integer> SelectMgr_MapOfOwners;
//! Returns map of owners.
const SelectMgr_MapOfOwners& Owners() const { return myOwnersMap; }
+ //! Returns map of entities.
+ Standard_EXPORT Standard_Boolean HasEntityWithPersistence() const { return myHasEntityWithPersistence; }
+
+ //! Updates outdated BVH trees and remembers the last state of the
+ //! camera view-projection matrices and viewport (window) dimensions.
+ Standard_EXPORT void UpdateBVH (const Handle(Graphic3d_Camera)& theCamera,
+ const Graphic3d_Mat4d& theProjectionMat,
+ const Graphic3d_Mat4d& theWorldViewMat,
+ const Graphic3d_WorldViewProjState& theViewState,
+ const Standard_Integer theViewportWidth,
+ const Standard_Integer theViewportHeight);
+
protected:
//! Adds entity owner to the map of owners (or increases its counter if it is already there).
SelectMgr_IndexedMapOfHSensitive mySensitives; //!< Map of entities and its corresponding index in BVH
SelectMgr_MapOfOwners myOwnersMap; //!< Map of entity owners and its corresponding number of sensitives
+ Handle(SelectMgr_AdaptorPersistent) myAdaptorPersistent; //!< camera parameters to apply transform persistence
+ Standard_Boolean myHasEntityWithPersistence; //!< flag if some of sensitive entity has own transform persistence
};
#endif // _SelectMgr_SensitiveEntitySet_HeaderFile
return;
}
+ if (anEntitySet->HasEntityWithPersistence())
+ {
+ Standard_Integer aWidth;
+ Standard_Integer aHeight;
+ mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
+ anEntitySet->UpdateBVH (mySelectingVolumeMgr.Camera(),
+ mySelectingVolumeMgr.ProjectionMatrix(),
+ mySelectingVolumeMgr.WorldViewMatrix(),
+ mySelectingVolumeMgr.WorldViewProjState(),
+ aWidth, aHeight);
+ }
const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
gp_GTrsf aInversedTrsf;
if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
: theMgr;
- if (!aMgr.Overlaps (aSensitivesTree->MinPoint (0),
+ if (!anEntitySet->HasEntityWithPersistence()
+ && !aMgr.Overlaps (aSensitivesTree->MinPoint (0),
aSensitivesTree->MaxPoint (0)))
{
return;
const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
if (aSensitive->IsActiveForSelection())
{
+ gp_GTrsf aInversedTrsf_;
+ if (aSensitive->BaseSensitive()->TransformPersistence().IsNull())
+ {
+ aInversedTrsf_ = aInversedTrsf;
+ }
+ else
+ {
+ gp_GTrsf aTPers;
+ Graphic3d_Mat4d aMat = aSensitive->BaseSensitive()->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
+
+ aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
+ aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
+ aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
+ aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
+ aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
+ aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
+ aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
+ aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
+ aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
+ aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
+
+ aInversedTrsf_ = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
+ }
+
const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
- computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
- checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
+ computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf_, aScaledTrnsfFrustums, aTmpMgr);
+ checkOverlap (anEnt, aInversedTrsf_, aTmpMgr);
}
}
}