1 // Created on: 2015-06-18
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2015 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef _Graphic3d_TransformPers_HeaderFile
17 #define _Graphic3d_TransformPers_HeaderFile
19 #include <Bnd_Box.hxx>
20 #include <BVH_Box.hxx>
21 #include <Graphic3d_Camera.hxx>
22 #include <Graphic3d_TransformUtils.hxx>
23 #include <Graphic3d_TransModeFlags.hxx>
24 #include <NCollection_Mat4.hxx>
25 #include <NCollection_Vec4.hxx>
27 //! Class for keeping and computing transformation persistence.
28 class Graphic3d_TransformPers
34 //! Default constructor.
35 Graphic3d_TransformPers()
36 : Flags (Graphic3d_TMF_None),
37 Point (0.0, 0.0, 0.0) {}
39 //! Transformation persistence mode flags.
40 Graphic3d_TransModeFlags Flags;
42 //! Reference point for transformation.
43 Graphic3d_Vec3d Point;
47 //! Apply transformation to bounding box of presentation.
48 //! @param theCamera [in] camera definition
49 //! @param theProjection [in] the projection transformation matrix.
50 //! @param theWorldView [in] the world view transformation matrix.
51 //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
52 //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
53 //! @param theBoundingBox [in/out] the bounding box to transform.
55 void Apply (const Handle(Graphic3d_Camera)& theCamera,
56 const NCollection_Mat4<T>& theProjection,
57 const NCollection_Mat4<T>& theWorldView,
58 const Standard_Integer theViewportWidth,
59 const Standard_Integer theViewportHeight,
60 Bnd_Box& theBoundingBox) const;
62 //! Apply transformation to bounding box of presentation
63 //! @param theCamera [in] camera definition
64 //! @param theProjection [in] the projection transformation matrix.
65 //! @param theWorldView [in] the world view transformation matrix.
66 //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
67 //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
68 //! @param theBoundingBox [in/out] the bounding box to transform.
70 void Apply (const Handle(Graphic3d_Camera)& theCamera,
71 const NCollection_Mat4<T>& theProjection,
72 const NCollection_Mat4<T>& theWorldView,
73 const Standard_Integer theViewportWidth,
74 const Standard_Integer theViewportHeight,
75 BVH_Box<T, 4>& theBoundingBox) const;
77 //! Compute transformation.
78 //! Computed matrix can be applied to model world transformation
79 //! of an object to implement effect of transformation persistence.
80 //! @param theCamera [in] camera definition
81 //! @param theProjection [in] the projection transformation matrix.
82 //! @param theWorldView [in] the world view transformation matrix.
83 //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
84 //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
85 //! @return transformation matrix to be applied to model world transformation of an object.
87 NCollection_Mat4<T> Compute (const Handle(Graphic3d_Camera)& theCamera,
88 const NCollection_Mat4<T>& theProjection,
89 const NCollection_Mat4<T>& theWorldView,
90 const Standard_Integer theViewportWidth,
91 const Standard_Integer theViewportHeight) const;
94 void Apply (const Handle(Graphic3d_Camera)& theCamera,
95 NCollection_Mat4<T>& theProjection,
96 NCollection_Mat4<T>& theWorldView,
97 const Standard_Integer theViewportWidth,
98 const Standard_Integer theViewportHeight) const;
101 // =======================================================================
103 // purpose : Apply transformation to world view and projection matrices.
104 // =======================================================================
106 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
107 NCollection_Mat4<T>& theProjection,
108 NCollection_Mat4<T>& theWorldView,
109 const Standard_Integer theViewportWidth,
110 const Standard_Integer theViewportHeight) const
112 (void )theViewportWidth;
118 const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight;
119 if (Flags == Graphic3d_TMF_TriedronPers)
121 // reset Z focus for trihedron persistence
122 const Standard_Real aFocus = theCamera->IsOrthographic()
123 ? theCamera->Distance()
124 : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
125 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
126 : Standard_Real(theCamera->ZFocus()));
128 // scale factor to pixels
129 const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
130 const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
132 // offset from the corner
133 const Standard_Real anOffset = Point.z() * aScale;
135 const gp_Dir aForward (theCamera->Center().XYZ() - theCamera->Eye().XYZ());
136 gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance());
137 if (Point.x() != 0.0)
139 const gp_Dir aSide = aForward.Crossed (theCamera->Up());
142 aCenter += aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffset);
146 aCenter -= aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffset);
149 if (Point.y() != 0.0)
153 aCenter += theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffset);
157 aCenter -= theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffset);
161 Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z()));
162 Graphic3d_TransformUtils::Scale (theWorldView, T(aScale), T(aScale), T(aScale));
165 else if (Flags == Graphic3d_TMF_2d)
167 const Standard_Real aFocus = theCamera->IsOrthographic()
168 ? theCamera->Distance()
169 : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
170 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
171 : Standard_Real(theCamera->ZFocus()));
173 // scale factor to pixels
174 const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
175 const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
176 gp_XYZ aCenter (0.0, 0.0, -aFocus);
177 if (Point.x() != 0.0)
179 aCenter.SetX (-aViewDim.X() * 0.5 + Point.z() * aScale);
182 aCenter.SetX (-aCenter.X());
185 if (Point.y() != 0.0)
187 aCenter.SetY (-aViewDim.Y() * 0.5 + Point.z() * aScale);
190 aCenter.SetY (-aCenter.Y());
194 theWorldView.InitIdentity();
195 Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z()));
196 Graphic3d_TransformUtils::Scale (theWorldView, T(aScale), T(aScale), T(aScale));
201 // Compute reference point for transformation in untransformed projection space.
202 NCollection_Vec4<T> aRefPoint (static_cast<T> (Point.x()),
203 static_cast<T> (Point.y()),
204 static_cast<T> (Point.z()),
205 static_cast<T> (1.0));
206 NCollection_Vec4<T> aRefPointProj;
207 if ((Flags & Graphic3d_TMF_PanPers) != Graphic3d_TMF_PanPers)
209 aRefPointProj = theProjection * (theWorldView * aRefPoint);
210 aRefPointProj /= aRefPointProj.w();
214 if ((Flags & Graphic3d_TMF_ZoomPers) != 0)
216 const T aSize = static_cast<T> (1.0);
217 const Standard_Integer aViewport[4] = { 0, 0, theViewportHeight, theViewportHeight };
218 NCollection_Mat4<T> aWorldView;
219 aWorldView.InitIdentity();
221 NCollection_Vec3<T> aWinCoordsRefPoint;
222 Graphic3d_TransformUtils::Project (static_cast<T> (Point.x()),
223 static_cast<T> (Point.y()),
224 static_cast<T> (Point.z()),
225 theWorldView, theProjection, aViewport,
226 aWinCoordsRefPoint.x(), aWinCoordsRefPoint.y(), aWinCoordsRefPoint.z());
228 NCollection_Vec3<T> anUnProj1;
229 Graphic3d_TransformUtils::UnProject (aWinCoordsRefPoint.x(), aWinCoordsRefPoint.y(), aWinCoordsRefPoint.z(),
230 aWorldView, theProjection, aViewport,
231 anUnProj1.x(), anUnProj1.y(), anUnProj1.z());
233 NCollection_Vec3<T> anUnProj2;
234 Graphic3d_TransformUtils::UnProject (aWinCoordsRefPoint.x(), aWinCoordsRefPoint.y() + aSize, aWinCoordsRefPoint.z(),
235 aWorldView, theProjection, aViewport,
236 anUnProj2.x(), anUnProj2.y(), anUnProj2.z());
238 const T aScale = (anUnProj2.y() - anUnProj1.y()) / aSize;
240 Graphic3d_TransformUtils::Scale (theWorldView, aScale, aScale, aScale);
243 // Prevent translation by nullifying translation component.
244 if ((Flags & Graphic3d_TMF_PanPers) != 0)
246 theWorldView .SetValue (0, 3, static_cast<T> (0.0));
247 theWorldView .SetValue (1, 3, static_cast<T> (0.0));
248 theWorldView .SetValue (2, 3, static_cast<T> (0.0));
249 theProjection.SetValue (0, 3, static_cast<T> (0.0));
250 theProjection.SetValue (1, 3, static_cast<T> (0.0));
251 theProjection.SetValue (2, 3, static_cast<T> (0.0));
254 // Prevent rotation by nullifying rotation component.
255 if (Flags & Graphic3d_TMF_RotatePers)
257 theWorldView.SetValue (0, 0, static_cast<T> (1.0));
258 theWorldView.SetValue (1, 0, static_cast<T> (0.0));
259 theWorldView.SetValue (2, 0, static_cast<T> (0.0));
261 theWorldView.SetValue (0, 1, static_cast<T> (0.0));
262 theWorldView.SetValue (1, 1, static_cast<T> (1.0));
263 theWorldView.SetValue (2, 1, static_cast<T> (0.0));
265 theWorldView.SetValue (0, 2, static_cast<T> (0.0));
266 theWorldView.SetValue (1, 2, static_cast<T> (0.0));
267 theWorldView.SetValue (2, 2, static_cast<T> (1.0));
270 if ((Flags & Graphic3d_TMF_PanPers) != Graphic3d_TMF_PanPers)
272 NCollection_Mat4<T> anUnviewMat;
274 if (!(theProjection * theWorldView).Inverted (anUnviewMat))
276 Standard_ProgramError::Raise ("Graphic3d_TransformPers::Apply, can not inverse world view projection matrix.");
279 // Move to reference point location in transformed view projection space.
280 aRefPoint = anUnviewMat * aRefPointProj;
281 aRefPoint /= aRefPoint.w();
283 Graphic3d_TransformUtils::Translate<T> (theWorldView, aRefPoint.x(), aRefPoint.y(), aRefPoint.z());
288 // =======================================================================
290 // purpose : Apply transformation to bounding box of presentation.
291 // =======================================================================
293 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
294 const NCollection_Mat4<T>& theProjection,
295 const NCollection_Mat4<T>& theWorldView,
296 const Standard_Integer theViewportWidth,
297 const Standard_Integer theViewportHeight,
298 Bnd_Box& theBoundingBox) const
300 if (theBoundingBox.IsVoid())
305 T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
307 theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
309 typename BVH_Box<T, 4>::BVH_VecNt aMin (aXmin, aYmin, aZmin, static_cast<T> (1.0));
310 typename BVH_Box<T, 4>::BVH_VecNt aMax (aXmax, aYmax, aZmax, static_cast<T> (1.0));
311 BVH_Box<T, 4> aBBox (aMin, aMax);
313 Apply (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox);
315 theBoundingBox = Bnd_Box();
316 theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(),
317 aBBox.CornerMax().x(), aBBox.CornerMax().y(), aBBox.CornerMax().z());
320 // =======================================================================
322 // purpose : Apply transformation to bounding box of presentation.
323 // =======================================================================
325 void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
326 const NCollection_Mat4<T>& theProjection,
327 const NCollection_Mat4<T>& theWorldView,
328 const Standard_Integer theViewportWidth,
329 const Standard_Integer theViewportHeight,
330 BVH_Box<T, 4>& theBoundingBox) const
332 NCollection_Mat4<T> aTPers = Compute (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight);
333 if (aTPers.IsIdentity()
334 || !theBoundingBox.IsValid())
339 const typename BVH_Box<T, 4>::BVH_VecNt& aMin = theBoundingBox.CornerMin();
340 const typename BVH_Box<T, 4>::BVH_VecNt& aMax = theBoundingBox.CornerMax();
342 typename BVH_Box<T, 4>::BVH_VecNt anArrayOfCorners[8];
343 anArrayOfCorners[0] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
344 anArrayOfCorners[1] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
345 anArrayOfCorners[2] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
346 anArrayOfCorners[3] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
347 anArrayOfCorners[4] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
348 anArrayOfCorners[5] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
349 anArrayOfCorners[6] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
350 anArrayOfCorners[7] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
352 theBoundingBox.Clear();
353 for (Standard_Integer anIt = 0; anIt < 8; ++anIt)
355 typename BVH_Box<T, 4>::BVH_VecNt& aCorner = anArrayOfCorners[anIt];
356 aCorner = aTPers * aCorner;
357 aCorner /= aCorner.w();
358 theBoundingBox.Add (aCorner);
362 // =======================================================================
363 // function : Compute
364 // purpose : Compute transformation.
365 // =======================================================================
367 NCollection_Mat4<T> Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Camera)& theCamera,
368 const NCollection_Mat4<T>& theProjection,
369 const NCollection_Mat4<T>& theWorldView,
370 const Standard_Integer theViewportWidth,
371 const Standard_Integer theViewportHeight) const
373 if (Flags == Graphic3d_TMF_None)
375 return NCollection_Mat4<T>();
378 NCollection_Mat4<T> anUnviewMat;
380 if (!(theProjection * theWorldView).Inverted (anUnviewMat))
382 return NCollection_Mat4<T>();
385 NCollection_Mat4<T> aProjection (theProjection);
386 NCollection_Mat4<T> aWorldView (theWorldView);
388 Apply (theCamera, aProjection, aWorldView, theViewportWidth, theViewportHeight);
390 return anUnviewMat * (aProjection * aWorldView);
393 #endif // _Graphic3d_TransformPers_HeaderFile