Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:47:02

0001 // Created on: 2015-06-18
0002 // Created by: Anton POLETAEV
0003 // Copyright (c) 2015 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _Graphic3d_TransformPers_HeaderFile
0017 #define _Graphic3d_TransformPers_HeaderFile
0018 
0019 #include <Aspect_TypeOfTriedronPosition.hxx>
0020 #include <BVH_Box.hxx>
0021 #include <Graphic3d_Camera.hxx>
0022 #include <Graphic3d_TransformUtils.hxx>
0023 #include <Graphic3d_TransModeFlags.hxx>
0024 #include <Graphic3d_Vec.hxx>
0025 #include <NCollection_Mat4.hxx>
0026 
0027 DEFINE_STANDARD_HANDLE(Graphic3d_TransformPers, Standard_Transient)
0028 
0029 //! Transformation Persistence definition.
0030 //!
0031 //! Transformation Persistence defines a mutable Local Coordinate system which depends on camera position,
0032 //! so that visual appearance of the object becomes partially immutable while camera moves.
0033 //! Object visually preserves particular property such as size, placement, rotation or their combination.
0034 //!
0035 //! Graphic3d_TMF_ZoomPers, Graphic3d_TMF_RotatePers and Graphic3d_TMF_ZoomRotatePers define Local Coordinate system
0036 //! having origin in specified anchor point defined in World Coordinate system,
0037 //! while Graphic3d_TMF_TriedronPers and Graphic3d_TMF_2d define origin as 2D offset from screen corner in pixels.
0038 //!
0039 //! Graphic3d_TMF_2d, Graphic3d_TMF_TriedronPers and Graphic3d_TMF_ZoomPers defines Local Coordinate system where length units are pixels.
0040 //! Beware that Graphic3d_RenderingParams::ResolutionRatio() will be ignored!
0041 //! For other Persistence flags, normal (world) length units will apply.
0042 //!
0043 //! WARNING: Graphic3d_TMF_None is not permitted for defining instance of this class - NULL handle should be used for this purpose!
0044 class Graphic3d_TransformPers : public Standard_Transient
0045 {
0046   DEFINE_STANDARD_RTTIEXT(Graphic3d_TransformPers, Standard_Transient)
0047 public:
0048 
0049   //! Return true if specified mode is zoom/rotate transformation persistence.
0050   static Standard_Boolean IsZoomOrRotate (Graphic3d_TransModeFlags theMode)
0051   {
0052     return (theMode & (Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers)) != 0;
0053   }
0054 
0055   //! Return true if specified mode is 2d/trihedron transformation persistence.
0056   static Standard_Boolean IsTrihedronOr2d (Graphic3d_TransModeFlags theMode)
0057   {
0058     return (theMode & (Graphic3d_TMF_TriedronPers | Graphic3d_TMF_2d)) != 0;
0059   }
0060 
0061 public:
0062 
0063   //! Set transformation persistence.
0064   Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode)
0065   : myMode (theMode)
0066   {
0067     if (IsZoomOrRotate (theMode))
0068     {
0069       SetPersistence (theMode, gp_Pnt(0.0, 0.0, 0.0));
0070     }
0071     else if (IsTrihedronOr2d (theMode))
0072     {
0073       SetPersistence (theMode, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (0, 0));
0074     }
0075     else if (theMode == Graphic3d_TMF_CameraPers)
0076     {
0077       myMode = theMode;
0078     }
0079     else
0080     {
0081       throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
0082     }
0083   }
0084 
0085   //! Set Zoom/Rotate transformation persistence with an anchor 3D point.
0086   //! Anchor point defines the origin of Local Coordinate system within World Coordinate system.
0087   //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers.
0088   Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode,
0089                            const gp_Pnt& thePnt)
0090   : myMode (Graphic3d_TMF_None)
0091   {
0092     SetPersistence (theMode, thePnt);
0093   }
0094 
0095   //! Set 2d/trihedron transformation persistence with a corner and 2D offset.
0096   //! 2D offset defines the origin of Local Coordinate system as projection of 2D point on screen plane into World Coordinate system.
0097   //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d.
0098   //! The offset is a positive displacement from the view corner in pixels.
0099   Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode,
0100                            const Aspect_TypeOfTriedronPosition theCorner,
0101                            const Graphic3d_Vec2i& theOffset = Graphic3d_Vec2i (0, 0))
0102   : myMode (Graphic3d_TMF_None)
0103   {
0104     SetPersistence (theMode, theCorner, theOffset);
0105   }
0106 
0107   //! Return true for Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers modes.
0108   Standard_Boolean IsZoomOrRotate() const { return IsZoomOrRotate (myMode); }
0109 
0110   //! Return true for Graphic3d_TMF_TriedronPers and Graphic3d_TMF_2d modes.
0111   Standard_Boolean IsTrihedronOr2d() const { return IsTrihedronOr2d (myMode); }
0112 
0113   //! Transformation persistence mode flags.
0114   Graphic3d_TransModeFlags Mode() const { return myMode; }
0115 
0116   //! Transformation persistence mode flags.
0117   Graphic3d_TransModeFlags Flags() const { return myMode; }
0118 
0119   //! Set Zoom/Rotate transformation persistence with an anchor 3D point.
0120   //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers.
0121   void SetPersistence (const Graphic3d_TransModeFlags theMode,
0122                        const gp_Pnt& thePnt)
0123   {
0124     if (!IsZoomOrRotate (theMode))
0125     {
0126       throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
0127     }
0128 
0129     myMode = theMode;
0130     myParams.Params3d.PntX = thePnt.X();
0131     myParams.Params3d.PntY = thePnt.Y();
0132     myParams.Params3d.PntZ = thePnt.Z();
0133   }
0134 
0135   //! Set 2d/trihedron transformation persistence with a corner and 2D offset.
0136   //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d.
0137   void SetPersistence (const Graphic3d_TransModeFlags theMode,
0138                        const Aspect_TypeOfTriedronPosition theCorner,
0139                        const Graphic3d_Vec2i& theOffset)
0140   {
0141     if (!IsTrihedronOr2d (theMode))
0142     {
0143       throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
0144     }
0145 
0146     myMode = theMode;
0147     myParams.Params2d.Corner  = theCorner;
0148     myParams.Params2d.OffsetX = theOffset.x();
0149     myParams.Params2d.OffsetY = theOffset.y();
0150   }
0151 
0152 public:
0153 
0154   //! Return the anchor point for zoom/rotate transformation persistence.
0155   gp_Pnt AnchorPoint() const
0156   {
0157     if (!IsZoomOrRotate())
0158     {
0159       throw Standard_ProgramError("Graphic3d_TransformPers::AnchorPoint(), wrong persistence mode.");
0160     }
0161 
0162     return gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ);
0163   }
0164 
0165   //! Set the anchor point for zoom/rotate transformation persistence.
0166   void SetAnchorPoint (const gp_Pnt& thePnt)
0167   {
0168     if (!IsZoomOrRotate())
0169     {
0170       throw Standard_ProgramError("Graphic3d_TransformPers::SetAnchorPoint(), wrong persistence mode.");
0171     }
0172 
0173     myParams.Params3d.PntX = thePnt.X();
0174     myParams.Params3d.PntY = thePnt.Y();
0175     myParams.Params3d.PntZ = thePnt.Z();
0176   }
0177 
0178   //! Return the corner for 2d/trihedron transformation persistence.
0179   Aspect_TypeOfTriedronPosition Corner2d() const
0180   {
0181     if (!IsTrihedronOr2d())
0182     {
0183       throw Standard_ProgramError("Graphic3d_TransformPers::Corner2d(), wrong persistence mode.");
0184     }
0185 
0186     return myParams.Params2d.Corner;
0187   }
0188 
0189   //! Set the corner for 2d/trihedron transformation persistence.
0190   void SetCorner2d (const Aspect_TypeOfTriedronPosition thePos)
0191   {
0192     if (!IsTrihedronOr2d())
0193     {
0194       throw Standard_ProgramError("Graphic3d_TransformPers::SetCorner2d(), wrong persistence mode.");
0195     }
0196 
0197     myParams.Params2d.Corner = thePos;
0198   }
0199 
0200   //! Return the offset from the corner for 2d/trihedron transformation persistence.
0201   Graphic3d_Vec2i Offset2d() const
0202   {
0203     if (!IsTrihedronOr2d())
0204     {
0205       throw Standard_ProgramError("Graphic3d_TransformPers::Offset2d(), wrong persistence mode.");
0206     }
0207 
0208     return Graphic3d_Vec2i (myParams.Params2d.OffsetX, myParams.Params2d.OffsetY);
0209   }
0210 
0211   //! Set the offset from the corner for 2d/trihedron transformation persistence.
0212   void SetOffset2d (const Graphic3d_Vec2i& theOffset)
0213   {
0214     if (!IsTrihedronOr2d())
0215     {
0216       throw Standard_ProgramError("Graphic3d_TransformPers::SetOffset2d(), wrong persistence mode.");
0217     }
0218 
0219     myParams.Params2d.OffsetX = theOffset.x();
0220     myParams.Params2d.OffsetY = theOffset.y();
0221   }
0222 
0223 public:
0224 
0225   //! Find scale value based on the camera position and view dimensions
0226   //! @param theCamera [in] camera definition
0227   //! @param theViewportWidth [in] the width of viewport.
0228   //! @param theViewportHeight [in] the height of viewport.
0229   virtual Standard_Real persistentScale (const Handle(Graphic3d_Camera)& theCamera,
0230                                          const Standard_Integer theViewportWidth,
0231                                          const Standard_Integer theViewportHeight) const
0232   {
0233     (void )theViewportWidth;
0234     // use total size when tiling is active
0235     const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight;
0236 
0237     gp_Vec aVecToEye (theCamera->Direction());
0238     gp_Vec aVecToObj (theCamera->Eye(), gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ));
0239     const Standard_Real aFocus = aVecToObj.Dot (aVecToEye);
0240     const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
0241     return Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
0242   }
0243 
0244   //! Apply transformation to bounding box of presentation.
0245   //! @param theCamera [in] camera definition
0246   //! @param theProjection [in] the projection transformation matrix.
0247   //! @param theWorldView [in] the world view transformation matrix.
0248   //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
0249   //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
0250   //! @param theBoundingBox [in/out] the bounding box to transform.
0251   template<class T>
0252   void Apply (const Handle(Graphic3d_Camera)& theCamera,
0253               const NCollection_Mat4<T>& theProjection,
0254               const NCollection_Mat4<T>& theWorldView,
0255               const Standard_Integer theViewportWidth,
0256               const Standard_Integer theViewportHeight,
0257               Bnd_Box& theBoundingBox) const;
0258 
0259   //! Apply transformation to bounding box of presentation
0260   //! @param theCamera [in] camera definition
0261   //! @param theProjection [in] the projection transformation matrix.
0262   //! @param theWorldView [in] the world view transformation matrix.
0263   //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
0264   //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
0265   //! @param theBoundingBox [in/out] the bounding box to transform.
0266   template<class T>
0267   void Apply (const Handle(Graphic3d_Camera)& theCamera,
0268               const NCollection_Mat4<T>& theProjection,
0269               const NCollection_Mat4<T>& theWorldView,
0270               const Standard_Integer theViewportWidth,
0271               const Standard_Integer theViewportHeight,
0272               BVH_Box<T, 3>& theBoundingBox) const;
0273 
0274   //! Compute transformation.
0275   //! Computed matrix can be applied to model world transformation
0276   //! of an object to implement effect of transformation persistence.
0277   //! @param theCamera [in] camera definition
0278   //! @param theProjection [in] the projection transformation matrix.
0279   //! @param theWorldView [in] the world view transformation matrix.
0280   //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
0281   //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
0282   //! @return transformation matrix to be applied to model world transformation of an object.
0283   template<class T>
0284   NCollection_Mat4<T> Compute (const Handle(Graphic3d_Camera)& theCamera,
0285                                const NCollection_Mat4<T>& theProjection,
0286                                const NCollection_Mat4<T>& theWorldView,
0287                                const Standard_Integer theViewportWidth,
0288                                const Standard_Integer theViewportHeight) const;
0289 
0290   //! Apply transformation persistence on specified matrices.
0291   //! @param theCamera camera definition
0292   //! @param theProjection projection matrix to modify
0293   //! @param theWorldView  world-view matrix to modify
0294   //! @param theViewportWidth  viewport width
0295   //! @param theViewportHeight viewport height
0296   //! @param theAnchor if not NULL, overrides anchor point
0297   template<class T>
0298   void Apply (const Handle(Graphic3d_Camera)& theCamera,
0299               const NCollection_Mat4<T>& theProjection,
0300               NCollection_Mat4<T>& theWorldView,
0301               const Standard_Integer theViewportWidth,
0302               const Standard_Integer theViewportHeight,
0303               const gp_Pnt* theAnchor = NULL) const;
0304 
0305   //! Dumps the content of me into the stream
0306   Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
0307 
0308 private:
0309 
0310   //! 3D anchor point for zoom/rotate transformation persistence.
0311   struct PersParams3d
0312   {
0313     Standard_Real PntX;
0314     Standard_Real PntY;
0315     Standard_Real PntZ;
0316 
0317     //! Dumps the content of me into the stream
0318     Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
0319   };
0320 
0321   //! 2d/trihedron transformation persistence parameters.
0322   struct PersParams2d
0323   {
0324     Standard_Integer OffsetX;
0325     Standard_Integer OffsetY;
0326     Aspect_TypeOfTriedronPosition Corner;
0327 
0328     //! Dumps the content of me into the stream
0329     Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
0330   };
0331 
0332 private:
0333 
0334   Graphic3d_TransModeFlags myMode;  //!< Transformation persistence mode flags
0335   union
0336   {
0337     PersParams3d Params3d;
0338     PersParams2d Params2d;
0339   } myParams;
0340 
0341 };
0342 
0343 // =======================================================================
0344 // function : Apply
0345 // purpose  : Apply transformation to world view and projection matrices.
0346 // =======================================================================
0347 template<class T>
0348 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
0349                                      const NCollection_Mat4<T>& theProjection,
0350                                      NCollection_Mat4<T>& theWorldView,
0351                                      const Standard_Integer theViewportWidth,
0352                                      const Standard_Integer theViewportHeight,
0353                                      const gp_Pnt* theAnchor) const
0354 {
0355   (void )theViewportWidth;
0356   (void )theProjection;
0357   if (myMode == Graphic3d_TMF_None
0358    || theViewportHeight == 0)
0359   {
0360     return;
0361   }
0362 
0363   // use total size when tiling is active
0364   const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight;
0365 
0366   // a small enough jitter compensation offset
0367   // to avoid image dragging within single pixel in corner cases
0368   const Standard_Real aJitterComp = 0.001;
0369   if (myMode == Graphic3d_TMF_TriedronPers)
0370   {
0371     // reset Z focus for trihedron persistence
0372     const Standard_Real aFocus = theCamera->IsOrthographic()
0373                                ? theCamera->Distance()
0374                                : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
0375                                 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
0376                                 : Standard_Real(theCamera->ZFocus()));
0377 
0378     // scale factor to pixels
0379     const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
0380     const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
0381     const gp_Dir aForward = theCamera->Direction();
0382     gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance());
0383     if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
0384     {
0385       const Standard_Real anOffsetX = (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale;
0386       const gp_Dir aSide   = aForward.Crossed (theCamera->Up());
0387       const gp_XYZ aDeltaX = aSide.XYZ() * (Abs(aViewDim.X()) * theCamera->NDC2dOffsetX() - anOffsetX);
0388       if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0)
0389       {
0390         aCenter += aDeltaX;
0391       }
0392       else
0393       {
0394         aCenter -= aDeltaX;
0395       }
0396     }
0397     if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
0398     {
0399       const Standard_Real anOffsetY = (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale;
0400       const gp_XYZ aDeltaY = theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * theCamera->NDC2dOffsetY() - anOffsetY);
0401       if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0)
0402       {
0403         aCenter += aDeltaY;
0404       }
0405       else
0406       {
0407         aCenter -= aDeltaY;
0408       }
0409     }
0410 
0411     NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix();
0412     Graphic3d_TransformUtils::Translate (aWorldView, aCenter.X(), aCenter.Y(), aCenter.Z());
0413     Graphic3d_TransformUtils::Scale     (aWorldView, aScale,      aScale,      aScale);
0414     theWorldView.ConvertFrom (aWorldView);
0415     return;
0416   }
0417   else if (myMode == Graphic3d_TMF_2d)
0418   {
0419     const Standard_Real aFocus = theCamera->IsOrthographic()
0420                                ? theCamera->Distance()
0421                                : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
0422                                 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
0423                                 : Standard_Real(theCamera->ZFocus()));
0424 
0425     // scale factor to pixels
0426     const gp_XYZ        aViewDim = theCamera->ViewDimensions (aFocus);
0427     const Standard_Real aScale   = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
0428     gp_XYZ aCenter (0.0, 0.0, -aFocus);
0429     if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
0430     {
0431       aCenter.SetX (-aViewDim.X() * theCamera->NDC2dOffsetX() + (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale);
0432       if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0)
0433       {
0434         aCenter.SetX (-aCenter.X());
0435       }
0436     }
0437     if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
0438     {
0439       aCenter.SetY (-aViewDim.Y() * theCamera->NDC2dOffsetY() + (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale);
0440       if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0)
0441       {
0442         aCenter.SetY (-aCenter.Y());
0443       }
0444     }
0445 
0446     theWorldView.InitIdentity();
0447     Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z()));
0448     Graphic3d_TransformUtils::Scale     (theWorldView, T(aScale),      T(aScale),      T(aScale));
0449     return;
0450   }
0451   else if ((myMode & Graphic3d_TMF_CameraPers) != 0)
0452   {
0453     theWorldView.InitIdentity();
0454   }
0455   else
0456   {
0457     // Compute reference point for transformation in untransformed projection space.
0458     NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix();
0459     if (theAnchor != NULL)
0460     {
0461       Graphic3d_TransformUtils::Translate (aWorldView, theAnchor->X(), theAnchor->Y(), theAnchor->Z());
0462     }
0463     else
0464     {
0465       Graphic3d_TransformUtils::Translate (aWorldView, myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ);
0466     }
0467 
0468     if ((myMode & Graphic3d_TMF_RotatePers) != 0)
0469     {
0470       // lock rotation by nullifying rotation component
0471       aWorldView.SetValue (0, 0, 1.0);
0472       aWorldView.SetValue (1, 0, 0.0);
0473       aWorldView.SetValue (2, 0, 0.0);
0474 
0475       aWorldView.SetValue (0, 1, 0.0);
0476       aWorldView.SetValue (1, 1, 1.0);
0477       aWorldView.SetValue (2, 1, 0.0);
0478 
0479       aWorldView.SetValue (0, 2, 0.0);
0480       aWorldView.SetValue (1, 2, 0.0);
0481       aWorldView.SetValue (2, 2, 1.0);
0482     }
0483 
0484     if ((myMode & Graphic3d_TMF_ZoomPers) != 0)
0485     {
0486       // lock zooming
0487       Standard_Real aScale = persistentScale (theCamera, theViewportWidth, theViewportHeight);
0488       Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale);
0489     }
0490     theWorldView.ConvertFrom (aWorldView);
0491     return;
0492   }
0493 }
0494 
0495 // =======================================================================
0496 // function : Apply
0497 // purpose  : Apply transformation to bounding box of presentation.
0498 // =======================================================================
0499 template<class T>
0500 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
0501                                      const NCollection_Mat4<T>& theProjection,
0502                                      const NCollection_Mat4<T>& theWorldView,
0503                                      const Standard_Integer theViewportWidth,
0504                                      const Standard_Integer theViewportHeight,
0505                                      Bnd_Box& theBoundingBox) const
0506 {
0507   if (theBoundingBox.IsVoid())
0508   {
0509     return;
0510   }
0511 
0512   T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
0513 
0514   theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
0515 
0516   typename BVH_Box<T, 3>::BVH_VecNt aMin (aXmin, aYmin, aZmin);
0517   typename BVH_Box<T, 3>::BVH_VecNt aMax (aXmax, aYmax, aZmax);
0518   BVH_Box<T, 3> aBBox (aMin, aMax);
0519 
0520   Apply (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox);
0521 
0522   theBoundingBox = Bnd_Box();
0523   theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(),
0524                          aBBox.CornerMax().x(), aBBox.CornerMax().y(), aBBox.CornerMax().z());
0525 }
0526 
0527 // =======================================================================
0528 // function : Apply
0529 // purpose  : Apply transformation to bounding box of presentation.
0530 // =======================================================================
0531 template<class T>
0532 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
0533                                      const NCollection_Mat4<T>& theProjection,
0534                                      const NCollection_Mat4<T>& theWorldView,
0535                                      const Standard_Integer theViewportWidth,
0536                                      const Standard_Integer theViewportHeight,
0537                                      BVH_Box<T, 3>& theBoundingBox) const
0538 {
0539   NCollection_Mat4<T> aTPers = Compute (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight);
0540   if (aTPers.IsIdentity()
0541   || !theBoundingBox.IsValid())
0542   {
0543     return;
0544   }
0545 
0546   const typename BVH_Box<T, 3>::BVH_VecNt& aMin = theBoundingBox.CornerMin();
0547   const typename BVH_Box<T, 3>::BVH_VecNt& aMax = theBoundingBox.CornerMax();
0548 
0549   typename BVH_Box<T, 4>::BVH_VecNt anArrayOfCorners[8];
0550   anArrayOfCorners[0] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
0551   anArrayOfCorners[1] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
0552   anArrayOfCorners[2] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
0553   anArrayOfCorners[3] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
0554   anArrayOfCorners[4] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
0555   anArrayOfCorners[5] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
0556   anArrayOfCorners[6] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
0557   anArrayOfCorners[7] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
0558 
0559   theBoundingBox.Clear();
0560   for (Standard_Integer anIt = 0; anIt < 8; ++anIt)
0561   {
0562     typename BVH_Box<T, 4>::BVH_VecNt& aCorner = anArrayOfCorners[anIt];
0563     aCorner  = aTPers * aCorner;
0564     aCorner = aCorner / aCorner.w();
0565     theBoundingBox.Add (typename BVH_Box<T, 3>::BVH_VecNt (aCorner.x(), aCorner.y(), aCorner.z()));
0566   }
0567 }
0568 
0569 // =======================================================================
0570 // function : Compute
0571 // purpose  : Compute transformation.
0572 // =======================================================================
0573 template<class T>
0574 NCollection_Mat4<T> Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Camera)& theCamera,
0575                                                       const NCollection_Mat4<T>& theProjection,
0576                                                       const NCollection_Mat4<T>& theWorldView,
0577                                                       const Standard_Integer theViewportWidth,
0578                                                       const Standard_Integer theViewportHeight) const
0579 {
0580   if (myMode == Graphic3d_TMF_None)
0581   {
0582     return NCollection_Mat4<T>();
0583   }
0584 
0585   NCollection_Mat4<T> aWorldView (theWorldView);
0586   NCollection_Mat4<T> anUnviewMat;
0587   if (!theWorldView.Inverted (anUnviewMat))
0588   {
0589     return NCollection_Mat4<T>();
0590   }
0591 
0592   // compute only world-view matrix difference to avoid floating point instability
0593   // caused by projection matrix modifications outside of this algorithm (e.g. by Z-fit)
0594   Apply (theCamera, theProjection, aWorldView, theViewportWidth, theViewportHeight);
0595   return anUnviewMat * aWorldView;
0596 }
0597 
0598 #endif // _Graphic3d_TransformPers_HeaderFile