Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/opencascade/Graphic3d_Flipper.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (c) 2024 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013 
0014 #ifndef _Graphic3d_Flipper_HeaderFile
0015 #define _Graphic3d_Flipper_HeaderFile
0016 
0017 #include <BVH_Box.hxx>
0018 #include <Bnd_Box.hxx>
0019 #include <NCollection_Mat4.hxx>
0020 #include <Standard_Transient.hxx>
0021 #include <gp_Ax2.hxx>
0022 
0023 //! CPU-side analogue of OpenGl_Flipper used by the selection pipeline.
0024 //! Describes a reference coordinate system used at draw time to mirror
0025 //! group contents so that they remain upright relative to the camera.
0026 //! The same logic is used here to compute the flipping matrix applied
0027 //! to bounding boxes and sensitive frustums, so that selection matches
0028 //! the rendered geometry.
0029 class Graphic3d_Flipper : public Standard_Transient
0030 {
0031   DEFINE_STANDARD_RTTIEXT(Graphic3d_Flipper, Standard_Transient)
0032 
0033 public:
0034   //! Constructor.
0035   Graphic3d_Flipper(const gp_Ax2& theRefPlane)
0036       : myRefPlane(theRefPlane)
0037   {
0038   }
0039 
0040   //! Return reference plane used for flipping.
0041   gp_Ax2 RefPlane() const { return myRefPlane; }
0042 
0043   //! Set reference plane used for flipping.
0044   void SetRefPlane(const gp_Ax2& theValue) { myRefPlane = theValue; }
0045 
0046   //! Apply flipping transformation to a Bnd_Box of presentation.
0047   //! @param theWorldView   [in]     the world view transformation matrix
0048   //! @param theBoundingBox [in,out] the bounding box to transform
0049   template <class T>
0050   void Apply(const NCollection_Mat4<T>& theWorldView, Bnd_Box& theBoundingBox) const;
0051 
0052   //! Apply flipping transformation to a BVH_Box of presentation.
0053   //! @param theWorldView   [in]     the world view transformation matrix
0054   //! @param theBoundingBox [in,out] the bounding box to transform
0055   template <class T>
0056   void Apply(const NCollection_Mat4<T>& theWorldView, BVH_Box<T, 3>& theBoundingBox) const;
0057 
0058   //! Compute the flipping transformation matrix.
0059   //! The returned matrix can be composed with the model-world transformation
0060   //! of an object to reproduce the render-time flip. Note: each branch of
0061   //! the flip is a 180 degree rotation (self-inverse), so the returned matrix
0062   //! is its own inverse.
0063   //! @param theWorldView [in] the composed World-View * ModelWorld matrix that
0064   //!                          the caller would use at draw time. To agree with
0065   //!                          OpenGl_Flipper::Render() the caller must include
0066   //!                          the owning object's Transformation() and, when
0067   //!                          available, the flipping group's own
0068   //!                          Transformation(). Passing the bare WorldView
0069   //!                          matrix is only correct for objects/groups with
0070   //!                          identity transformations.
0071   //! TODO: group-level Graphic3d_Group::Transformation() is not folded in by
0072   //! the selection pipeline yet (the sensitive entity does not carry a
0073   //! reference to its host group). This only affects consumers that give the
0074   //! flipping group its own gp_Trsf - uncommon in stock OCCT.
0075   template <class T>
0076   NCollection_Mat4<T> Compute(const NCollection_Mat4<T>& theWorldView) const;
0077 
0078   //! Dumps the content of me into the stream.
0079   Standard_EXPORT virtual void DumpJson(Standard_OStream& theOStream, int theDepth = -1) const;
0080 
0081 private:
0082   gp_Ax2 myRefPlane;
0083 };
0084 
0085 //=================================================================================================
0086 
0087 template <class T>
0088 void Graphic3d_Flipper::Apply(const NCollection_Mat4<T>& theWorldView,
0089                               Bnd_Box&                   theBoundingBox) const
0090 {
0091   if (theBoundingBox.IsVoid())
0092   {
0093     return;
0094   }
0095 
0096   T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
0097   theBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
0098 
0099   typename BVH_Box<T, 3>::BVH_VecNt aMin(aXmin, aYmin, aZmin);
0100   typename BVH_Box<T, 3>::BVH_VecNt aMax(aXmax, aYmax, aZmax);
0101   BVH_Box<T, 3>                     aBBox(aMin, aMax);
0102 
0103   Apply(theWorldView, aBBox);
0104 
0105   theBoundingBox = Bnd_Box();
0106   theBoundingBox.Update(aBBox.CornerMin().x(),
0107                         aBBox.CornerMin().y(),
0108                         aBBox.CornerMin().z(),
0109                         aBBox.CornerMax().x(),
0110                         aBBox.CornerMax().y(),
0111                         aBBox.CornerMax().z());
0112 }
0113 
0114 //=================================================================================================
0115 
0116 template <class T>
0117 void Graphic3d_Flipper::Apply(const NCollection_Mat4<T>& theWorldView,
0118                               BVH_Box<T, 3>&             theBoundingBox) const
0119 {
0120   NCollection_Mat4<T> aTPers = Compute(theWorldView);
0121   if (aTPers.IsIdentity() || !theBoundingBox.IsValid())
0122   {
0123     return;
0124   }
0125 
0126   const typename BVH_Box<T, 3>::BVH_VecNt& aMin = theBoundingBox.CornerMin();
0127   const typename BVH_Box<T, 3>::BVH_VecNt& aMax = theBoundingBox.CornerMax();
0128 
0129   typename BVH_Box<T, 4>::BVH_VecNt anArrayOfCorners[8];
0130   anArrayOfCorners[0] =
0131     typename BVH_Box<T, 4>::BVH_VecNt(aMin.x(), aMin.y(), aMin.z(), static_cast<T>(1.0));
0132   anArrayOfCorners[1] =
0133     typename BVH_Box<T, 4>::BVH_VecNt(aMin.x(), aMin.y(), aMax.z(), static_cast<T>(1.0));
0134   anArrayOfCorners[2] =
0135     typename BVH_Box<T, 4>::BVH_VecNt(aMin.x(), aMax.y(), aMin.z(), static_cast<T>(1.0));
0136   anArrayOfCorners[3] =
0137     typename BVH_Box<T, 4>::BVH_VecNt(aMin.x(), aMax.y(), aMax.z(), static_cast<T>(1.0));
0138   anArrayOfCorners[4] =
0139     typename BVH_Box<T, 4>::BVH_VecNt(aMax.x(), aMin.y(), aMin.z(), static_cast<T>(1.0));
0140   anArrayOfCorners[5] =
0141     typename BVH_Box<T, 4>::BVH_VecNt(aMax.x(), aMin.y(), aMax.z(), static_cast<T>(1.0));
0142   anArrayOfCorners[6] =
0143     typename BVH_Box<T, 4>::BVH_VecNt(aMax.x(), aMax.y(), aMin.z(), static_cast<T>(1.0));
0144   anArrayOfCorners[7] =
0145     typename BVH_Box<T, 4>::BVH_VecNt(aMax.x(), aMax.y(), aMax.z(), static_cast<T>(1.0));
0146 
0147   theBoundingBox.Clear();
0148   for (int anIt = 0; anIt < 8; ++anIt)
0149   {
0150     typename BVH_Box<T, 4>::BVH_VecNt& aCorner = anArrayOfCorners[anIt];
0151     aCorner                                    = aTPers * aCorner;
0152     aCorner                                    = aCorner / aCorner.w();
0153     theBoundingBox.Add(typename BVH_Box<T, 3>::BVH_VecNt(aCorner.x(), aCorner.y(), aCorner.z()));
0154   }
0155 }
0156 
0157 //=================================================================================================
0158 
0159 template <class T>
0160 NCollection_Mat4<T> Graphic3d_Flipper::Compute(const NCollection_Mat4<T>& theWorldView) const
0161 {
0162   NCollection_Vec4<T> aReferenceOrigin(static_cast<T>(myRefPlane.Location().X()),
0163                                        static_cast<T>(myRefPlane.Location().Y()),
0164                                        static_cast<T>(myRefPlane.Location().Z()),
0165                                        static_cast<T>(1));
0166   NCollection_Vec4<T> aReferenceX(static_cast<T>(myRefPlane.XDirection().X()),
0167                                   static_cast<T>(myRefPlane.XDirection().Y()),
0168                                   static_cast<T>(myRefPlane.XDirection().Z()),
0169                                   static_cast<T>(1));
0170   NCollection_Vec4<T> aReferenceY(static_cast<T>(myRefPlane.YDirection().X()),
0171                                   static_cast<T>(myRefPlane.YDirection().Y()),
0172                                   static_cast<T>(myRefPlane.YDirection().Z()),
0173                                   static_cast<T>(1));
0174   NCollection_Vec4<T> aReferenceZ(static_cast<T>(myRefPlane.Axis().Direction().X()),
0175                                   static_cast<T>(myRefPlane.Axis().Direction().Y()),
0176                                   static_cast<T>(myRefPlane.Axis().Direction().Z()),
0177                                   static_cast<T>(1));
0178 
0179   NCollection_Mat4<T> aMatrixMV;
0180   aMatrixMV.Convert(theWorldView);
0181 
0182   const NCollection_Vec4<T> aMVReferenceOrigin = aMatrixMV * aReferenceOrigin;
0183   const NCollection_Vec4<T> aMVReferenceX =
0184     aMatrixMV * NCollection_Vec4<T>(aReferenceX.xyz() + aReferenceOrigin.xyz(), static_cast<T>(1));
0185   const NCollection_Vec4<T> aMVReferenceY =
0186     aMatrixMV * NCollection_Vec4<T>(aReferenceY.xyz() + aReferenceOrigin.xyz(), static_cast<T>(1));
0187   const NCollection_Vec4<T> aMVReferenceZ =
0188     aMatrixMV * NCollection_Vec4<T>(aReferenceZ.xyz() + aReferenceOrigin.xyz(), static_cast<T>(1));
0189 
0190   const NCollection_Vec4<T> aDirX = aMVReferenceX - aMVReferenceOrigin;
0191   const NCollection_Vec4<T> aDirY = aMVReferenceY - aMVReferenceOrigin;
0192   const NCollection_Vec4<T> aDirZ = aMVReferenceZ - aMVReferenceOrigin;
0193 
0194   const bool isReversedX = aDirX.xyz().Dot(NCollection_Vec3<T>::DX()) < static_cast<T>(0);
0195   const bool isReversedY = aDirY.xyz().Dot(NCollection_Vec3<T>::DY()) < static_cast<T>(0);
0196   const bool isReversedZ = aDirZ.xyz().Dot(NCollection_Vec3<T>::DZ()) < static_cast<T>(0);
0197 
0198   NCollection_Mat4<T> aTransform;
0199   if ((isReversedX || isReversedY) && !isReversedZ)
0200   {
0201     // invert by Z axis: left, up vectors mirrored
0202     aTransform.SetColumn(0, -aTransform.GetColumn(0).xyz());
0203     aTransform.SetColumn(1, -aTransform.GetColumn(1).xyz());
0204   }
0205   else if (isReversedY && isReversedZ)
0206   {
0207     // rotate by X axis: up, forward vectors mirrored
0208     aTransform.SetColumn(1, -aTransform.GetColumn(1).xyz());
0209     aTransform.SetColumn(2, -aTransform.GetColumn(2).xyz());
0210   }
0211   else if (isReversedZ)
0212   {
0213     // rotate by Y axis: left, forward vectors mirrored
0214     aTransform.SetColumn(0, -aTransform.GetColumn(0).xyz());
0215     aTransform.SetColumn(2, -aTransform.GetColumn(2).xyz());
0216   }
0217   else
0218   {
0219     return NCollection_Mat4<T>();
0220   }
0221 
0222   NCollection_Mat4<T> aRefAxes;
0223   NCollection_Mat4<T> aRefInv;
0224   aRefAxes.SetColumn(0, aReferenceX.xyz());
0225   aRefAxes.SetColumn(1, aReferenceY.xyz());
0226   aRefAxes.SetColumn(2, aReferenceZ.xyz());
0227   aRefAxes.SetColumn(3, aReferenceOrigin.xyz());
0228   aRefAxes.Inverted(aRefInv);
0229 
0230   aTransform = aRefAxes * aTransform * aRefInv;
0231   return aTransform;
0232 }
0233 
0234 #endif // _Graphic3d_Flipper_HeaderFile