mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-10 17:40:24 +08:00
Selection was broken for presentations that used Graphic3d_Group::SetFlippingOptions (AIS_TextLabel, PrsDim_Dimension): OpenGl_Flipper mirrors the geometry at draw time to keep labels upright relative to the camera, but the selection pipeline computed BVH boxes and sensitive frustums in the unflipped local coordinates. When the camera was rotated past the flipping threshold, clicks on the on-screen label missed. - Add Graphic3d_Flipper: a CPU-side analogue of OpenGl_Flipper carrying the reference plane and templated Compute()/Apply() that reproduces the render-time flip matrix. Each flip branch is a 180 deg rotation (involution), so the matrix is self-inverse. - Extend Graphic3d_CStructure with HasGroupFlipping()/SetGroupFlipping() alongside the existing transform-persistence flag; reset it in Graphic3d_Structure::clear(). - Add Graphic3d_Group::Flipper() and a myFlipper member populated from OpenGl_Group::SetFlippingOptions(true,...). The render-side OpenGl_Flipper element is still emitted for the push/pop bracket; myFlipper persists across the matching SetFlippingOptions(false,...) call so the selection side can see that the group contains flipped geometry. - Add Select3D_SensitiveEntity::Flipper() / SetFlippingOptions() so sensitive entities can carry the same flipping metadata used by the selection traversal; include the handle in DumpJson. - SelectMgr_SensitiveEntitySet tracks myNbEntityWithFlipping in Append()/Remove(); HasEntityWithFlipping() exposes it to the viewer selector. - SelectMgr_SelectableObjectSet::appropriateSubset() routes presentations with HasGroupFlipping() to the 3d-persistent BVH subset (same as transform persistence). - BVHBuilderAdaptorPersistent merges the flipping and transform-persistence loops into a single pass: for each group with a Flipper or TransformPersistence, build its local bbox, apply the flip (if any), then apply the TransformPersistence (if any), then add the resulting box to the object bbox; object-level TransformPersistence is applied once to the merged box. Note: for the rare case of object-level + group-level TransformPersistence the application order differs from the prior code (object-TP now runs after group-TP contributions are added). Common cases (only one or the other) are behavior-preserving. - SelectMgr_ViewerSelector::traverseObject() bypasses the root/per-node overlap early-outs when the entity set contains flipped sensitives, and folds the flip matrix into aInvFlippingAndPers = T_flip * aInvSensTrsf before computeFrustum() and checkOverlap(). Using T_flip directly is valid because it is self-inverse. Before Compute(), the object's Transformation() is folded into aMVForFlip via Graphic3d_TransformUtils::Convert<double> so the isReversedX/Y/Z decision agrees with OpenGl_Flipper::Render() which uses WorldView * ModelWorld. - SelectMgr_SelectableObjectSet::BVHBuilderAdaptorPersistent computes the same aMVForFlip once per object (hoisted outside the group loop) and passes it to Graphic3d_Flipper::Apply, so BVH bounds and per-sensitive overlap testing use the same flip matrix. - SelectMgr::ComputeSensitivePrs() forwards the flipper to the debug presentation's current group so selection-mode visualization reflects the flip. Known limitation (narrowed): the selection pipeline now folds the object's Transformation() into the MV passed to Graphic3d_Flipper::Compute, covering the common case of a flipping label on a rotated assembly. Group-level Graphic3d_Group::Transformation() is still not folded in on the selection side because the sensitive entity does not carry a reference to its host group; this only affects consumers that give the flipping group its own non-identity gp_Trsf (uncommon in stock OCCT). A TODO in Graphic3d_Flipper::Compute and SelectMgr_ViewerSelector marks the deferred follow-up.