0031511: Point Cloud Rendering, Volume Rendering - reuse Graphic3d_CullingTool
[occt.git] / src / Graphic3d / Graphic3d_TransformPers.hxx
1 // Created on: 2015-06-18
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2015 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _Graphic3d_TransformPers_HeaderFile
17 #define _Graphic3d_TransformPers_HeaderFile
18
19 #include <Aspect_TypeOfTriedronPosition.hxx>
20 #include <Bnd_Box.hxx>
21 #include <BVH_Box.hxx>
22 #include <Graphic3d_Camera.hxx>
23 #include <Graphic3d_TransformUtils.hxx>
24 #include <Graphic3d_TransModeFlags.hxx>
25 #include <Graphic3d_Vec.hxx>
26 #include <NCollection_Mat4.hxx>
27
28 DEFINE_STANDARD_HANDLE(Graphic3d_TransformPers, Standard_Transient)
29
30 //! Transformation Persistence definition.
31 //!
32 //! Transformation Persistence defines a mutable Local Coordinate system which depends on camera position,
33 //! so that visual appearance of the object becomes partially immutable while camera moves.
34 //! Object visually preserves particular property such as size, placement, rotation or their combination.
35 //!
36 //! Graphic3d_TMF_ZoomPers, Graphic3d_TMF_RotatePers and Graphic3d_TMF_ZoomRotatePers define Local Coordinate system
37 //! having origin in specified anchor point defined in World Coordinate system,
38 //! while Graphic3d_TMF_TriedronPers and Graphic3d_TMF_2d define origin as 2D offset from screen corner in pixels.
39 //!
40 //! Graphic3d_TMF_2d, Graphic3d_TMF_TriedronPers and Graphic3d_TMF_ZoomPers defines Local Coordinate system where length units are pixels.
41 //! Beware that Graphic3d_RenderingParams::ResolutionRatio() will be ignored!
42 //! For other Persistence flags, normal (world) length units will apply.
43 //!
44 //! WARNING: Graphic3d_TMF_None is not permitted for defining instance of this class - NULL handle should be used for this purpose!
45 class Graphic3d_TransformPers : public Standard_Transient
46 {
47   DEFINE_STANDARD_RTTIEXT(Graphic3d_TransformPers, Standard_Transient)
48 public:
49
50   //! Return true if specified mode is zoom/rotate transformation persistence.
51   static Standard_Boolean IsZoomOrRotate (Graphic3d_TransModeFlags theMode)
52   {
53     return (theMode & (Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers)) != 0;
54   }
55
56   //! Return true if specified mode is 2d/trihedron transformation persistence.
57   static Standard_Boolean IsTrihedronOr2d (Graphic3d_TransModeFlags theMode)
58   {
59     return (theMode & (Graphic3d_TMF_TriedronPers | Graphic3d_TMF_2d)) != 0;
60   }
61
62   //! Create Graphic3d_TransformPers instance from deprecated parameters set
63   //! decoding 2D corner + offset parameters from 3D point.
64   Standard_EXPORT static Handle(Graphic3d_TransformPers) FromDeprecatedParams (Graphic3d_TransModeFlags theFlag,
65                                                                                const gp_Pnt&            thePoint);
66
67 public:
68
69   //! Set transformation persistence.
70   Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode)
71   : myMode (theMode)
72   {
73     if (IsZoomOrRotate (theMode))
74     {
75       SetPersistence (theMode, gp_Pnt(0.0, 0.0, 0.0));
76     }
77     else if (IsTrihedronOr2d (theMode))
78     {
79       SetPersistence (theMode, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (0, 0));
80     }
81     else
82     {
83       throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
84     }
85   }
86
87   //! Set Zoom/Rotate transformation persistence with an anchor 3D point.
88   //! Anchor point defines the origin of Local Coordinate system within World Coordinate system.
89   //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers.
90   Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode,
91                            const gp_Pnt& thePnt)
92   : myMode (Graphic3d_TMF_None)
93   {
94     SetPersistence (theMode, thePnt);
95   }
96
97   //! Set 2d/trihedron transformation persistence with a corner and 2D offset.
98   //! 2D offset defines the origin of Local Coordinate system as projection of 2D point on screen plane into World Coordinate system.
99   //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d.
100   //! The offset is a positive displacement from the view corner in pixels.
101   Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode,
102                            const Aspect_TypeOfTriedronPosition theCorner,
103                            const Graphic3d_Vec2i& theOffset = Graphic3d_Vec2i (0, 0))
104   : myMode (Graphic3d_TMF_None)
105   {
106     SetPersistence (theMode, theCorner, theOffset);
107   }
108
109   //! Return true for Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers modes.
110   Standard_Boolean IsZoomOrRotate() const { return IsZoomOrRotate (myMode); }
111
112   //! Return true for Graphic3d_TMF_TriedronPers and Graphic3d_TMF_2d modes.
113   Standard_Boolean IsTrihedronOr2d() const { return IsTrihedronOr2d (myMode); }
114
115   //! Transformation persistence mode flags.
116   Graphic3d_TransModeFlags Mode() const { return myMode; }
117
118   //! Transformation persistence mode flags.
119   Graphic3d_TransModeFlags Flags() const { return myMode; }
120
121   //! Set Zoom/Rotate transformation persistence with an anchor 3D point.
122   //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers.
123   void SetPersistence (const Graphic3d_TransModeFlags theMode,
124                        const gp_Pnt& thePnt)
125   {
126     if (!IsZoomOrRotate (theMode))
127     {
128       throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
129     }
130
131     myMode = theMode;
132     myParams.Params3d.PntX = thePnt.X();
133     myParams.Params3d.PntY = thePnt.Y();
134     myParams.Params3d.PntZ = thePnt.Z();
135   }
136
137   //! Set 2d/trihedron transformation persistence with a corner and 2D offset.
138   //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d.
139   void SetPersistence (const Graphic3d_TransModeFlags theMode,
140                        const Aspect_TypeOfTriedronPosition theCorner,
141                        const Graphic3d_Vec2i& theOffset)
142   {
143     if (!IsTrihedronOr2d (theMode))
144     {
145       throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
146     }
147
148     myMode = theMode;
149     myParams.Params2d.Corner  = theCorner;
150     myParams.Params2d.OffsetX = theOffset.x();
151     myParams.Params2d.OffsetY = theOffset.y();
152   }
153
154 public:
155
156   //! Return the anchor point for zoom/rotate transformation persistence.
157   gp_Pnt AnchorPoint() const
158   {
159     if (!IsZoomOrRotate())
160     {
161       throw Standard_ProgramError("Graphic3d_TransformPers::AnchorPoint(), wrong persistence mode.");
162     }
163
164     return gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ);
165   }
166
167   //! Set the anchor point for zoom/rotate transformation persistence.
168   void SetAnchorPoint (const gp_Pnt& thePnt)
169   {
170     if (!IsZoomOrRotate())
171     {
172       throw Standard_ProgramError("Graphic3d_TransformPers::SetAnchorPoint(), wrong persistence mode.");
173     }
174
175     myParams.Params3d.PntX = thePnt.X();
176     myParams.Params3d.PntY = thePnt.Y();
177     myParams.Params3d.PntZ = thePnt.Z();
178   }
179
180   //! Return the corner for 2d/trihedron transformation persistence.
181   Aspect_TypeOfTriedronPosition Corner2d() const
182   {
183     if (!IsTrihedronOr2d())
184     {
185       throw Standard_ProgramError("Graphic3d_TransformPers::Corner2d(), wrong persistence mode.");
186     }
187
188     return myParams.Params2d.Corner;
189   }
190
191   //! Set the corner for 2d/trihedron transformation persistence.
192   void SetCorner2d (const Aspect_TypeOfTriedronPosition thePos)
193   {
194     if (!IsTrihedronOr2d())
195     {
196       throw Standard_ProgramError("Graphic3d_TransformPers::SetCorner2d(), wrong persistence mode.");
197     }
198
199     myParams.Params2d.Corner = thePos;
200   }
201
202   //! Return the offset from the corner for 2d/trihedron transformation persistence.
203   Graphic3d_Vec2i Offset2d() const
204   {
205     if (!IsTrihedronOr2d())
206     {
207       throw Standard_ProgramError("Graphic3d_TransformPers::Offset2d(), wrong persistence mode.");
208     }
209
210     return Graphic3d_Vec2i (myParams.Params2d.OffsetX, myParams.Params2d.OffsetY);
211   }
212
213   //! Set the offset from the corner for 2d/trihedron transformation persistence.
214   void SetOffset2d (const Graphic3d_Vec2i& theOffset)
215   {
216     if (!IsTrihedronOr2d())
217     {
218       throw Standard_ProgramError("Graphic3d_TransformPers::SetOffset2d(), wrong persistence mode.");
219     }
220
221     myParams.Params2d.OffsetX = theOffset.x();
222     myParams.Params2d.OffsetY = theOffset.y();
223   }
224
225 public:
226
227   //! Apply transformation to bounding box of presentation.
228   //! @param theCamera [in] camera definition
229   //! @param theProjection [in] the projection transformation matrix.
230   //! @param theWorldView [in] the world view transformation matrix.
231   //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
232   //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
233   //! @param theBoundingBox [in/out] the bounding box to transform.
234   template<class T>
235   void Apply (const Handle(Graphic3d_Camera)& theCamera,
236               const NCollection_Mat4<T>& theProjection,
237               const NCollection_Mat4<T>& theWorldView,
238               const Standard_Integer theViewportWidth,
239               const Standard_Integer theViewportHeight,
240               Bnd_Box& theBoundingBox) const;
241
242   //! Apply transformation to bounding box of presentation
243   //! @param theCamera [in] camera definition
244   //! @param theProjection [in] the projection transformation matrix.
245   //! @param theWorldView [in] the world view transformation matrix.
246   //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
247   //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
248   //! @param theBoundingBox [in/out] the bounding box to transform.
249   template<class T>
250   void Apply (const Handle(Graphic3d_Camera)& theCamera,
251               const NCollection_Mat4<T>& theProjection,
252               const NCollection_Mat4<T>& theWorldView,
253               const Standard_Integer theViewportWidth,
254               const Standard_Integer theViewportHeight,
255               BVH_Box<T, 3>& theBoundingBox) const;
256
257   //! Compute transformation.
258   //! Computed matrix can be applied to model world transformation
259   //! of an object to implement effect of transformation persistence.
260   //! @param theCamera [in] camera definition
261   //! @param theProjection [in] the projection transformation matrix.
262   //! @param theWorldView [in] the world view transformation matrix.
263   //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
264   //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
265   //! @return transformation matrix to be applied to model world transformation of an object.
266   template<class T>
267   NCollection_Mat4<T> Compute (const Handle(Graphic3d_Camera)& theCamera,
268                                const NCollection_Mat4<T>& theProjection,
269                                const NCollection_Mat4<T>& theWorldView,
270                                const Standard_Integer theViewportWidth,
271                                const Standard_Integer theViewportHeight) const;
272
273   //! Apply transformation persistence on specified matrices.
274   //! @param theCamera camera definition
275   //! @param theProjection projection matrix to modify
276   //! @param theWorldView  world-view matrix to modify
277   //! @param theViewportWidth  viewport width
278   //! @param theViewportHeight viewport height
279   template<class T>
280   void Apply (const Handle(Graphic3d_Camera)& theCamera,
281               const NCollection_Mat4<T>& theProjection,
282               NCollection_Mat4<T>& theWorldView,
283               const Standard_Integer theViewportWidth,
284               const Standard_Integer theViewportHeight) const;
285
286   //! Dumps the content of me into the stream
287   Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
288
289 private:
290
291   //! 3D anchor point for zoom/rotate transformation persistence.
292   struct PersParams3d
293   {
294     Standard_Real PntX;
295     Standard_Real PntY;
296     Standard_Real PntZ;
297
298     //! Dumps the content of me into the stream
299     Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
300   };
301
302   //! 2d/trihedron transformation persistence parameters.
303   struct PersParams2d
304   {
305     Standard_Integer OffsetX;
306     Standard_Integer OffsetY;
307     Aspect_TypeOfTriedronPosition Corner;
308
309     //! Dumps the content of me into the stream
310     Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
311   };
312
313 private:
314
315   Graphic3d_TransModeFlags myMode;  //!< Transformation persistence mode flags
316   union
317   {
318     PersParams3d Params3d;
319     PersParams2d Params2d;
320   } myParams;
321
322 };
323
324 // =======================================================================
325 // function : Apply
326 // purpose  : Apply transformation to world view and projection matrices.
327 // =======================================================================
328 template<class T>
329 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
330                                      const NCollection_Mat4<T>& theProjection,
331                                      NCollection_Mat4<T>& theWorldView,
332                                      const Standard_Integer theViewportWidth,
333                                      const Standard_Integer theViewportHeight) const
334 {
335   (void )theViewportWidth;
336   (void )theProjection;
337   if (myMode == Graphic3d_TMF_None
338    || theViewportHeight == 0)
339   {
340     return;
341   }
342
343   // use total size when tiling is active
344   const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight;
345
346   // a small enough jitter compensation offset
347   // to avoid image dragging within single pixel in corner cases
348   const Standard_Real aJitterComp = 0.001;
349   if (myMode == Graphic3d_TMF_TriedronPers)
350   {
351     // reset Z focus for trihedron persistence
352     const Standard_Real aFocus = theCamera->IsOrthographic()
353                                ? theCamera->Distance()
354                                : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
355                                 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
356                                 : Standard_Real(theCamera->ZFocus()));
357
358     // scale factor to pixels
359     const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
360     const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
361     const gp_Dir aForward = theCamera->Direction();
362     gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance());
363     if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
364     {
365       const Standard_Real anOffsetX = (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale;
366       const gp_Dir aSide   = aForward.Crossed (theCamera->Up());
367       const gp_XYZ aDeltaX = aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffsetX);
368       if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0)
369       {
370         aCenter += aDeltaX;
371       }
372       else
373       {
374         aCenter -= aDeltaX;
375       }
376     }
377     if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
378     {
379       const Standard_Real anOffsetY = (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale;
380       const gp_XYZ aDeltaY = theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffsetY);
381       if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0)
382       {
383         aCenter += aDeltaY;
384       }
385       else
386       {
387         aCenter -= aDeltaY;
388       }
389     }
390
391     NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix();
392     Graphic3d_TransformUtils::Translate (aWorldView, aCenter.X(), aCenter.Y(), aCenter.Z());
393     Graphic3d_TransformUtils::Scale     (aWorldView, aScale,      aScale,      aScale);
394     theWorldView.ConvertFrom (aWorldView);
395     return;
396   }
397   else if (myMode == Graphic3d_TMF_2d)
398   {
399     const Standard_Real aFocus = theCamera->IsOrthographic()
400                                ? theCamera->Distance()
401                                : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
402                                 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
403                                 : Standard_Real(theCamera->ZFocus()));
404
405     // scale factor to pixels
406     const gp_XYZ        aViewDim = theCamera->ViewDimensions (aFocus);
407     const Standard_Real aScale   = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
408     gp_XYZ aCenter (0.0, 0.0, -aFocus);
409     if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
410     {
411       aCenter.SetX (-aViewDim.X() * 0.5 + (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale);
412       if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0)
413       {
414         aCenter.SetX (-aCenter.X());
415       }
416     }
417     if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
418     {
419       aCenter.SetY (-aViewDim.Y() * 0.5 + (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale);
420       if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0)
421       {
422         aCenter.SetY (-aCenter.Y());
423       }
424     }
425
426     theWorldView.InitIdentity();
427     Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z()));
428     Graphic3d_TransformUtils::Scale     (theWorldView, T(aScale),      T(aScale),      T(aScale));
429     return;
430   }
431   else
432   {
433     // Compute reference point for transformation in untransformed projection space.
434     NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix();
435     Graphic3d_TransformUtils::Translate (aWorldView, myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ);
436     if ((myMode & Graphic3d_TMF_RotatePers) != 0)
437     {
438       // lock rotation by nullifying rotation component
439       aWorldView.SetValue (0, 0, 1.0);
440       aWorldView.SetValue (1, 0, 0.0);
441       aWorldView.SetValue (2, 0, 0.0);
442
443       aWorldView.SetValue (0, 1, 0.0);
444       aWorldView.SetValue (1, 1, 1.0);
445       aWorldView.SetValue (2, 1, 0.0);
446
447       aWorldView.SetValue (0, 2, 0.0);
448       aWorldView.SetValue (1, 2, 0.0);
449       aWorldView.SetValue (2, 2, 1.0);
450     }
451
452     if ((myMode & Graphic3d_TMF_ZoomPers) != 0)
453     {
454       // lock zooming
455       gp_Vec aVecToEye (theCamera->Direction());
456       gp_Vec aVecToObj (theCamera->Eye(), gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ));
457       const Standard_Real aFocus = aVecToObj.Dot (aVecToEye);
458       const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
459       const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
460       Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale);
461     }
462     theWorldView.ConvertFrom (aWorldView);
463     return;
464   }
465 }
466
467 // =======================================================================
468 // function : Apply
469 // purpose  : Apply transformation to bounding box of presentation.
470 // =======================================================================
471 template<class T>
472 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
473                                      const NCollection_Mat4<T>& theProjection,
474                                      const NCollection_Mat4<T>& theWorldView,
475                                      const Standard_Integer theViewportWidth,
476                                      const Standard_Integer theViewportHeight,
477                                      Bnd_Box& theBoundingBox) const
478 {
479   if (theBoundingBox.IsVoid())
480   {
481     return;
482   }
483
484   T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
485
486   theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
487
488   typename BVH_Box<T, 3>::BVH_VecNt aMin (aXmin, aYmin, aZmin);
489   typename BVH_Box<T, 3>::BVH_VecNt aMax (aXmax, aYmax, aZmax);
490   BVH_Box<T, 3> aBBox (aMin, aMax);
491
492   Apply (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox);
493
494   theBoundingBox = Bnd_Box();
495   theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(),
496                          aBBox.CornerMax().x(), aBBox.CornerMax().y(), aBBox.CornerMax().z());
497 }
498
499 // =======================================================================
500 // function : Apply
501 // purpose  : Apply transformation to bounding box of presentation.
502 // =======================================================================
503 template<class T>
504 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
505                                      const NCollection_Mat4<T>& theProjection,
506                                      const NCollection_Mat4<T>& theWorldView,
507                                      const Standard_Integer theViewportWidth,
508                                      const Standard_Integer theViewportHeight,
509                                      BVH_Box<T, 3>& theBoundingBox) const
510 {
511   NCollection_Mat4<T> aTPers = Compute (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight);
512   if (aTPers.IsIdentity()
513   || !theBoundingBox.IsValid())
514   {
515     return;
516   }
517
518   const typename BVH_Box<T, 3>::BVH_VecNt& aMin = theBoundingBox.CornerMin();
519   const typename BVH_Box<T, 3>::BVH_VecNt& aMax = theBoundingBox.CornerMax();
520
521   typename BVH_Box<T, 4>::BVH_VecNt anArrayOfCorners[8];
522   anArrayOfCorners[0] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
523   anArrayOfCorners[1] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
524   anArrayOfCorners[2] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
525   anArrayOfCorners[3] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
526   anArrayOfCorners[4] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
527   anArrayOfCorners[5] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
528   anArrayOfCorners[6] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
529   anArrayOfCorners[7] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
530
531   theBoundingBox.Clear();
532   for (Standard_Integer anIt = 0; anIt < 8; ++anIt)
533   {
534     typename BVH_Box<T, 4>::BVH_VecNt& aCorner = anArrayOfCorners[anIt];
535     aCorner  = aTPers * aCorner;
536     aCorner = aCorner / aCorner.w();
537     theBoundingBox.Add (typename BVH_Box<T, 3>::BVH_VecNt (aCorner.x(), aCorner.y(), aCorner.z()));
538   }
539 }
540
541 // =======================================================================
542 // function : Compute
543 // purpose  : Compute transformation.
544 // =======================================================================
545 template<class T>
546 NCollection_Mat4<T> Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Camera)& theCamera,
547                                                       const NCollection_Mat4<T>& theProjection,
548                                                       const NCollection_Mat4<T>& theWorldView,
549                                                       const Standard_Integer theViewportWidth,
550                                                       const Standard_Integer theViewportHeight) const
551 {
552   if (myMode == Graphic3d_TMF_None)
553   {
554     return NCollection_Mat4<T>();
555   }
556
557   NCollection_Mat4<T> aWorldView (theWorldView);
558   NCollection_Mat4<T> anUnviewMat;
559   if (!theWorldView.Inverted (anUnviewMat))
560   {
561     return NCollection_Mat4<T>();
562   }
563
564   // compute only world-view matrix difference to avoid floating point instability
565   // caused by projection matrix modifications outside of this algorithm (e.g. by Z-fit)
566   Apply (theCamera, theProjection, aWorldView, theViewportWidth, theViewportHeight);
567   return anUnviewMat * aWorldView;
568 }
569
570 #endif // _Graphic3d_TransformPers_HeaderFile